[PATCH] i2c: Add support for device-tree based chip initialization
Some I2C devices are not or not correctly initialized by the firmware. Configuration would be possible via platform data, but that would require per-driver platform data and a lot of code, and changing it would not be possible without re-compiling the kernel. It is more elegant to do it generically via devicetree properties. Add a generic I2C devicetree property named "reg-init". This property provides a sequence of device initialization commands to be executed prior to calling the probe function for a given device. Signed-off-by: Guenter Roeck --- .../devicetree/bindings/i2c/trivial-devices.txt| 24 +++ drivers/i2c/i2c-core.c | 68 2 files changed, 92 insertions(+) diff --git a/Documentation/devicetree/bindings/i2c/trivial-devices.txt b/Documentation/devicetree/bindings/i2c/trivial-devices.txt index 2f5322b..33b694e 100644 --- a/Documentation/devicetree/bindings/i2c/trivial-devices.txt +++ b/Documentation/devicetree/bindings/i2c/trivial-devices.txt @@ -2,6 +2,30 @@ This is a list of trivial i2c devices that have simple device tree bindings, consisting only of a compatible field, an address and possibly an interrupt line. +Device initialization is supported with an optional reg-init property. +This property contains a sequence of commands to be written into the chip. +Each command consists of four values: Register, command type, mask, and data. + Register: + Register or command address + Command type: + 0: SMBus write byte + 1: SMBus write byte data + 2: SMBus write word data + Mask: + If set, the register is read and masked with this value. + Data: + Data to be written (or with original data and mask if set) + +Example: + max6696@1a { + compatible = "maxim,max6696"; + reg = <0x1a>; + reg-init = < + 0x09 1 0x00 0x24 + 0x21 1 0x00 0x05 + >; + }; + If a device needs more specific bindings, such as properties to describe some aspect of it, there needs to be a specific binding document for it just like any other devices. diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index a7edf98..49f8b74 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -104,6 +104,69 @@ static int i2c_device_uevent(struct device *dev, struct kobj_uevent_env *env) #define i2c_device_uevent NULL #endif /* CONFIG_HOTPLUG */ +static int i2c_dev_of_init(struct i2c_client *client, struct device *dev) +{ + const u32 *reg_init; + int rlen; + int val; + u32 reg, access, mask, data; + + reg_init = of_get_property(dev->of_node, "reg-init", &rlen); + if (!reg_init) + return 0; + + if (!rlen || rlen % 4) + return -EINVAL; + + while (rlen >= 4) { + reg = reg_init[0]; + access = reg_init[1]; + mask = reg_init[2]; + data = reg_init[3]; + + if (reg > 0xff) + return -EINVAL; + + switch (access) { + default: + return -EINVAL; + case 0: + val = 0; + break; + case 1: + val = mask ? i2c_smbus_read_byte_data(client, reg) : 0; + break; + case 2: + val = mask ? i2c_smbus_read_word_data(client, reg) : 0; + break; + } + if (val < 0) + return val; + + val &= mask; + val |= data; + + switch (access) { + default: + case 0: + val = i2c_smbus_write_byte(client, reg); + break; + case 1: + val = i2c_smbus_write_byte_data(client, reg, val); + break; + case 2: + val = i2c_smbus_write_word_data(client, reg, val); + break; + } + if (val < 0) + return val; + + reg_init += 4; + rlen -= 4 * sizeof(u32); + } + return 0; +} + static int i2c_device_probe(struct device *dev) { struct i2c_client *client = i2c_verify_client(dev); @@ -122,7 +185,12 @@ static int i2c_device_probe(struct device *dev) client->flags & I2C_CLIENT_WAKE); dev_dbg(dev, "probe\n"); + status = i2c_dev_of_init(client, dev); + if (status) + goto error; + status = driver->probe(client, i2c_match_id(driver->id_table, client)); +error: if (status) { client->driver = NULL; i2c_set_clientdata(client, NULL)
Re: [PATCH 3/3] i2c: at91: add dma support
On 11/14/2012 05:44 PM, ludovic.desroc...@atmel.com : > From: Ludovic Desroches > > Add dma support for Atmel TWI which is available on sam9x5 and later. > > When using dma for reception, you have to read only n-2 bytes. The last > two bytes are read manually. Don't doing this should cause to send the > STOP command too late and then to get extra data in the receive > register. > > Signed-off-by: Ludovic Desroches Even nicer ;-) Acked-by: Nicolas Ferre > --- > drivers/i2c/busses/i2c-at91.c | 306 > -- > 1 file changed, 298 insertions(+), 8 deletions(-) > > diff --git a/drivers/i2c/busses/i2c-at91.c b/drivers/i2c/busses/i2c-at91.c > index 2c437df..ceef40f 100644 > --- a/drivers/i2c/busses/i2c-at91.c > +++ b/drivers/i2c/busses/i2c-at91.c > @@ -19,6 +19,8 @@ > > #include > #include > +#include > +#include > #include > #include > #include > @@ -29,9 +31,11 @@ > #include > #include > #include > +#include > > #define TWI_CLK_HZ 10 /* max 400 Kbits/s */ > #define AT91_I2C_TIMEOUT msecs_to_jiffies(100) /* transfer timeout */ > +#define AT91_I2C_DMA_THRESHOLD 8 /* enable DMA > if transfer size is bigger than this threshold */ > > /* AT91 TWI register definitions */ > #define AT91_TWI_CR 0x /* Control Register */ > @@ -69,6 +73,18 @@ struct at91_twi_pdata { > unsigned clk_max_div; > unsigned clk_offset; > bool has_unre_flag; > + bool has_dma_support; > + struct at_dma_slave dma_slave; > +}; > + > +struct at91_twi_dma { > + struct dma_chan *chan_rx; > + struct dma_chan *chan_tx; > + struct scatterlist sg; > + struct dma_async_tx_descriptor *data_desc; > + enum dma_data_direction direction; > + bool buf_mapped; > + bool xfer_in_progress; > }; > > struct at91_twi_dev { > @@ -80,10 +96,13 @@ struct at91_twi_dev { > size_t buf_len; > struct i2c_msg *msg; > int irq; > + unsigned imr; > unsigned transfer_status; > struct i2c_adapter adapter; > unsigned twi_cwgr_reg; > struct at91_twi_pdata *pdata; > + bool use_dma; > + struct at91_twi_dma dma; > }; > > static unsigned at91_twi_read(struct at91_twi_dev *dev, unsigned reg) > @@ -102,6 +121,17 @@ static void at91_disable_twi_interrupts(struct > at91_twi_dev *dev) > AT91_TWI_TXCOMP | AT91_TWI_RXRDY | AT91_TWI_TXRDY); > } > > +static void at91_twi_irq_save(struct at91_twi_dev *dev) > +{ > + dev->imr = at91_twi_read(dev, AT91_TWI_IMR) & 0x7; > + at91_disable_twi_interrupts(dev); > +} > + > +static void at91_twi_irq_restore(struct at91_twi_dev *dev) > +{ > + at91_twi_write(dev, AT91_TWI_IER, dev->imr); > +} > + > static void at91_init_twi_bus(struct at91_twi_dev *dev) > { > at91_disable_twi_interrupts(dev); > @@ -138,6 +168,28 @@ static void __devinit at91_calc_twi_clock(struct > at91_twi_dev *dev, int twi_clk) > dev_dbg(dev->dev, "cdiv %d ckdiv %d\n", cdiv, ckdiv); > } > > +static void at91_twi_dma_cleanup(struct at91_twi_dev *dev) > +{ > + struct at91_twi_dma *dma = &dev->dma; > + > + at91_twi_irq_save(dev); > + > + if (dma->xfer_in_progress) { > + if (dma->direction == DMA_FROM_DEVICE) > + dmaengine_terminate_all(dma->chan_rx); > + else > + dmaengine_terminate_all(dma->chan_tx); > + dma->xfer_in_progress = false; > + } > + if (dma->buf_mapped) { > + dma_unmap_single(dev->dev, sg_dma_address(&dma->sg), > + dev->buf_len, dma->direction); > + dma->buf_mapped = false; > + } > + > + at91_twi_irq_restore(dev); > +} > + > static void at91_twi_write_next_byte(struct at91_twi_dev *dev) > { > if (dev->buf_len <= 0) > @@ -154,6 +206,60 @@ static void at91_twi_write_next_byte(struct at91_twi_dev > *dev) > ++dev->buf; > } > > +static void at91_twi_write_data_dma_callback(void *data) > +{ > + struct at91_twi_dev *dev = (struct at91_twi_dev *)data; > + > + dma_unmap_single(dev->dev, sg_dma_address(&dev->dma.sg), > + dev->buf_len, DMA_MEM_TO_DEV); > + > + at91_twi_write(dev, AT91_TWI_CR, AT91_TWI_STOP); > +} > + > +static void at91_twi_write_data_dma(struct at91_twi_dev *dev) > +{ > + dma_addr_t dma_addr; > + struct dma_async_tx_descriptor *txdesc; > + struct at91_twi_dma *dma = &dev->dma; > + struct dma_chan *chan_tx = dma->chan_tx; > + > + if (dev->buf_len <= 0) > + return; > + > + dma->direction = DMA_TO_DEVICE; > + > + at91_twi_irq_save(dev); > + dma_addr = dma_map_single(dev->dev, dev->buf, dev->buf_len, > + DMA_TO_DEVICE); > + if (dma_mapping_error(dev->dev, dma_addr)) { > + dev_err(dev->dev, "dma map failed\n"); > + return; > + } > + dma->
Re: [PATCH 2/3] i2c: at91: change struct members indentation
On 11/14/2012 05:44 PM, ludovic.desroc...@atmel.com : > From: Ludovic Desroches > > Replace tabs for struct members indentation by space to minimise line changes > when adding new members which would require extra tabs to keep alignment. Lol, you followed Wolfram's advice... You know my preferences ;-) > Signed-off-by: Ludovic Desroches Ok, then: Acked-by: Nicolas Ferre > --- > drivers/i2c/busses/i2c-at91.c | 30 +++--- > 1 file changed, 15 insertions(+), 15 deletions(-) > > diff --git a/drivers/i2c/busses/i2c-at91.c b/drivers/i2c/busses/i2c-at91.c > index dc8cb22..2c437df 100644 > --- a/drivers/i2c/busses/i2c-at91.c > +++ b/drivers/i2c/busses/i2c-at91.c > @@ -66,24 +66,24 @@ > #define AT91_TWI_THR0x0034 /* Transmit Holding Register */ > > struct at91_twi_pdata { > - unsignedclk_max_div; > - unsignedclk_offset; > - boolhas_unre_flag; > + unsigned clk_max_div; > + unsigned clk_offset; > + bool has_unre_flag; > }; > > struct at91_twi_dev { > - struct device *dev; > - void __iomem*base; > - struct completion cmd_complete; > - struct clk *clk; > - u8 *buf; > - size_t buf_len; > - struct i2c_msg *msg; > - int irq; > - unsignedtransfer_status; > - struct i2c_adapter adapter; > - unsignedtwi_cwgr_reg; > - struct at91_twi_pdata *pdata; > + struct device *dev; > + void __iomem *base; > + struct completion cmd_complete; > + struct clk *clk; > + u8 *buf; > + size_t buf_len; > + struct i2c_msg *msg; > + int irq; > + unsigned transfer_status; > + struct i2c_adapter adapter; > + unsigned twi_cwgr_reg; > + struct at91_twi_pdata *pdata; > }; > > static unsigned at91_twi_read(struct at91_twi_dev *dev, unsigned reg) > -- Nicolas Ferre -- To unsubscribe from this list: send the line "unsubscribe linux-i2c" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 1/3] i2c: at91: fix compilation warning
On 11/14/2012 05:44 PM, ludovic.desroc...@atmel.com : > From: Ludovic Desroches > > Signed-off-by: Ludovic Desroches Acked-by: Nicolas Ferre Maybe tell Wolfram to remove this one from the series and add it to his 3.7 tree... Bye, > --- > drivers/i2c/busses/i2c-at91.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/drivers/i2c/busses/i2c-at91.c b/drivers/i2c/busses/i2c-at91.c > index a6670eb..dc8cb22 100644 > --- a/drivers/i2c/busses/i2c-at91.c > +++ b/drivers/i2c/busses/i2c-at91.c > @@ -412,7 +412,7 @@ static struct at91_twi_pdata * __devinit > at91_twi_get_driver_data( > match = of_match_node(atmel_twi_dt_ids, pdev->dev.of_node); > if (!match) > return NULL; > - return match->data; > + return (struct at91_twi_pdata *) match->data; > } > return (struct at91_twi_pdata *) > platform_get_device_id(pdev)->driver_data; > } > -- Nicolas Ferre -- To unsubscribe from this list: send the line "unsubscribe linux-i2c" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v6 2/2] i2c: i2c-ocores: Add support for the GRLIB port of the controller and use function pointers for getreg and setreg functions
> "Andreas" == Andreas Larsson writes: Andreas> The registers in the GRLIB port of the controller are 32-bit Andreas> and in big endian byte order. The PRELOW and PREHIGH registers Andreas> are merged into one register. The subsequent registers have Andreas> their offset decreased accordingly. Hence the register access Andreas> needs to be handled in a non-standard manner using custom Andreas> getreg and setreg functions. Andreas> Add setreg and getreg functions for different register widths Andreas> and let oc_setreg and oc_getreg use function pointers to call Andreas> the appropriate functions. Andreas> A type is added as the data of the of match table entries. A Andreas> new entry with a different compatible string is added to the Andreas> table. The type of that entry triggers usage of the custom Andreas> grlib functions by setting the setreg and getreg function Andreas> pointers. Andreas> Signed-off-by: Andreas Larsson Acked-by: Peter Korsgaard Thanks! -- Bye, Peter Korsgaard -- To unsubscribe from this list: send the line "unsubscribe linux-i2c" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] bindings: i2c: use consistent naming for i2c binding descriptions
On Tue, 13 Nov 2012 18:16:43 +0100, Wolfram Sang wrote: > Filenames of devictree binding documentation seems to be arbitrary and > for me it is unneeded hazzle to find the corresponding documentation for > a specific driver. > > Naming the description the same as the driver is a lot easier and makes > sense to me since the driver defines the binding it understands. > > Also, remove a reference in one source to the binding documentation, since > path > information easily gets stale. > > Signed-off-by: Wolfram Sang > Cc: Rob Herring > Cc: Grant Likely Applied, thanks. g. -- To unsubscribe from this list: send the line "unsubscribe linux-i2c" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v6 1/2] i2c: i2c-ocores: Add irq support for sparc
Add sparc support by using platform_get_irq instead of platform_get_resource. There are no platform resources of type IORESOURCE_IRQ for sparc, but platform_get_irq works for sparc. In the non-sparc case platform_get_irq internally uses platform_get_resource. Signed-off-by: Andreas Larsson Acked-by: Peter Korsgaard --- Changes since v5: - None drivers/i2c/busses/i2c-ocores.c | 11 ++- 1 files changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/i2c/busses/i2c-ocores.c b/drivers/i2c/busses/i2c-ocores.c index bffd550..1d204cb 100644 --- a/drivers/i2c/busses/i2c-ocores.c +++ b/drivers/i2c/busses/i2c-ocores.c @@ -267,7 +267,8 @@ static int __devinit ocores_i2c_probe(struct platform_device *pdev) { struct ocores_i2c *i2c; struct ocores_i2c_platform_data *pdata; - struct resource *res, *res2; + struct resource *res; + int irq; int ret; int i; @@ -275,9 +276,9 @@ static int __devinit ocores_i2c_probe(struct platform_device *pdev) if (!res) return -ENODEV; - res2 = platform_get_resource(pdev, IORESOURCE_IRQ, 0); - if (!res2) - return -ENODEV; + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return irq; i2c = devm_kzalloc(&pdev->dev, sizeof(*i2c), GFP_KERNEL); if (!i2c) @@ -313,7 +314,7 @@ static int __devinit ocores_i2c_probe(struct platform_device *pdev) ocores_init(i2c); init_waitqueue_head(&i2c->wait); - ret = devm_request_irq(&pdev->dev, res2->start, ocores_isr, 0, + ret = devm_request_irq(&pdev->dev, irq, ocores_isr, 0, pdev->name, i2c); if (ret) { dev_err(&pdev->dev, "Cannot claim IRQ\n"); -- 1.7.0.4 -- To unsubscribe from this list: send the line "unsubscribe linux-i2c" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v6 2/2] i2c: i2c-ocores: Add support for the GRLIB port of the controller and use function pointers for getreg and setreg functions
The registers in the GRLIB port of the controller are 32-bit and in big endian byte order. The PRELOW and PREHIGH registers are merged into one register. The subsequent registers have their offset decreased accordingly. Hence the register access needs to be handled in a non-standard manner using custom getreg and setreg functions. Add setreg and getreg functions for different register widths and let oc_setreg and oc_getreg use function pointers to call the appropriate functions. A type is added as the data of the of match table entries. A new entry with a different compatible string is added to the table. The type of that entry triggers usage of the custom grlib functions by setting the setreg and getreg function pointers. Signed-off-by: Andreas Larsson --- Changes since v5: - Function pointers for different widths are set together - oc_setreg and oc_getreg are kept as wrappers .../devicetree/bindings/i2c/i2c-ocores.txt |2 +- drivers/i2c/busses/i2c-ocores.c| 138 +--- 2 files changed, 121 insertions(+), 19 deletions(-) diff --git a/Documentation/devicetree/bindings/i2c/i2c-ocores.txt b/Documentation/devicetree/bindings/i2c/i2c-ocores.txt index c15781f..1637c29 100644 --- a/Documentation/devicetree/bindings/i2c/i2c-ocores.txt +++ b/Documentation/devicetree/bindings/i2c/i2c-ocores.txt @@ -1,7 +1,7 @@ Device tree configuration for i2c-ocores Required properties: -- compatible : "opencores,i2c-ocores" +- compatible : "opencores,i2c-ocores" or "aeroflexgaisler,i2cmst" - reg : bus address start and address range size of device - interrupts : interrupt number - clock-frequency : frequency of bus clock in Hz diff --git a/drivers/i2c/busses/i2c-ocores.c b/drivers/i2c/busses/i2c-ocores.c index 1d204cb..2ef318b 100644 --- a/drivers/i2c/busses/i2c-ocores.c +++ b/drivers/i2c/busses/i2c-ocores.c @@ -4,6 +4,9 @@ * * Peter Korsgaard * + * Support for the GRLIB port of the controller by + * Andreas Larsson + * * This file is licensed under the terms of the GNU General Public License * version 2. This program is licensed "as is" without any warranty of any * kind, whether express or implied. @@ -38,6 +41,8 @@ struct ocores_i2c { int nmsgs; int state; /* see STATE_ */ int clock_khz; + void (*setreg)(struct ocores_i2c *i2c, int reg, u8 value); + u8 (*getreg)(struct ocores_i2c *i2c, int reg); }; /* registers */ @@ -71,24 +76,81 @@ struct ocores_i2c { #define STATE_READ 3 #define STATE_ERROR4 +#define TYPE_OCORES0 +#define TYPE_GRLIB 1 + +static void oc_setreg_8(struct ocores_i2c *i2c, int reg, u8 value) +{ + iowrite8(value, i2c->base + (reg << i2c->reg_shift)); +} + +static void oc_setreg_16(struct ocores_i2c *i2c, int reg, u8 value) +{ + iowrite16(value, i2c->base + (reg << i2c->reg_shift)); +} + +static void oc_setreg_32(struct ocores_i2c *i2c, int reg, u8 value) +{ + iowrite32(value, i2c->base + (reg << i2c->reg_shift)); +} + +static inline u8 oc_getreg_8(struct ocores_i2c *i2c, int reg) +{ + return ioread8(i2c->base + (reg << i2c->reg_shift)); +} + +static inline u8 oc_getreg_16(struct ocores_i2c *i2c, int reg) +{ + return ioread16(i2c->base + (reg << i2c->reg_shift)); +} + +static inline u8 oc_getreg_32(struct ocores_i2c *i2c, int reg) +{ + return ioread32(i2c->base + (reg << i2c->reg_shift)); +} + +/* Read and write functions for the GRLIB port of the controller. Registers are + * 32-bit big endian and the PRELOW and PREHIGH registers are merged into one + * register. The subsequent registers has their offset decreased accordingly. */ +static u8 oc_getreg_grlib(struct ocores_i2c *i2c, int reg) +{ + u32 rd; + int rreg = reg; + if (reg != OCI2C_PRELOW) + rreg--; + rd = ioread32be(i2c->base + (rreg << i2c->reg_shift)); + if (reg == OCI2C_PREHIGH) + return (u8)(rd >> 8); + else + return (u8)rd; +} + +static void oc_setreg_grlib(struct ocores_i2c *i2c, int reg, u8 value) +{ + u32 curr, wr; + int rreg = reg; + if (reg != OCI2C_PRELOW) + rreg--; + if (reg == OCI2C_PRELOW || reg == OCI2C_PREHIGH) { + curr = ioread32be(i2c->base + (rreg << i2c->reg_shift)); + if (reg == OCI2C_PRELOW) + wr = (curr & 0xff00) | value; + else + wr = (((u32)value) << 8) | (curr & 0xff); + } else { + wr = value; + } + iowrite32be(wr, i2c->base + (rreg << i2c->reg_shift)); +} + static inline void oc_setreg(struct ocores_i2c *i2c, int reg, u8 value) { - if (i2c->reg_io_width == 4) - iowrite32(value, i2c->base + (reg << i2c->reg_shift)); - else if (i2c->reg_io_width == 2) - iowrite16(value, i2c->base + (reg << i2c->reg_shift)); - else -
[PATCH v6 0/2] i2c: i2c-ocores: Add support for sparc, custom set and get functions, and the GRLIB port of the controller
On sparc, irqs are not present as an IORESOURCE in the struct platform_device representation. By using platform_get_irq instead of platform_get_resource the driver works for sparc. The GRLIB port of the ocores i2c controller needs custom getreg and setreg functions to allow for big endian register access and to deal with the fact that the PRELOW and PREHIGH registers have been merged into one register. Signed-off-by: Andreas Larsson Changes since v5: - Function pointers for different widths are set together - oc_setreg and oc_getreg are kept as wrappers Andreas Larsson (2): i2c: i2c-ocores: Add irq support for sparc i2c: i2c-ocores: Add support for the GRLIB port of the controller and use function pointers for getreg and setreg functions .../devicetree/bindings/i2c/i2c-ocores.txt |2 +- drivers/i2c/busses/i2c-ocores.c| 149 +--- 2 files changed, 127 insertions(+), 24 deletions(-) -- To unsubscribe from this list: send the line "unsubscribe linux-i2c" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v5 2/2] i2c: i2c-ocores: Add support for the GRLIB port of the controller and use function pointers for getreg and setreg functions
> "Andreas" == Andreas Larsson writes: Andreas> The registers in the GRLIB port of the controller are 32-bit Andreas> and in big endian byte order. The PRELOW and PREHIGH registers Andreas> are merged into one register. The subsequent registers have Andreas> their offset decreased accordingly. Hence the register access Andreas> needs to be handled in a non-standard manner using custom Andreas> getreg and setreg functions. Andreas> The single oc_getreg and one oc_setreg functions, that Andreas> branches and call different ioread and iowrite functions, are Andreas> replaced by specific functions that uses the appropriate Andreas> ioread and iowrite functions and function pointers are Andreas> initiated and used to call the approproate functions. Andreas> A type is added as the data of the of match table entries. A Andreas> new entry with a different compatible string is added to the Andreas> table. The type of that entry triggers usage of the custom Andreas> grlib functions by setting the new getreg and setreg function Andreas> pointers to these functions. Sorry to keep on requesting changes, but see below for a bit more: Andreas> static void ocores_process(struct ocores_i2c *i2c) Andreas> { Andreas> struct i2c_msg *msg = i2c->msg; Andreas> - u8 stat = oc_getreg(i2c, OCI2C_STATUS); Andreas> + u8 stat = i2c->getreg(i2c, OCI2C_STATUS); The patch would have been quite a bit smaller/easier to read if you had kept oc_getreg / oc_setreg as wrappers. Andreas> #ifdef CONFIG_OF Andreas> static int ocores_i2c_of_probe(struct platform_device *pdev, Andreas> struct ocores_i2c *i2c) Andreas> { Andreas> struct device_node *np = pdev->dev.of_node; Andreas> + const struct of_device_id *match; Andreas> u32 val; Andreas> if (of_property_read_u32(np, "reg-shift", &i2c->reg_shift)) { Andreas> @@ -257,6 +324,14 @@ static int ocores_i2c_of_probe(struct platform_device *pdev, Andreas> of_property_read_u32(pdev->dev.of_node, "reg-io-width", Andreas> &i2c->reg_io_width); Andreas> + Andreas> + match = of_match_node(ocores_i2c_match, pdev->dev.of_node); Andreas> + if (match && (int)match->data == TYPE_GRLIB) { Andreas> + dev_dbg(&pdev->dev, "GRLIB variant of i2c-ocores\n"); Andreas> + i2c->setreg = oc_setreg_grlib; Andreas> + i2c->getreg = oc_getreg_grlib; Andreas> + } Andreas> + Andreas> return 0; Andreas> } Andreas> #else Andreas> @@ -311,6 +386,23 @@ static int __devinit ocores_i2c_probe(struct platform_device *pdev) Andreas> if (i2c->reg_io_width == 0) i2c-> reg_io_width = 1; /* Set to default value */ Andreas> + if (!i2c->getreg) { Andreas> + if (i2c->reg_io_width == 4) Andreas> + i2c->getreg = oc_getreg_32; Andreas> + else if (i2c->reg_io_width == 2) Andreas> + i2c->getreg = oc_getreg_16; Andreas> + else Andreas> + i2c->getreg = oc_getreg_8; Andreas> + } Andreas> + if (!i2c->setreg) { Andreas> + if (i2c->reg_io_width == 4) Andreas> + i2c->setreg = oc_setreg_32; Andreas> + else if (i2c->reg_io_width == 2) Andreas> + i2c->setreg = oc_setreg_16; Andreas> + else Andreas> + i2c->setreg = oc_setreg_8; Andreas> + } Andreas> + These are always set together (could even move to a single ops structure), so it would be shorter to assign them at the same time: if (!i2c->setreg || !i2c->getreg) { switch (i2c->reg_io_width) { case 1: i2c->setreg = oc_setreg_8; i2c->getreg = oc_getreg_8; break; case 2: i2c->setreg = oc_setreg_16; ... default: dev_err(&pdev->dev "Unsupported I/O width (%d)\n", i2c->reg_io_width); return -EINVAL; } } -- Bye, Peter Korsgaard -- To unsubscribe from this list: send the line "unsubscribe linux-i2c" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v5 1/2] i2c: i2c-ocores: Add irq support for sparc
Add sparc support by using platform_get_irq instead of platform_get_resource. There are no platform resources of type IORESOURCE_IRQ for sparc, but platform_get_irq works for sparc. In the non-sparc case platform_get_irq internally uses platform_get_resource. Signed-off-by: Andreas Larsson Acked-by: Peter Korsgaard --- Changes since v4: - None drivers/i2c/busses/i2c-ocores.c | 11 ++- 1 files changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/i2c/busses/i2c-ocores.c b/drivers/i2c/busses/i2c-ocores.c index bffd550..1d204cb 100644 --- a/drivers/i2c/busses/i2c-ocores.c +++ b/drivers/i2c/busses/i2c-ocores.c @@ -267,7 +267,8 @@ static int __devinit ocores_i2c_probe(struct platform_device *pdev) { struct ocores_i2c *i2c; struct ocores_i2c_platform_data *pdata; - struct resource *res, *res2; + struct resource *res; + int irq; int ret; int i; @@ -275,9 +276,9 @@ static int __devinit ocores_i2c_probe(struct platform_device *pdev) if (!res) return -ENODEV; - res2 = platform_get_resource(pdev, IORESOURCE_IRQ, 0); - if (!res2) - return -ENODEV; + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return irq; i2c = devm_kzalloc(&pdev->dev, sizeof(*i2c), GFP_KERNEL); if (!i2c) @@ -313,7 +314,7 @@ static int __devinit ocores_i2c_probe(struct platform_device *pdev) ocores_init(i2c); init_waitqueue_head(&i2c->wait); - ret = devm_request_irq(&pdev->dev, res2->start, ocores_isr, 0, + ret = devm_request_irq(&pdev->dev, irq, ocores_isr, 0, pdev->name, i2c); if (ret) { dev_err(&pdev->dev, "Cannot claim IRQ\n"); -- 1.7.0.4 -- To unsubscribe from this list: send the line "unsubscribe linux-i2c" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v5 2/2] i2c: i2c-ocores: Add support for the GRLIB port of the controller and use function pointers for getreg and setreg functions
The registers in the GRLIB port of the controller are 32-bit and in big endian byte order. The PRELOW and PREHIGH registers are merged into one register. The subsequent registers have their offset decreased accordingly. Hence the register access needs to be handled in a non-standard manner using custom getreg and setreg functions. The single oc_getreg and one oc_setreg functions, that branches and call different ioread and iowrite functions, are replaced by specific functions that uses the appropriate ioread and iowrite functions and function pointers are initiated and used to call the approproate functions. A type is added as the data of the of match table entries. A new entry with a different compatible string is added to the table. The type of that entry triggers usage of the custom grlib functions by setting the new getreg and setreg function pointers to these functions. Signed-off-by: Andreas Larsson --- Changes since v4: - Replace the ocores_get_type function with inline code in the probe function - Replace the oc_(get|set)reg functions with oc_(get|set)reg_(8|16|32) functions and always use the function pointers to call them. .../devicetree/bindings/i2c/i2c-ocores.txt |2 +- drivers/i2c/busses/i2c-ocores.c| 176 +++- 2 files changed, 132 insertions(+), 46 deletions(-) diff --git a/Documentation/devicetree/bindings/i2c/i2c-ocores.txt b/Documentation/devicetree/bindings/i2c/i2c-ocores.txt index c15781f..1637c29 100644 --- a/Documentation/devicetree/bindings/i2c/i2c-ocores.txt +++ b/Documentation/devicetree/bindings/i2c/i2c-ocores.txt @@ -1,7 +1,7 @@ Device tree configuration for i2c-ocores Required properties: -- compatible : "opencores,i2c-ocores" +- compatible : "opencores,i2c-ocores" or "aeroflexgaisler,i2cmst" - reg : bus address start and address range size of device - interrupts : interrupt number - clock-frequency : frequency of bus clock in Hz diff --git a/drivers/i2c/busses/i2c-ocores.c b/drivers/i2c/busses/i2c-ocores.c index 1d204cb..566193d 100644 --- a/drivers/i2c/busses/i2c-ocores.c +++ b/drivers/i2c/busses/i2c-ocores.c @@ -4,6 +4,9 @@ * * Peter Korsgaard * + * Support for the GRLIB port of the controller by + * Andreas Larsson + * * This file is licensed under the terms of the GNU General Public License * version 2. This program is licensed "as is" without any warranty of any * kind, whether express or implied. @@ -38,6 +41,8 @@ struct ocores_i2c { int nmsgs; int state; /* see STATE_ */ int clock_khz; + void (*setreg)(struct ocores_i2c *i2c, int reg, u8 value); + u8 (*getreg)(struct ocores_i2c *i2c, int reg); }; /* registers */ @@ -71,34 +76,82 @@ struct ocores_i2c { #define STATE_READ 3 #define STATE_ERROR4 -static inline void oc_setreg(struct ocores_i2c *i2c, int reg, u8 value) +#define TYPE_OCORES0 +#define TYPE_GRLIB 1 + +static void oc_setreg_8(struct ocores_i2c *i2c, int reg, u8 value) { - if (i2c->reg_io_width == 4) - iowrite32(value, i2c->base + (reg << i2c->reg_shift)); - else if (i2c->reg_io_width == 2) - iowrite16(value, i2c->base + (reg << i2c->reg_shift)); - else - iowrite8(value, i2c->base + (reg << i2c->reg_shift)); + iowrite8(value, i2c->base + (reg << i2c->reg_shift)); +} + +static void oc_setreg_16(struct ocores_i2c *i2c, int reg, u8 value) +{ + iowrite16(value, i2c->base + (reg << i2c->reg_shift)); } -static inline u8 oc_getreg(struct ocores_i2c *i2c, int reg) +static void oc_setreg_32(struct ocores_i2c *i2c, int reg, u8 value) { - if (i2c->reg_io_width == 4) - return ioread32(i2c->base + (reg << i2c->reg_shift)); - else if (i2c->reg_io_width == 2) - return ioread16(i2c->base + (reg << i2c->reg_shift)); + iowrite32(value, i2c->base + (reg << i2c->reg_shift)); +} + +static inline u8 oc_getreg_8(struct ocores_i2c *i2c, int reg) +{ + return ioread8(i2c->base + (reg << i2c->reg_shift)); +} + +static inline u8 oc_getreg_16(struct ocores_i2c *i2c, int reg) +{ + return ioread16(i2c->base + (reg << i2c->reg_shift)); +} + +static inline u8 oc_getreg_32(struct ocores_i2c *i2c, int reg) +{ + return ioread32(i2c->base + (reg << i2c->reg_shift)); +} + + +/* Read and write functions for the GRLIB port of the controller. Registers are + * 32-bit big endian and the PRELOW and PREHIGH registers are merged into one + * register. The subsequent registers has their offset decreased accordingly. */ +static u8 oc_getreg_grlib(struct ocores_i2c *i2c, int reg) +{ + u32 rd; + int rreg = reg; + if (reg != OCI2C_PRELOW) + rreg--; + rd = ioread32be(i2c->base + (rreg << i2c->reg_shift)); + if (reg == OCI2C_PREHIGH) + return (u8)(rd >> 8); else - return ioread8(i2c->base + (reg <<
[PATCH v5 0/2] i2c: i2c-ocores: Add support for sparc, custom set and get functions, and the GRLIB port of the controller
On sparc, irqs are not present as an IORESOURCE in the struct platform_device representation. By using platform_get_irq instead of platform_get_resource the driver works for sparc. The GRLIB port of the ocores i2c controller needs custom getreg and setreg functions to allow for big endian register access and to deal with the fact that the PRELOW and PREHIGH registers have been merged into one register. Signed-off-by: Andreas Larsson Changes since v4: - Replace the ocores_get_type function with inline code in the probe function - Replace the oc_(get|set)reg functions with oc_(get|set)reg_(8|16|32) functions and always use the function pointers to call them. Andreas Larsson (2): i2c: i2c-ocores: Add irq support for sparc i2c: i2c-ocores: Add support for the GRLIB port of the controller and use function pointers for getreg and setreg functions .../devicetree/bindings/i2c/i2c-ocores.txt |2 +- drivers/i2c/busses/i2c-ocores.c| 187 ++-- 2 files changed, 138 insertions(+), 51 deletions(-) -- To unsubscribe from this list: send the line "unsubscribe linux-i2c" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v3] i2c-hid: introduce HID over i2c specification implementation
On Thu, Nov 15, 2012 at 2:51 PM, Jiri Kosina wrote: > On Mon, 12 Nov 2012, Benjamin Tissoires wrote: > >> Microsoft published the protocol specification of HID over i2c: >> http://msdn.microsoft.com/en-us/library/windows/hardware/hh852380.aspx >> >> This patch introduces an implementation of this protocol. >> >> This implementation does not includes the ACPI part of the specification. >> This will come when ACPI 5.0 devices enumeration will be available. >> >> Once the ACPI part is done, OEM will not have to declare HID over I2C >> devices in their platform specific driver. >> >> Signed-off-by: Benjamin Tissoires > > Out of curiosity -- has this been tested on a real device (is there any > such device available anyway?), or is that just the implementation of the > defined protocol? It has been tested on an ELAN microelectronics device (a prototype), on an odroid-x board. That's how we figure out the bug in the set_report command. I think we manage to test all main features of the protocol (get_report, irqs, hid descriptor, report descriptors, set_report). I'm currently waiting for a Synaptics touchpad to check if it's also working with their devices. The thing is that HID over i2c for x86 platform will presumably require the Haswell platform from Intel (we need ACPI 5 for enumeration), but it would be very nice to get this in the kernel just before hardware arrive on the market :) However, I won't be surprise if android OEMs also start using this specification because it won't force them to write kernel drivers... Cheers, Benjamin > > Thanks, > > -- > Jiri Kosina > SUSE Labs -- To unsubscribe from this list: send the line "unsubscribe linux-i2c" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v3] i2c-hid: introduce HID over i2c specification implementation
On Mon, 12 Nov 2012, Benjamin Tissoires wrote: > Microsoft published the protocol specification of HID over i2c: > http://msdn.microsoft.com/en-us/library/windows/hardware/hh852380.aspx > > This patch introduces an implementation of this protocol. > > This implementation does not includes the ACPI part of the specification. > This will come when ACPI 5.0 devices enumeration will be available. > > Once the ACPI part is done, OEM will not have to declare HID over I2C > devices in their platform specific driver. > > Signed-off-by: Benjamin Tissoires Out of curiosity -- has this been tested on a real device (is there any such device available anyway?), or is that just the implementation of the defined protocol? Thanks, -- Jiri Kosina SUSE Labs -- To unsubscribe from this list: send the line "unsubscribe linux-i2c" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] i2c: omap: don't save a value only needed for read-clearing
Hi, On Thu, Nov 15, 2012 at 03:34:10PM +0530, Shubhrajyoti Datta wrote: > On Thu, Nov 15, 2012 at 12:20 AM, Wolfram Sang wrote: > > > >> > This makes one of my code analyzers happy and makes me a part of the > >> > >> anything open source which we could all be using ? :-) > > > > 'my' as in 'one of those I am using'. It was cppcheck which found that > > flaw. Its use for kernel code is limited, but it does find one or the > > other thing. > > sparse did not complain though. > So it seems it helps to run multiple static tools:-) or sending a patch to sparse ;-) -- balbi signature.asc Description: Digital signature
[PATCH 7/7] decode-dimms: Strip former manufacturer name in side-by-side mode
Strip former manufacturer name in side-by-side output mode, to avoid overly large columns. --- eeprom/decode-dimms |1 + 1 file changed, 1 insertion(+) --- i2c-tools.orig/eeprom/decode-dimms 2012-11-15 11:47:17.878976012 +0100 +++ i2c-tools/eeprom/decode-dimms 2012-11-15 11:47:19.684976039 +0100 @@ -342,6 +342,7 @@ sub manufacturer_ddr3($$) return "Invalid" if parity($code) != 1; return "Unknown" if ($code & 0x7F) - 1 > $vendors[$count & 0x7F]; $manufacturer = $vendors[$count & 0x7F][($code & 0x7F) - 1]; + $manufacturer =~ s/ \(former .*\)$// if $opt_side_by_side; $manufacturer .= "? (Invalid parity)" if parity($count) != 1; return $manufacturer; } -- Jean Delvare -- To unsubscribe from this list: send the line "unsubscribe linux-i2c" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 6/7] decode-dimms: Bad manufacturer page count parity is not fatal
If DDR3 manufacturer page count parity is wrong, still print the manufacturer name (if valid) but add a question mark. --- eeprom/decode-dimms |9 ++--- 1 file changed, 6 insertions(+), 3 deletions(-) --- i2c-tools.orig/eeprom/decode-dimms 2012-11-15 11:45:52.020974740 +0100 +++ i2c-tools/eeprom/decode-dimms 2012-11-15 11:47:17.878976012 +0100 @@ -337,10 +337,13 @@ sub parity($) sub manufacturer_ddr3($$) { my ($count, $code) = @_; - return "Invalid" if parity($count) != 1; + my $manufacturer; + return "Invalid" if parity($code) != 1; - return (($code & 0x7F) - 1 > $vendors[$count & 0x7F]) ? "Unknown" : - $vendors[$count & 0x7F][($code & 0x7F) - 1]; + return "Unknown" if ($code & 0x7F) - 1 > $vendors[$count & 0x7F]; + $manufacturer = $vendors[$count & 0x7F][($code & 0x7F) - 1]; + $manufacturer .= "? (Invalid parity)" if parity($count) != 1; + return $manufacturer; } sub manufacturer(@) -- Jean Delvare -- To unsubscribe from this list: send the line "unsubscribe linux-i2c" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 4/4] i2c-s3c2410: do not special case HDMIPHY stuck bus detection
From: Daniel Kurtz Commit "i2c-s3c2410: Add HDMIPHY quirk for S3C2440" added support for HDMIPHY with some special handling in s3c24xx_i2c_set_master: "due to unknown reason (probably HW bug in HDMIPHY and/or the controller) a transfer fails to finish. The controller hangs after sending the last byte, the workaround for this bug is resetting the controller after each transfer" The "unknown reason" was that the proper sequence for generating a STOP condition wasn't being followed as per the datasheet. Since this is fixed by "PATCH: i2c-s3c2410: do not generate STOP for QUIRK_HDMIPHY buses", remove the special handling. Signed-off-by: Daniel Kurtz Cc: Daniel Kurtz Signed-off-by: Naveen Krishna Chatradhi --- drivers/i2c/busses/i2c-s3c2410.c | 16 1 file changed, 16 deletions(-) diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c index 362a307..c76ca7c 100644 --- a/drivers/i2c/busses/i2c-s3c2410.c +++ b/drivers/i2c/busses/i2c-s3c2410.c @@ -531,13 +531,6 @@ static int s3c24xx_i2c_set_master(struct s3c24xx_i2c *i2c) unsigned long iicstat; int timeout = 400; - /* the timeout for HDMIPHY is reduced to 10 ms because -* the hangup is expected to happen, so waiting 400 ms -* causes only unnecessary system hangup -*/ - if (i2c->quirks & QUIRK_HDMIPHY) - timeout = 10; - while (timeout-- > 0) { iicstat = readl(i2c->regs + S3C2410_IICSTAT); @@ -547,15 +540,6 @@ static int s3c24xx_i2c_set_master(struct s3c24xx_i2c *i2c) msleep(1); } - /* hang-up of bus dedicated for HDMIPHY occurred, resetting */ - if (i2c->quirks & QUIRK_HDMIPHY) { - writel(0, i2c->regs + S3C2410_IICCON); - writel(0, i2c->regs + S3C2410_IICSTAT); - writel(0, i2c->regs + S3C2410_IICDS); - - return 0; - } - return -ETIMEDOUT; } -- 1.7.9.5 -- To unsubscribe from this list: send the line "unsubscribe linux-i2c" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 3/4] i2c-s3c2410: use exponential back off while polling for bus idle
From: Daniel Kurtz Usually, the i2c controller has finished emitting the i2c STOP before the driver reaches the bus idle polling loop. Optimize for this most common case by reading IICSTAT first and potentially skipping the loop. If the cpu is faster than the hardware, we wait for bus idle in a polling loop. However, since the duration of one iteration of the loop is dependent on cpu freq, and this i2c IP is used on many different systems, use a time based loop timeout (5 ms). We would like very low latencies to detect bus idle for the normal 'fast' case. However, if a device is slow to release the bus for some reason, it could hold off the STOP generation for up to several milliseconds. Rapidly polling for bus idle would seriously load the CPU while waiting for it to release the bus. So, use a partial exponential backoff as a compromise between idle detection latency and cpu load. Signed-off-by: Daniel Kurtz Cc: Olof Johansson Cc: Benson Leung Cc: Doug Anderson Cc: Daniel Kurtz Signed-off-by: Naveen Krishna Chatradhi --- drivers/i2c/busses/i2c-s3c2410.c | 67 ++ 1 file changed, 47 insertions(+), 20 deletions(-) diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c index fc4bf35..362a307 100644 --- a/drivers/i2c/busses/i2c-s3c2410.c +++ b/drivers/i2c/busses/i2c-s3c2410.c @@ -49,6 +49,9 @@ #define QUIRK_HDMIPHY (1 << 1) #define QUIRK_NO_GPIO (1 << 2) +/* Max time to wait for bus to become idle after a xfer (in us) */ +#define S3C2410_IDLE_TIMEOUT 5000 + /* i2c controller state */ enum s3c24xx_i2c_state { STATE_IDLE, @@ -556,6 +559,48 @@ static int s3c24xx_i2c_set_master(struct s3c24xx_i2c *i2c) return -ETIMEDOUT; } +/* s3c24xx_i2c_wait_idle + * + * wait for the i2c bus to become idle. +*/ + +static void s3c24xx_i2c_wait_idle(struct s3c24xx_i2c *i2c) +{ + unsigned long iicstat; + ktime_t start, now; + unsigned long delay; + + /* ensure the stop has been through the bus */ + + dev_dbg(i2c->dev, "waiting for bus idle\n"); + + start = now = ktime_get(); + + /* +* Most of the time, the bus is already idle within a few usec of the +* end of a transaction. However, really slow i2c devices can stretch +* the clock, delaying STOP generation. +* +* As a compromise between idle detection latency for the normal, fast +* case, and system load in the slow device case, use an exponential +* back off in the polling loop, up to 1/10th of the total timeout, +* then continue to poll at a constant rate up to the timeout. +*/ + iicstat = readl(i2c->regs + S3C2410_IICSTAT); + delay = 1; + while ((iicstat & S3C2410_IICSTAT_START) && + ktime_us_delta(now, start) < S3C2410_IDLE_TIMEOUT) { + usleep_range(delay, 2 * delay); + if (delay < S3C2410_IDLE_TIMEOUT / 10) + delay <<= 1; + now = ktime_get(); + iicstat = readl(i2c->regs + S3C2410_IICSTAT); + } + + if (iicstat & S3C2410_IICSTAT_START) + dev_warn(i2c->dev, "timeout waiting for bus idle\n"); +} + /* s3c24xx_i2c_doxfer * * this starts an i2c transfer @@ -564,8 +609,7 @@ static int s3c24xx_i2c_set_master(struct s3c24xx_i2c *i2c) static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c, struct i2c_msg *msgs, int num) { - unsigned long iicstat, timeout; - int spins = 20; + unsigned long timeout; int ret; if (i2c->suspended) @@ -603,24 +647,7 @@ static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c, if (i2c->quirks & QUIRK_HDMIPHY) goto out; - /* ensure the stop has been through the bus */ - - dev_dbg(i2c->dev, "waiting for bus idle\n"); - - /* first, try busy waiting briefly */ - do { - cpu_relax(); - iicstat = readl(i2c->regs + S3C2410_IICSTAT); - } while ((iicstat & S3C2410_IICSTAT_START) && --spins); - - /* if that timed out sleep */ - if (!spins) { - msleep(1); - iicstat = readl(i2c->regs + S3C2410_IICSTAT); - } - - if (iicstat & S3C2410_IICSTAT_START) - dev_warn(i2c->dev, "timeout waiting for bus idle\n"); + s3c24xx_i2c_wait_idle(i2c); out: return ret; -- 1.7.9.5 -- To unsubscribe from this list: send the line "unsubscribe linux-i2c" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 2/4] i2c-s3c2410: do not generate STOP for QUIRK_HDMIPHY
From: Daniel Kurtz buses The datasheet says that the STOP sequence should be: 1) I2CSTAT.5 = 0 - Clear BUSY (or 'generate STOP') 2) I2CCON.4 = 0- Clear IRQPEND 3) Wait until the stop condition takes effect. 4*) I2CSTAT.4 = 0 - Clear TXRXEN Where, step "4*" is only for buses with the "HDMIPHY" quirk. However, after much experimentation, it appears that: a) normal buses automatically clear BUSY and transition from Master->Slave when they complete generating a STOP condition. Therefore, step (3) can be done in doxfer() by polling I2CCON.4 after starting the STOP generation here. b) HDMIPHY bus does neither, so there is no way to do step 3. There is no indication when this bus has finished generating STOP. In fact, we have found that as soon as the IRQPEND bit is cleared in step 2, the HDMIPHY bus generates the STOP condition, and then immediately starts transferring another data byte, even though the bus is supposedly stopped. This is presumably because the bus is still in "Master" mode, and its BUSY bit is still set. To avoid these extra post-STOP transactions on HDMI phy devices, we just disable Serial Output on the bus (I2CSTAT.4 = 0) directly, instead of first generating a proper STOP condition. This should float SDA & SCK terminating the transfer. Subsequent transfers start with a proper START condition, and proceed normally. The HDMIPHY bus is an internal bus that always has exactly two devices, the host as Master and the HDMIPHY device as the slave. Skipping the STOP condition has been tested on this bus and works. Also, since we disable the bus directly from the isr, we can skip the bus idle polling loop at the end of doxfer(). Signed-off-by: Daniel Kurtz Cc: Doug Anderson Cc: Daniel Kurtz Signed-off-by: Naveen Krishna Chatradhi --- drivers/i2c/busses/i2c-s3c2410.c | 47 -- 1 file changed, 45 insertions(+), 2 deletions(-) diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c index 155cb04..fc4bf35 100644 --- a/drivers/i2c/busses/i2c-s3c2410.c +++ b/drivers/i2c/busses/i2c-s3c2410.c @@ -234,8 +234,47 @@ static inline void s3c24xx_i2c_stop(struct s3c24xx_i2c *i2c, int ret) dev_dbg(i2c->dev, "STOP\n"); - /* stop the transfer */ - iicstat &= ~S3C2410_IICSTAT_START; + /* +* The datasheet says that the STOP sequence should be: +* 1) I2CSTAT.5 = 0- Clear BUSY (or 'generate STOP') +* 2) I2CCON.4 = 0 - Clear IRQPEND +* 3) Wait until the stop condition takes effect. +* 4*) I2CSTAT.4 = 0 - Clear TXRXEN +* +* Where, step "4*" is only for buses with the "HDMIPHY" quirk. +* +* However, after much experimentation, it appears that: +* a) normal buses automatically clear BUSY and transition from +*Master->Slave when they complete generating a STOP condition. +*Therefore, step (3) can be done in doxfer() by polling I2CCON.4 +*after starting the STOP generation here. +* b) HDMIPHY bus does neither, so there is no way to do step 3. +*There is no indication when this bus has finished generating +*STOP. +* +* In fact, we have found that as soon as the IRQPEND bit is cleared in +* step 2, the HDMIPHY bus generates the STOP condition, and then +* immediately starts transferring another data byte, even though the +* bus is supposedly stopped. This is presumably because the bus is +* still in "Master" mode, and its BUSY bit is still set. +* +* To avoid these extra post-STOP transactions on HDMI phy devices, we +* just disable Serial Output on the bus (I2CSTAT.4 = 0) directly, +* instead of first generating a proper STOP condition. This should +* float SDA & SCK terminating the transfer. Subsequent transfers +* start with a proper START condition, and proceed normally. +* +* The HDMIPHY bus is an internal bus that always has exactly two +* devices, the host as Master and the HDMIPHY device as the slave. +* Skipping the STOP condition has been tested on this bus and works. +*/ + if (i2c->quirks & QUIRK_HDMIPHY) { + /* Stop driving the I2C pins */ + iicstat &= ~S3C2410_IICSTAT_TXRXEN; + } else { + /* stop the transfer */ + iicstat &= ~S3C2410_IICSTAT_START; + } writel(iicstat, i2c->regs + S3C2410_IICSTAT); i2c->state = STATE_STOP; @@ -560,6 +599,10 @@ static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c, else if (ret != num) dev_dbg(i2c->dev, "incomplete xfer (%d)\n", ret); + /* For QUIRK_HDMIPHY, bus is already disabled */ + if (i2c->quirks & QUIRK_HDMIPHY) + goto out; + /* ensure the stop has been through the bus */ dev
[PATCH 1/4] i2c-s3c2410: grab adapter lock while changing i2c clock
From: Daniel Kurtz We probably don't want to change I2C frequency while a transfer is in progress. The current implementation grabs a spinlock, but that only protected the writes to IICCON when starting a message, it didn't protect against clock changes in the middle of a transaction. Note: The i2c-core already grabs the adapter lock before calling s3c24xx_i2c_doxfer(), which ensures that only one caller is issuing a xfer at a time. This means it is not necessary to disable interrupts (spin_lock_irqsave) when changing frequencies, since there won't be any i2c interrupts if there is no on-going xfer. Lastly, i2c_lock_adapter() may cause the cpufreq_transition to sleep if if a xfer is in progress, but this is ok since cpufreq notifiers are called in a kernel thread, and there are already cases where it could sleep, such as when using i2c to update the output of a voltage regulator. Note: the cpufreq part of this change has no functional affect on exynos, where the i2c clock is independent of the cpufreq. But, there is a slight perfomance boost since we no longer need to lock/unlock an additional spinlock. Signed-off-by: Daniel Kurtz Cc: Olof Johansson Cc: Doug Anderson Cc: Daniel Kurtz Signed-off-by: Naveen Krishna Chatradhi --- drivers/i2c/busses/i2c-s3c2410.c | 10 ++ 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c index 3e0335f..155cb04 100644 --- a/drivers/i2c/busses/i2c-s3c2410.c +++ b/drivers/i2c/busses/i2c-s3c2410.c @@ -59,7 +59,6 @@ enum s3c24xx_i2c_state { }; struct s3c24xx_i2c { - spinlock_t lock; wait_queue_head_t wait; unsigned intquirks; unsigned intsuspended:1; @@ -540,8 +539,6 @@ static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c, goto out; } - spin_lock_irq(&i2c->lock); - i2c->msg = msgs; i2c->msg_num = num; i2c->msg_ptr = 0; @@ -550,7 +547,6 @@ static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c, s3c24xx_i2c_enable_irq(i2c); s3c24xx_i2c_message_start(i2c, msgs); - spin_unlock_irq(&i2c->lock); timeout = wait_event_timeout(i2c->wait, i2c->msg_num == 0, HZ * 5); @@ -740,7 +736,6 @@ static int s3c24xx_i2c_cpufreq_transition(struct notifier_block *nb, unsigned long val, void *data) { struct s3c24xx_i2c *i2c = freq_to_i2c(nb); - unsigned long flags; unsigned int got; int delta_f; int ret; @@ -754,9 +749,9 @@ static int s3c24xx_i2c_cpufreq_transition(struct notifier_block *nb, if ((val == CPUFREQ_POSTCHANGE && delta_f < 0) || (val == CPUFREQ_PRECHANGE && delta_f > 0)) { - spin_lock_irqsave(&i2c->lock, flags); + i2c_lock_adapter(&i2c->adap); ret = s3c24xx_i2c_clockrate(i2c, &got); - spin_unlock_irqrestore(&i2c->lock, flags); + i2c_unlock_adapter(&i2c->adap); if (ret < 0) dev_err(i2c->dev, "cannot find frequency\n"); @@ -962,7 +957,6 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev) i2c->adap.class = I2C_CLASS_HWMON | I2C_CLASS_SPD; i2c->tx_setup = 50; - spin_lock_init(&i2c->lock); init_waitqueue_head(&i2c->wait); /* find the clock and enable it */ -- 1.7.9.5 -- To unsubscribe from this list: send the line "unsubscribe linux-i2c" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 0/4] i2c-s3c2410: Fix a bug and optimize code
The following set of patches fixes a bug in i2c-s3c2410 driver with respect to the functioning of dedicated HDMIPHY channel. 1. Removing unwanted spinlock 2. Correcting the Stop sequence 3. Optimizing the wait loop for bus idle. 4. Removing unnecessary HDMI special cases Respectively. Daniel Kurtz (4): i2c-s3c2410: grab adapter lock while changing i2c clock i2c-s3c2410: do not generate STOP for QUIRK_HDMIPHY i2c-s3c2410: use exponential back off while polling for bus idle i2c-s3c2410: do not special case HDMIPHY stuck bus detection drivers/i2c/busses/i2c-s3c2410.c | 134 ++ 1 file changed, 91 insertions(+), 43 deletions(-) -- 1.7.9.5 -- To unsubscribe from this list: send the line "unsubscribe linux-i2c" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 5/7] decode-dimms: Manufacturer names from Jedec JEP106AJ
Add manufacturer names from Jedec document JEP106AJ. --- eeprom/decode-dimms |8 ++-- 1 file changed, 6 insertions(+), 2 deletions(-) --- i2c-tools.orig/eeprom/decode-dimms 2012-11-15 11:11:22.0 +0100 +++ i2c-tools/eeprom/decode-dimms 2012-11-15 11:45:52.020974740 +0100 @@ -64,7 +64,7 @@ $revision =~ s/ \([^()]*\)//; "Lattice Semi.", "NCR", "Wafer Scale Integration", "IBM", "Tristar", "Visic", "Intl. CMOS Technology", "SSSI", "MicrochipTechnology", "Ricoh Ltd.", "VLSI", "Micron Technology", - "Hynix Semiconductor Inc. (former Hyundai Electronics)", "OKI Semiconductor", "ACTEL", "Sharp", + "SK Hynix (former Hyundai Electronics)", "OKI Semiconductor", "ACTEL", "Sharp", "Catalyst", "Panasonic", "IDT", "Cypress", "DEC", "LSI Logic", "Zarlink (former Plessey)", "UTMC", "Thinking Machine", "Thomson CSF", "Integrated CMOS (Vertex)", "Honeywell", @@ -293,7 +293,11 @@ $revision =~ s/ \([^()]*\)//; "Accord Software & Systems Pvt. Ltd.", "Active-Semi Inc.", "Denso Corporation", "TLSI Inc.", "Shenzhen Daling Electronic Co. Ltd.", "Mustang", "Orca Systems", "Passif Semiconductor", "GigaDevice Semiconductor (Beijing) Inc.", "Memphis Electronic", "Beckhoff Automation GmbH", - "Harmony Semiconductor Corp (former ProPlus Design Solutions)", "Air Computers SRL", "TMT Memory"] + "Harmony Semiconductor Corp (former ProPlus Design Solutions)", "Air Computers SRL", "TMT Memory", + "Eorex Corporation", "Xingtera", "Netsol", "Bestdon Technology Co. Ltd.", "Baysand Inc.", + "Uroad Technology Co. Ltd. (former Triple Grow Industrial Ltd.)", "Wilk Elektronik S.A.", + "AAI", "Harman", "Berg Microelectronics Inc.", "ASSIA, Inc.", "Visiontek Products LLC", + "OCMEMORY", "Welink Solution Inc."] ); $use_sysfs = -d '/sys/bus'; -- Jean Delvare -- To unsubscribe from this list: send the line "unsubscribe linux-i2c" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 4/7] decode-dimms: Introduce helper function as_ddr
Introduce helper function as_ddr(), hopefully this makes the code a little more readable. --- eeprom/decode-dimms | 24 1 file changed, 16 insertions(+), 8 deletions(-) --- i2c-tools.orig/eeprom/decode-dimms 2012-11-15 10:52:06.0 +0100 +++ i2c-tools/eeprom/decode-dimms 2012-11-15 10:57:57.171530598 +0100 @@ -830,6 +830,14 @@ sub decode_sdr_sdram($) (($bytes->[35] >> 7) ? -$temp : $temp) . " ns"); } +sub as_ddr($$) +{ + my ($gen, $ctime) = @_; + + return " as DDR" . ($gen == 1 ? "" : $gen) . "-" . + int(2000 / $ctime); +} + sub ddr_core_timings($) { my ($cas, $ctime, $trcd, $trp, $tras) = @_; @@ -931,7 +939,7 @@ sub decode_ddr_sdram($) if (exists $cas{$highestCAS}) { $core_timings = ddr_core_timings($highestCAS, $ctime, - $trcd, $trp, $tras) . " as DDR-" . int(2000 / $ctime); + $trcd, $trp, $tras) . as_ddr(1, $ctime); $cycle_time = "$ctime ns at CAS $highestCAS"; $access_time = (($bytes->[10] >> 4) * 0.1 + ($bytes->[10] & 0xf) * 0.01) @@ -941,7 +949,7 @@ sub decode_ddr_sdram($) if (exists $cas{$highestCAS-0.5} && spd_written(@$bytes[23..24])) { $ctime1 = ($bytes->[23] >> 4) + ($bytes->[23] & 0xf) * 0.1; $core_timings .= "\n".ddr_core_timings($highestCAS-0.5, $ctime1, - $trcd, $trp, $tras) . " as DDR-" . int(2000 / $ctime1); + $trcd, $trp, $tras) . as_ddr(1, $ctime1); $cycle_time .= "\n$ctime1 ns at CAS ".($highestCAS-0.5); $access_time .= "\n".(($bytes->[24] >> 4) * 0.1 + ($bytes->[24] & 0xf) * 0.01) @@ -951,7 +959,7 @@ sub decode_ddr_sdram($) if (exists $cas{$highestCAS-1} && spd_written(@$bytes[25..26])) { $ctime2 = ($bytes->[25] >> 4) + ($bytes->[25] & 0xf) * 0.1, $core_timings .= "\n".ddr_core_timings($highestCAS-1, $ctime2, - $trcd, $trp, $tras) . " as DDR-" . int(2000 / $ctime2); + $trcd, $trp, $tras) . as_ddr(1, $ctime2); $cycle_time .= "\n$ctime2 ns at CAS ".($highestCAS-1); $access_time .= "\n".(($bytes->[26] >> 4) * 0.1 + ($bytes->[26] & 0xf) * 0.01) @@ -984,7 +992,7 @@ sub decode_ddr_sdram($) } printl_cond($ctime >= $ctime_min && ($ctime_max < 1 || $ctime <= $ctime_max), - "tCL-tRCD-tRP-tRAS as DDR-".int(2000 / $ctime), + "tCL-tRCD-tRP-tRAS" . as_ddr(1, $ctime), ddr_core_timings($best_cas, $ctime, $trcd, $trp, $tras)); } @@ -1182,7 +1190,7 @@ sub decode_ddr2_sdram($) if (exists $cas{$highestCAS}) { $core_timings = ddr_core_timings($highestCAS, $ctime, - $trcd, $trp, $tras) . " as DDR2-" . int(2000 / $ctime); + $trcd, $trp, $tras) . as_ddr(2, $ctime); $cycle_time = tns($ctime) . " at CAS $highestCAS (tCK min)"; $access_time = tns(ddr2_sdram_atime($bytes->[10])) @@ -1192,7 +1200,7 @@ sub decode_ddr2_sdram($) if (exists $cas{$highestCAS-1} && spd_written(@$bytes[23..24])) { $ctime1 = ddr2_sdram_ctime($bytes->[23]); $core_timings .= "\n".ddr_core_timings($highestCAS-1, $ctime1, - $trcd, $trp, $tras) . " as DDR2-" . int(2000 / $ctime1); + $trcd, $trp, $tras) . as_ddr(2, $ctime1); $cycle_time .= "\n".tns($ctime1) . " at CAS ".($highestCAS-1); @@ -1203,7 +1211,7 @@ sub decode_ddr2_sdram($) if (exists $cas{$highestCAS-2} && spd_written(@$bytes[25..26])) { $ctime2 = ddr2_sdram_ctime($bytes->[25]); $core_timings .= "\n".ddr_core_timings($highestCAS-2, $ctime2, - $trcd, $trp, $tras) . " as DDR2-" . int(2000 / $ctime2); + $trcd, $trp, $tras) . as_ddr(2, $ctime2); $cycle_time .= "\n".tns($ctime2) . " at CAS ".($highestCAS-2); @@ -1236,7 +1244,7 @@ sub decode_ddr2_sdram($) } printl_cond($ctime >= $ctime_min && $ctime <= $ctime_max, - "tCL-tRCD-tRP-tRAS as DDR2-".int(2000 / $ctime), + "tCL-tRCD-tRP-tRAS" . as_ddr(2,$ctime), ddr_core_timings($best_cas, $ctime, $trcd, $trp, $tras)); } -- Jean Delvare -- To unsubscribe from this list: send the line "unsubscribe linux-i2c" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 3/7] decode-dimms: Delete ddr2_core_timings
ddr2_core_timings is now the exact same function as ddr_core_timings so delete the former and user the latter everywhere. --- eeprom/decode-dimms | 18 +- 1 file changed, 5 insertions(+), 13 deletions(-) --- i2c-tools.orig/eeprom/decode-dimms 2012-11-15 09:59:02.0 +0100 +++ i2c-tools/eeprom/decode-dimms 2012-11-15 09:59:33.500544032 +0100 @@ -1091,14 +1091,6 @@ sub ddr2_refresh_rate($) ($byte & 0x80 ? " - Self Refresh" : ""); } -sub ddr2_core_timings($) -{ - my ($cas, $ctime, $trcd, $trp, $tras) = @_; - - return $cas . "-" . ceil($trcd/$ctime) . "-" . ceil($trp/$ctime) . - "-" . ceil($tras/$ctime); -} - # Parameter: EEPROM bytes 0-127 (using 3-62) sub decode_ddr2_sdram($) { @@ -1189,7 +1181,7 @@ sub decode_ddr2_sdram($) my ($cycle_time, $access_time, $core_timings); if (exists $cas{$highestCAS}) { - $core_timings = ddr2_core_timings($highestCAS, $ctime, + $core_timings = ddr_core_timings($highestCAS, $ctime, $trcd, $trp, $tras) . " as DDR2-" . int(2000 / $ctime); $cycle_time = tns($ctime) . " at CAS $highestCAS (tCK min)"; @@ -1199,7 +1191,7 @@ sub decode_ddr2_sdram($) if (exists $cas{$highestCAS-1} && spd_written(@$bytes[23..24])) { $ctime1 = ddr2_sdram_ctime($bytes->[23]); - $core_timings .= "\n".ddr2_core_timings($highestCAS-1, $ctime1, + $core_timings .= "\n".ddr_core_timings($highestCAS-1, $ctime1, $trcd, $trp, $tras) . " as DDR2-" . int(2000 / $ctime1); $cycle_time .= "\n".tns($ctime1) @@ -1210,7 +1202,7 @@ sub decode_ddr2_sdram($) if (exists $cas{$highestCAS-2} && spd_written(@$bytes[25..26])) { $ctime2 = ddr2_sdram_ctime($bytes->[25]); - $core_timings .= "\n".ddr2_core_timings($highestCAS-2, $ctime2, + $core_timings .= "\n".ddr_core_timings($highestCAS-2, $ctime2, $trcd, $trp, $tras) . " as DDR2-" . int(2000 / $ctime2); $cycle_time .= "\n".tns($ctime2) @@ -1245,8 +1237,8 @@ sub decode_ddr2_sdram($) printl_cond($ctime >= $ctime_min && $ctime <= $ctime_max, "tCL-tRCD-tRP-tRAS as DDR2-".int(2000 / $ctime), - ddr2_core_timings($best_cas, $ctime, - $trcd, $trp, $tras)); + ddr_core_timings($best_cas, $ctime, +$trcd, $trp, $tras)); } # more timing information -- Jean Delvare -- To unsubscribe from this list: send the line "unsubscribe linux-i2c" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 2/7] decode-dimms: Print timings at standard DDR speeds
Print timings at standard DDR speeds. The minimum cycle times for the 3 supported CAS latency values do not necessarily match standard speeds, and even if they do, they may not cover all standard speeds. Display the timings at all standard supported speeds. This makes it easier to figure out which memory modules will work well together without tinkering with BIOS options. --- eeprom/decode-dimms | 46 ++ 1 file changed, 34 insertions(+), 12 deletions(-) --- i2c-tools.orig/eeprom/decode-dimms 2012-11-15 09:37:36.0 +0100 +++ i2c-tools/eeprom/decode-dimms 2012-11-15 10:40:13.765625180 +0100 @@ -835,7 +835,7 @@ sub ddr_core_timings($) my ($cas, $ctime, $trcd, $trp, $tras) = @_; return $cas . "-" . ceil($trcd/$ctime) . "-" . ceil($trp/$ctime) . - "-" . ceil($tras/$ctime) . " as DDR-" . int(2000 / $ctime); + "-" . ceil($tras/$ctime); } # Parameter: EEPROM bytes 0-127 (using 3-62) @@ -843,6 +843,7 @@ sub decode_ddr_sdram($) { my $bytes = shift; my $temp; + my ($ctime, $ctime1, $ctime2, $ctime_min, $ctime_max); # SPD revision printl_cond($bytes->[62] != 0xff, "SPD Revision", @@ -851,7 +852,7 @@ sub decode_ddr_sdram($) # speed prints("Memory Characteristics"); - my $ctime = ($bytes->[9] >> 4) + ($bytes->[9] & 0xf) * 0.1; + $ctime_min = $ctime = ($bytes->[9] >> 4) + ($bytes->[9] & 0xf) * 0.1; my $ddrclk = 2 * (1000 / $ctime); my $tbits = ($bytes->[7] * 256) + $bytes->[6]; if (($bytes->[11] == 2) || ($bytes->[11] == 1)) { $tbits = $tbits - 8; } @@ -930,7 +931,7 @@ sub decode_ddr_sdram($) if (exists $cas{$highestCAS}) { $core_timings = ddr_core_timings($highestCAS, $ctime, - $trcd, $trp, $tras); + $trcd, $trp, $tras) . " as DDR-" . int(2000 / $ctime); $cycle_time = "$ctime ns at CAS $highestCAS"; $access_time = (($bytes->[10] >> 4) * 0.1 + ($bytes->[10] & 0xf) * 0.01) @@ -938,25 +939,27 @@ sub decode_ddr_sdram($) } if (exists $cas{$highestCAS-0.5} && spd_written(@$bytes[23..24])) { - $ctime = ($bytes->[23] >> 4) + ($bytes->[23] & 0xf) * 0.1; - $core_timings .= "\n".ddr_core_timings($highestCAS-0.5, $ctime, - $trcd, $trp, $tras); + $ctime1 = ($bytes->[23] >> 4) + ($bytes->[23] & 0xf) * 0.1; + $core_timings .= "\n".ddr_core_timings($highestCAS-0.5, $ctime1, + $trcd, $trp, $tras) . " as DDR-" . int(2000 / $ctime1); - $cycle_time .= "\n$ctime ns at CAS ".($highestCAS-0.5); + $cycle_time .= "\n$ctime1 ns at CAS ".($highestCAS-0.5); $access_time .= "\n".(($bytes->[24] >> 4) * 0.1 + ($bytes->[24] & 0xf) * 0.01) . " ns at CAS ".($highestCAS-0.5); } if (exists $cas{$highestCAS-1} && spd_written(@$bytes[25..26])) { - $ctime = ($bytes->[25] >> 4) + ($bytes->[25] & 0xf) * 0.1, - $core_timings .= "\n".ddr_core_timings($highestCAS-1, $ctime, - $trcd, $trp, $tras); + $ctime2 = ($bytes->[25] >> 4) + ($bytes->[25] & 0xf) * 0.1, + $core_timings .= "\n".ddr_core_timings($highestCAS-1, $ctime2, + $trcd, $trp, $tras) . " as DDR-" . int(2000 / $ctime2); - $cycle_time .= "\n$ctime ns at CAS ".($highestCAS-1); + $cycle_time .= "\n$ctime2 ns at CAS ".($highestCAS-1); $access_time .= "\n".(($bytes->[26] >> 4) * 0.1 + ($bytes->[26] & 0xf) * 0.01) . " ns at CAS ".($highestCAS-1); } + $ctime_max = $bytes->[43] == 0xff ? 0 : $bytes->[43]/4; + printl_cond(defined $core_timings, "tCL-tRCD-tRP-tRAS", $core_timings); printl_cond(defined $cycle_time, "Minimum Cycle Time", $cycle_time); printl_cond(defined $access_time, "Maximum Access Time", $access_time); @@ -964,8 +967,27 @@ sub decode_ddr_sdram($) "Maximum Cycle Time (tCK max)", $bytes->[43] == 0xff ? "No minimum frequency" : $bytes->[43] == 0 ? "" : # Wouldn't be displayed, prevent div by 0 - tns1($bytes->[43]/4)." (DDR-".int(8000 / $bytes->[43]).")"); + tns1($ctime_max)." (DDR-".int(8000 / $bytes->[43]).")"); + +# standard DDR speeds + prints("Timings at Standard Speeds"); + foreach $ctime (5, 6, 7.5, 10) { + my $best_cas; + # Find min CAS latency at this speed + if (defined $ctime2 && $ctime >= $ctime2) { + $best_cas = $highestCAS-1; + } elsif (defined $ctime1 && $ctime >= $ctime1) { + $best_cas = $highestCAS-0.5; + } else { + $best_ca
Re: [PATCH 1/2] i2c: Add possibility for user-defined (i2c-)devices for bus-drivers.
Hello, Am 15.11.2012 12:04, schrieb Till Harbaum: There's actually one thing you can do: You device doesn't seem to expose the i2c bus, anyway. What you have is an rtc connected via usb. So why not move all the i2c intelligence into the device? Do pure usb-rtc's exist? Could you perhaps even make your device compatible to one of these? Then a driver for this would imho have good chances to find their way into the kernel. Sorry, but I'm satisfied with what I've done and I didn't do it just to get "something" into the kernel. I don't need my patches to become part of in the kernel, I can handle them by myself. And my free resources to submit patches just became exhausted (again). Maybe in some weeks or month ..., I don't know. Regards, Alexander -- To unsubscribe from this list: send the line "unsubscribe linux-i2c" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: Fwd: [PATCH 1/7] I2c-nomadik: Fix the usage of wait_for_completion_timeout
On Thu, Nov 15, 2012 at 11:18:20 +0100, Wolfram Sang wrote: > On Thu, Nov 15, 2012 at 03:27:42PM +0530, Srinidhi Kasagar wrote: > > On Thu, Nov 15, 2012 at 10:29:53 +0100, Wolfram Sang wrote: > > > > > > > > - if (timeout < 0) { > > > > > - dev_err(&dev->adev->dev, > > > > > - "wait_for_completion_timeout " > > > > > - "returned %d waiting for event\n", timeout); > > > > > - status = timeout; > > > > > - } > > > > > - > > > > No, it is wrong. You need to update the status variable in the case of > > > > timeout. > > > > > > Looking at the patch context, such code comes later. > > But it causes regressions; without looking at the "later" code, we can't > > afford merging > > this code now. > > Later as in "a few lines later" not "some time later". Or am I missing > something else? I was too fast in reading emails after my short vacation...Sorry. Acked-by: srinidhi kasagar regards/srinidhi -- To unsubscribe from this list: send the line "unsubscribe linux-i2c" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 1/7] sensors-detect: Print timings at standard DDR2 speeds
Print timings at standard DDR2 speeds. The minimum cycle times for the 3 supported CAS latency values do not necessarily match standard speeds, and even if they do, they may not cover all standard speeds. Display the timings at all standard supported speeds. This makes it easier to figure out which memory modules will work well together without tinkering with BIOS options. --- eeprom/decode-dimms | 51 --- 1 file changed, 36 insertions(+), 15 deletions(-) --- i2c-tools.orig/eeprom/decode-dimms 2012-10-25 14:02:21.0 +0200 +++ i2c-tools/eeprom/decode-dimms 2012-11-15 09:37:36.686924305 +0100 @@ -1074,7 +1074,7 @@ sub ddr2_core_timings($) my ($cas, $ctime, $trcd, $trp, $tras) = @_; return $cas . "-" . ceil($trcd/$ctime) . "-" . ceil($trp/$ctime) . - "-" . ceil($tras/$ctime) . " as DDR2-" . int(2000 / $ctime); + "-" . ceil($tras/$ctime); } # Parameter: EEPROM bytes 0-127 (using 3-62) @@ -1082,7 +1082,7 @@ sub decode_ddr2_sdram($) { my $bytes = shift; my $temp; - my $ctime; + my ($ctime, $ctime1, $ctime2, $ctime_min, $ctime_max); # SPD revision printl_cond($bytes->[62] != 0xff, "SPD Revision", @@ -1091,7 +1091,7 @@ sub decode_ddr2_sdram($) # speed prints("Memory Characteristics"); - $ctime = ddr2_sdram_ctime($bytes->[9]); + $ctime_min = $ctime = ddr2_sdram_ctime($bytes->[9]); my $ddrclk = 2 * (1000 / $ctime); my $tbits = ($bytes->[7] * 256) + $bytes->[6]; if ($bytes->[11] & 0x03) { $tbits = $tbits - 8; } @@ -1168,7 +1168,7 @@ sub decode_ddr2_sdram($) if (exists $cas{$highestCAS}) { $core_timings = ddr2_core_timings($highestCAS, $ctime, - $trcd, $trp, $tras); + $trcd, $trp, $tras) . " as DDR2-" . int(2000 / $ctime); $cycle_time = tns($ctime) . " at CAS $highestCAS (tCK min)"; $access_time = tns(ddr2_sdram_atime($bytes->[10])) @@ -1176,35 +1176,56 @@ sub decode_ddr2_sdram($) } if (exists $cas{$highestCAS-1} && spd_written(@$bytes[23..24])) { - $ctime = ddr2_sdram_ctime($bytes->[23]); - $core_timings .= "\n".ddr2_core_timings($highestCAS-1, $ctime, - $trcd, $trp, $tras); + $ctime1 = ddr2_sdram_ctime($bytes->[23]); + $core_timings .= "\n".ddr2_core_timings($highestCAS-1, $ctime1, + $trcd, $trp, $tras) . " as DDR2-" . int(2000 / $ctime1); - $cycle_time .= "\n".tns($ctime) + $cycle_time .= "\n".tns($ctime1) . " at CAS ".($highestCAS-1); $access_time .= "\n".tns(ddr2_sdram_atime($bytes->[24])) . " at CAS ".($highestCAS-1); } if (exists $cas{$highestCAS-2} && spd_written(@$bytes[25..26])) { - $ctime = ddr2_sdram_ctime($bytes->[25]); - $core_timings .= "\n".ddr2_core_timings($highestCAS-2, $ctime, - $trcd, $trp, $tras); + $ctime2 = ddr2_sdram_ctime($bytes->[25]); + $core_timings .= "\n".ddr2_core_timings($highestCAS-2, $ctime2, + $trcd, $trp, $tras) . " as DDR2-" . int(2000 / $ctime2); - $cycle_time .= "\n".tns($ctime) + $cycle_time .= "\n".tns($ctime2) . " at CAS ".($highestCAS-2); $access_time .= "\n".tns(ddr2_sdram_atime($bytes->[26])) . " at CAS ".($highestCAS-2); } + $ctime_max = ddr2_sdram_ctime($bytes->[43]); + printl_cond(defined $core_timings, "tCL-tRCD-tRP-tRAS", $core_timings); printl_cond(defined $cycle_time, "Minimum Cycle Time", $cycle_time); printl_cond(defined $access_time, "Maximum Access Time", $access_time); - $temp = ddr2_sdram_ctime($bytes->[43]); printl_cond(($bytes->[43] & 0xf0) && $bytes->[43] != 0xff, "Maximum Cycle Time (tCK max)", - $temp == 0 ? "" : # Wouldn't be displayed, prevent div by 0 - tns($temp)." (DDR2-".int(2000 / $temp).")"); + $ctime_max == 0 ? "" : # Wouldn't be displayed, prevent div by 0 + tns($ctime_max)." (DDR2-".int(2000 / $ctime_max).")"); + +# standard DDR2 speeds + prints("Timings at Standard Speeds"); + foreach $ctime (1.875, 2.5, 3, 3.75, 5) { + my $best_cas; + + # Find min CAS latency at this speed + if (defined $ctime2 && $ctime >= $ctime2) { + $best_cas = $highestCAS-2; + } elsif (defined $ctime1 && $ctime >= $ctime1) { + $best_cas = $highestCAS-1; + } else { + $best_cas = $highestCAS; + } + + printl_cond($
[PATCH 0/7] Improvements to decode-dimms
Here is a patch series improving decode-dimms: * Show timings at all standard DDR and DDR2 speeds. * Code refactoring. * New manufacturer names from JEP106AJ. * Smarter decoding of manufacturer names. -- Jean Delvare -- To unsubscribe from this list: send the line "unsubscribe linux-i2c" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v4 2/2] i2c: i2c-ocores: Add support for the GRLIB port of the controller and custom getreg and setreg functions
> "Andreas" == Andreas Larsson writes: Hi, Andreas> The registers in the GRLIB port of the controller are 32-bit Andreas> and in big endian byte order. The PRELOW and PREHIGH registers Andreas> are merged into one register. The subsequent registers have Andreas> their offset decreased accordingly. Hence the register access Andreas> needs to be handled in a non-standard manner using custom Andreas> getreg and setreg functions. Andreas> A type is added as the data of the of match table entries. A Andreas> new entry with a different compatible string is added to the Andreas> table. The type of that entry triggers usage of the grlib Andreas> functions. Andreas> Signed-off-by: Andreas Larsson Andreas> --- Andreas> Changes since v3: Andreas> - Use a separate entry in the of match table for the grlib Andreas> variant and trigger grlib function usage on type put in the Andreas> data field of that table entry Thanks. A few more comments: Andreas> static inline void oc_setreg(struct ocores_i2c *i2c, int reg, u8 value) Andreas> { Andreas> - if (i2c->reg_io_width == 4) Andreas> + if (i2c->setreg) Andreas> + i2c->setreg(i2c, reg, value); Andreas> + else if (i2c->reg_io_width == 4) Andreas> iowrite32(value, i2c->base + (reg << i2c->reg_shift)); Andreas> else if (i2c->reg_io_width == 2) Andreas> iowrite16(value, i2c->base + (reg << i2c->reg_shift)); It would have been nice to add oc_getreg_8/16/32 functions and always use the function pointers - But ok, that can be done later. Andreas> #ifdef CONFIG_OF Andreas> +static int ocores_i2c_get_type(struct platform_device *pdev); Andreas> + Why not just move the implementation up here instead of the forward declaration? Andreas> +static int ocores_i2c_get_type(struct platform_device *pdev) Andreas> +{ Andreas> + const struct of_device_id *match; Andreas> + Andreas> + match = of_match_node(ocores_i2c_match, pdev->dev.of_node); Andreas> + if (match) Andreas> + return (int)match->data; Can this ever fail? If not, you might as well do the of_match_node inline in the probe instead of this helper. Other than that it looks good. -- Bye, Peter Korsgaard -- To unsubscribe from this list: send the line "unsubscribe linux-i2c" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v4 0/2] i2c: i2c-ocores: Add support for sparc, custom set and get functions, and the GRLIB port of the controller
On sparc, irqs are not present as an IORESOURCE in the struct platform_device representation. By using platform_get_irq instead of platform_get_resource the driver works for sparc. The GRLIB port of the ocores i2c controller needs custom getreg and setreg functions to allow for big endian register access and to deal with the fact that the PRELOW and PREHIGH registers have been merged into one register. Signed-off-by: Andreas Larsson Changes since v3: - Use a separate entry in the of match table for the grlib variant and trigger grlib function usage on type put in the data field of that table entry Andreas Larsson (2): i2c: i2c-ocores: Add irq support for sparc i2c: i2c-ocores: Add support for the GRLIB port of the controller and custom getreg and setreg functions .../devicetree/bindings/i2c/i2c-ocores.txt |2 +- drivers/i2c/busses/i2c-ocores.c| 90 ++-- 2 files changed, 83 insertions(+), 9 deletions(-) -- To unsubscribe from this list: send the line "unsubscribe linux-i2c" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v4 1/2] i2c: i2c-ocores: Add irq support for sparc
Add sparc support by using platform_get_irq instead of platform_get_resource. There are no platform resources of type IORESOURCE_IRQ for sparc, but platform_get_irq works for sparc. In the non-sparc case platform_get_irq internally uses platform_get_resource. Signed-off-by: Andreas Larsson Acked-by: Peter Korsgaard --- Changes since v3: - None drivers/i2c/busses/i2c-ocores.c | 11 ++- 1 files changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/i2c/busses/i2c-ocores.c b/drivers/i2c/busses/i2c-ocores.c index bffd550..1d204cb 100644 --- a/drivers/i2c/busses/i2c-ocores.c +++ b/drivers/i2c/busses/i2c-ocores.c @@ -267,7 +267,8 @@ static int __devinit ocores_i2c_probe(struct platform_device *pdev) { struct ocores_i2c *i2c; struct ocores_i2c_platform_data *pdata; - struct resource *res, *res2; + struct resource *res; + int irq; int ret; int i; @@ -275,9 +276,9 @@ static int __devinit ocores_i2c_probe(struct platform_device *pdev) if (!res) return -ENODEV; - res2 = platform_get_resource(pdev, IORESOURCE_IRQ, 0); - if (!res2) - return -ENODEV; + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return irq; i2c = devm_kzalloc(&pdev->dev, sizeof(*i2c), GFP_KERNEL); if (!i2c) @@ -313,7 +314,7 @@ static int __devinit ocores_i2c_probe(struct platform_device *pdev) ocores_init(i2c); init_waitqueue_head(&i2c->wait); - ret = devm_request_irq(&pdev->dev, res2->start, ocores_isr, 0, + ret = devm_request_irq(&pdev->dev, irq, ocores_isr, 0, pdev->name, i2c); if (ret) { dev_err(&pdev->dev, "Cannot claim IRQ\n"); -- 1.7.0.4 -- To unsubscribe from this list: send the line "unsubscribe linux-i2c" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v4 2/2] i2c: i2c-ocores: Add support for the GRLIB port of the controller and custom getreg and setreg functions
The registers in the GRLIB port of the controller are 32-bit and in big endian byte order. The PRELOW and PREHIGH registers are merged into one register. The subsequent registers have their offset decreased accordingly. Hence the register access needs to be handled in a non-standard manner using custom getreg and setreg functions. A type is added as the data of the of match table entries. A new entry with a different compatible string is added to the table. The type of that entry triggers usage of the grlib functions. Signed-off-by: Andreas Larsson --- Changes since v3: - Use a separate entry in the of match table for the grlib variant and trigger grlib function usage on type put in the data field of that table entry .../devicetree/bindings/i2c/i2c-ocores.txt |2 +- drivers/i2c/busses/i2c-ocores.c| 79 +++- 2 files changed, 77 insertions(+), 4 deletions(-) diff --git a/Documentation/devicetree/bindings/i2c/i2c-ocores.txt b/Documentation/devicetree/bindings/i2c/i2c-ocores.txt index c15781f..1637c29 100644 --- a/Documentation/devicetree/bindings/i2c/i2c-ocores.txt +++ b/Documentation/devicetree/bindings/i2c/i2c-ocores.txt @@ -1,7 +1,7 @@ Device tree configuration for i2c-ocores Required properties: -- compatible : "opencores,i2c-ocores" +- compatible : "opencores,i2c-ocores" or "aeroflexgaisler,i2cmst" - reg : bus address start and address range size of device - interrupts : interrupt number - clock-frequency : frequency of bus clock in Hz diff --git a/drivers/i2c/busses/i2c-ocores.c b/drivers/i2c/busses/i2c-ocores.c index 1d204cb..fc6e6e7 100644 --- a/drivers/i2c/busses/i2c-ocores.c +++ b/drivers/i2c/busses/i2c-ocores.c @@ -4,6 +4,9 @@ * * Peter Korsgaard * + * Support for the GRLIB port of the controller by + * Andreas Larsson + * * This file is licensed under the terms of the GNU General Public License * version 2. This program is licensed "as is" without any warranty of any * kind, whether express or implied. @@ -38,6 +41,8 @@ struct ocores_i2c { int nmsgs; int state; /* see STATE_ */ int clock_khz; + void (*setreg)(struct ocores_i2c *i2c, int reg, u8 value); + u8 (*getreg)(struct ocores_i2c *i2c, int reg); }; /* registers */ @@ -71,9 +76,14 @@ struct ocores_i2c { #define STATE_READ 3 #define STATE_ERROR4 +#define TYPE_OCORES0 +#define TYPE_GRLIB 1 + static inline void oc_setreg(struct ocores_i2c *i2c, int reg, u8 value) { - if (i2c->reg_io_width == 4) + if (i2c->setreg) + i2c->setreg(i2c, reg, value); + else if (i2c->reg_io_width == 4) iowrite32(value, i2c->base + (reg << i2c->reg_shift)); else if (i2c->reg_io_width == 2) iowrite16(value, i2c->base + (reg << i2c->reg_shift)); @@ -83,7 +93,9 @@ static inline void oc_setreg(struct ocores_i2c *i2c, int reg, u8 value) static inline u8 oc_getreg(struct ocores_i2c *i2c, int reg) { - if (i2c->reg_io_width == 4) + if (i2c->getreg) + return i2c->getreg(i2c, reg); + else if (i2c->reg_io_width == 4) return ioread32(i2c->base + (reg << i2c->reg_shift)); else if (i2c->reg_io_width == 2) return ioread16(i2c->base + (reg << i2c->reg_shift)); @@ -91,6 +103,40 @@ static inline u8 oc_getreg(struct ocores_i2c *i2c, int reg) return ioread8(i2c->base + (reg << i2c->reg_shift)); } +/* Read and write functions for the GRLIB port of the controller. Registers are + * 32-bit big endian and the PRELOW and PREHIGH registers are merged into one + * register. The subsequent registers has their offset decreased accordingly. */ +static u8 oc_getreg_grlib(struct ocores_i2c *i2c, int reg) +{ + u32 rd; + int rreg = reg; + if (reg != OCI2C_PRELOW) + rreg--; + rd = ioread32be(i2c->base + (rreg << i2c->reg_shift)); + if (reg == OCI2C_PREHIGH) + return (u8)(rd >> 8); + else + return (u8)rd; +} + +static void oc_setreg_grlib(struct ocores_i2c *i2c, int reg, u8 value) +{ + u32 curr, wr; + int rreg = reg; + if (reg != OCI2C_PRELOW) + rreg--; + if (reg == OCI2C_PRELOW || reg == OCI2C_PREHIGH) { + curr = ioread32be(i2c->base + (rreg << i2c->reg_shift)); + if (reg == OCI2C_PRELOW) + wr = (curr & 0xff00) | value; + else + wr = (((u32)value) << 8) | (curr & 0xff); + } else { + wr = value; + } + iowrite32be(wr, i2c->base + (rreg << i2c->reg_shift)); +} + static void ocores_process(struct ocores_i2c *i2c) { struct i2c_msg *msg = i2c->msg; @@ -228,6 +274,8 @@ static struct i2c_adapter ocores_adapter = { }; #ifdef CONFIG_OF +static int ocores_i2c_get_type(struct platform_device *pdev); + stat
Re: Fwd: [PATCH 1/7] I2c-nomadik: Fix the usage of wait_for_completion_timeout
On Thu, Nov 15, 2012 at 03:27:42PM +0530, Srinidhi Kasagar wrote: > On Thu, Nov 15, 2012 at 10:29:53 +0100, Wolfram Sang wrote: > > > > > > - if (timeout < 0) { > > > > - dev_err(&dev->adev->dev, > > > > - "wait_for_completion_timeout " > > > > - "returned %d waiting for event\n", timeout); > > > > - status = timeout; > > > > - } > > > > - > > > No, it is wrong. You need to update the status variable in the case of > > > timeout. > > > > Looking at the patch context, such code comes later. > But it causes regressions; without looking at the "later" code, we can't > afford merging > this code now. Later as in "a few lines later" not "some time later". Or am I missing something else? -- Pengutronix e.K. | Wolfram Sang| Industrial Linux Solutions | http://www.pengutronix.de/ | signature.asc Description: Digital signature
Re: [PATCH] i2c: omap: don't save a value only needed for read-clearing
On Thu, Nov 15, 2012 at 12:20 AM, Wolfram Sang wrote: > >> > This makes one of my code analyzers happy and makes me a part of the >> >> anything open source which we could all be using ? :-) > > 'my' as in 'one of those I am using'. It was cppcheck which found that > flaw. Its use for kernel code is limited, but it does find one or the > other thing. sparse did not complain though. So it seems it helps to run multiple static tools:-) > > -- > Pengutronix e.K. | Wolfram Sang| > Industrial Linux Solutions | http://www.pengutronix.de/ | -- To unsubscribe from this list: send the line "unsubscribe linux-i2c" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: Fwd: [PATCH 1/7] I2c-nomadik: Fix the usage of wait_for_completion_timeout
On Thu, Nov 15, 2012 at 10:29:53 +0100, Wolfram Sang wrote: > > > > - if (timeout < 0) { > > > - dev_err(&dev->adev->dev, > > > - "wait_for_completion_timeout " > > > - "returned %d waiting for event\n", timeout); > > > - status = timeout; > > > - } > > > - > > No, it is wrong. You need to update the status variable in the case of > > timeout. > > Looking at the patch context, such code comes later. But it causes regressions; without looking at the "later" code, we can't afford merging this code now. regards/srinidhi -- To unsubscribe from this list: send the line "unsubscribe linux-i2c" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: Fwd: [PATCH 1/7] I2c-nomadik: Fix the usage of wait_for_completion_timeout
> > - if (timeout < 0) { > > - dev_err(&dev->adev->dev, > > - "wait_for_completion_timeout " > > - "returned %d waiting for event\n", timeout); > > - status = timeout; > > - } > > - > No, it is wrong. You need to update the status variable in the case of > timeout. Looking at the patch context, such code comes later. -- Pengutronix e.K. | Wolfram Sang| Industrial Linux Solutions | http://www.pengutronix.de/ | signature.asc Description: Digital signature
Re: Fwd: [PATCH 1/7] I2c-nomadik: Fix the usage of wait_for_completion_timeout
[...] > From: Chuansheng Liu > Date: Tue, Nov 6, 2012 at 6:18 PM > Subject: [PATCH 1/7] I2c-nomadik: Fix the usage of wait_for_completion_timeout > To: linus.wall...@linaro.org, w.s...@pengutronix.de > Cc: linux-arm-ker...@lists.infradead.org, > linux-ker...@vger.kernel.org, chuansheng@intel.com > > > > The return value of wait_for_completion_timeout() is always > >= 0 with unsigned int type. > > So the condition "ret < 0" or "ret >= 0" is pointless. > > Signed-off-by: liu chuansheng > --- > drivers/i2c/busses/i2c-nomadik.c | 14 -- > 1 files changed, 0 insertions(+), 14 deletions(-) > > diff --git a/drivers/i2c/busses/i2c-nomadik.c > b/drivers/i2c/busses/i2c-nomadik.c > index 02c3115..8b2ffcf 100644 > --- a/drivers/i2c/busses/i2c-nomadik.c > +++ b/drivers/i2c/busses/i2c-nomadik.c > @@ -435,13 +435,6 @@ static int read_i2c(struct nmk_i2c_dev *dev, u16 flags) > timeout = wait_for_completion_timeout( > &dev->xfer_complete, dev->adap.timeout); > > - if (timeout < 0) { > - dev_err(&dev->adev->dev, > - "wait_for_completion_timeout " > - "returned %d waiting for event\n", timeout); > - status = timeout; > - } > - No, it is wrong. You need to update the status variable in the case of timeout. It is used further in nmk_i2c_xfer_one. You could perhaps use if (timeout == 0) { ...and the rest of the code as is } regards/srinidhi -- To unsubscribe from this list: send the line "unsubscribe linux-i2c" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v3 2/2] i2c: i2c-ocores: Add support for the GRLIB port of the controller and custom getreg and setreg functions
> "Andreas" == Andreas Larsson writes: Hi, >> Adding a type define (TYPE_OCORES / TYPE_GRLIB) and a 2nd >> of_device_id entry with .data = TYPE_GRLIB, and then using that in >> the probe routine would be nicer. Have a look at i2c-at91.c for an >> example of a driver doing something like that. Andreas> Yes, that is a good idea. Do you think casting to and from Andreas> void * in the following solution is too ugly and rather have a Andreas> struct pointed to, or do you think that would be unnecessary? I find the casting OK. Thanks. -- Bye, Peter Korsgaard -- To unsubscribe from this list: send the line "unsubscribe linux-i2c" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCHv2] i2c: omap: Move the remove constraint
On Thu, Nov 15, 2012 at 9:51 AM, Shubhrajyoti Datta wrote: > On Thu, Nov 15, 2012 at 1:46 PM, Jean Pihet wrote: >> Hi Shubhrajyoti, >> >> On Thu, Nov 15, 2012 at 8:34 AM, Shubhrajyoti D wrote: >>> Currently we just queue the transfer and release the >>> qos constraints, however we donot wait for the transfer >> Typo: donot > Just fixed and resent. > >> >>> to complete to release the constraint. Move the remove >>> constraint after the bus busy as we are sure that the >>> transfers are completed by then. >>> >>> Signed-off-by: Shubhrajyoti D >> Looks good! >> Acked-by: Jean Pihet > > Thanks for review. Thanks! Regards, Jean > >> >> Regards, >> Jean >> -- To unsubscribe from this list: send the line "unsubscribe linux-i2c" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCHv2] i2c: omap: Move the remove constraint
On Thu, Nov 15, 2012 at 1:46 PM, Jean Pihet wrote: > Hi Shubhrajyoti, > > On Thu, Nov 15, 2012 at 8:34 AM, Shubhrajyoti D wrote: >> Currently we just queue the transfer and release the >> qos constraints, however we donot wait for the transfer > Typo: donot Just fixed and resent. > >> to complete to release the constraint. Move the remove >> constraint after the bus busy as we are sure that the >> transfers are completed by then. >> >> Signed-off-by: Shubhrajyoti D > Looks good! > Acked-by: Jean Pihet Thanks for review. > > Regards, > Jean > -- To unsubscribe from this list: send the line "unsubscribe linux-i2c" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCHv3] i2c: omap: Move the remove constraint
Currently we just queue the transfer and release the qos constraints, however we do not wait for the transfer to complete to release the constraint. Move the remove constraint after the bus busy as we are sure that the transfers are completed by then. Acked-by: Jean Pihet Signed-off-by: Shubhrajyoti D --- v2: rebase to the for-next branch v3: Fix a typo drivers/i2c/busses/i2c-omap.c |7 --- 1 files changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index 482c63d..fabcbe1 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -654,13 +654,14 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) break; } - if (dev->set_mpu_wkup_lat != NULL) - dev->set_mpu_wkup_lat(dev->dev, -1); - if (r == 0) r = num; omap_i2c_wait_for_bb(dev); + + if (dev->set_mpu_wkup_lat != NULL) + dev->set_mpu_wkup_lat(dev->dev, -1); + out: pm_runtime_mark_last_busy(dev->dev); pm_runtime_put_autosuspend(dev->dev); -- 1.7.5.4 -- To unsubscribe from this list: send the line "unsubscribe linux-i2c" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v3 2/2] i2c: i2c-ocores: Add support for the GRLIB port of the controller and custom getreg and setreg functions
On 2012-11-13 23:45, Peter Korsgaard wrote: "Andreas" == Andreas Larsson writes: Hi, Andreas> The registers in the GRLIB port of the controller are 32-bit Andreas> and in big endian byte order. The PRELOW and PREHIGH registers Andreas> are merged into one register. The subsequent registers have Andreas> their offset decreased accordingly. Hence the register access Andreas> needs to be handled in a non-standard manner using custom Andreas> getreg and setreg functions. Andreas> @@ -257,6 +300,14 @@ static int ocores_i2c_of_probe(struct platform_device *pdev, Andreas> of_property_read_u32(pdev->dev.of_node, "reg-io-width", Andreas> &i2c->reg_io_width); Andreas> + Andreas> + if (of_device_is_compatible(pdev->dev.of_node, Andreas> + "aeroflexgaisler,i2cmst")) { Andreas> + dev_dbg(&pdev->dev, "GRLIB variant of i2c-ocores\n"); Andreas> + i2c->setreg = oc_setreg_grlib; Andreas> + i2c->getreg = oc_getreg_grlib; Andreas> + } Andreas> + Please also update the bindings documentation under Documentation/devicetree/bindings/i2c. Sure! With this core you need to add both aeroflexgaisler,i2cmst and opencores,i2c-ocores to the compatible property, but the grlib variant is NOT compatible with i2c-ocores, so that's not really nice. Adding a type define (TYPE_OCORES / TYPE_GRLIB) and a 2nd of_device_id entry with .data = TYPE_GRLIB, and then using that in the probe routine would be nicer. Have a look at i2c-at91.c for an example of a driver doing something like that. Yes, that is a good idea. Do you think casting to and from void * in the following solution is too ugly and rather have a struct pointed to, or do you think that would be unnecessary? static struct of_device_id ocores_i2c_match[] = { { .compatible = "opencores,i2c-ocores", .data = (void *)TYPE_OCORES, }, { .compatible = "aeroflexgaisler,i2cmst", .data = (void *)TYPE_GRLIB, }, {}, }; MODULE_DEVICE_TABLE(of, ocores_i2c_match); static int ocores_i2c_get_type(struct platform_device *pdev) { const struct of_device_id *match; match = of_match_node(ocores_i2c_match, pdev->dev.of_node); if (match) return (int)match->data; else return TYPE_OCORES; } Cheers, Andreas -- To unsubscribe from this list: send the line "unsubscribe linux-i2c" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCHv2] i2c: omap: Move the remove constraint
Hi Shubhrajyoti, On Thu, Nov 15, 2012 at 8:34 AM, Shubhrajyoti D wrote: > Currently we just queue the transfer and release the > qos constraints, however we donot wait for the transfer Typo: donot > to complete to release the constraint. Move the remove > constraint after the bus busy as we are sure that the > transfers are completed by then. > > Signed-off-by: Shubhrajyoti D Looks good! Acked-by: Jean Pihet Regards, Jean > --- > v2: rebase to the for-next branch > > drivers/i2c/busses/i2c-omap.c |7 --- > 1 files changed, 4 insertions(+), 3 deletions(-) > > diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c > index 482c63d..fabcbe1 100644 > --- a/drivers/i2c/busses/i2c-omap.c > +++ b/drivers/i2c/busses/i2c-omap.c > @@ -654,13 +654,14 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg > msgs[], int num) > break; > } > > - if (dev->set_mpu_wkup_lat != NULL) > - dev->set_mpu_wkup_lat(dev->dev, -1); > - > if (r == 0) > r = num; > > omap_i2c_wait_for_bb(dev); > + > + if (dev->set_mpu_wkup_lat != NULL) > + dev->set_mpu_wkup_lat(dev->dev, -1); > + > out: > pm_runtime_mark_last_busy(dev->dev); > pm_runtime_put_autosuspend(dev->dev); > -- > 1.7.5.4 > > -- > To unsubscribe from this list: send the line "unsubscribe linux-omap" in > the body of a message to majord...@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line "unsubscribe linux-i2c" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html