Re: [PATCH v2] i2c: add Renesas R-Car I2C driver
On Fri, Sep 28, 2012 at 11:26 AM, Kuninori Morimoto kuninori.morimoto...@renesas.com wrote: Dear Shubhrajyoti Thank you for your comment. Hi A few suggestions, On Tue, Aug 28, 2012 at 2:07 PM, Kuninori Morimoto kuninori.morimoto...@renesas.com wrote: R-Car I2C is similar with SH7760 I2C. But the SH7760 I2C driver had many workaround operations, since H/W had bugs. Thus, it was pointless to keep compatible between SH7760 and R-Car I2C drivers. This patch creates new Renesas R-Car I2C driver. Signed-off-by: Kuninori Morimoto kuninori.morimoto...@renesas.com --- v1 - v2 - removed #if 0 function - add explanation on rcar_i2c_bus_barrier() - removed IGNORE_NAK support - rename rcar_i2c_soft_reset() - rcar_i2c_init() - removed devm_kfree/devm_iounmap - __raw_writel/readl = writel/readl - removed un-needed return from rcar_i2c_bus_phase() - tidyup calculation method on rcar_i2c_clock_calculate() - tidyup English type - tidyup comment to i2c device disabled drivers/i2c/busses/Kconfig| 10 + drivers/i2c/busses/Makefile |1 + drivers/i2c/busses/i2c-rcar.c | 715 + include/linux/i2c/i2c-rcar.h | 10 + 4 files changed, 736 insertions(+), 0 deletions(-) create mode 100644 drivers/i2c/busses/i2c-rcar.c create mode 100644 include/linux/i2c/i2c-rcar.h diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index b4aaa1b..51baa08 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -709,6 +709,16 @@ config I2C_XLR This driver can also be built as a module. If so, the module will be called i2c-xlr. +config I2C_RCAR + tristate Renesas R-Car I2C Controller + depends on ARCH_SHMOBILE I2C + help + If you say yes to this option, support will be included for the + R-Car I2C controller. + + This driver can also be built as a module. If so, the module + will be called i2c-rcar. + comment External I2C/SMBus adapter drivers config I2C_DIOLAN_U2C diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile index ce3c2be..e98ff51 100644 --- a/drivers/i2c/busses/Makefile +++ b/drivers/i2c/busses/Makefile @@ -70,6 +70,7 @@ obj-$(CONFIG_I2C_VERSATILE) += i2c-versatile.o obj-$(CONFIG_I2C_OCTEON) += i2c-octeon.o obj-$(CONFIG_I2C_XILINX) += i2c-xiic.o obj-$(CONFIG_I2C_XLR) += i2c-xlr.o +obj-$(CONFIG_I2C_RCAR) += i2c-rcar.o # External I2C/SMBus adapter drivers obj-$(CONFIG_I2C_DIOLAN_U2C) += i2c-diolan-u2c.o diff --git a/drivers/i2c/busses/i2c-rcar.c b/drivers/i2c/busses/i2c-rcar.c new file mode 100644 index 000..bd8fcf1 --- /dev/null +++ b/drivers/i2c/busses/i2c-rcar.c @@ -0,0 +1,715 @@ +/* + * drivers/i2c/busses/i2c-rcar.c + * + * Copyright (C) 2012 Renesas Solutions Corp. + * Kuninori Morimoto kuninori.morimoto...@renesas.com + * + * This file is based on the drivers/i2c/busses/i2c-sh7760.c + * (c) 2005-2008 MSC Vertriebsges.m.b.H, Manuel Lauss m...@msc-ge.com + * + * This file used out-of-tree driver i2c-rcar.c + * Copyright (C) 2011-2012 Renesas Electronics Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include linux/clk.h +#include linux/delay.h +#include linux/err.h +#include linux/init.h +#include linux/interrupt.h +#include linux/io.h +#include linux/i2c.h +#include linux/i2c/i2c-rcar.h +#include linux/kernel.h +#include linux/module.h +#include linux/platform_device.h +#include linux/pm_runtime.h +#include linux/slab.h +#include linux/spinlock.h + +/* register offsets */ +#define ICSCR 0x00/* slave ctrl */ +#define ICMCR 0x04/* master ctrl */ +#define ICSSR 0x08/* slave status */ +#define ICMSR 0x0C/* master status */ +#define ICSIER 0x10/* slave irq enable */ +#define ICMIER 0x14/* master irq enable */ +#define ICCCR 0x18/* clock dividers */ +#define ICSAR 0x1C/* slave address */ +#define ICMAR 0x20/* master address */ +#define ICRXTX 0x24/* data port */ + +/* ICMCR */ +#define MDBS (1 7)/* non-fifo mode switch */ +#define FSCL (1 6)
[PATCH v3] i2c: add Renesas R-Car I2C driver
R-Car I2C is similar with SH7760 I2C. But the SH7760 I2C driver had many workaround operations, since H/W had bugs. Thus, it was pointless to keep compatible between SH7760 and R-Car I2C drivers. This patch creates new Renesas R-Car I2C driver. Signed-off-by: Kuninori Morimoto kuninori.morimoto...@renesas.com --- v2 - v3 - used simple comment on rcar_i2c_irq_recv() - used LOOP_TIMEOUT - used pm_runtime_put() - used devm_request_irq() drivers/i2c/busses/Kconfig| 10 + drivers/i2c/busses/Makefile |1 + drivers/i2c/busses/i2c-rcar.c | 709 + include/linux/i2c/i2c-rcar.h | 10 + 4 files changed, 730 insertions(+) create mode 100644 drivers/i2c/busses/i2c-rcar.c create mode 100644 include/linux/i2c/i2c-rcar.h diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index b4aaa1b..51baa08 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -709,6 +709,16 @@ config I2C_XLR This driver can also be built as a module. If so, the module will be called i2c-xlr. +config I2C_RCAR + tristate Renesas R-Car I2C Controller + depends on ARCH_SHMOBILE I2C + help + If you say yes to this option, support will be included for the + R-Car I2C controller. + + This driver can also be built as a module. If so, the module + will be called i2c-rcar. + comment External I2C/SMBus adapter drivers config I2C_DIOLAN_U2C diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile index ce3c2be..e98ff51 100644 --- a/drivers/i2c/busses/Makefile +++ b/drivers/i2c/busses/Makefile @@ -70,6 +70,7 @@ obj-$(CONFIG_I2C_VERSATILE) += i2c-versatile.o obj-$(CONFIG_I2C_OCTEON) += i2c-octeon.o obj-$(CONFIG_I2C_XILINX) += i2c-xiic.o obj-$(CONFIG_I2C_XLR) += i2c-xlr.o +obj-$(CONFIG_I2C_RCAR) += i2c-rcar.o # External I2C/SMBus adapter drivers obj-$(CONFIG_I2C_DIOLAN_U2C) += i2c-diolan-u2c.o diff --git a/drivers/i2c/busses/i2c-rcar.c b/drivers/i2c/busses/i2c-rcar.c new file mode 100644 index 000..f9399d1 --- /dev/null +++ b/drivers/i2c/busses/i2c-rcar.c @@ -0,0 +1,709 @@ +/* + * drivers/i2c/busses/i2c-rcar.c + * + * Copyright (C) 2012 Renesas Solutions Corp. + * Kuninori Morimoto kuninori.morimoto...@renesas.com + * + * This file is based on the drivers/i2c/busses/i2c-sh7760.c + * (c) 2005-2008 MSC Vertriebsges.m.b.H, Manuel Lauss m...@msc-ge.com + * + * This file used out-of-tree driver i2c-rcar.c + * Copyright (C) 2011-2012 Renesas Electronics Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include linux/clk.h +#include linux/delay.h +#include linux/err.h +#include linux/init.h +#include linux/interrupt.h +#include linux/io.h +#include linux/i2c.h +#include linux/i2c/i2c-rcar.h +#include linux/kernel.h +#include linux/module.h +#include linux/platform_device.h +#include linux/pm_runtime.h +#include linux/slab.h +#include linux/spinlock.h + +/* register offsets */ +#define ICSCR 0x00/* slave ctrl */ +#define ICMCR 0x04/* master ctrl */ +#define ICSSR 0x08/* slave status */ +#define ICMSR 0x0C/* master status */ +#define ICSIER 0x10/* slave irq enable */ +#define ICMIER 0x14/* master irq enable */ +#define ICCCR 0x18/* clock dividers */ +#define ICSAR 0x1C/* slave address */ +#define ICMAR 0x20/* master address */ +#define ICRXTX 0x24/* data port */ + +/* ICMCR */ +#define MDBS (1 7)/* non-fifo mode switch */ +#define FSCL (1 6)/* override SCL pin */ +#define FSDA (1 5)/* override SDA pin */ +#define OBPC (1 4)/* override pins */ +#define MIE(1 3)/* master if enable */ +#define TSBE (1 2) +#define FSB(1 1)/* force stop bit */ +#define ESG(1 0)/* en startbit gen */ + +/* ICMSR */ +#define MNR(1 6)/* nack received */ +#define MAL(1 5)/* arbitration lost */ +#define MST(1 4)/* sent a stop */ +#define MDE(1 3) +#define MDT(1 2) +#define MDR(1 1) +#define MAT(1 0)/* slave addr xfer done */ + +/* ICMIE */ +#define MNRE (1 6)/* nack irq en */ +#define MALE (1 5)/* arblos irq en */ +#define MSTE (1 4)/* stop irq en */ +#define MDEE (1 3) +#define MDTE (1
Re: [PATCH V4 Resend 1/2] i2c/adapter: Add bus recovery infrastructure
Hi, But before i send another version of this patchset, need some inputs from Wolfram. I am trying to have another I2C weekend this weekend. And your patches have been scheduled for that. The generic feeling is: Very useful but the interface could probably be simplified. This is why it takes me so long, working on interfaces needs more thought than the average patch review :/ Thanks, Wolfram -- Pengutronix e.K. | Wolfram Sang| Industrial Linux Solutions | http://www.pengutronix.de/ | signature.asc Description: Digital signature
Re: [PATCH V4 Resend 1/2] i2c/adapter: Add bus recovery infrastructure
On 28 September 2012 12:30, Wolfram Sang w.s...@pengutronix.de wrote: I am trying to have another I2C weekend this weekend. And your patches have been scheduled for that. The generic feeling is: Very useful but the interface could probably be simplified. This is why it takes me so long, working on interfaces needs more thought than the average patch review :/ Glad to hear that. Even i would like to make it better :) Waiting for your comments. -- Viresh -- 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 Resend 1/2] i2c/adapter: Add bus recovery infrastructure
Hi Uwe, On 28 September 2012 12:57, Uwe Kleine-König u.kleine-koe...@pengutronix.de wrote: On Fri, Sep 28, 2012 at 09:11:34AM +0530, viresh kumar wrote: This was done, because few platforms may not have configuration bits to read status of sda line.. For them skip_sda_polling was required. Whereas, others would need this to see if we can return early. What is the upside of returning early? I'd say, just don't do it. Save time. Why give additional clocks when you don't actually need them? Can use likely/unlikely to make it more efficient for 9 clock pulse scenario though. + * @put_gpio: called after recover_bus() to get padmux configured for scl line + * as scl. Only required if is_gpio_recovery == true. + * @scl_gpio: gpio number of the scl line. Only required if is_gpio_recovery == + * true. + * @sda_gpio: gpio number of the sda line. Only required if is_gpio_recovery == + * true and skip_sda_polling == false. + * @scl_gpio_flags: flag for gpio_request_one of scl_gpio. 0 implies + * GPIOF_OUT_INIT_LOW. IMHO you should not make this configurable but use GPIOF_OUT_INIT_HIGH | GPIOF_OPEN_DRAIN Discussed here: http://www.spinics.net/lists/linux-i2c/msg07325.html Why do you default to GPIOF_OUT_INIT_LOW? The idle state of scl is high. Using low here introduces an additional clk pulse. We aren't giving any clock pulses to scl line. Are you talking about sda? -- viresh -- 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
[RFC PATCH 1/6] Introduce acpi_match_device_id().
From 72df5d1f51fb27a4ba7f70a3b07df759d32b8288 Mon Sep 17 00:00:00 2001 From: Zhang Rui rui.zh...@intel.com Date: Thu, 27 Sep 2012 15:11:55 +0800 Subject: [RFC PATCH 1/6] Introduce acpi_match_device_id(). This API is used to check if a device id string is compatible with an ACPI device, either PNP id exported via _HID or compatible ids exported via _CID control method. Signed-off-by: Zhang Rui rui.zh...@intel.com --- drivers/acpi/scan.c | 22 ++ include/acpi/acpi_bus.h |6 ++ 2 files changed, 28 insertions(+), 0 deletions(-) diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index d1ecca2..936a7c9 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -312,6 +312,28 @@ int acpi_match_device_ids(struct acpi_device *device, } EXPORT_SYMBOL(acpi_match_device_ids); +int acpi_match_device_id(const struct device *dev, const char *id) +{ + acpi_handle handle = DEVICE_ACPI_HANDLE(dev); + struct acpi_device *device; + struct acpi_hardware_id *hwid; + acpi_status status; + + if (!handle || !id) + return -ENODEV; + + status = acpi_bus_get_device(handle, device); + if (ACPI_FAILURE(status)) + return -ENODEV; + + list_for_each_entry(hwid, device-pnp.ids, list) + if (!strcmp(id, hwid-id)) + return 0; + + return -ENODEV; +} +EXPORT_SYMBOL(acpi_match_device_id); + static void acpi_free_ids(struct acpi_device *device) { struct acpi_hardware_id *id, *tmp; diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index bde976e..8b5b124 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -378,6 +378,7 @@ int acpi_bus_start(struct acpi_device *device); acpi_status acpi_bus_get_ejd(acpi_handle handle, acpi_handle * ejd); int acpi_match_device_ids(struct acpi_device *device, const struct acpi_device_id *ids); +int acpi_match_device_id(const struct device *, const char *); int acpi_create_dir(struct acpi_device *); void acpi_remove_dir(struct acpi_device *); @@ -448,6 +449,11 @@ static inline int acpi_pm_device_sleep_wake(struct device *dev, bool enable) static inline int register_acpi_bus_type(void *bus) { return 0; } static inline int unregister_acpi_bus_type(void *bus) { return 0; } +static inline int acpi_match_device_id(const struct device *device, + const char *name) +{ + return -ENODEV; +} #endif /* CONFIG_ACPI */ -- 1.7.7.6 -- 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
[RFC PATCH 3/6] ACPI: introduce acpi_get_generic_resources
From 9a851d177794129a89f720c7122cb39fd163126b Mon Sep 17 00:00:00 2001 From: Zhang Rui rui.zh...@intel.com Date: Fri, 28 Sep 2012 08:34:05 +0800 Subject: [RFC PATCH 3/6] ACPI: introduce acpi_get_generic_resources Introduce acpi_get_generic_resources() to convert ACPI style resources to struct resource. Signed-off-by: Zhang Rui rui.zh...@intel.com --- drivers/acpi/Makefile |1 + drivers/acpi/resource.c | 165 +++ include/acpi/acpi_bus.h |1 + 3 files changed, 167 insertions(+), 0 deletions(-) create mode 100644 drivers/acpi/resource.c diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index 6b1d535..4b65608 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -46,6 +46,7 @@ acpi-$(CONFIG_ACPI_PROCFS_POWER) += cm_sbs.o ifdef CONFIG_ACPI_VIDEO acpi-y += video_detect.o endif +acpi-y += resource.o # These are (potentially) separate modules obj-$(CONFIG_ACPI_AC) += ac.o diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c new file mode 100644 index 000..30a5204 --- /dev/null +++ b/drivers/acpi/resource.c @@ -0,0 +1,165 @@ +/* + * resource.c -- convert ACPI resource to generic resource + * + * Copyright (c) 2012 Zhang Rui rui.zh...@intel.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + */ +#include linux/kernel.h +#include linux/export.h +#include linux/acpi.h + +static int irq_flags(int triggering, int polarity, int sharable) +{ + int flags; + + if (triggering == ACPI_LEVEL_SENSITIVE) { + if (polarity == ACPI_ACTIVE_LOW) + flags = IORESOURCE_IRQ_LOWLEVEL; + else + flags = IORESOURCE_IRQ_HIGHLEVEL; + } else { + if (polarity == ACPI_ACTIVE_LOW) + flags = IORESOURCE_IRQ_LOWEDGE; + else + flags = IORESOURCE_IRQ_HIGHEDGE; + } + + if (sharable == ACPI_SHARED) + flags |= IORESOURCE_IRQ_SHAREABLE; + + return flags; +} + +static void acpi_get_irq_resource(struct acpi_resource *res, + struct resource *resource) +{ + struct acpi_resource_irq *irq = res-data.irq; + int t, p; + + if (irq-interrupt_count == 0) + resource-flags = IORESOURCE_DISABLED; + + if (!acpi_get_override_irq(irq-interrupts[0], t, p)) { + t = t ? ACPI_LEVEL_SENSITIVE : ACPI_EDGE_SENSITIVE; + p = p ? ACPI_ACTIVE_LOW : ACPI_ACTIVE_HIGH; + + if (irq-triggering != t || irq-polarity != p) { + irq-triggering = t; + irq-polarity = p; + } + } + + resource-flags = + irq_flags(irq-triggering, irq-polarity, irq-sharable); + resource-flags |= IORESOURCE_IRQ; + resource-start = irq-interrupts[0]; + resource-end = irq-interrupts[0]; +} + +static void acpi_get_extended_irq_resource(struct acpi_resource *res, + struct resource *resource) +{ + struct acpi_resource_extended_irq *irq = res-data.extended_irq; + int t, p; + + if (irq-interrupt_count == 0) + resource-flags = IORESOURCE_DISABLED; + + if (!acpi_get_override_irq(irq-interrupts[0], t, p)) { + t = t ? ACPI_LEVEL_SENSITIVE : ACPI_EDGE_SENSITIVE; + p = p ? ACPI_ACTIVE_LOW : ACPI_ACTIVE_HIGH; + + if (irq-triggering != t || irq-polarity != p) { + irq-triggering = t; + irq-polarity = p; + } + } + + resource-flags = + irq_flags(irq-triggering, irq-polarity, irq-sharable); + resource-flags |= IORESOURCE_IRQ; + resource-start = irq-interrupts[0]; + resource-end = irq-interrupts[0]; +} + +static void acpi_get_mem_resource(struct acpi_resource *res, + struct resource *resource) +{ + struct acpi_resource_fixed_memory32 *mem = res-data.fixed_memory32; + + if (mem-address_length == 0) + resource-flags |= IORESOURCE_DISABLED; + if (mem-write_protect == ACPI_READ_WRITE_MEMORY) + resource-flags |= IORESOURCE_MEM_WRITEABLE; + + resource-flags |= IORESOURCE_MEM; + resource-start = mem-address; + resource-end = mem-address + mem-address_length - 1; +} + +int acpi_get_generic_resources(struct acpi_device *device, + struct resource
[RFC PATCH 4/6] Change i2c_register_board_info from __init to __devinit
From 34aa38e12c04544d89af2eae46de284dc8a03b8d Mon Sep 17 00:00:00 2001 From: Zhang Rui rui.zh...@intel.com Date: Thu, 27 Sep 2012 15:42:23 +0800 Subject: [RFC PATCH 4/6] Change i2c_register_board_info from __init to __devinit. ACPI 5 supports enumerating I2C adapter and its slaves via ACPI namespace, and this needs to be done at runtime, after the ACPI I2C controller driver being loaded. detailed usage of this API can be found in next patch. Signed-off-by: Zhang Rui rui.zh...@intel.com --- drivers/i2c/i2c-boardinfo.c |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/drivers/i2c/i2c-boardinfo.c b/drivers/i2c/i2c-boardinfo.c index f24cc64..1ecbbdc 100644 --- a/drivers/i2c/i2c-boardinfo.c +++ b/drivers/i2c/i2c-boardinfo.c @@ -61,7 +61,7 @@ EXPORT_SYMBOL_GPL(__i2c_first_dynamic_bus_num); * The board info passed can safely be __initdata, but be careful of embedded * pointers (for platform_data, functions, etc) since that won't be copied. */ -int __init +int __devinit i2c_register_board_info(int busnum, struct i2c_board_info const *info, unsigned len) { -- 1.7.7.6 -- 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
[RFC PATCH 5/6] ACPI: Introduce ACPI I2C controller enumeration driver
From 6077a62f2865201ab6727ca7d628ee5e43aa57e1 Mon Sep 17 00:00:00 2001 From: Zhang Rui rui.zh...@intel.com Date: Fri, 24 Aug 2012 15:18:25 +0800 Subject: [RFC PATCH 5/6] ACPI: Introduce ACPI I2C controller enumeration driver This driver is able to 1) enumerate I2C controller via ACPI namespace and register it as a platform device. 2) enumerate I2C slave devices via ACPI namespace. Signed-off-by: Zhang Rui rui.zh...@intel.com --- drivers/acpi/Makefile |1 + drivers/acpi/i2c_root.c | 229 +++ drivers/acpi/sysfs.c|1 + include/acpi/acpi_drivers.h |1 + 4 files changed, 232 insertions(+), 0 deletions(-) create mode 100644 drivers/acpi/i2c_root.c diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index 4b65608..5b14f05 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -35,6 +35,7 @@ acpi-y+= scan.o acpi-y += processor_core.o acpi-y += ec.o acpi-y += gpio.o +acpi-y += i2c_root.o acpi-$(CONFIG_ACPI_DOCK) += dock.o acpi-y += pci_root.o pci_link.o pci_irq.o pci_bind.o acpi-y += power.o diff --git a/drivers/acpi/i2c_root.c b/drivers/acpi/i2c_root.c new file mode 100644 index 000..b9a042b --- /dev/null +++ b/drivers/acpi/i2c_root.c @@ -0,0 +1,229 @@ +/* + * i2c_root.c - ACPI I2C controller Driver ($Revision: 40 $) + * + * Copyright (C) 2012 Intel Corp + * Copyright (C) 2012 Zhang Rui rui.zh...@intel.com + * + * ~~ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * ~~ + */ + +#include linux/kernel.h +#include linux/module.h +#include linux/init.h +#include linux/types.h +#include linux/spinlock.h +#include linux/pm.h +#include linux/pm_runtime.h +#include linux/platform_device.h +#include linux/i2c.h +#include linux/acpi.h +#include linux/slab.h +#include acpi/acpi_bus.h +#include acpi/acpi_drivers.h +#include acpi/apei.h + +#define PREFIX ACPI: + +#define _COMPONENT ACPI_SPB_COMPONENT +ACPI_MODULE_NAME(i2c_root); +#define ACPI_I2C_ROOT_CLASSi2c_root +#define ACPI_I2C_ROOT_DEVICE_NAME I2C Controller + +static int acpi_i2c_root_add(struct acpi_device *device); +static int acpi_i2c_root_remove(struct acpi_device *device, int type); + +static const struct acpi_device_id root_device_ids[] = { + {INT33B1, 0}, + {, 0}, +}; + +MODULE_DEVICE_TABLE(acpi, root_device_ids); + +static struct acpi_driver acpi_i2c_root_driver = { + .name = i2c_root, + .class = ACPI_I2C_ROOT_CLASS, + .ids = root_device_ids, + .ops = { + .add = acpi_i2c_root_add, + .remove = acpi_i2c_root_remove, + }, +}; + +struct acpi_i2c_root { + struct acpi_device *device; + struct platform_device *pdev; + int busnum; + int slaves; + struct i2c_board_info *info; +}; + +static int add_slave(struct acpi_i2c_root *root, struct i2c_board_info *info) +{ + struct i2c_board_info *p; + + if (!info) + return 0; + + p = kzalloc(sizeof(*p) * (root-slaves + 1), GFP_KERNEL); + if (!p) + return -ENOMEM; + + memcpy(p, info, sizeof(*p)); + if (root-info) + memcpy(p + 1, root-info, sizeof(*p) * root-slaves); + + kfree(root-info); + root-info = p; + root-slaves++; + return 0; +} + +static int register_slaves(struct acpi_i2c_root *root) +{ + return i2c_register_board_info(root-busnum, root-info, root-slaves); +} + +/* + * The i2c info registering call back for each i2c slave device + */ +acpi_status __init i2c_enumerate_slave(acpi_handle handle, u32 level, + void *data, void **return_value) +{ + int result; + acpi_status status; + struct acpi_buffer buffer; + struct acpi_resource *resource; + struct acpi_resource_gpio *gpio; + struct acpi_resource_i2c_serialbus *i2c; + int i; + struct acpi_i2c_root *root = data; + struct i2c_board_info info; + struct acpi_device *device; + +
[RFC PATCH 6/6] Introduce INT33B1 I2C controller driver
From 817d814ecae91862f42a0447f455dae7f74cba27 Mon Sep 17 00:00:00 2001 From: Zhang Rui rui.zh...@intel.com Date: Fri, 24 Aug 2012 15:20:38 +0800 Subject: [RFC PATCH 6/6] Introduce INT33B1 I2C controller driver This is a dummy platform device driver to illustrate my idea about how a really I2C controller should work on ACPI 5 platforms. It just probes the INT33B1 I2C controller which is enumerated by ACPI. Signed-off-by: Zhang Rui rui.zh...@intel.com --- drivers/i2c/busses/Kconfig|8 +++ drivers/i2c/busses/Makefile |1 + drivers/i2c/busses/i2c-33b1.c | 117 + 3 files changed, 126 insertions(+), 0 deletions(-) create mode 100644 drivers/i2c/busses/i2c-33b1.c diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index b4aaa1b..536a19c 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -257,6 +257,14 @@ config I2C_SCMI To compile this driver as a module, choose M here: the module will be called i2c-scmi. +config I2C_33B1 + tristate INT33B1 I2C controller + help + This driver supports the ACPI enumerated INT33B1 I2C controller. + + To compile this driver as a module, choose M here: + the module will be called i2c-scmi. + endif # ACPI comment Mac SMBus host controller drivers diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile index ce3c2be..8e478bd 100644 --- a/drivers/i2c/busses/Makefile +++ b/drivers/i2c/busses/Makefile @@ -4,6 +4,7 @@ # ACPI drivers obj-$(CONFIG_I2C_SCMI) += i2c-scmi.o +obj-$(CONFIG_I2C_33B1) += i2c-33b1.o # PC SMBus host controller drivers obj-$(CONFIG_I2C_ALI1535) += i2c-ali1535.o diff --git a/drivers/i2c/busses/i2c-33b1.c b/drivers/i2c/busses/i2c-33b1.c new file mode 100644 index 000..152c3e4 --- /dev/null +++ b/drivers/i2c/busses/i2c-33b1.c @@ -0,0 +1,117 @@ +/* + * i2c_33b1.c -INT33B1 i2c Controller Driver + * + * Copyright (c) 2012 Intel Corp + * Copyright (c) 2012 Zhang Rui rui.zh...@intel.com + * + * ~~ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * ~~ + */ + +#include linux/kernel.h +#include linux/module.h +#include linux/slab.h +#include linux/init.h +#include linux/ioport.h +#include linux/delay.h +#include linux/errno.h +#include linux/i2c.h +#include linux/io.h +#include linux/platform_device.h + + +struct int33b1_i2c_private { +struct i2c_adapter adap; +void __iomem *iobase; +}; + + +static int int33b1_i2c_xfer(struct i2c_adapter *adap, + struct i2c_msg *msgs, int num) +{ + return 0; +} + +static u32 int33b1_func(struct i2c_adapter *adap) +{ + /* Emulate SMBUS over I2C */ + return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_I2C; +} + +static struct i2c_algorithm int33b1_i2c_algo = { + .master_xfer= int33b1_i2c_xfer, + .functionality = int33b1_func, +}; + +static int __devinit int33b1_i2c_probe(struct platform_device *pdev) +{ + struct int33b1_i2c_private *priv; + struct resource *res; + int ret; + + priv = devm_kzalloc(pdev-dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + priv-iobase = devm_request_and_ioremap(pdev-dev, res); + if (!priv-iobase) { + dev_err(pdev-dev, devm_request_and_ioremap failed\n); + return -EBUSY; + } + + priv-adap.dev.parent = pdev-dev; + priv-adap.owner= THIS_MODULE; + priv-adap.algo_data= priv; + priv-adap.algo = int33b1_i2c_algo; + priv-adap.nr = pdev-id; + priv-adap.class= I2C_CLASS_HWMON; + snprintf(priv-adap.name, sizeof(priv-adap.name), int33b1-i2c); + + i2c_set_adapdata(priv-adap, priv); + ret = i2c_add_numbered_adapter(priv-adap); + if (ret 0) { + dev_err(priv-adap.dev, Failed to add i2c bus.\n); + return ret; + } + + platform_set_drvdata(pdev, priv); + dev_info(priv-adap.dev, Added I2C Bus.\n); + return 0; +} + +static int __devexit int33b1_i2c_remove(struct platform_device *pdev) +{ + struct int33b1_i2c_private *priv; + + priv = platform_get_drvdata(pdev); + i2c_del_adapter(priv-adap); + platform_set_drvdata(pdev, NULL); + return 0; +} + +static struct platform_driver
Re: [PATCH V4 Resend 1/2] i2c/adapter: Add bus recovery infrastructure
On 28 September 2012 12:57, Uwe Kleine-König u.kleine-koe...@pengutronix.de wrote: Why do you default to GPIOF_OUT_INIT_LOW? The idle state of scl is high. Using low here introduces an additional clk pulse. Went deep into the code i wrote ages ago to check why i did so :) My initial idea was, because the idle state of scl is high, giving another high initially with gpio would be a waste. As the slave will not notice a change. So, i will do it low and then following code will run with delay before setting gpio again. This will ensure, the initial gpio-set is used as clock. for (i = 0; i bri-clock_cnt * 2; i++, val = !val) { ndelay(delay); gpio_set_value(bri-scl_gpio, val); ... } Yes, you are correct in saying that i have generated 9 *2 + 1 = 19 half-clocks... or 9.5 clocks. Will fix it by making initial value of i as 1. Also, will take care of this when user sends his own flags :) -- viresh -- 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/adapter: Add bus recovery infrastructure
From: Viresh Kumar viresh.ku...@st.com Add i2c bus recovery infrastructure to i2c adapters as specified in the i2c protocol Rev. 03 section 3.1.16 titled Bus clear. http://www.nxp.com/documents/user_manual/UM10204.pdf Sometimes during operation i2c bus hangs and we need to give dummy clocks to slave device to start the transfer again. Now we may have capability in the bus controller to generate these clocks or platform may have gpio pins which can be toggled to generate dummy clocks. This patch supports both. This patch also adds in generic bus recovery routines gpio or scl line based which can be used by bus controller. In addition controller driver may provide its own version of the bus recovery routine. This doesn't support multi-master recovery for now. Signed-off-by: Viresh Kumar viresh.ku...@st.com --- V4-V5: - section name corrected to 3.1.16 - merged gpio and non-gpio recovery routines to remove code redundancy - Changed types of gpio and gpio-flags to unsigned and unsigned long - Checking return value of get_gpio() now - using DIV_ROUND_UP for calculating delay, to get more correct value drivers/i2c/i2c-core.c | 153 + include/linux/i2c.h| 52 + 2 files changed, 205 insertions(+) diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index a7edf98..bdc249a 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -27,7 +27,9 @@ #include linux/module.h #include linux/kernel.h +#include linux/delay.h #include linux/errno.h +#include linux/gpio.h #include linux/slab.h #include linux/i2c.h #include linux/init.h @@ -104,6 +106,116 @@ static int i2c_device_uevent(struct device *dev, struct kobj_uevent_env *env) #define i2c_device_uevent NULL #endif /* CONFIG_HOTPLUG */ +/* i2c bus recovery routines */ +static inline void set_scl_value(struct i2c_adapter *adap, int val) +{ + struct i2c_bus_recovery_info *bri = adap-bus_recovery_info; + + if (bri-is_gpio_recovery) + gpio_set_value(bri-scl_gpio, val); + else + bri-set_scl(adap, val); +} + +static inline int get_sda_value(struct i2c_adapter *adap) +{ + struct i2c_bus_recovery_info *bri = adap-bus_recovery_info; + + if (bri-is_gpio_recovery) + return gpio_get_value(bri-sda_gpio); + else + return bri-get_sda(adap); +} + +static int i2c_get_gpios_for_recovery(struct i2c_adapter *adap) +{ + struct i2c_bus_recovery_info *bri = adap-bus_recovery_info; + struct device *dev = adap-dev; + int ret = 0; + + if (bri-get_gpio) { + ret = bri-get_gpio(bri-scl_gpio); + if (ret) { + dev_warn(dev, scl get_gpio: %d\n, bri-scl_gpio); + return ret; + } + } + + ret = gpio_request_one(bri-scl_gpio, bri-scl_gpio_flags, i2c-scl); + if (ret) { + dev_warn(dev, gpio request fail: %d\n, bri-scl_gpio); + goto scl_put_gpio; + } + + if (!bri-skip_sda_polling) { + if (bri-get_gpio) + ret = bri-get_gpio(bri-sda_gpio); + + if (unlikely(ret || + gpio_request_one(bri-sda_gpio, bri-sda_gpio_flags, + i2c-sda))) { + /* work without sda polling */ + dev_warn(dev, can't get sda: %d. Skip sda polling\n, + bri-sda_gpio); + bri-skip_sda_polling = true; + if (!ret bri-put_gpio) + bri-put_gpio(bri-sda_gpio); + + ret = 0; + } + } + +scl_put_gpio: + if (bri-put_gpio) + bri-put_gpio(bri-scl_gpio); + + return ret; +} + +static void i2c_put_gpios_for_recovery(struct i2c_adapter *adap) +{ + struct i2c_bus_recovery_info *bri = adap-bus_recovery_info; + + gpio_free(bri-scl_gpio); + + if (!bri-skip_sda_polling) { + gpio_free(bri-sda_gpio); + + if (bri-put_gpio) + bri-put_gpio(bri-sda_gpio); + } +} + +static int i2c_recover_bus(struct i2c_adapter *adap) +{ + struct i2c_bus_recovery_info *bri = adap-bus_recovery_info; + unsigned long delay = 100; + int i, ret, val = 1; + + if (bri-is_gpio_recovery) { + ret = i2c_get_gpios_for_recovery(adap); + if (ret) + return ret; + } + + delay = DIV_ROUND_UP(delay, bri-clock_rate_khz * 2); + + for (i = 0; i bri-clock_cnt * 2; i++, val = !val) { + set_scl_value(adap, val); + ndelay(delay); + + /* break if sda got high, check only when scl line is high */ + if (!bri-skip_sda_polling val) + if (unlikely(get_sda_value(adap))) +
[PATCH V5 2/2] i2c/designware: Provide i2c bus recovery support
From: Viresh Kumar viresh.ku...@st.com Add bus recovery support for designware_i2c controller. It uses generic gpio based i2c_gpio_recover_bus() routine. Signed-off-by: Vincenzo Frascino vincenzo.frasc...@st.com Signed-off-by: Shiraz Hashim shiraz.has...@st.com Signed-off-by: Viresh Kumar viresh.ku...@st.com --- drivers/i2c/busses/i2c-designware-core.c| 7 - drivers/i2c/busses/i2c-designware-platdrv.c | 40 +-- include/linux/i2c/i2c-designware.h | 49 + 3 files changed, 93 insertions(+), 3 deletions(-) create mode 100644 include/linux/i2c/i2c-designware.h diff --git a/drivers/i2c/busses/i2c-designware-core.c b/drivers/i2c/busses/i2c-designware-core.c index 7b8ebbe..3073178 100644 --- a/drivers/i2c/busses/i2c-designware-core.c +++ b/drivers/i2c/busses/i2c-designware-core.c @@ -538,7 +538,12 @@ i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) ret = wait_for_completion_interruptible_timeout(dev-cmd_complete, HZ); if (ret == 0) { dev_err(dev-dev, controller timed out\n); - i2c_dw_init(dev); + if (adap-bus_recovery_info + adap-bus_recovery_info-recover_bus) { + dev_dbg(dev-dev, try i2c bus recovery\n); + adap-bus_recovery_info-recover_bus(adap); + } + ret = -ETIMEDOUT; goto done; } else if (ret 0) diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c b/drivers/i2c/busses/i2c-designware-platdrv.c index 0506fef..9e8b7e3 100644 --- a/drivers/i2c/busses/i2c-designware-platdrv.c +++ b/drivers/i2c/busses/i2c-designware-platdrv.c @@ -29,6 +29,7 @@ #include linux/module.h #include linux/delay.h #include linux/i2c.h +#include linux/i2c/i2c-designware.h #include linux/clk.h #include linux/errno.h #include linux/sched.h @@ -45,6 +46,7 @@ static struct i2c_algorithm i2c_dw_algo = { .master_xfer= i2c_dw_xfer, .functionality = i2c_dw_func, }; + static u32 i2c_dw_get_clk_rate_khz(struct dw_i2c_dev *dev) { return clk_get_rate(dev-clk)/1000; @@ -55,6 +57,8 @@ static int __devinit dw_i2c_probe(struct platform_device *pdev) struct dw_i2c_dev *dev; struct i2c_adapter *adap; struct resource *mem, *ioarea; + struct i2c_dw_pdata *pdata; + struct i2c_bus_recovery_info *recovery_info = NULL; int irq, r; /* NOTE: driver uses the static register mapping */ @@ -141,17 +145,47 @@ static int __devinit dw_i2c_probe(struct platform_device *pdev) adap-dev.parent = pdev-dev; adap-dev.of_node = pdev-dev.of_node; + /* Bus recovery support */ + pdata = dev_get_platdata(pdev-dev); + if (pdata) { + recovery_info = kzalloc(sizeof(*recovery_info), GFP_KERNEL); + if (!recovery_info) { + adap-bus_recovery_info = NULL; + dev_err(pdev-dev, + failure to allocate memory for bus recovery\n); + goto skip_recovery; + } + + recovery_info-is_gpio_recovery = true; + recovery_info-get_gpio = pdata-get_gpio; + recovery_info-put_gpio = pdata-put_gpio; + recovery_info-scl_gpio = pdata-scl_gpio; + recovery_info-scl_gpio_flags = pdata-scl_gpio_flags; + recovery_info-clock_rate_khz = clk_get_rate(dev-clk) / 1000; + + if (!pdata-skip_sda_polling) { + recovery_info-sda_gpio = pdata-sda_gpio; + recovery_info-sda_gpio_flags = pdata-sda_gpio_flags; + } + + adap-bus_recovery_info = recovery_info; + } else { + adap-bus_recovery_info = NULL; + } + +skip_recovery: adap-nr = pdev-id; r = i2c_add_numbered_adapter(adap); if (r) { dev_err(pdev-dev, failure adding adapter\n); - goto err_free_irq; + goto err_free_recovery_info; } of_i2c_register_devices(adap); return 0; -err_free_irq: +err_free_recovery_info: + kfree(recovery_info); free_irq(dev-irq, dev); err_iounmap: iounmap(dev-base); @@ -174,6 +208,8 @@ static int __devexit dw_i2c_remove(struct platform_device *pdev) struct dw_i2c_dev *dev = platform_get_drvdata(pdev); struct resource *mem; + kfree(dev-adapter.bus_recovery_info); + platform_set_drvdata(pdev, NULL); i2c_del_adapter(dev-adapter); put_device(pdev-dev); diff --git a/include/linux/i2c/i2c-designware.h b/include/linux/i2c/i2c-designware.h new file mode 100644 index 000..d60cb61c --- /dev/null +++ b/include/linux/i2c/i2c-designware.h @@ -0,0 +1,49 @@ +/* + * Synopsys DesignWare I2C adapter driver's platform data + * + * Copyright (C) 2012 ST Microelectronics. +
Re: [RFC PATCH 5/6] ACPI: Introduce ACPI I2C controller enumeration driver
On Fri, 28 Sep 2012 15:40:32 +0800 Zhang Rui rui.zh...@intel.com wrote: From 6077a62f2865201ab6727ca7d628ee5e43aa57e1 Mon Sep 17 00:00:00 2001 From: Zhang Rui rui.zh...@intel.com Date: Fri, 24 Aug 2012 15:18:25 +0800 Subject: [RFC PATCH 5/6] ACPI: Introduce ACPI I2C controller enumeration driver This driver is able to 1) enumerate I2C controller via ACPI namespace and register it as a platform device. 2) enumerate I2C slave devices via ACPI namespace. Will this also trigger and work with the ACPI4 based devices that seem to have I²C tables that Linux currently doesn't understand (eq some GMA600/Oaktrail platforms) ? -- 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 v2] i2c: nomadik: adopt pinctrl support
From: Patrice Chotard patrice.chot...@stericsson.com Amend the I2C nomadik pin controller to optionally take a pin control handle and set the state of the pins to: - default on boot, resume and before performing an i2c transfer - idle after initial default, after resume default, and after each i2c xfer - sleep on suspend() This should make it possible to optimize energy usage for the pins both for the suspend/resume cycle, and for runtime cases inbetween I2C transfers. Signed-off-by: Patrice Chotard patrice.chot...@stericsson.com Signed-off-by: Linus Walleij linus.wall...@linaro.org --- ChangeLog v1-v2: - We used only two states initially: default and sleep. It turns out you can save some energy when idling (between transfers) and even more when suspending on our platform, so grab all three states and use them as applicable. --- drivers/i2c/busses/i2c-nomadik.c | 102 +++ 1 file changed, 102 insertions(+) diff --git a/drivers/i2c/busses/i2c-nomadik.c b/drivers/i2c/busses/i2c-nomadik.c index 1b898b6..bd3da46 100644 --- a/drivers/i2c/busses/i2c-nomadik.c +++ b/drivers/i2c/busses/i2c-nomadik.c @@ -24,6 +24,7 @@ #include linux/io.h #include linux/pm_runtime.h #include linux/platform_data/i2c-nomadik.h +#include linux/pinctrl/consumer.h #define DRIVER_NAME nmk-i2c @@ -145,6 +146,10 @@ struct i2c_nmk_client { * @stop: stop condition. * @xfer_complete: acknowledge completion for a I2C message. * @result: controller propogated result. + * @pinctrl: pinctrl handle. + * @pins_default: default state for the pins. + * @pins_idle: idle state for the pins. + * @pins_sleep: sleep state for the pins. * @busy: Busy doing transfer. */ struct nmk_i2c_dev { @@ -158,6 +163,11 @@ struct nmk_i2c_dev { int stop; struct completion xfer_complete; int result; + /* Three pin states - default, idle sleep */ + struct pinctrl *pinctrl; + struct pinctrl_state*pins_default; + struct pinctrl_state*pins_idle; + struct pinctrl_state*pins_sleep; boolbusy; }; @@ -642,6 +652,15 @@ static int nmk_i2c_xfer(struct i2c_adapter *i2c_adap, pm_runtime_get_sync(dev-adev-dev); + /* Optionaly enable pins to be muxed in and configured */ + if (!IS_ERR(dev-pins_default)) { + status = pinctrl_select_state(dev-pinctrl, + dev-pins_default); + if (status) + dev_err(dev-adev-dev, + could not set default pins\n); + } + clk_enable(dev-clk); status = init_hw(dev); @@ -670,6 +689,16 @@ static int nmk_i2c_xfer(struct i2c_adapter *i2c_adap, out: clk_disable(dev-clk); + + /* Optionally let pins go into idle state */ + if (!IS_ERR(dev-pins_idle)) { + status = pinctrl_select_state(dev-pinctrl, + dev-pins_idle); + if (status) + dev_err(dev-adev-dev, + could not set pins to idle state\n); + } + pm_runtime_put_sync(dev-adev-dev); dev-busy = false; @@ -864,15 +893,44 @@ static int nmk_i2c_suspend(struct device *dev) { struct amba_device *adev = to_amba_device(dev); struct nmk_i2c_dev *nmk_i2c = amba_get_drvdata(adev); + int ret; if (nmk_i2c-busy) return -EBUSY; + if (!IS_ERR(nmk_i2c-pins_sleep)) { + ret = pinctrl_select_state(nmk_i2c-pinctrl, + nmk_i2c-pins_sleep); + if (ret) + dev_err(dev, + could not set pins to sleep state\n); + } + return 0; } static int nmk_i2c_resume(struct device *dev) { + struct amba_device *adev = to_amba_device(dev); + struct nmk_i2c_dev *nmk_i2c = amba_get_drvdata(adev); + int ret; + + /* First go to the default state */ + if (!IS_ERR(nmk_i2c-pins_default)) { + ret = pinctrl_select_state(nmk_i2c-pinctrl, + nmk_i2c-pins_default); + if (ret) + dev_err(dev, + could not set pins to default state\n); + } + /* Then let's idle the pins until the next transfer happens */ + if (!IS_ERR(nmk_i2c-pins_idle)) { + ret = pinctrl_select_state(nmk_i2c-pinctrl, + nmk_i2c-pins_idle); + if (ret) + dev_err(dev, + could not set pins to idle state\n); + } return 0; } #else @@ -936,6 +994,40 @@ static int nmk_i2c_probe(struct amba_device *adev, const struct amba_id *id) dev-adev = adev;
Re: [RFC PATCH 1/6] Introduce acpi_match_device_id().
On Fri, Sep 28, 2012 at 03:38:30PM +0800, Zhang Rui wrote: From 72df5d1f51fb27a4ba7f70a3b07df759d32b8288 Mon Sep 17 00:00:00 2001 From: Zhang Rui rui.zh...@intel.com Date: Thu, 27 Sep 2012 15:11:55 +0800 Subject: [RFC PATCH 1/6] Introduce acpi_match_device_id(). This API is used to check if a device id string is compatible with an ACPI device, either PNP id exported via _HID or compatible ids exported via _CID control method. Signed-off-by: Zhang Rui rui.zh...@intel.com --- drivers/acpi/scan.c | 22 ++ include/acpi/acpi_bus.h |6 ++ 2 files changed, 28 insertions(+), 0 deletions(-) diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index d1ecca2..936a7c9 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -312,6 +312,28 @@ int acpi_match_device_ids(struct acpi_device *device, } EXPORT_SYMBOL(acpi_match_device_ids); +int acpi_match_device_id(const struct device *dev, const char *id) Would be good idea to implement this in terms of of_match_device() so that it returns pointer to the matched id. This way drivers can get the -driver_data pretty easily if needed. +{ + acpi_handle handle = DEVICE_ACPI_HANDLE(dev); If the device is not bound to an ACPI handle this will return NULL. And I don't see you doing that in this series meaning that.. + struct acpi_device *device; + struct acpi_hardware_id *hwid; + acpi_status status; + + if (!handle || !id) + return -ENODEV; ..you always return -ENODEV here, right? + + status = acpi_bus_get_device(handle, device); + if (ACPI_FAILURE(status)) + return -ENODEV; + + list_for_each_entry(hwid, device-pnp.ids, list) + if (!strcmp(id, hwid-id)) + return 0; + + return -ENODEV; +} +EXPORT_SYMBOL(acpi_match_device_id); -- 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