diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/Kconfig | 1 | ||||
-rw-r--r-- | drivers/Makefile | 1 | ||||
-rw-r--r-- | drivers/clk/Kconfig | 4 | ||||
-rw-r--r-- | drivers/clk/Makefile | 2 | ||||
-rw-r--r-- | drivers/clk/clkdev.c | 168 | ||||
-rw-r--r-- | drivers/i2c/Kconfig | 18 | ||||
-rw-r--r-- | drivers/i2c/Makefile | 15 | ||||
-rw-r--r-- | drivers/i2c/busses/Kconfig | 15 | ||||
-rw-r--r-- | drivers/i2c/busses/Makefile | 2 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-imx.c (renamed from drivers/i2c/i2c-imx.c) | 10 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-omap.c (renamed from drivers/i2c/i2c-omap.c) | 0 | ||||
-rw-r--r-- | drivers/serial/amba-pl011.c | 4 | ||||
-rw-r--r-- | drivers/serial/arm_dcc.c | 1 | ||||
-rw-r--r-- | drivers/video/imx-ipu-fb.c | 1 |
14 files changed, 216 insertions, 26 deletions
diff --git a/drivers/Kconfig b/drivers/Kconfig index ae9efce379..f7154c62dc 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -9,5 +9,6 @@ source "drivers/mtd/Kconfig" source "drivers/ata/Kconfig" source "drivers/usb/Kconfig" source "drivers/video/Kconfig" +source "drivers/clk/Kconfig" endmenu diff --git a/drivers/Makefile b/drivers/Makefile index bce68bc7b5..706e1c8ac2 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -7,3 +7,4 @@ obj-$(CONFIG_ATA) += ata/ obj-$(CONFIG_SPI) += spi/ obj-$(CONFIG_I2C) += i2c/ obj-$(CONFIG_VIDEO) += video/ +obj-y += clk/ diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig new file mode 100644 index 0000000000..4168c8896e --- /dev/null +++ b/drivers/clk/Kconfig @@ -0,0 +1,4 @@ + +config CLKDEV_LOOKUP + bool + select HAVE_CLK diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile new file mode 100644 index 0000000000..07613fa172 --- /dev/null +++ b/drivers/clk/Makefile @@ -0,0 +1,2 @@ + +obj-$(CONFIG_CLKDEV_LOOKUP) += clkdev.o diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c new file mode 100644 index 0000000000..717fea5689 --- /dev/null +++ b/drivers/clk/clkdev.c @@ -0,0 +1,168 @@ +/* + * drivers/clk/lookup_clkdev.c + * + * Copyright (C) 2008 Russell King. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Helper for the clk API to assist looking up a struct clk. + */ + +#include <common.h> +#include <linux/list.h> +#include <errno.h> +#include <linux/err.h> +#include <linux/string.h> +#include <linux/clk.h> +#include <linux/clkdev.h> +#include <init.h> +#include <malloc.h> +#include <stdio.h> + +static LIST_HEAD(clocks); + +/* + * Find the correct struct clk for the device and connection ID. + * We do slightly fuzzy matching here: + * An entry with a NULL ID is assumed to be a wildcard. + * If an entry has a device ID, it must match + * If an entry has a connection ID, it must match + * Then we take the most specific entry - with the following + * order of precedence: dev+con > dev only > con only. + */ +static struct clk *clk_find(const char *dev_id, const char *con_id) +{ + struct clk_lookup *p; + struct clk *clk = NULL; + int match, best = 0; + + list_for_each_entry(p, &clocks, node) { + match = 0; + if (p->dev_id) { + if (!dev_id || strcmp(p->dev_id, dev_id)) + continue; + match += 2; + } + if (p->con_id) { + if (!con_id || strcmp(p->con_id, con_id)) + continue; + match += 1; + } + + if (match > best) { + clk = p->clk; + if (match != 3) + best = match; + else + break; + } + } + return clk; +} + +struct clk *clk_get_sys(const char *dev_id, const char *con_id) +{ + struct clk *clk; + + clk = clk_find(dev_id, con_id); + if (clk && !__clk_get(clk)) + clk = NULL; + + return clk ? clk : ERR_PTR(-ENOENT); +} +EXPORT_SYMBOL(clk_get_sys); + +struct clk *clk_get(struct device_d *dev, const char *con_id) +{ + const char *dev_id = dev ? dev_name(dev) : NULL; + + return clk_get_sys(dev_id, con_id); +} +EXPORT_SYMBOL(clk_get); + +void clk_put(struct clk *clk) +{ + __clk_put(clk); +} +EXPORT_SYMBOL(clk_put); + +void clkdev_add(struct clk_lookup *cl) +{ + list_add_tail(&cl->node, &clocks); +} +EXPORT_SYMBOL(clkdev_add); + +void __init clkdev_add_table(struct clk_lookup *cl, size_t num) +{ + while (num--) { + list_add_tail(&cl->node, &clocks); + cl++; + } +} + +#define MAX_DEV_ID 20 +#define MAX_CON_ID 16 + +struct clk_lookup_alloc { + struct clk_lookup cl; + char dev_id[MAX_DEV_ID]; + char con_id[MAX_CON_ID]; +}; + +struct clk_lookup *clkdev_alloc(struct clk *clk, const char *con_id, + const char *dev_fmt, ...) +{ + struct clk_lookup_alloc *cla; + + cla = kzalloc(sizeof(*cla), GFP_KERNEL); + if (!cla) + return NULL; + + cla->cl.clk = clk; + if (con_id) { + strlcpy(cla->con_id, con_id, sizeof(cla->con_id)); + cla->cl.con_id = cla->con_id; + } + + if (dev_fmt) { + va_list ap; + + va_start(ap, dev_fmt); + vscnprintf(cla->dev_id, sizeof(cla->dev_id), dev_fmt, ap); + cla->cl.dev_id = cla->dev_id; + va_end(ap); + } + + return &cla->cl; +} +EXPORT_SYMBOL(clkdev_alloc); + +int clk_add_alias(const char *alias, const char *alias_dev_name, char *id, + struct device_d *dev) +{ + struct clk *r = clk_get(dev, id); + struct clk_lookup *l; + + if (IS_ERR(r)) + return PTR_ERR(r); + + l = clkdev_alloc(r, alias, alias_dev_name); + clk_put(r); + if (!l) + return -ENODEV; + clkdev_add(l); + return 0; +} +EXPORT_SYMBOL(clk_add_alias); + +/* + * clkdev_drop - remove a clock dynamically allocated + */ +void clkdev_drop(struct clk_lookup *cl) +{ + list_del(&cl->node); + kfree(cl); +} +EXPORT_SYMBOL(clkdev_drop); diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig index 66a7cf7c76..9ce16558c4 100644 --- a/drivers/i2c/Kconfig +++ b/drivers/i2c/Kconfig @@ -3,27 +3,21 @@ menuconfig I2C if I2C -config DRIVER_I2C_IMX - bool "i.MX I2C Master driver" - depends on ARCH_IMX +source drivers/i2c/busses/Kconfig -config DRIVER_I2C_OMAP - bool "OMAP I2C Master driver" - depends on ARCH_OMAP - -config DRIVER_I2C_MC13892 +config I2C_MC13892 bool "MC13892 a.k.a. PMIC driver" -config DRIVER_I2C_MC34704 +config I2C_MC34704 bool "MC34704 PMIC driver" -config DRIVER_I2C_MC9SDZ60 +config I2C_MC9SDZ60 bool "MC9SDZ60 driver" -config DRIVER_I2C_LP3972 +config I2C_LP3972 bool "LP3972 driver" -config DRIVER_I2C_TWL4030 +config I2C_TWL4030 bool "TWL4030 driver" select GPIO diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile index 7d07cf06c3..0584b5589d 100644 --- a/drivers/i2c/Makefile +++ b/drivers/i2c/Makefile @@ -1,10 +1,7 @@ -obj-$(CONFIG_I2C) += i2c.o +obj-$(CONFIG_I2C) += i2c.o busses/ -obj-$(CONFIG_DRIVER_I2C_IMX) += i2c-imx.o -obj-$(CONFIG_DRIVER_I2C_OMAP) += i2c-omap.o - -obj-$(CONFIG_DRIVER_I2C_MC13892) += mc13892.o -obj-$(CONFIG_DRIVER_I2C_MC34704) += mc34704.o -obj-$(CONFIG_DRIVER_I2C_MC9SDZ60) += mc9sdz60.o -obj-$(CONFIG_DRIVER_I2C_LP3972) += lp3972.o -obj-$(CONFIG_DRIVER_I2C_TWL4030) += twl4030.o +obj-$(CONFIG_I2C_MC13892) += mc13892.o +obj-$(CONFIG_I2C_MC34704) += mc34704.o +obj-$(CONFIG_I2C_MC9SDZ60) += mc9sdz60.o +obj-$(CONFIG_I2C_LP3972) += lp3972.o +obj-$(CONFIG_I2C_TWL4030) += twl4030.o diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig new file mode 100644 index 0000000000..4b170caba6 --- /dev/null +++ b/drivers/i2c/busses/Kconfig @@ -0,0 +1,15 @@ +# +# Sensor device configuration +# + +menu "I2C Hardware Bus support" + +config I2C_IMX + bool "i.MX I2C Master driver" + depends on ARCH_IMX + +config I2C_OMAP + bool "OMAP I2C Master driver" + depends on ARCH_OMAP + +endmenu diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile new file mode 100644 index 0000000000..e4c5125580 --- /dev/null +++ b/drivers/i2c/busses/Makefile @@ -0,0 +1,2 @@ +obj-$(CONFIG_I2C_IMX) += i2c-imx.o +obj-$(CONFIG_I2C_OMAP) += i2c-omap.o diff --git a/drivers/i2c/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c index cc64d943c1..266cb52c0c 100644 --- a/drivers/i2c/i2c-imx.c +++ b/drivers/i2c/busses/i2c-imx.c @@ -265,7 +265,9 @@ static void i2c_imx_stop(struct i2c_adapter *adapter) temp = readb(base + IMX_I2C_I2CR); temp &= ~(I2CR_MSTA | I2CR_MTX); writeb(temp, base + IMX_I2C_I2CR); - i2c_imx->stopped = 1; + /* wait for the stop condition to be send, otherwise the i2c + * controller is disabled before the STOP is sent completely */ + i2c_imx->stopped = i2c_imx_bus_busy(adapter, 0) ? 0 : 1; } if (cpu_is_mx1()) { /* @@ -275,11 +277,9 @@ static void i2c_imx_stop(struct i2c_adapter *adapter) udelay(i2c_imx->disable_delay); } - if (!i2c_imx->stopped) - i2c_imx_bus_busy(adapter, 0); - - /* Disable I2C controller */ + /* Disable I2C controller, and force our state to stopped */ writeb(0, base + IMX_I2C_I2CR); + i2c_imx->stopped = 1; } static void i2c_imx_set_clk(struct imx_i2c_struct *i2c_imx, diff --git a/drivers/i2c/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index 8e7a8b500c..8e7a8b500c 100644 --- a/drivers/i2c/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c diff --git a/drivers/serial/amba-pl011.c b/drivers/serial/amba-pl011.c index 07508d03b0..bc9b0def8e 100644 --- a/drivers/serial/amba-pl011.c +++ b/drivers/serial/amba-pl011.c @@ -34,6 +34,7 @@ #include <asm/io.h> #include <linux/amba/serial.h> #include <linux/clk.h> +#include <linux/err.h> /* * We wrap our port structure around the generic console_device. @@ -160,6 +161,9 @@ static int pl011_probe(struct device_d *dev) uart->clk = clk_get(dev, NULL); + if (IS_ERR(uart->clk)) + return PTR_ERR(uart->clk); + cdev = &uart->uart; dev->type_data = cdev; cdev->dev = dev; diff --git a/drivers/serial/arm_dcc.c b/drivers/serial/arm_dcc.c index 151730b188..0199da30f9 100644 --- a/drivers/serial/arm_dcc.c +++ b/drivers/serial/arm_dcc.c @@ -155,6 +155,7 @@ static struct driver_d arm_dcc_driver = { }; static struct device_d arm_dcc_device = { + .id = -1, .name = "arm_dcc", .size = 4096, }; diff --git a/drivers/video/imx-ipu-fb.c b/drivers/video/imx-ipu-fb.c index 7e2c74bccc..2c25b81f41 100644 --- a/drivers/video/imx-ipu-fb.c +++ b/drivers/video/imx-ipu-fb.c @@ -748,6 +748,7 @@ static int mx3fb_set_par(struct fb_info *info) rgb = &def_rgb_24; break; case 16: + default: rgb = &def_rgb_16; break; } |