From 523817bd22617cd62199ae4ca2a6f5e1aa250654 Mon Sep 17 00:00:00 2001 From: Dave Martin <dave.martin@linaro.org> Date: Wed, 5 Oct 2011 14:44:57 +0100 Subject: ARM: amba: Auto-generate AMBA driver module aliases during modpost This patch adds the necessary support in file2alias.c to define suitable aliases based on the amba_id table in AMBA driver modules. This should be sufficient to allow such modules to be auto-loaded via udev. The AMBA bus driver's uevent hotplug code is also modified to pass an approriate MODALIAS string in the event. For simplicity, the AMBA ID is treated an an opaque 32-bit numeber. Module alises use patterns as appropriate to describe the value- mask pairs described in the driver's amba_id list. The proposed alias format is (extended regex): ^amba:d(HEX){8}$ Where HEX is a single upper-case HEX digit or a pattern (? or [] expression) matching a single upper-case HEX digit, as expected by udev. "d" is short for "device", following existing alias naming conventions for other device types. This adds some flexibility for unambiguously extending the alias format in the future by adding additional leading and trailing fields, if this turns out to be necessary. Signed-off-by: Dave Martin <dave.martin@linaro.org> Acked-by: Pawel Moll <pawel.moll@arm.com> --- scripts/mod/file2alias.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) (limited to 'scripts/mod/file2alias.c') diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c index f936d1fa969..363ab4666b1 100644 --- a/scripts/mod/file2alias.c +++ b/scripts/mod/file2alias.c @@ -880,6 +880,74 @@ static int do_isapnp_entry(const char *filename, return 1; } +/* + * Append a match expression for a single masked hex digit. + * outp points to a pointer to the character at which to append. + * *outp is updated on return to point just after the appended text, + * to facilitate further appending. + */ +static void append_nibble_mask(char **outp, + unsigned int nibble, unsigned int mask) +{ + char *p = *outp; + unsigned int i; + + switch (mask) { + case 0: + *p++ = '?'; + break; + + case 0xf: + p += sprintf(p, "%X", nibble); + break; + + default: + /* + * Dumbly emit a match pattern for all possible matching + * digits. This could be improved in some cases using ranges, + * but it has the advantage of being trivially correct, and is + * often optimal. + */ + *p++ = '['; + for (i = 0; i < 0x10; i++) + if ((i & mask) == nibble) + p += sprintf(p, "%X", i); + *p++ = ']'; + } + + /* Ensure that the string remains NUL-terminated: */ + *p = '\0'; + + /* Advance the caller's end-of-string pointer: */ + *outp = p; +} + +/* + * looks like: "amba:dN" + * + * N is exactly 8 digits, where each is an upper-case hex digit, or + * a ? or [] pattern matching exactly one digit. + */ +static int do_amba_entry(const char *filename, + struct amba_id *id, char *alias) +{ + unsigned int digit; + char *p = alias; + + if ((id->id & id->mask) != id->id) + fatal("%s: Masked-off bit(s) of AMBA device ID are non-zero: " + "id=0x%08X, mask=0x%08X. Please fix this driver.\n", + filename, id->id, id->mask); + + p += sprintf(alias, "amba:d"); + for (digit = 0; digit < 8; digit++) + append_nibble_mask(&p, + (id->id >> (4 * (7 - digit))) & 0xf, + (id->mask >> (4 * (7 - digit))) & 0xf); + + return 1; +} + /* Ignore any prefix, eg. some architectures prepend _ */ static inline int sym_is(const char *symbol, const char *name) { @@ -1047,6 +1115,10 @@ void handle_moddevtable(struct module *mod, struct elf_info *info, do_table(symval, sym->st_size, sizeof(struct isapnp_device_id), "isa", do_isapnp_entry, mod); + else if (sym_is(symname, "__mod_amba_device_table")) + do_table(symval, sym->st_size, + sizeof(struct amba_id), "amba", + do_amba_entry, mod); free(zeros); } -- cgit v1.2.3-70-g09d2 From 5dd7bf59e0e8563265b3e5b33276099ef628fcc7 Mon Sep 17 00:00:00 2001 From: Jochen Friedrich <jochen@scram.de> Date: Sun, 27 Nov 2011 22:00:54 +0100 Subject: ARM: sa11x0: Implement autoloading of codec and codec pdata for mcp bus. Signed-off-by: Jochen Friedrich <jochen@scram.de> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com> --- arch/arm/mach-sa1100/assabet.c | 1 + arch/arm/mach-sa1100/cerf.c | 1 + arch/arm/mach-sa1100/collie.c | 8 +++++- arch/arm/mach-sa1100/include/mach/mcp.h | 2 ++ arch/arm/mach-sa1100/lart.c | 1 + arch/arm/mach-sa1100/shannon.c | 1 + arch/arm/mach-sa1100/simpad.c | 8 +++++- drivers/mfd/mcp-core.c | 44 ++++++++++++++++++++++++++++-- drivers/mfd/mcp-sa11x0.c | 7 +++-- drivers/mfd/ucb1x00-core.c | 48 +++++++++++++++++++++++++-------- drivers/mfd/ucb1x00-ts.c | 2 +- include/linux/mfd/mcp.h | 7 +++-- include/linux/mfd/ucb1x00.h | 5 +++- include/linux/mod_devicetable.h | 11 ++++++++ scripts/mod/file2alias.c | 13 +++++++++ 15 files changed, 138 insertions(+), 21 deletions(-) (limited to 'scripts/mod/file2alias.c') diff --git a/arch/arm/mach-sa1100/assabet.c b/arch/arm/mach-sa1100/assabet.c index 3dd133f1841..14b31f116ef 100644 --- a/arch/arm/mach-sa1100/assabet.c +++ b/arch/arm/mach-sa1100/assabet.c @@ -202,6 +202,7 @@ static struct irda_platform_data assabet_irda_data = { static struct mcp_plat_data assabet_mcp_data = { .mccr0 = MCCR0_ADM, .sclk_rate = 11981000, + .codec = "ucb1x00", }; static void __init assabet_init(void) diff --git a/arch/arm/mach-sa1100/cerf.c b/arch/arm/mach-sa1100/cerf.c index 7f3da4b11ec..b7db7cd0830 100644 --- a/arch/arm/mach-sa1100/cerf.c +++ b/arch/arm/mach-sa1100/cerf.c @@ -124,6 +124,7 @@ static void __init cerf_map_io(void) static struct mcp_plat_data cerf_mcp_data = { .mccr0 = MCCR0_ADM, .sclk_rate = 11981000, + .codec = "ucb1x00", }; static void __init cerf_init(void) diff --git a/arch/arm/mach-sa1100/collie.c b/arch/arm/mach-sa1100/collie.c index 2965cc9d424..b0b5efee683 100644 --- a/arch/arm/mach-sa1100/collie.c +++ b/arch/arm/mach-sa1100/collie.c @@ -27,6 +27,7 @@ #include <linux/timer.h> #include <linux/gpio.h> #include <linux/pda_power.h> +#include <linux/mfd/ucb1x00.h> #include <mach/hardware.h> #include <asm/mach-types.h> @@ -85,10 +86,15 @@ static struct scoop_pcmcia_config collie_pcmcia_config = { .num_devs = 1, }; +static struct ucb1x00_plat_data collie_ucb1x00_data = { + .gpio_base = COLLIE_TC35143_GPIO_BASE, +}; + static struct mcp_plat_data collie_mcp_data = { .mccr0 = MCCR0_ADM | MCCR0_ExtClk, .sclk_rate = 9216000, - .gpio_base = COLLIE_TC35143_GPIO_BASE, + .codec = "ucb1x00", + .codec_pdata = &collie_ucb1x00_data, }; /* diff --git a/arch/arm/mach-sa1100/include/mach/mcp.h b/arch/arm/mach-sa1100/include/mach/mcp.h index ed1a331508a..586cec898b3 100644 --- a/arch/arm/mach-sa1100/include/mach/mcp.h +++ b/arch/arm/mach-sa1100/include/mach/mcp.h @@ -17,6 +17,8 @@ struct mcp_plat_data { u32 mccr1; unsigned int sclk_rate; int gpio_base; + const char *codec; + void *codec_pdata; }; #endif diff --git a/arch/arm/mach-sa1100/lart.c b/arch/arm/mach-sa1100/lart.c index 5bc59d0947b..34bbdd986e4 100644 --- a/arch/arm/mach-sa1100/lart.c +++ b/arch/arm/mach-sa1100/lart.c @@ -24,6 +24,7 @@ static struct mcp_plat_data lart_mcp_data = { .mccr0 = MCCR0_ADM, .sclk_rate = 11981000, + .codec = "ucb1x00", }; static void __init lart_init(void) diff --git a/arch/arm/mach-sa1100/shannon.c b/arch/arm/mach-sa1100/shannon.c index 1cccbf5b9e9..252faa5e239 100644 --- a/arch/arm/mach-sa1100/shannon.c +++ b/arch/arm/mach-sa1100/shannon.c @@ -55,6 +55,7 @@ static struct resource shannon_flash_resource = { static struct mcp_plat_data shannon_mcp_data = { .mccr0 = MCCR0_ADM, .sclk_rate = 11981000, + .codec = "ucb1x00", }; static void __init shannon_init(void) diff --git a/arch/arm/mach-sa1100/simpad.c b/arch/arm/mach-sa1100/simpad.c index 4790f3f3d00..7eac8ebab94 100644 --- a/arch/arm/mach-sa1100/simpad.c +++ b/arch/arm/mach-sa1100/simpad.c @@ -14,6 +14,7 @@ #include <linux/mtd/partitions.h> #include <linux/io.h> #include <linux/gpio.h> +#include <linux/mfd/ucb1x00.h> #include <asm/irq.h> #include <mach/hardware.h> @@ -187,10 +188,15 @@ static struct resource simpad_flash_resources [] = { } }; +static struct ucb1x00_plat_data simpad_ucb1x00_data = { + .gpio_base = SIMPAD_UCB1X00_GPIO_BASE, +}; + static struct mcp_plat_data simpad_mcp_data = { .mccr0 = MCCR0_ADM, .sclk_rate = 11981000, - .gpio_base = SIMPAD_UCB1X00_GPIO_BASE, + .codec = "ucb1300", + .codec_pdata = &simpad_ucb1x00_data, }; diff --git a/drivers/mfd/mcp-core.c b/drivers/mfd/mcp-core.c index 84815f9ef63..63be60bc345 100644 --- a/drivers/mfd/mcp-core.c +++ b/drivers/mfd/mcp-core.c @@ -26,9 +26,35 @@ #define to_mcp(d) container_of(d, struct mcp, attached_device) #define to_mcp_driver(d) container_of(d, struct mcp_driver, drv) +static const struct mcp_device_id *mcp_match_id(const struct mcp_device_id *id, + const char *codec) +{ + while (id->name[0]) { + if (strcmp(codec, id->name) == 0) + return id; + id++; + } + return NULL; +} + +const struct mcp_device_id *mcp_get_device_id(const struct mcp *mcp) +{ + const struct mcp_driver *driver = + to_mcp_driver(mcp->attached_device.driver); + + return mcp_match_id(driver->id_table, mcp->codec); +} +EXPORT_SYMBOL(mcp_get_device_id); + static int mcp_bus_match(struct device *dev, struct device_driver *drv) { - return 1; + const struct mcp *mcp = to_mcp(dev); + const struct mcp_driver *driver = to_mcp_driver(drv); + + if (driver->id_table) + return !!mcp_match_id(driver->id_table, mcp->codec); + + return 0; } static int mcp_bus_probe(struct device *dev) @@ -74,9 +100,18 @@ static int mcp_bus_resume(struct device *dev) return ret; } +static int mcp_bus_uevent(struct device *dev, struct kobj_uevent_env *env) +{ + struct mcp *mcp = to_mcp(dev); + + add_uevent_var(env, "MODALIAS=%s%s", MCP_MODULE_PREFIX, mcp->codec); + return 0; +} + static struct bus_type mcp_bus_type = { .name = "mcp", .match = mcp_bus_match, + .uevent = mcp_bus_uevent, .probe = mcp_bus_probe, .remove = mcp_bus_remove, .suspend = mcp_bus_suspend, @@ -212,9 +247,14 @@ struct mcp *mcp_host_alloc(struct device *parent, size_t size) } EXPORT_SYMBOL(mcp_host_alloc); -int mcp_host_register(struct mcp *mcp) +int mcp_host_register(struct mcp *mcp, void *pdata) { + if (!mcp->codec) + return -EINVAL; + + mcp->attached_device.platform_data = pdata; dev_set_name(&mcp->attached_device, "mcp0"); + request_module("%s%s", MCP_MODULE_PREFIX, mcp->codec); return device_register(&mcp->attached_device); } EXPORT_SYMBOL(mcp_host_register); diff --git a/drivers/mfd/mcp-sa11x0.c b/drivers/mfd/mcp-sa11x0.c index 02c53a0766c..da4e077a1be 100644 --- a/drivers/mfd/mcp-sa11x0.c +++ b/drivers/mfd/mcp-sa11x0.c @@ -146,6 +146,9 @@ static int mcp_sa11x0_probe(struct platform_device *pdev) if (!data) return -ENODEV; + if (!data->codec) + return -ENODEV; + if (!request_mem_region(0x80060000, 0x60, "sa11x0-mcp")) return -EBUSY; @@ -162,7 +165,7 @@ static int mcp_sa11x0_probe(struct platform_device *pdev) mcp->dma_audio_wr = DMA_Ser4MCP0Wr; mcp->dma_telco_rd = DMA_Ser4MCP1Rd; mcp->dma_telco_wr = DMA_Ser4MCP1Wr; - mcp->gpio_base = data->gpio_base; + mcp->codec = data->codec; platform_set_drvdata(pdev, mcp); @@ -195,7 +198,7 @@ static int mcp_sa11x0_probe(struct platform_device *pdev) mcp->rw_timeout = (64 * 3 * 1000000 + mcp->sclk_rate - 1) / mcp->sclk_rate; - ret = mcp_host_register(mcp); + ret = mcp_host_register(mcp, data->codec_pdata); if (ret == 0) goto out; diff --git a/drivers/mfd/ucb1x00-core.c b/drivers/mfd/ucb1x00-core.c index b281217334e..91c4f25e0e5 100644 --- a/drivers/mfd/ucb1x00-core.c +++ b/drivers/mfd/ucb1x00-core.c @@ -36,6 +36,15 @@ static DEFINE_MUTEX(ucb1x00_mutex); static LIST_HEAD(ucb1x00_drivers); static LIST_HEAD(ucb1x00_devices); +static struct mcp_device_id ucb1x00_id[] = { + { "ucb1x00", 0 }, /* auto-detection */ + { "ucb1200", UCB_ID_1200 }, + { "ucb1300", UCB_ID_1300 }, + { "tc35143", UCB_ID_TC35143 }, + { } +}; +MODULE_DEVICE_TABLE(mcp, ucb1x00_id); + /** * ucb1x00_io_set_dir - set IO direction * @ucb: UCB1x00 structure describing chip @@ -527,17 +536,33 @@ static struct class ucb1x00_class = { static int ucb1x00_probe(struct mcp *mcp) { + const struct mcp_device_id *mid; struct ucb1x00 *ucb; struct ucb1x00_driver *drv; + struct ucb1x00_plat_data *pdata; unsigned int id; int ret = -ENODEV; int temp; mcp_enable(mcp); id = mcp_reg_read(mcp, UCB_ID); + mid = mcp_get_device_id(mcp); - if (id != UCB_ID_1200 && id != UCB_ID_1300 && id != UCB_ID_TC35143) { - printk(KERN_WARNING "UCB1x00 ID not found: %04x\n", id); + if (mid && mid->driver_data) { + if (id != mid->driver_data) { + printk(KERN_WARNING "%s wrong ID %04x found: %04x\n", + mid->name, (unsigned int) mid->driver_data, id); + goto err_disable; + } + } else { + mid = &ucb1x00_id[1]; + while (mid->driver_data) { + if (id == mid->driver_data) + break; + mid++; + } + printk(KERN_WARNING "%s ID not found: %04x\n", + ucb1x00_id[0].name, id); goto err_disable; } @@ -546,28 +571,28 @@ static int ucb1x00_probe(struct mcp *mcp) if (!ucb) goto err_disable; - + pdata = mcp->attached_device.platform_data; ucb->dev.class = &ucb1x00_class; ucb->dev.parent = &mcp->attached_device; - dev_set_name(&ucb->dev, "ucb1x00"); + dev_set_name(&ucb->dev, mid->name); spin_lock_init(&ucb->lock); spin_lock_init(&ucb->io_lock); sema_init(&ucb->adc_sem, 1); - ucb->id = id; + ucb->id = mid; ucb->mcp = mcp; ucb->irq = ucb1x00_detect_irq(ucb); if (ucb->irq == NO_IRQ) { - printk(KERN_ERR "UCB1x00: IRQ probe failed\n"); + printk(KERN_ERR "%s: IRQ probe failed\n", mid->name); ret = -ENODEV; goto err_free; } ucb->gpio.base = -1; - if (mcp->gpio_base != 0) { + if (pdata && (pdata->gpio_base >= 0)) { ucb->gpio.label = dev_name(&ucb->dev); - ucb->gpio.base = mcp->gpio_base; + ucb->gpio.base = pdata->gpio_base; ucb->gpio.ngpio = 10; ucb->gpio.set = ucb1x00_gpio_set; ucb->gpio.get = ucb1x00_gpio_get; @@ -580,10 +605,10 @@ static int ucb1x00_probe(struct mcp *mcp) dev_info(&ucb->dev, "gpio_base not set so no gpiolib support"); ret = request_irq(ucb->irq, ucb1x00_irq, IRQF_TRIGGER_RISING, - "UCB1x00", ucb); + mid->name, ucb); if (ret) { - printk(KERN_ERR "ucb1x00: unable to grab irq%d: %d\n", - ucb->irq, ret); + printk(KERN_ERR "%s: unable to grab irq%d: %d\n", + mid->name, ucb->irq, ret); goto err_gpio; } @@ -705,6 +730,7 @@ static struct mcp_driver ucb1x00_driver = { .remove = ucb1x00_remove, .suspend = ucb1x00_suspend, .resume = ucb1x00_resume, + .id_table = ucb1x00_id, }; static int __init ucb1x00_init(void) diff --git a/drivers/mfd/ucb1x00-ts.c b/drivers/mfd/ucb1x00-ts.c index 38ffbd50a0d..40ec3c11886 100644 --- a/drivers/mfd/ucb1x00-ts.c +++ b/drivers/mfd/ucb1x00-ts.c @@ -382,7 +382,7 @@ static int ucb1x00_ts_add(struct ucb1x00_dev *dev) ts->adcsync = adcsync ? UCB_SYNC : UCB_NOSYNC; idev->name = "Touchscreen panel"; - idev->id.product = ts->ucb->id; + idev->id.product = ts->ucb->id->driver_data; idev->open = ucb1x00_ts_open; idev->close = ucb1x00_ts_close; diff --git a/include/linux/mfd/mcp.h b/include/linux/mfd/mcp.h index ee496708e38..1515e64e366 100644 --- a/include/linux/mfd/mcp.h +++ b/include/linux/mfd/mcp.h @@ -10,6 +10,7 @@ #ifndef MCP_H #define MCP_H +#include <linux/mod_devicetable.h> #include <mach/dma.h> struct mcp_ops; @@ -26,7 +27,7 @@ struct mcp { dma_device_t dma_telco_rd; dma_device_t dma_telco_wr; struct device attached_device; - int gpio_base; + const char *codec; }; struct mcp_ops { @@ -44,10 +45,11 @@ void mcp_reg_write(struct mcp *, unsigned int, unsigned int); unsigned int mcp_reg_read(struct mcp *, unsigned int); void mcp_enable(struct mcp *); void mcp_disable(struct mcp *); +const struct mcp_device_id *mcp_get_device_id(const struct mcp *mcp); #define mcp_get_sclk_rate(mcp) ((mcp)->sclk_rate) struct mcp *mcp_host_alloc(struct device *, size_t); -int mcp_host_register(struct mcp *); +int mcp_host_register(struct mcp *, void *); void mcp_host_unregister(struct mcp *); struct mcp_driver { @@ -56,6 +58,7 @@ struct mcp_driver { void (*remove)(struct mcp *); int (*suspend)(struct mcp *, pm_message_t); int (*resume)(struct mcp *); + const struct mcp_device_id *id_table; }; int mcp_driver_register(struct mcp_driver *); diff --git a/include/linux/mfd/ucb1x00.h b/include/linux/mfd/ucb1x00.h index 4321f044d1e..bc19e5fb7ea 100644 --- a/include/linux/mfd/ucb1x00.h +++ b/include/linux/mfd/ucb1x00.h @@ -104,6 +104,9 @@ #define UCB_MODE_DYN_VFLAG_ENA (1 << 12) #define UCB_MODE_AUD_OFF_CAN (1 << 13) +struct ucb1x00_plat_data { + int gpio_base; +}; struct ucb1x00_irq { void *devid; @@ -116,7 +119,7 @@ struct ucb1x00 { unsigned int irq; struct semaphore adc_sem; spinlock_t io_lock; - u16 id; + const struct mcp_device_id *id; u16 io_dir; u16 io_out; u16 adc_cr; diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h index 468819cdde8..bc50d9a80d8 100644 --- a/include/linux/mod_devicetable.h +++ b/include/linux/mod_devicetable.h @@ -436,6 +436,17 @@ struct spi_device_id { __attribute__((aligned(sizeof(kernel_ulong_t)))); }; +/* mcp */ + +#define MCP_NAME_SIZE 20 +#define MCP_MODULE_PREFIX "mcp:" + +struct mcp_device_id { + char name[MCP_NAME_SIZE]; + kernel_ulong_t driver_data /* Data private to the driver */ + __attribute__((aligned(sizeof(kernel_ulong_t)))); +}; + /* dmi */ enum dmi_field { DMI_NONE, diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c index f936d1fa969..e8c7eb16c0e 100644 --- a/scripts/mod/file2alias.c +++ b/scripts/mod/file2alias.c @@ -774,6 +774,15 @@ static int do_spi_entry(const char *filename, struct spi_device_id *id, return 1; } +/* Looks like: mcp:S */ +static int do_mcp_entry(const char *filename, struct mcp_device_id *id, + char *alias) +{ + sprintf(alias, MCP_MODULE_PREFIX "%s", id->name); + + return 1; +} + static const struct dmifield { const char *prefix; int field; @@ -1027,6 +1036,10 @@ void handle_moddevtable(struct module *mod, struct elf_info *info, do_table(symval, sym->st_size, sizeof(struct spi_device_id), "spi", do_spi_entry, mod); + else if (sym_is(symname, "__mod_mcp_device_table")) + do_table(symval, sym->st_size, + sizeof(struct mcp_device_id), "mcp", + do_mcp_entry, mod); else if (sym_is(symname, "__mod_dmi_device_table")) do_table(symval, sym->st_size, sizeof(struct dmi_system_id), "dmi", -- cgit v1.2.3-70-g09d2 From 626596e295d477c0fefa08cd5daa7dd011b1bb2c Mon Sep 17 00:00:00 2001 From: Rusty Russell <rusty@rustcorp.com.au> Date: Fri, 13 Jan 2012 09:32:15 +1030 Subject: modpost: use a table rather than a giant if/else statement. We look for symbols of form __mod_<busname>_device_table, and for all but three cases we use a standard interation function (do_table) to walk over the contents and dump out the aliases. Alessandro Rubini did this first, I just repainted the bikeshed a bit. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> Cc: Alessandro Rubini <rubini@gnudd.com> --- scripts/mod/file2alias.c | 192 ++++++++++++++++++----------------------------- 1 file changed, 73 insertions(+), 119 deletions(-) (limited to 'scripts/mod/file2alias.c') diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c index 363ab4666b1..395e7479bcf 100644 --- a/scripts/mod/file2alias.c +++ b/scripts/mod/file2alias.c @@ -28,6 +28,7 @@ typedef Elf64_Addr kernel_ulong_t; #endif #include <ctype.h> +#include <stdbool.h> typedef uint32_t __u32; typedef uint16_t __u16; @@ -948,15 +949,13 @@ static int do_amba_entry(const char *filename, return 1; } -/* Ignore any prefix, eg. some architectures prepend _ */ -static inline int sym_is(const char *symbol, const char *name) +/* Does namelen bytes of name exactly match the symbol? */ +static bool sym_is(const char *name, unsigned namelen, const char *symbol) { - const char *match; + if (namelen != strlen(symbol)) + return false; - match = strstr(symbol, name); - if (!match) - return 0; - return match[strlen(name)] == '\0'; + return memcmp(name, symbol, namelen) == 0; } static void do_table(void *symval, unsigned long size, @@ -981,6 +980,43 @@ static void do_table(void *symval, unsigned long size, } } +/* This array collects all instances that use the generic do_table above */ +struct devtable_switch { + const char *device_id; /* name of table, __mod_<name>_device_table. */ + unsigned long id_size; + void *function; +}; + +static const struct devtable_switch devtable_switch[] = { + { "acpi", sizeof(struct acpi_device_id), do_acpi_entry }, + { "amba", sizeof(struct amba_id), do_amba_entry }, + { "ap", sizeof(struct ap_device_id), do_ap_entry }, + { "bcma", sizeof(struct bcma_device_id), do_bcma_entry }, + { "ccw", sizeof(struct ccw_device_id), do_ccw_entry }, + { "css", sizeof(struct css_device_id), do_css_entry }, + { "dmi", sizeof(struct dmi_system_id), do_dmi_entry }, + { "eisa", sizeof(struct eisa_device_id), do_eisa_entry }, + { "hid", sizeof(struct hid_device_id), do_hid_entry }, + { "i2c", sizeof(struct i2c_device_id), do_i2c_entry }, + { "ieee1394", sizeof(struct ieee1394_device_id), do_ieee1394_entry }, + { "input", sizeof(struct input_device_id), do_input_entry }, + { "isa", sizeof(struct isapnp_device_id), do_isapnp_entry }, + { "mdio", sizeof(struct mdio_device_id), do_mdio_entry }, + { "of", sizeof(struct of_device_id), do_of_entry }, + { "parisc", sizeof(struct parisc_device_id), do_parisc_entry }, + { "pci", sizeof(struct pci_device_id), do_pci_entry }, + { "pcmcia", sizeof(struct pcmcia_device_id), do_pcmcia_entry }, + { "platform", sizeof(struct platform_device_id), do_platform_entry }, + { "sdio", sizeof(struct sdio_device_id), do_sdio_entry }, + { "serio", sizeof(struct serio_device_id), do_serio_entry }, + { "spi", sizeof(struct spi_device_id), do_spi_entry }, + { "ssb", sizeof(struct ssb_device_id), do_ssb_entry }, + { "vio", sizeof(struct vio_device_id), do_vio_entry }, + { "virtio", sizeof(struct virtio_device_id), do_virtio_entry }, + { "vmbus", sizeof(struct hv_vmbus_device_id), do_vmbus_entry }, + { "zorro", sizeof(struct zorro_device_id), do_zorro_entry }, +}; + /* Create MODULE_ALIAS() statements. * At this time, we cannot write the actual output C source yet, * so we write into the mod->dev_table_buf buffer. */ @@ -989,11 +1025,25 @@ void handle_moddevtable(struct module *mod, struct elf_info *info, { void *symval; char *zeros = NULL; + const char *name; + unsigned int namelen; /* We're looking for a section relative symbol */ if (!sym->st_shndx || get_secindex(info, sym) >= info->num_sections) return; + /* All our symbols are of form <prefix>__mod_XXX_device_table. */ + name = strstr(symname, "__mod_"); + if (!name) + return; + name += strlen("__mod_"); + namelen = strlen(name); + if (namelen < strlen("_device_table")) + return; + if (strcmp(name + namelen - strlen("_device_table"), "_device_table")) + return; + namelen -= strlen("_device_table"); + /* Handle all-NULL symbols allocated into .bss */ if (info->sechdrs[get_secindex(info, sym)].sh_type & SHT_NOBITS) { zeros = calloc(1, sym->st_size); @@ -1004,121 +1054,25 @@ void handle_moddevtable(struct module *mod, struct elf_info *info, + sym->st_value; } - if (sym_is(symname, "__mod_pci_device_table")) - do_table(symval, sym->st_size, - sizeof(struct pci_device_id), "pci", - do_pci_entry, mod); - else if (sym_is(symname, "__mod_usb_device_table")) - /* special case to handle bcdDevice ranges */ + /* First handle the "special" cases */ + if (sym_is(name, namelen, "usb")) do_usb_table(symval, sym->st_size, mod); - else if (sym_is(symname, "__mod_hid_device_table")) - do_table(symval, sym->st_size, - sizeof(struct hid_device_id), "hid", - do_hid_entry, mod); - else if (sym_is(symname, "__mod_ieee1394_device_table")) - do_table(symval, sym->st_size, - sizeof(struct ieee1394_device_id), "ieee1394", - do_ieee1394_entry, mod); - else if (sym_is(symname, "__mod_ccw_device_table")) - do_table(symval, sym->st_size, - sizeof(struct ccw_device_id), "ccw", - do_ccw_entry, mod); - else if (sym_is(symname, "__mod_ap_device_table")) - do_table(symval, sym->st_size, - sizeof(struct ap_device_id), "ap", - do_ap_entry, mod); - else if (sym_is(symname, "__mod_css_device_table")) - do_table(symval, sym->st_size, - sizeof(struct css_device_id), "css", - do_css_entry, mod); - else if (sym_is(symname, "__mod_serio_device_table")) - do_table(symval, sym->st_size, - sizeof(struct serio_device_id), "serio", - do_serio_entry, mod); - else if (sym_is(symname, "__mod_acpi_device_table")) - do_table(symval, sym->st_size, - sizeof(struct acpi_device_id), "acpi", - do_acpi_entry, mod); - else if (sym_is(symname, "__mod_pnp_device_table")) + else if (sym_is(name, namelen, "pnp")) do_pnp_device_entry(symval, sym->st_size, mod); - else if (sym_is(symname, "__mod_pnp_card_device_table")) + else if (sym_is(name, namelen, "pnp_card")) do_pnp_card_entries(symval, sym->st_size, mod); - else if (sym_is(symname, "__mod_pcmcia_device_table")) - do_table(symval, sym->st_size, - sizeof(struct pcmcia_device_id), "pcmcia", - do_pcmcia_entry, mod); - else if (sym_is(symname, "__mod_of_device_table")) - do_table(symval, sym->st_size, - sizeof(struct of_device_id), "of", - do_of_entry, mod); - else if (sym_is(symname, "__mod_vio_device_table")) - do_table(symval, sym->st_size, - sizeof(struct vio_device_id), "vio", - do_vio_entry, mod); - else if (sym_is(symname, "__mod_input_device_table")) - do_table(symval, sym->st_size, - sizeof(struct input_device_id), "input", - do_input_entry, mod); - else if (sym_is(symname, "__mod_eisa_device_table")) - do_table(symval, sym->st_size, - sizeof(struct eisa_device_id), "eisa", - do_eisa_entry, mod); - else if (sym_is(symname, "__mod_parisc_device_table")) - do_table(symval, sym->st_size, - sizeof(struct parisc_device_id), "parisc", - do_parisc_entry, mod); - else if (sym_is(symname, "__mod_sdio_device_table")) - do_table(symval, sym->st_size, - sizeof(struct sdio_device_id), "sdio", - do_sdio_entry, mod); - else if (sym_is(symname, "__mod_ssb_device_table")) - do_table(symval, sym->st_size, - sizeof(struct ssb_device_id), "ssb", - do_ssb_entry, mod); - else if (sym_is(symname, "__mod_bcma_device_table")) - do_table(symval, sym->st_size, - sizeof(struct bcma_device_id), "bcma", - do_bcma_entry, mod); - else if (sym_is(symname, "__mod_virtio_device_table")) - do_table(symval, sym->st_size, - sizeof(struct virtio_device_id), "virtio", - do_virtio_entry, mod); - else if (sym_is(symname, "__mod_vmbus_device_table")) - do_table(symval, sym->st_size, - sizeof(struct hv_vmbus_device_id), "vmbus", - do_vmbus_entry, mod); - else if (sym_is(symname, "__mod_i2c_device_table")) - do_table(symval, sym->st_size, - sizeof(struct i2c_device_id), "i2c", - do_i2c_entry, mod); - else if (sym_is(symname, "__mod_spi_device_table")) - do_table(symval, sym->st_size, - sizeof(struct spi_device_id), "spi", - do_spi_entry, mod); - else if (sym_is(symname, "__mod_dmi_device_table")) - do_table(symval, sym->st_size, - sizeof(struct dmi_system_id), "dmi", - do_dmi_entry, mod); - else if (sym_is(symname, "__mod_platform_device_table")) - do_table(symval, sym->st_size, - sizeof(struct platform_device_id), "platform", - do_platform_entry, mod); - else if (sym_is(symname, "__mod_mdio_device_table")) - do_table(symval, sym->st_size, - sizeof(struct mdio_device_id), "mdio", - do_mdio_entry, mod); - else if (sym_is(symname, "__mod_zorro_device_table")) - do_table(symval, sym->st_size, - sizeof(struct zorro_device_id), "zorro", - do_zorro_entry, mod); - else if (sym_is(symname, "__mod_isapnp_device_table")) - do_table(symval, sym->st_size, - sizeof(struct isapnp_device_id), "isa", - do_isapnp_entry, mod); - else if (sym_is(symname, "__mod_amba_device_table")) - do_table(symval, sym->st_size, - sizeof(struct amba_id), "amba", - do_amba_entry, mod); + else { + const struct devtable_switch *p = devtable_switch; + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(devtable_switch); i++, p++) { + if (sym_is(name, namelen, p->device_id)) { + do_table(symval, sym->st_size, p->id_size, + p->device_id, p->function, mod); + break; + } + } + } free(zeros); } -- cgit v1.2.3-70-g09d2 From e49ce14150c64b29a8dd211df785576fa19a9858 Mon Sep 17 00:00:00 2001 From: Rusty Russell <rusty@rustcorp.com.au> Date: Fri, 13 Jan 2012 09:32:16 +1030 Subject: modpost: use linker section to generate table. This means (most) future busses need only have one hunk in their patch. Also took the opportunity to check that function matches the type. Again, inspired by Alessandro's patch series. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> Cc: Alessandro Rubini <rubini@gnudd.com> --- scripts/mod/file2alias.c | 106 +++++++++++++++++++++++++++-------------------- 1 file changed, 61 insertions(+), 45 deletions(-) (limited to 'scripts/mod/file2alias.c') diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c index 395e7479bcf..e8c96957776 100644 --- a/scripts/mod/file2alias.c +++ b/scripts/mod/file2alias.c @@ -39,6 +39,35 @@ typedef unsigned char __u8; * we handle those differences explicitly below */ #include "../../include/linux/mod_devicetable.h" +/* This array collects all instances that use the generic do_table */ +struct devtable { + const char *device_id; /* name of table, __mod_<name>_device_table. */ + unsigned long id_size; + void *function; +}; + +/* We construct a table of pointers in an ELF section (pointers generally + * go unpadded by gcc). ld creates boundary syms for us. */ +extern struct devtable *__start___devtable[], *__stop___devtable[]; +#define ___cat(a,b) a ## b +#define __cat(a,b) ___cat(a,b) + +#if __GNUC__ == 3 && __GNUC_MINOR__ < 3 +# define __used __attribute__((__unused__)) +#else +# define __used __attribute__((__used__)) +#endif + +/* Add a table entry. We test function type matches while we're here. */ +#define ADD_TO_DEVTABLE(device_id, type, function) \ + static struct devtable __cat(devtable,__LINE__) = { \ + device_id + 0*sizeof((function)((const char *)NULL, \ + (type *)NULL, \ + (char *)NULL)), \ + sizeof(type), (function) }; \ + static struct devtable *__attribute__((section("__devtable"))) \ + __used __cat(devtable_ptr,__LINE__) = &__cat(devtable,__LINE__) + #define ADD(str, sep, cond, field) \ do { \ strcat(str, sep); \ @@ -290,6 +319,7 @@ static int do_hid_entry(const char *filename, return 1; } +ADD_TO_DEVTABLE("hid", struct hid_device_id, do_hid_entry); /* Looks like: ieee1394:venNmoNspNverN */ static int do_ieee1394_entry(const char *filename, @@ -314,6 +344,7 @@ static int do_ieee1394_entry(const char *filename, add_wildcard(alias); return 1; } +ADD_TO_DEVTABLE("ieee1394", struct ieee1394_device_id, do_ieee1394_entry); /* Looks like: pci:vNdNsvNsdNbcNscNiN. */ static int do_pci_entry(const char *filename, @@ -357,6 +388,7 @@ static int do_pci_entry(const char *filename, add_wildcard(alias); return 1; } +ADD_TO_DEVTABLE("pci", struct pci_device_id, do_pci_entry); /* looks like: "ccw:tNmNdtNdmN" */ static int do_ccw_entry(const char *filename, @@ -380,6 +412,7 @@ static int do_ccw_entry(const char *filename, add_wildcard(alias); return 1; } +ADD_TO_DEVTABLE("ccw", struct ccw_device_id, do_ccw_entry); /* looks like: "ap:tN" */ static int do_ap_entry(const char *filename, @@ -388,6 +421,7 @@ static int do_ap_entry(const char *filename, sprintf(alias, "ap:t%02X*", id->dev_type); return 1; } +ADD_TO_DEVTABLE("ap", struct ap_device_id, do_ap_entry); /* looks like: "css:tN" */ static int do_css_entry(const char *filename, @@ -396,6 +430,7 @@ static int do_css_entry(const char *filename, sprintf(alias, "css:t%01X", id->type); return 1; } +ADD_TO_DEVTABLE("css", struct css_device_id, do_css_entry); /* Looks like: "serio:tyNprNidNexN" */ static int do_serio_entry(const char *filename, @@ -415,6 +450,7 @@ static int do_serio_entry(const char *filename, add_wildcard(alias); return 1; } +ADD_TO_DEVTABLE("serio", struct serio_device_id, do_serio_entry); /* looks like: "acpi:ACPI0003 or acpi:PNP0C0B" or "acpi:LNXVIDEO" */ static int do_acpi_entry(const char *filename, @@ -423,6 +459,7 @@ static int do_acpi_entry(const char *filename, sprintf(alias, "acpi*:%s:*", id->id); return 1; } +ADD_TO_DEVTABLE("acpi", struct acpi_device_id, do_acpi_entry); /* looks like: "pnp:dD" */ static void do_pnp_device_entry(void *symval, unsigned long size, @@ -545,8 +582,7 @@ static int do_pcmcia_entry(const char *filename, add_wildcard(alias); return 1; } - - +ADD_TO_DEVTABLE("pcmcia", struct pcmcia_device_id, do_pcmcia_entry); static int do_of_entry (const char *filename, struct of_device_id *of, char *alias) { @@ -569,6 +605,7 @@ static int do_of_entry (const char *filename, struct of_device_id *of, char *ali add_wildcard(alias); return 1; } +ADD_TO_DEVTABLE("of", struct of_device_id, do_of_entry); static int do_vio_entry(const char *filename, struct vio_device_id *vio, char *alias) @@ -586,6 +623,7 @@ static int do_vio_entry(const char *filename, struct vio_device_id *vio, add_wildcard(alias); return 1; } +ADD_TO_DEVTABLE("vio", struct vio_device_id, do_vio_entry); #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) @@ -641,6 +679,7 @@ static int do_input_entry(const char *filename, struct input_device_id *id, do_input(alias, id->swbit, 0, INPUT_DEVICE_ID_SW_MAX); return 1; } +ADD_TO_DEVTABLE("input", struct input_device_id, do_input_entry); static int do_eisa_entry(const char *filename, struct eisa_device_id *eisa, char *alias) @@ -651,6 +690,7 @@ static int do_eisa_entry(const char *filename, struct eisa_device_id *eisa, strcat(alias, "*"); return 1; } +ADD_TO_DEVTABLE("eisa", struct eisa_device_id, do_eisa_entry); /* Looks like: parisc:tNhvNrevNsvN */ static int do_parisc_entry(const char *filename, struct parisc_device_id *id, @@ -670,6 +710,7 @@ static int do_parisc_entry(const char *filename, struct parisc_device_id *id, add_wildcard(alias); return 1; } +ADD_TO_DEVTABLE("parisc", struct parisc_device_id, do_parisc_entry); /* Looks like: sdio:cNvNdN. */ static int do_sdio_entry(const char *filename, @@ -686,6 +727,7 @@ static int do_sdio_entry(const char *filename, add_wildcard(alias); return 1; } +ADD_TO_DEVTABLE("sdio", struct sdio_device_id, do_sdio_entry); /* Looks like: ssb:vNidNrevN. */ static int do_ssb_entry(const char *filename, @@ -702,6 +744,7 @@ static int do_ssb_entry(const char *filename, add_wildcard(alias); return 1; } +ADD_TO_DEVTABLE("ssb", struct ssb_device_id, do_ssb_entry); /* Looks like: bcma:mNidNrevNclN. */ static int do_bcma_entry(const char *filename, @@ -720,6 +763,7 @@ static int do_bcma_entry(const char *filename, add_wildcard(alias); return 1; } +ADD_TO_DEVTABLE("bcma", struct bcma_device_id, do_bcma_entry); /* Looks like: virtio:dNvN */ static int do_virtio_entry(const char *filename, struct virtio_device_id *id, @@ -735,6 +779,7 @@ static int do_virtio_entry(const char *filename, struct virtio_device_id *id, add_wildcard(alias); return 1; } +ADD_TO_DEVTABLE("virtio", struct virtio_device_id, do_virtio_entry); /* * Looks like: vmbus:guid @@ -756,6 +801,7 @@ static int do_vmbus_entry(const char *filename, struct hv_vmbus_device_id *id, return 1; } +ADD_TO_DEVTABLE("vmbus", struct hv_vmbus_device_id, do_vmbus_entry); /* Looks like: i2c:S */ static int do_i2c_entry(const char *filename, struct i2c_device_id *id, @@ -765,6 +811,7 @@ static int do_i2c_entry(const char *filename, struct i2c_device_id *id, return 1; } +ADD_TO_DEVTABLE("i2c", struct i2c_device_id, do_i2c_entry); /* Looks like: spi:S */ static int do_spi_entry(const char *filename, struct spi_device_id *id, @@ -774,6 +821,7 @@ static int do_spi_entry(const char *filename, struct spi_device_id *id, return 1; } +ADD_TO_DEVTABLE("spi", struct spi_device_id, do_spi_entry); static const struct dmifield { const char *prefix; @@ -828,6 +876,7 @@ static int do_dmi_entry(const char *filename, struct dmi_system_id *id, strcat(alias, ":"); return 1; } +ADD_TO_DEVTABLE("dmi", struct dmi_system_id, do_dmi_entry); static int do_platform_entry(const char *filename, struct platform_device_id *id, char *alias) @@ -835,6 +884,7 @@ static int do_platform_entry(const char *filename, sprintf(alias, PLATFORM_MODULE_PREFIX "%s", id->name); return 1; } +ADD_TO_DEVTABLE("platform", struct platform_device_id, do_platform_entry); static int do_mdio_entry(const char *filename, struct mdio_device_id *id, char *alias) @@ -857,6 +907,7 @@ static int do_mdio_entry(const char *filename, return 1; } +ADD_TO_DEVTABLE("mdio", struct mdio_device_id, do_mdio_entry); /* Looks like: zorro:iN. */ static int do_zorro_entry(const char *filename, struct zorro_device_id *id, @@ -867,6 +918,7 @@ static int do_zorro_entry(const char *filename, struct zorro_device_id *id, ADD(alias, "i", id->id != ZORRO_WILDCARD, id->id); return 1; } +ADD_TO_DEVTABLE("zorro", struct zorro_device_id, do_zorro_entry); /* looks like: "pnp:dD" */ static int do_isapnp_entry(const char *filename, @@ -880,6 +932,7 @@ static int do_isapnp_entry(const char *filename, (id->function >> 12) & 0x0f, (id->function >> 8) & 0x0f); return 1; } +ADD_TO_DEVTABLE("isa", struct isapnp_device_id, do_isapnp_entry); /* * Append a match expression for a single masked hex digit. @@ -948,6 +1001,7 @@ static int do_amba_entry(const char *filename, return 1; } +ADD_TO_DEVTABLE("amba", struct amba_id, do_amba_entry); /* Does namelen bytes of name exactly match the symbol? */ static bool sym_is(const char *name, unsigned namelen, const char *symbol) @@ -980,43 +1034,6 @@ static void do_table(void *symval, unsigned long size, } } -/* This array collects all instances that use the generic do_table above */ -struct devtable_switch { - const char *device_id; /* name of table, __mod_<name>_device_table. */ - unsigned long id_size; - void *function; -}; - -static const struct devtable_switch devtable_switch[] = { - { "acpi", sizeof(struct acpi_device_id), do_acpi_entry }, - { "amba", sizeof(struct amba_id), do_amba_entry }, - { "ap", sizeof(struct ap_device_id), do_ap_entry }, - { "bcma", sizeof(struct bcma_device_id), do_bcma_entry }, - { "ccw", sizeof(struct ccw_device_id), do_ccw_entry }, - { "css", sizeof(struct css_device_id), do_css_entry }, - { "dmi", sizeof(struct dmi_system_id), do_dmi_entry }, - { "eisa", sizeof(struct eisa_device_id), do_eisa_entry }, - { "hid", sizeof(struct hid_device_id), do_hid_entry }, - { "i2c", sizeof(struct i2c_device_id), do_i2c_entry }, - { "ieee1394", sizeof(struct ieee1394_device_id), do_ieee1394_entry }, - { "input", sizeof(struct input_device_id), do_input_entry }, - { "isa", sizeof(struct isapnp_device_id), do_isapnp_entry }, - { "mdio", sizeof(struct mdio_device_id), do_mdio_entry }, - { "of", sizeof(struct of_device_id), do_of_entry }, - { "parisc", sizeof(struct parisc_device_id), do_parisc_entry }, - { "pci", sizeof(struct pci_device_id), do_pci_entry }, - { "pcmcia", sizeof(struct pcmcia_device_id), do_pcmcia_entry }, - { "platform", sizeof(struct platform_device_id), do_platform_entry }, - { "sdio", sizeof(struct sdio_device_id), do_sdio_entry }, - { "serio", sizeof(struct serio_device_id), do_serio_entry }, - { "spi", sizeof(struct spi_device_id), do_spi_entry }, - { "ssb", sizeof(struct ssb_device_id), do_ssb_entry }, - { "vio", sizeof(struct vio_device_id), do_vio_entry }, - { "virtio", sizeof(struct virtio_device_id), do_virtio_entry }, - { "vmbus", sizeof(struct hv_vmbus_device_id), do_vmbus_entry }, - { "zorro", sizeof(struct zorro_device_id), do_zorro_entry }, -}; - /* Create MODULE_ALIAS() statements. * At this time, we cannot write the actual output C source yet, * so we write into the mod->dev_table_buf buffer. */ @@ -1062,13 +1079,12 @@ void handle_moddevtable(struct module *mod, struct elf_info *info, else if (sym_is(name, namelen, "pnp_card")) do_pnp_card_entries(symval, sym->st_size, mod); else { - const struct devtable_switch *p = devtable_switch; - unsigned int i; + struct devtable **p; - for (i = 0; i < ARRAY_SIZE(devtable_switch); i++, p++) { - if (sym_is(name, namelen, p->device_id)) { - do_table(symval, sym->st_size, p->id_size, - p->device_id, p->function, mod); + for (p = __start___devtable; p < __stop___devtable; p++) { + if (sym_is(name, namelen, (*p)->device_id)) { + do_table(symval, sym->st_size, (*p)->id_size, + (*p)->device_id, (*p)->function, mod); break; } } -- cgit v1.2.3-70-g09d2 From 65f2e753f1eb09d3a7e2a0d16408a5433b4097b2 Mon Sep 17 00:00:00 2001 From: Russell King <rmk+kernel@arm.linux.org.uk> Date: Fri, 20 Jan 2012 17:38:58 +0000 Subject: Revert "ARM: sa11x0: Implement autoloading of codec and codec pdata for mcp bus." This reverts commit 5dd7bf59e0e8563265b3e5b33276099ef628fcc7. Conflicts: scripts/mod/file2alias.c This change is wrong on many levels. First and foremost, it causes a regression. On boot on Assabet, which this patch gives a codec id of 'ucb1x00', it gives: ucb1x00 ID not found: 1005 0x1005 is a valid ID for the UCB1300 device. Secondly, this patch is way over the top in terms of complexity. The only device which has been seen to be connected with this MCP code is the UCB1x00 (UCB1200, UCB1300 etc) devices, and they all use the same driver. Adding a match table, requiring the codec string to match the hardware ID read out of the ID register, etc is completely over the top when we can just read the hardware ID register. --- arch/arm/mach-sa1100/assabet.c | 1 - arch/arm/mach-sa1100/cerf.c | 1 - arch/arm/mach-sa1100/collie.c | 8 +----- arch/arm/mach-sa1100/include/mach/mcp.h | 2 -- arch/arm/mach-sa1100/lart.c | 1 - arch/arm/mach-sa1100/shannon.c | 1 - arch/arm/mach-sa1100/simpad.c | 8 +----- drivers/mfd/mcp-core.c | 44 ++---------------------------- drivers/mfd/mcp-sa11x0.c | 7 ++--- drivers/mfd/ucb1x00-core.c | 48 ++++++++------------------------- drivers/mfd/ucb1x00-ts.c | 2 +- include/linux/mfd/mcp.h | 7 ++--- include/linux/mfd/ucb1x00.h | 5 +--- include/linux/mod_devicetable.h | 11 -------- scripts/mod/file2alias.c | 10 ------- 15 files changed, 21 insertions(+), 135 deletions(-) (limited to 'scripts/mod/file2alias.c') diff --git a/arch/arm/mach-sa1100/assabet.c b/arch/arm/mach-sa1100/assabet.c index d8aa1c28353..0c4b76ab4d8 100644 --- a/arch/arm/mach-sa1100/assabet.c +++ b/arch/arm/mach-sa1100/assabet.c @@ -202,7 +202,6 @@ static struct irda_platform_data assabet_irda_data = { static struct mcp_plat_data assabet_mcp_data = { .mccr0 = MCCR0_ADM, .sclk_rate = 11981000, - .codec = "ucb1x00", }; static void __init assabet_init(void) diff --git a/arch/arm/mach-sa1100/cerf.c b/arch/arm/mach-sa1100/cerf.c index fcadc4cafe9..11bb6d0b9be 100644 --- a/arch/arm/mach-sa1100/cerf.c +++ b/arch/arm/mach-sa1100/cerf.c @@ -124,7 +124,6 @@ static void __init cerf_map_io(void) static struct mcp_plat_data cerf_mcp_data = { .mccr0 = MCCR0_ADM, .sclk_rate = 11981000, - .codec = "ucb1x00", }; static void __init cerf_init(void) diff --git a/arch/arm/mach-sa1100/collie.c b/arch/arm/mach-sa1100/collie.c index 6b7c74b304c..b9060e236de 100644 --- a/arch/arm/mach-sa1100/collie.c +++ b/arch/arm/mach-sa1100/collie.c @@ -27,7 +27,6 @@ #include <linux/timer.h> #include <linux/gpio.h> #include <linux/pda_power.h> -#include <linux/mfd/ucb1x00.h> #include <mach/hardware.h> #include <asm/mach-types.h> @@ -86,15 +85,10 @@ static struct scoop_pcmcia_config collie_pcmcia_config = { .num_devs = 1, }; -static struct ucb1x00_plat_data collie_ucb1x00_data = { - .gpio_base = COLLIE_TC35143_GPIO_BASE, -}; - static struct mcp_plat_data collie_mcp_data = { .mccr0 = MCCR0_ADM | MCCR0_ExtClk, .sclk_rate = 9216000, - .codec = "ucb1x00", - .codec_pdata = &collie_ucb1x00_data, + .gpio_base = COLLIE_TC35143_GPIO_BASE, }; /* diff --git a/arch/arm/mach-sa1100/include/mach/mcp.h b/arch/arm/mach-sa1100/include/mach/mcp.h index 586cec898b3..ed1a331508a 100644 --- a/arch/arm/mach-sa1100/include/mach/mcp.h +++ b/arch/arm/mach-sa1100/include/mach/mcp.h @@ -17,8 +17,6 @@ struct mcp_plat_data { u32 mccr1; unsigned int sclk_rate; int gpio_base; - const char *codec; - void *codec_pdata; }; #endif diff --git a/arch/arm/mach-sa1100/lart.c b/arch/arm/mach-sa1100/lart.c index 48a8f4ef0fc..af4e2761f3d 100644 --- a/arch/arm/mach-sa1100/lart.c +++ b/arch/arm/mach-sa1100/lart.c @@ -24,7 +24,6 @@ static struct mcp_plat_data lart_mcp_data = { .mccr0 = MCCR0_ADM, .sclk_rate = 11981000, - .codec = "ucb1x00", }; static void __init lart_init(void) diff --git a/arch/arm/mach-sa1100/shannon.c b/arch/arm/mach-sa1100/shannon.c index 3807c913527..318b2b766a0 100644 --- a/arch/arm/mach-sa1100/shannon.c +++ b/arch/arm/mach-sa1100/shannon.c @@ -55,7 +55,6 @@ static struct resource shannon_flash_resource = { static struct mcp_plat_data shannon_mcp_data = { .mccr0 = MCCR0_ADM, .sclk_rate = 11981000, - .codec = "ucb1x00", }; static void __init shannon_init(void) diff --git a/arch/arm/mach-sa1100/simpad.c b/arch/arm/mach-sa1100/simpad.c index d9b765c441f..e17c04d6e32 100644 --- a/arch/arm/mach-sa1100/simpad.c +++ b/arch/arm/mach-sa1100/simpad.c @@ -14,7 +14,6 @@ #include <linux/mtd/partitions.h> #include <linux/io.h> #include <linux/gpio.h> -#include <linux/mfd/ucb1x00.h> #include <asm/irq.h> #include <mach/hardware.h> @@ -188,15 +187,10 @@ static struct resource simpad_flash_resources [] = { } }; -static struct ucb1x00_plat_data simpad_ucb1x00_data = { - .gpio_base = SIMPAD_UCB1X00_GPIO_BASE, -}; - static struct mcp_plat_data simpad_mcp_data = { .mccr0 = MCCR0_ADM, .sclk_rate = 11981000, - .codec = "ucb1300", - .codec_pdata = &simpad_ucb1x00_data, + .gpio_base = SIMPAD_UCB1X00_GPIO_BASE, }; diff --git a/drivers/mfd/mcp-core.c b/drivers/mfd/mcp-core.c index 63be60bc345..84815f9ef63 100644 --- a/drivers/mfd/mcp-core.c +++ b/drivers/mfd/mcp-core.c @@ -26,35 +26,9 @@ #define to_mcp(d) container_of(d, struct mcp, attached_device) #define to_mcp_driver(d) container_of(d, struct mcp_driver, drv) -static const struct mcp_device_id *mcp_match_id(const struct mcp_device_id *id, - const char *codec) -{ - while (id->name[0]) { - if (strcmp(codec, id->name) == 0) - return id; - id++; - } - return NULL; -} - -const struct mcp_device_id *mcp_get_device_id(const struct mcp *mcp) -{ - const struct mcp_driver *driver = - to_mcp_driver(mcp->attached_device.driver); - - return mcp_match_id(driver->id_table, mcp->codec); -} -EXPORT_SYMBOL(mcp_get_device_id); - static int mcp_bus_match(struct device *dev, struct device_driver *drv) { - const struct mcp *mcp = to_mcp(dev); - const struct mcp_driver *driver = to_mcp_driver(drv); - - if (driver->id_table) - return !!mcp_match_id(driver->id_table, mcp->codec); - - return 0; + return 1; } static int mcp_bus_probe(struct device *dev) @@ -100,18 +74,9 @@ static int mcp_bus_resume(struct device *dev) return ret; } -static int mcp_bus_uevent(struct device *dev, struct kobj_uevent_env *env) -{ - struct mcp *mcp = to_mcp(dev); - - add_uevent_var(env, "MODALIAS=%s%s", MCP_MODULE_PREFIX, mcp->codec); - return 0; -} - static struct bus_type mcp_bus_type = { .name = "mcp", .match = mcp_bus_match, - .uevent = mcp_bus_uevent, .probe = mcp_bus_probe, .remove = mcp_bus_remove, .suspend = mcp_bus_suspend, @@ -247,14 +212,9 @@ struct mcp *mcp_host_alloc(struct device *parent, size_t size) } EXPORT_SYMBOL(mcp_host_alloc); -int mcp_host_register(struct mcp *mcp, void *pdata) +int mcp_host_register(struct mcp *mcp) { - if (!mcp->codec) - return -EINVAL; - - mcp->attached_device.platform_data = pdata; dev_set_name(&mcp->attached_device, "mcp0"); - request_module("%s%s", MCP_MODULE_PREFIX, mcp->codec); return device_register(&mcp->attached_device); } EXPORT_SYMBOL(mcp_host_register); diff --git a/drivers/mfd/mcp-sa11x0.c b/drivers/mfd/mcp-sa11x0.c index da4e077a1be..02c53a0766c 100644 --- a/drivers/mfd/mcp-sa11x0.c +++ b/drivers/mfd/mcp-sa11x0.c @@ -146,9 +146,6 @@ static int mcp_sa11x0_probe(struct platform_device *pdev) if (!data) return -ENODEV; - if (!data->codec) - return -ENODEV; - if (!request_mem_region(0x80060000, 0x60, "sa11x0-mcp")) return -EBUSY; @@ -165,7 +162,7 @@ static int mcp_sa11x0_probe(struct platform_device *pdev) mcp->dma_audio_wr = DMA_Ser4MCP0Wr; mcp->dma_telco_rd = DMA_Ser4MCP1Rd; mcp->dma_telco_wr = DMA_Ser4MCP1Wr; - mcp->codec = data->codec; + mcp->gpio_base = data->gpio_base; platform_set_drvdata(pdev, mcp); @@ -198,7 +195,7 @@ static int mcp_sa11x0_probe(struct platform_device *pdev) mcp->rw_timeout = (64 * 3 * 1000000 + mcp->sclk_rate - 1) / mcp->sclk_rate; - ret = mcp_host_register(mcp, data->codec_pdata); + ret = mcp_host_register(mcp); if (ret == 0) goto out; diff --git a/drivers/mfd/ucb1x00-core.c b/drivers/mfd/ucb1x00-core.c index 91c4f25e0e5..b281217334e 100644 --- a/drivers/mfd/ucb1x00-core.c +++ b/drivers/mfd/ucb1x00-core.c @@ -36,15 +36,6 @@ static DEFINE_MUTEX(ucb1x00_mutex); static LIST_HEAD(ucb1x00_drivers); static LIST_HEAD(ucb1x00_devices); -static struct mcp_device_id ucb1x00_id[] = { - { "ucb1x00", 0 }, /* auto-detection */ - { "ucb1200", UCB_ID_1200 }, - { "ucb1300", UCB_ID_1300 }, - { "tc35143", UCB_ID_TC35143 }, - { } -}; -MODULE_DEVICE_TABLE(mcp, ucb1x00_id); - /** * ucb1x00_io_set_dir - set IO direction * @ucb: UCB1x00 structure describing chip @@ -536,33 +527,17 @@ static struct class ucb1x00_class = { static int ucb1x00_probe(struct mcp *mcp) { - const struct mcp_device_id *mid; struct ucb1x00 *ucb; struct ucb1x00_driver *drv; - struct ucb1x00_plat_data *pdata; unsigned int id; int ret = -ENODEV; int temp; mcp_enable(mcp); id = mcp_reg_read(mcp, UCB_ID); - mid = mcp_get_device_id(mcp); - if (mid && mid->driver_data) { - if (id != mid->driver_data) { - printk(KERN_WARNING "%s wrong ID %04x found: %04x\n", - mid->name, (unsigned int) mid->driver_data, id); - goto err_disable; - } - } else { - mid = &ucb1x00_id[1]; - while (mid->driver_data) { - if (id == mid->driver_data) - break; - mid++; - } - printk(KERN_WARNING "%s ID not found: %04x\n", - ucb1x00_id[0].name, id); + if (id != UCB_ID_1200 && id != UCB_ID_1300 && id != UCB_ID_TC35143) { + printk(KERN_WARNING "UCB1x00 ID not found: %04x\n", id); goto err_disable; } @@ -571,28 +546,28 @@ static int ucb1x00_probe(struct mcp *mcp) if (!ucb) goto err_disable; - pdata = mcp->attached_device.platform_data; + ucb->dev.class = &ucb1x00_class; ucb->dev.parent = &mcp->attached_device; - dev_set_name(&ucb->dev, mid->name); + dev_set_name(&ucb->dev, "ucb1x00"); spin_lock_init(&ucb->lock); spin_lock_init(&ucb->io_lock); sema_init(&ucb->adc_sem, 1); - ucb->id = mid; + ucb->id = id; ucb->mcp = mcp; ucb->irq = ucb1x00_detect_irq(ucb); if (ucb->irq == NO_IRQ) { - printk(KERN_ERR "%s: IRQ probe failed\n", mid->name); + printk(KERN_ERR "UCB1x00: IRQ probe failed\n"); ret = -ENODEV; goto err_free; } ucb->gpio.base = -1; - if (pdata && (pdata->gpio_base >= 0)) { + if (mcp->gpio_base != 0) { ucb->gpio.label = dev_name(&ucb->dev); - ucb->gpio.base = pdata->gpio_base; + ucb->gpio.base = mcp->gpio_base; ucb->gpio.ngpio = 10; ucb->gpio.set = ucb1x00_gpio_set; ucb->gpio.get = ucb1x00_gpio_get; @@ -605,10 +580,10 @@ static int ucb1x00_probe(struct mcp *mcp) dev_info(&ucb->dev, "gpio_base not set so no gpiolib support"); ret = request_irq(ucb->irq, ucb1x00_irq, IRQF_TRIGGER_RISING, - mid->name, ucb); + "UCB1x00", ucb); if (ret) { - printk(KERN_ERR "%s: unable to grab irq%d: %d\n", - mid->name, ucb->irq, ret); + printk(KERN_ERR "ucb1x00: unable to grab irq%d: %d\n", + ucb->irq, ret); goto err_gpio; } @@ -730,7 +705,6 @@ static struct mcp_driver ucb1x00_driver = { .remove = ucb1x00_remove, .suspend = ucb1x00_suspend, .resume = ucb1x00_resume, - .id_table = ucb1x00_id, }; static int __init ucb1x00_init(void) diff --git a/drivers/mfd/ucb1x00-ts.c b/drivers/mfd/ucb1x00-ts.c index 40ec3c11886..38ffbd50a0d 100644 --- a/drivers/mfd/ucb1x00-ts.c +++ b/drivers/mfd/ucb1x00-ts.c @@ -382,7 +382,7 @@ static int ucb1x00_ts_add(struct ucb1x00_dev *dev) ts->adcsync = adcsync ? UCB_SYNC : UCB_NOSYNC; idev->name = "Touchscreen panel"; - idev->id.product = ts->ucb->id->driver_data; + idev->id.product = ts->ucb->id; idev->open = ucb1x00_ts_open; idev->close = ucb1x00_ts_close; diff --git a/include/linux/mfd/mcp.h b/include/linux/mfd/mcp.h index 1515e64e366..ee496708e38 100644 --- a/include/linux/mfd/mcp.h +++ b/include/linux/mfd/mcp.h @@ -10,7 +10,6 @@ #ifndef MCP_H #define MCP_H -#include <linux/mod_devicetable.h> #include <mach/dma.h> struct mcp_ops; @@ -27,7 +26,7 @@ struct mcp { dma_device_t dma_telco_rd; dma_device_t dma_telco_wr; struct device attached_device; - const char *codec; + int gpio_base; }; struct mcp_ops { @@ -45,11 +44,10 @@ void mcp_reg_write(struct mcp *, unsigned int, unsigned int); unsigned int mcp_reg_read(struct mcp *, unsigned int); void mcp_enable(struct mcp *); void mcp_disable(struct mcp *); -const struct mcp_device_id *mcp_get_device_id(const struct mcp *mcp); #define mcp_get_sclk_rate(mcp) ((mcp)->sclk_rate) struct mcp *mcp_host_alloc(struct device *, size_t); -int mcp_host_register(struct mcp *, void *); +int mcp_host_register(struct mcp *); void mcp_host_unregister(struct mcp *); struct mcp_driver { @@ -58,7 +56,6 @@ struct mcp_driver { void (*remove)(struct mcp *); int (*suspend)(struct mcp *, pm_message_t); int (*resume)(struct mcp *); - const struct mcp_device_id *id_table; }; int mcp_driver_register(struct mcp_driver *); diff --git a/include/linux/mfd/ucb1x00.h b/include/linux/mfd/ucb1x00.h index bc19e5fb7ea..4321f044d1e 100644 --- a/include/linux/mfd/ucb1x00.h +++ b/include/linux/mfd/ucb1x00.h @@ -104,9 +104,6 @@ #define UCB_MODE_DYN_VFLAG_ENA (1 << 12) #define UCB_MODE_AUD_OFF_CAN (1 << 13) -struct ucb1x00_plat_data { - int gpio_base; -}; struct ucb1x00_irq { void *devid; @@ -119,7 +116,7 @@ struct ucb1x00 { unsigned int irq; struct semaphore adc_sem; spinlock_t io_lock; - const struct mcp_device_id *id; + u16 id; u16 io_dir; u16 io_out; u16 adc_cr; diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h index b29e7f6f8fa..83ac0713ed0 100644 --- a/include/linux/mod_devicetable.h +++ b/include/linux/mod_devicetable.h @@ -436,17 +436,6 @@ struct spi_device_id { __attribute__((aligned(sizeof(kernel_ulong_t)))); }; -/* mcp */ - -#define MCP_NAME_SIZE 20 -#define MCP_MODULE_PREFIX "mcp:" - -struct mcp_device_id { - char name[MCP_NAME_SIZE]; - kernel_ulong_t driver_data /* Data private to the driver */ - __attribute__((aligned(sizeof(kernel_ulong_t)))); -}; - /* dmi */ enum dmi_field { DMI_NONE, diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c index c0e14b3f230..e8c96957776 100644 --- a/scripts/mod/file2alias.c +++ b/scripts/mod/file2alias.c @@ -823,16 +823,6 @@ static int do_spi_entry(const char *filename, struct spi_device_id *id, } ADD_TO_DEVTABLE("spi", struct spi_device_id, do_spi_entry); -/* Looks like: mcp:S */ -static int do_mcp_entry(const char *filename, struct mcp_device_id *id, - char *alias) -{ - sprintf(alias, MCP_MODULE_PREFIX "%s", id->name); - - return 1; -} -ADD_TO_DEVTABLE("mcp", struct mcp_device_id, do_mcp_entry); - static const struct dmifield { const char *prefix; int field; -- cgit v1.2.3-70-g09d2 From 0d86f65ed0b727daa06d3aa176314cd175323db6 Mon Sep 17 00:00:00 2001 From: Ondrej Zary <linux@rainbow-software.org> Date: Fri, 10 Feb 2012 20:12:27 +0100 Subject: module: fix broken isapnp handling in file2alias Handling of isapnp module aliases was broken by commit 626596e295d477c0fefa08cd5daa7dd011b1bb2c by changing "isapnp" string to "isa". The code was then modified by commit e49ce14150c64b29a8dd211df785576fa19a9858 but this bug remained. Change the string back to "isapnp". Signed-off-by: Ondrej Zary <linux@rainbow-software.org> Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> --- scripts/mod/file2alias.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scripts/mod/file2alias.c') diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c index e8c96957776..d0de2a2c3a2 100644 --- a/scripts/mod/file2alias.c +++ b/scripts/mod/file2alias.c @@ -932,7 +932,7 @@ static int do_isapnp_entry(const char *filename, (id->function >> 12) & 0x0f, (id->function >> 8) & 0x0f); return 1; } -ADD_TO_DEVTABLE("isa", struct isapnp_device_id, do_isapnp_entry); +ADD_TO_DEVTABLE("isapnp", struct isapnp_device_id, do_isapnp_entry); /* * Append a match expression for a single masked hex digit. -- cgit v1.2.3-70-g09d2 From dd2a3acaecd7abb2d43b09a823cf2e4c967fa2ac Mon Sep 17 00:00:00 2001 From: Andreas Bießmann <andreas@biessmann.de> Date: Fri, 24 Feb 2012 08:23:53 +0100 Subject: mod/file2alias: make modpost compile on darwin again MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit e49ce14150c64b29a8dd211df785576fa19a9858 breaks cross compiling the linux kernel on darwin hosts. This fix introduce some minimal glue to adopt linker section handling for darwin hosts. Signed-off-by: Andreas Bießmann <andreas@biessmann.de> CC: Rusty Russell <rusty@rustcorp.com.au> CC: Greg Kroah-Hartman <gregkh@linuxfoundation.org> CC: Jochen Friedrich <jochen@scram.de> CC: Samuel Ortiz <sameo@linux.intel.com> CC: "K. Y. Srinivasan" <kys@microsoft.com> Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> Tested-by: Bernhard Walle <bernhard@bwalle.de> --- scripts/mod/file2alias.c | 35 +++++++++++++++++++++++++++++++---- 1 file changed, 31 insertions(+), 4 deletions(-) (limited to 'scripts/mod/file2alias.c') diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c index d0de2a2c3a2..b89efe6e4c8 100644 --- a/scripts/mod/file2alias.c +++ b/scripts/mod/file2alias.c @@ -46,11 +46,37 @@ struct devtable { void *function; }; +#define ___cat(a,b) a ## b +#define __cat(a,b) ___cat(a,b) + +/* we need some special handling for this host tool running eventually on + * Darwin. The Mach-O section handling is a bit different than ELF section + * handling. The differnces in detail are: + * a) we have segments which have sections + * b) we need a API call to get the respective section symbols */ +#if defined(__MACH__) +#include <mach-o/getsect.h> + +#define INIT_SECTION(name) do { \ + unsigned long name ## _len; \ + char *__cat(pstart_,name) = getsectdata("__TEXT", \ + #name, &__cat(name,_len)); \ + char *__cat(pstop_,name) = __cat(pstart_,name) + \ + __cat(name, _len); \ + __cat(__start_,name) = (void *)__cat(pstart_,name); \ + __cat(__stop_,name) = (void *)__cat(pstop_,name); \ + } while (0) +#define SECTION(name) __attribute__((section("__TEXT, " #name))) + +struct devtable **__start___devtable, **__stop___devtable; +#else +#define INIT_SECTION(name) /* no-op for ELF */ +#define SECTION(name) __attribute__((section(#name))) + /* We construct a table of pointers in an ELF section (pointers generally * go unpadded by gcc). ld creates boundary syms for us. */ extern struct devtable *__start___devtable[], *__stop___devtable[]; -#define ___cat(a,b) a ## b -#define __cat(a,b) ___cat(a,b) +#endif /* __MACH__ */ #if __GNUC__ == 3 && __GNUC_MINOR__ < 3 # define __used __attribute__((__unused__)) @@ -65,8 +91,8 @@ extern struct devtable *__start___devtable[], *__stop___devtable[]; (type *)NULL, \ (char *)NULL)), \ sizeof(type), (function) }; \ - static struct devtable *__attribute__((section("__devtable"))) \ - __used __cat(devtable_ptr,__LINE__) = &__cat(devtable,__LINE__) + static struct devtable *SECTION(__devtable) __used \ + __cat(devtable_ptr,__LINE__) = &__cat(devtable,__LINE__) #define ADD(str, sep, cond, field) \ do { \ @@ -1080,6 +1106,7 @@ void handle_moddevtable(struct module *mod, struct elf_info *info, do_pnp_card_entries(symval, sym->st_size, mod); else { struct devtable **p; + INIT_SECTION(__devtable); for (p = __start___devtable; p < __stop___devtable; p++) { if (sym_is(name, namelen, (*p)->device_id)) { -- cgit v1.2.3-70-g09d2