From 68ca406930d6380b3be7ada5f15fcf85bfcbd552 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Fri, 19 Feb 2010 00:09:22 -0500 Subject: [PATCH 0001/1337] ACPI: delete the "acpi=ht" boot option acpi=ht was important in 2003 -- before ACPI was universally deployed and enabled by default in the major Linux distributions. At that time, there were a fair number of people who or chose to, or needed to, run with acpi=off, yet also wanted access to Hyper-threading. Today we find that many invocations of "acpi=ht" are accidental, and thus is it possible that it is doing more harm than good. In 2.6.34, we warn on invocation of acpi=ht. In 2.6.35, we delete the boot option. Signed-off-by: Len Brown --- Documentation/kernel-parameters.txt | 3 +-- arch/ia64/include/asm/acpi.h | 1 - arch/x86/include/asm/acpi.h | 2 -- arch/x86/kernel/acpi/boot.c | 19 +++---------------- arch/x86/lguest/boot.c | 1 - drivers/acpi/tables.c | 4 ++-- 6 files changed, 6 insertions(+), 24 deletions(-) diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 3bc48b0bd3a9..41b924ff0b51 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -143,11 +143,10 @@ and is between 256 and 4096 characters. It is defined in the file acpi= [HW,ACPI,X86] Advanced Configuration and Power Interface - Format: { force | off | ht | strict | noirq | rsdt } + Format: { force | off | strict | noirq | rsdt } force -- enable ACPI if default was off off -- disable ACPI if default was on noirq -- do not use ACPI for IRQ routing - ht -- run only enough ACPI to enable Hyper Threading strict -- Be less tolerant of platforms that are not strictly ACPI specification compliant. rsdt -- prefer RSDT over (default) XSDT diff --git a/arch/ia64/include/asm/acpi.h b/arch/ia64/include/asm/acpi.h index 21adbd7f90f8..837dc82a013e 100644 --- a/arch/ia64/include/asm/acpi.h +++ b/arch/ia64/include/asm/acpi.h @@ -94,7 +94,6 @@ ia64_acpi_release_global_lock (unsigned int *lock) #define acpi_noirq 0 /* ACPI always enabled on IA64 */ #define acpi_pci_disabled 0 /* ACPI PCI always enabled on IA64 */ #define acpi_strict 1 /* no ACPI spec workarounds on IA64 */ -#define acpi_ht 0 /* no HT-only mode on IA64 */ #endif #define acpi_processor_cstate_check(x) (x) /* no idle limits on IA64 :) */ static inline void disable_acpi(void) { } diff --git a/arch/x86/include/asm/acpi.h b/arch/x86/include/asm/acpi.h index 56f462cf22d2..aa2c39d968fc 100644 --- a/arch/x86/include/asm/acpi.h +++ b/arch/x86/include/asm/acpi.h @@ -85,7 +85,6 @@ extern int acpi_ioapic; extern int acpi_noirq; extern int acpi_strict; extern int acpi_disabled; -extern int acpi_ht; extern int acpi_pci_disabled; extern int acpi_skip_timer_override; extern int acpi_use_timer_override; @@ -97,7 +96,6 @@ void acpi_pic_sci_set_trigger(unsigned int, u16); static inline void disable_acpi(void) { acpi_disabled = 1; - acpi_ht = 0; acpi_pci_disabled = 1; acpi_noirq = 1; } diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index 7914ab0ad76e..63bcf39f8f24 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c @@ -62,7 +62,6 @@ EXPORT_SYMBOL(acpi_disabled); int acpi_noirq; /* skip ACPI IRQ initialization */ int acpi_pci_disabled; /* skip ACPI PCI scan and IRQ initialization */ EXPORT_SYMBOL(acpi_pci_disabled); -int acpi_ht __initdata = 1; /* enable HT */ int acpi_lapic; int acpi_ioapic; @@ -1460,9 +1459,8 @@ void __init acpi_boot_table_init(void) /* * If acpi_disabled, bail out - * One exception: acpi=ht continues far enough to enumerate LAPICs */ - if (acpi_disabled && !acpi_ht) + if (acpi_disabled) return; /* @@ -1493,9 +1491,8 @@ int __init early_acpi_boot_init(void) { /* * If acpi_disabled, bail out - * One exception: acpi=ht continues far enough to enumerate LAPICs */ - if (acpi_disabled && !acpi_ht) + if (acpi_disabled) return 1; /* @@ -1513,9 +1510,8 @@ int __init acpi_boot_init(void) /* * If acpi_disabled, bail out - * One exception: acpi=ht continues far enough to enumerate LAPICs */ - if (acpi_disabled && !acpi_ht) + if (acpi_disabled) return 1; acpi_table_parse(ACPI_SIG_BOOT, acpi_parse_sbf); @@ -1550,21 +1546,12 @@ static int __init parse_acpi(char *arg) /* acpi=force to over-ride black-list */ else if (strcmp(arg, "force") == 0) { acpi_force = 1; - acpi_ht = 1; acpi_disabled = 0; } /* acpi=strict disables out-of-spec workarounds */ else if (strcmp(arg, "strict") == 0) { acpi_strict = 1; } - /* Limit ACPI just to boot-time to enable HT */ - else if (strcmp(arg, "ht") == 0) { - if (!acpi_force) { - printk(KERN_WARNING "acpi=ht will be removed in Linux-2.6.35\n"); - disable_acpi(); - } - acpi_ht = 1; - } /* acpi=rsdt use RSDT instead of XSDT */ else if (strcmp(arg, "rsdt") == 0) { acpi_rsdt_forced = 1; diff --git a/arch/x86/lguest/boot.c b/arch/x86/lguest/boot.c index 7e59dc1d3fc2..8eb9eed60282 100644 --- a/arch/x86/lguest/boot.c +++ b/arch/x86/lguest/boot.c @@ -1391,7 +1391,6 @@ __init void lguest_init(void) #endif #ifdef CONFIG_ACPI acpi_disabled = 1; - acpi_ht = 0; #endif /* diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c index 8a0ed2800e63..f336bca7c450 100644 --- a/drivers/acpi/tables.c +++ b/drivers/acpi/tables.c @@ -213,7 +213,7 @@ acpi_table_parse_entries(char *id, unsigned long table_end; acpi_size tbl_size; - if (acpi_disabled && !acpi_ht) + if (acpi_disabled) return -ENODEV; if (!handler) @@ -280,7 +280,7 @@ int __init acpi_table_parse(char *id, acpi_table_handler handler) struct acpi_table_header *table = NULL; acpi_size tbl_size; - if (acpi_disabled && !acpi_ht) + if (acpi_disabled) return -ENODEV; if (!handler) From 3ed3dec1568d1232fcfb2aa8c5f9e3f38940c9d8 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 16 Mar 2010 05:48:08 +0900 Subject: [PATCH 0002/1337] fat: use pack_hex_byte() instead of custom one Signed-off-by: Andy Shevchenko Signed-off-by: OGAWA Hirofumi --- fs/fat/dir.c | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/fs/fat/dir.c b/fs/fat/dir.c index 530b4ca01510..20a1b92e035e 100644 --- a/fs/fat/dir.c +++ b/fs/fat/dir.c @@ -19,6 +19,7 @@ #include #include #include +#include #include "fat.h" /* @@ -140,28 +141,22 @@ static int uni16_to_x8(unsigned char *ascii, const wchar_t *uni, int len, { const wchar_t *ip; wchar_t ec; - unsigned char *op, nc; + unsigned char *op; int charlen; - int k; ip = uni; op = ascii; while (*ip && ((len - NLS_MAX_CHARSET_SIZE) > 0)) { ec = *ip++; - if ( (charlen = nls->uni2char(ec, op, NLS_MAX_CHARSET_SIZE)) > 0) { + if ((charlen = nls->uni2char(ec, op, NLS_MAX_CHARSET_SIZE)) > 0) { op += charlen; len -= charlen; } else { if (uni_xlate == 1) { - *op = ':'; - for (k = 4; k > 0; k--) { - nc = ec & 0xF; - op[k] = nc > 9 ? nc + ('a' - 10) - : nc + '0'; - ec >>= 4; - } - op += 5; + *op++ = ':'; + op = pack_hex_byte(op, ec >> 8); + op = pack_hex_byte(op, ec); len -= 5; } else { *op++ = '?'; From 1bdb6f9199def1c3538c18089e499f5df5ff1747 Mon Sep 17 00:00:00 2001 From: OGAWA Hirofumi Date: Tue, 16 Mar 2010 05:48:09 +0900 Subject: [PATCH 0003/1337] fat: Cleanup nls_unload() usage Other users doesn't check NULL explicitly. So, these doesn't also check to remove inconsistency. Signed-off-by: OGAWA Hirofumi --- fs/fat/inode.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/fs/fat/inode.c b/fs/fat/inode.c index 0ce143bd7d56..c611818893b2 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c @@ -1497,10 +1497,8 @@ out_fail: iput(fat_inode); if (root_inode) iput(root_inode); - if (sbi->nls_io) - unload_nls(sbi->nls_io); - if (sbi->nls_disk) - unload_nls(sbi->nls_disk); + unload_nls(sbi->nls_io); + unload_nls(sbi->nls_disk); if (sbi->options.iocharset != fat_default_iocharset) kfree(sbi->options.iocharset); sb->s_fs_info = NULL; From e92dd4fd1aa1cd081dac03973b33c972637d5b7a Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Fri, 26 Mar 2010 19:27:58 -0700 Subject: [PATCH 0004/1337] slab: Fix continuation lines Signed-off-by: Joe Perches Signed-off-by: Pekka Enberg --- mm/slab.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/mm/slab.c b/mm/slab.c index a9f325b28bed..ceb4e3aa22f7 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -4227,10 +4227,11 @@ static int s_show(struct seq_file *m, void *p) unsigned long node_frees = cachep->node_frees; unsigned long overflows = cachep->node_overflow; - seq_printf(m, " : globalstat %7lu %6lu %5lu %4lu \ - %4lu %4lu %4lu %4lu %4lu", allocs, high, grown, - reaped, errors, max_freeable, node_allocs, - node_frees, overflows); + seq_printf(m, " : globalstat %7lu %6lu %5lu %4lu " + "%4lu %4lu %4lu %4lu %4lu", + allocs, high, grown, + reaped, errors, max_freeable, node_allocs, + node_frees, overflows); } /* cpu stats */ { From 6ad95513d60096b569e4e4bd721420f03b57e4d4 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Thu, 11 Mar 2010 12:20:06 -0700 Subject: [PATCH 0005/1337] ACPI: pci_root: save downstream bus range Previously, we only saved the root bus number, i.e., the beginning of the downstream bus range. We now support IORESOURCE_BUS resources, so this patch uses that to keep track of both the beginning and the end of the downstream bus range. It's important to know both the beginning and the end for supporting _CBA (see PCI Firmware spec, rev 3.0, sec 4.1.3) and so we know the limits for any possible PCI bus renumbering (we can't renumber downstream buses to be outside the bus number range claimed by the host bridge). It's clear from the spec that the bus range is supposed to be in _CRS, but if we don't find it there, we'll assume [_BBN - 0xFF] or [0 - 0xFF]. Signed-off-by: Bjorn Helgaas Reviewed-by: Kenji Kaneshige Signed-off-by: Len Brown --- drivers/acpi/pci_root.c | 67 ++++++++++++++++++++++++----------------- include/acpi/acpi_bus.h | 2 +- 2 files changed, 41 insertions(+), 28 deletions(-) diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index d724736d56c8..bf476fea97ab 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -119,7 +119,8 @@ acpi_handle acpi_get_pci_rootbridge_handle(unsigned int seg, unsigned int bus) struct acpi_pci_root *root; list_for_each_entry(root, &acpi_pci_roots, node) - if ((root->segment == (u16) seg) && (root->bus_nr == (u16) bus)) + if ((root->segment == (u16) seg) && + (root->secondary.start == (u16) bus)) return root->device->handle; return NULL; } @@ -153,7 +154,7 @@ EXPORT_SYMBOL_GPL(acpi_is_root_bridge); static acpi_status get_root_bridge_busnr_callback(struct acpi_resource *resource, void *data) { - int *busnr = data; + struct resource *res = data; struct acpi_resource_address64 address; if (resource->type != ACPI_RESOURCE_TYPE_ADDRESS16 && @@ -163,28 +164,27 @@ get_root_bridge_busnr_callback(struct acpi_resource *resource, void *data) acpi_resource_to_address64(resource, &address); if ((address.address_length > 0) && - (address.resource_type == ACPI_BUS_NUMBER_RANGE)) - *busnr = address.minimum; + (address.resource_type == ACPI_BUS_NUMBER_RANGE)) { + res->start = address.minimum; + res->end = address.minimum + address.address_length - 1; + } return AE_OK; } static acpi_status try_get_root_bridge_busnr(acpi_handle handle, - unsigned long long *bus) + struct resource *res) { acpi_status status; - int busnum; - busnum = -1; + res->start = -1; status = acpi_walk_resources(handle, METHOD_NAME__CRS, - get_root_bridge_busnr_callback, &busnum); + get_root_bridge_busnr_callback, res); if (ACPI_FAILURE(status)) return status; - /* Check if we really get a bus number from _CRS */ - if (busnum == -1) + if (res->start == -1) return AE_ERROR; - *bus = busnum; return AE_OK; } @@ -428,34 +428,47 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device) struct acpi_device *child; u32 flags, base_flags; + root = kzalloc(sizeof(struct acpi_pci_root), GFP_KERNEL); + if (!root) + return -ENOMEM; + segment = 0; status = acpi_evaluate_integer(device->handle, METHOD_NAME__SEG, NULL, &segment); if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { printk(KERN_ERR PREFIX "can't evaluate _SEG\n"); - return -ENODEV; + result = -ENODEV; + goto end; } /* Check _CRS first, then _BBN. If no _BBN, default to zero. */ - bus = 0; - status = try_get_root_bridge_busnr(device->handle, &bus); + root->secondary.flags = IORESOURCE_BUS; + status = try_get_root_bridge_busnr(device->handle, &root->secondary); if (ACPI_FAILURE(status)) { + /* + * We need both the start and end of the downstream bus range + * to interpret _CBA (MMCONFIG base address), so it really is + * supposed to be in _CRS. If we don't find it there, all we + * can do is assume [_BBN-0xFF] or [0-0xFF]. + */ + root->secondary.end = 0xFF; + printk(KERN_WARNING FW_BUG PREFIX + "no secondary bus range in _CRS\n"); status = acpi_evaluate_integer(device->handle, METHOD_NAME__BBN, NULL, &bus); - if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { - printk(KERN_ERR PREFIX - "no bus number in _CRS and can't evaluate _BBN\n"); - return -ENODEV; + if (ACPI_SUCCESS(status)) + root->secondary.start = bus; + else if (status == AE_NOT_FOUND) + root->secondary.start = 0; + else { + printk(KERN_ERR PREFIX "can't evaluate _BBN\n"); + result = -ENODEV; + goto end; } } - root = kzalloc(sizeof(struct acpi_pci_root), GFP_KERNEL); - if (!root) - return -ENOMEM; - INIT_LIST_HEAD(&root->node); root->device = device; root->segment = segment & 0xFFFF; - root->bus_nr = bus & 0xFF; strcpy(acpi_device_name(device), ACPI_PCI_ROOT_DEVICE_NAME); strcpy(acpi_device_class(device), ACPI_PCI_ROOT_CLASS); device->driver_data = root; @@ -474,9 +487,9 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device) /* TBD: Locking */ list_add_tail(&root->node, &acpi_pci_roots); - printk(KERN_INFO PREFIX "%s [%s] (%04x:%02x)\n", + printk(KERN_INFO PREFIX "%s [%s] (domain %04x %pR)\n", acpi_device_name(device), acpi_device_bid(device), - root->segment, root->bus_nr); + root->segment, &root->secondary); /* * Scan the Root Bridge @@ -485,11 +498,11 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device) * PCI namespace does not get created until this call is made (and * thus the root bridge's pci_dev does not exist). */ - root->bus = pci_acpi_scan_root(device, segment, bus); + root->bus = pci_acpi_scan_root(device, segment, root->secondary.start); if (!root->bus) { printk(KERN_ERR PREFIX "Bus %04x:%02x not present in PCI namespace\n", - root->segment, root->bus_nr); + root->segment, (unsigned int)root->secondary.start); result = -ENODEV; goto end; } diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 7bf83ddf82e0..baacd98e7cc6 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -373,7 +373,7 @@ struct acpi_pci_root { struct acpi_pci_id id; struct pci_bus *bus; u16 segment; - u8 bus_nr; + struct resource secondary; /* downstream bus range */ u32 osc_support_set; /* _OSC state of support bits */ u32 osc_control_set; /* _OSC state of control bits */ From 57283776b2b821ba4d592f61cad04d0293412740 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Thu, 11 Mar 2010 12:20:11 -0700 Subject: [PATCH 0006/1337] ACPI: pci_root: pass acpi_pci_root to arch-specific scan The acpi_pci_root structure contains all the individual items (acpi_device, domain, bus number) we pass to pci_acpi_scan_root(), so just pass the single acpi_pci_root pointer directly. This will make it easier to add _CBA support later. For _CBA, we need the entire downstream bus range, not just the base bus number. We have that in the acpi_pci_root structure, so passing the pointer makes it available to the arch-specific code. Signed-off-by: Bjorn Helgaas Reviewed-by: Kenji Kaneshige Signed-off-by: Len Brown --- arch/ia64/pci/pci.c | 5 ++++- arch/x86/pci/acpi.c | 5 ++++- drivers/acpi/pci_root.c | 2 +- include/acpi/acpi_drivers.h | 3 +-- 4 files changed, 10 insertions(+), 5 deletions(-) diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c index 64aff520b899..aa2533ae7e9e 100644 --- a/arch/ia64/pci/pci.c +++ b/arch/ia64/pci/pci.c @@ -335,8 +335,11 @@ pcibios_setup_root_windows(struct pci_bus *bus, struct pci_controller *ctrl) } struct pci_bus * __devinit -pci_acpi_scan_root(struct acpi_device *device, int domain, int bus) +pci_acpi_scan_root(struct acpi_pci_root *root) { + struct acpi_device *device = root->device; + int domain = root->segment; + int bus = root->secondary.start; struct pci_controller *controller; unsigned int windows = 0; struct pci_bus *pbus; diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c index e31160216efb..0b7882dbe784 100644 --- a/arch/x86/pci/acpi.c +++ b/arch/x86/pci/acpi.c @@ -229,8 +229,11 @@ res_alloc_fail: return; } -struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int domain, int busnum) +struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root) { + struct acpi_device *device = root->device; + int domain = root->segment; + int busnum = root->secondary.start; struct pci_bus *bus; struct pci_sysdata *sd; int node; diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index bf476fea97ab..680450c905b3 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -498,7 +498,7 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device) * PCI namespace does not get created until this call is made (and * thus the root bridge's pci_dev does not exist). */ - root->bus = pci_acpi_scan_root(device, segment, root->secondary.start); + root->bus = pci_acpi_scan_root(root); if (!root->bus) { printk(KERN_ERR PREFIX "Bus %04x:%02x not present in PCI namespace\n", diff --git a/include/acpi/acpi_drivers.h b/include/acpi/acpi_drivers.h index 4f7b44866b76..23d78b4d088b 100644 --- a/include/acpi/acpi_drivers.h +++ b/include/acpi/acpi_drivers.h @@ -104,8 +104,7 @@ int acpi_pci_bind_root(struct acpi_device *device); /* Arch-defined function to add a bus to the system */ -struct pci_bus *pci_acpi_scan_root(struct acpi_device *device, int domain, - int bus); +struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root); void pci_acpi_crs_quirks(void); /* -------------------------------------------------------------------------- From a009d29ea104c1bd8805a20018469897c2c2263c Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Thu, 1 Apr 2010 12:27:44 +0200 Subject: [PATCH 0007/1337] ds2782_battery: Fix clientdata on removal Probably due to a copy & paste bug, clientdata was set again to the data structure (which is freed immediately afterwards) when it should be NULLed. Just remove the calls as the i2c-core does this automatically now. Signed-off-by: Wolfram Sang Cc: Ryan Mallon Cc: Hans Verkuil Cc: Jean Delvare Signed-off-by: Anton Vorontsov --- drivers/power/ds2782_battery.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/power/ds2782_battery.c b/drivers/power/ds2782_battery.c index da14f374cb60..305d463a880c 100644 --- a/drivers/power/ds2782_battery.c +++ b/drivers/power/ds2782_battery.c @@ -236,8 +236,6 @@ static int ds2782_battery_remove(struct i2c_client *client) idr_remove(&battery_id, info->id); mutex_unlock(&battery_lock); - i2c_set_clientdata(client, info); - kfree(info); return 0; } @@ -289,7 +287,6 @@ static int ds2782_battery_probe(struct i2c_client *client, fail_register: kfree(info->battery.name); fail_name: - i2c_set_clientdata(client, info); kfree(info); fail_info: mutex_lock(&battery_lock); From e3e8d1c93f9e6b766424b05f23f2416f22a0329d Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 28 Feb 2010 12:47:49 +0100 Subject: [PATCH 0008/1337] Driver for Zipit Z2 battery chip This patch adds driver for Zipit Z2 battery chip called AER915. No details are known about the chip. The chip is available through I2C bus at address 0x55 and it's register 0x02 contains battery voltage. Signed-off-by: Marek Vasut Signed-off-by: Anton Vorontsov --- drivers/power/Kconfig | 6 + drivers/power/Makefile | 1 + drivers/power/z2_battery.c | 328 +++++++++++++++++++++++++++++++++++++ include/linux/z2_battery.h | 17 ++ 4 files changed, 352 insertions(+) create mode 100644 drivers/power/z2_battery.c create mode 100644 include/linux/z2_battery.h diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig index faaa9b4d0d07..22f2fa912127 100644 --- a/drivers/power/Kconfig +++ b/drivers/power/Kconfig @@ -125,6 +125,12 @@ config BATTERY_MAX17040 in handheld and portable equipment. The MAX17040 is configured to operate with a single lithium cell +config BATTERY_Z2 + tristate "Z2 battery driver" + depends on I2C && MACH_ZIPIT2 + help + Say Y to include support for the battery on the Zipit Z2. + config CHARGER_PCF50633 tristate "NXP PCF50633 MBC" depends on MFD_PCF50633 diff --git a/drivers/power/Makefile b/drivers/power/Makefile index a2ba7c85c97a..a82f292e5c94 100644 --- a/drivers/power/Makefile +++ b/drivers/power/Makefile @@ -31,4 +31,5 @@ obj-$(CONFIG_BATTERY_WM97XX) += wm97xx_battery.o obj-$(CONFIG_BATTERY_BQ27x00) += bq27x00_battery.o obj-$(CONFIG_BATTERY_DA9030) += da9030_battery.o obj-$(CONFIG_BATTERY_MAX17040) += max17040_battery.o +obj-$(CONFIG_BATTERY_Z2) += z2_battery.o obj-$(CONFIG_CHARGER_PCF50633) += pcf50633-charger.o diff --git a/drivers/power/z2_battery.c b/drivers/power/z2_battery.c new file mode 100644 index 000000000000..9cca465436e3 --- /dev/null +++ b/drivers/power/z2_battery.c @@ -0,0 +1,328 @@ +/* + * Battery measurement code for Zipit Z2 + * + * Copyright (C) 2009 Peter Edwards + * + * 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define Z2_DEFAULT_NAME "Z2" + +struct z2_charger { + struct z2_battery_info *info; + int bat_status; + struct i2c_client *client; + struct power_supply batt_ps; + struct mutex work_lock; + struct work_struct bat_work; +}; + +static unsigned long z2_read_bat(struct z2_charger *charger) +{ + int data; + data = i2c_smbus_read_byte_data(charger->client, + charger->info->batt_I2C_reg); + if (data < 0) + return 0; + + return data * charger->info->batt_mult / charger->info->batt_div; +} + +static int z2_batt_get_property(struct power_supply *batt_ps, + enum power_supply_property psp, + union power_supply_propval *val) +{ + struct z2_charger *charger = container_of(batt_ps, struct z2_charger, + batt_ps); + struct z2_battery_info *info = charger->info; + + switch (psp) { + case POWER_SUPPLY_PROP_STATUS: + val->intval = charger->bat_status; + break; + case POWER_SUPPLY_PROP_TECHNOLOGY: + val->intval = info->batt_tech; + break; + case POWER_SUPPLY_PROP_VOLTAGE_NOW: + if (info->batt_I2C_reg >= 0) + val->intval = z2_read_bat(charger); + else + return -EINVAL; + break; + case POWER_SUPPLY_PROP_VOLTAGE_MAX: + if (info->max_voltage >= 0) + val->intval = info->max_voltage; + else + return -EINVAL; + break; + case POWER_SUPPLY_PROP_VOLTAGE_MIN: + if (info->min_voltage >= 0) + val->intval = info->min_voltage; + else + return -EINVAL; + break; + case POWER_SUPPLY_PROP_PRESENT: + val->intval = 1; + break; + default: + return -EINVAL; + } + + return 0; +} + +static void z2_batt_ext_power_changed(struct power_supply *batt_ps) +{ + struct z2_charger *charger = container_of(batt_ps, struct z2_charger, + batt_ps); + schedule_work(&charger->bat_work); +} + +static void z2_batt_update(struct z2_charger *charger) +{ + int old_status = charger->bat_status; + struct z2_battery_info *info; + + info = charger->info; + + mutex_lock(&charger->work_lock); + + charger->bat_status = (info->charge_gpio >= 0) ? + (gpio_get_value(info->charge_gpio) ? + POWER_SUPPLY_STATUS_CHARGING : + POWER_SUPPLY_STATUS_DISCHARGING) : + POWER_SUPPLY_STATUS_UNKNOWN; + + if (old_status != charger->bat_status) { + pr_debug("%s: %i -> %i\n", charger->batt_ps.name, old_status, + charger->bat_status); + power_supply_changed(&charger->batt_ps); + } + + mutex_unlock(&charger->work_lock); +} + +static void z2_batt_work(struct work_struct *work) +{ + struct z2_charger *charger; + charger = container_of(work, struct z2_charger, bat_work); + z2_batt_update(charger); +} + +static irqreturn_t z2_charge_switch_irq(int irq, void *devid) +{ + struct z2_charger *charger = devid; + schedule_work(&charger->bat_work); + return IRQ_HANDLED; +} + +static int z2_batt_ps_init(struct z2_charger *charger, int props) +{ + int i = 0; + enum power_supply_property *prop; + struct z2_battery_info *info = charger->info; + + if (info->batt_tech >= 0) + props++; /* POWER_SUPPLY_PROP_TECHNOLOGY */ + if (info->batt_I2C_reg >= 0) + props++; /* POWER_SUPPLY_PROP_VOLTAGE_NOW */ + if (info->max_voltage >= 0) + props++; /* POWER_SUPPLY_PROP_VOLTAGE_MAX */ + if (info->min_voltage >= 0) + props++; /* POWER_SUPPLY_PROP_VOLTAGE_MIN */ + + prop = kzalloc(props * sizeof(*prop), GFP_KERNEL); + if (!prop) + return -ENOMEM; + + prop[i++] = POWER_SUPPLY_PROP_PRESENT; + if (info->charge_gpio >= 0) + prop[i++] = POWER_SUPPLY_PROP_STATUS; + if (info->batt_tech >= 0) + prop[i++] = POWER_SUPPLY_PROP_TECHNOLOGY; + if (info->batt_I2C_reg >= 0) + prop[i++] = POWER_SUPPLY_PROP_VOLTAGE_NOW; + if (info->max_voltage >= 0) + prop[i++] = POWER_SUPPLY_PROP_VOLTAGE_MAX; + if (info->min_voltage >= 0) + prop[i++] = POWER_SUPPLY_PROP_VOLTAGE_MIN; + + if (!info->batt_name) { + dev_info(&charger->client->dev, + "Please consider setting proper battery " + "name in platform definition file, falling " + "back to name \" Z2_DEFAULT_NAME \"\n"); + charger->batt_ps.name = Z2_DEFAULT_NAME; + } else + charger->batt_ps.name = info->batt_name; + + charger->batt_ps.properties = prop; + charger->batt_ps.num_properties = props; + charger->batt_ps.type = POWER_SUPPLY_TYPE_BATTERY; + charger->batt_ps.get_property = z2_batt_get_property; + charger->batt_ps.external_power_changed = z2_batt_ext_power_changed; + charger->batt_ps.use_for_apm = 1; + + return 0; +} + +static int __devinit z2_batt_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + int ret = 0; + int props = 1; /* POWER_SUPPLY_PROP_PRESENT */ + struct z2_charger *charger; + struct z2_battery_info *info = client->dev.platform_data; + + if (info == NULL) { + dev_err(&client->dev, + "Please set platform device platform_data" + " to a valid z2_battery_info pointer!\n"); + return -EINVAL; + } + + charger = kzalloc(sizeof(*charger), GFP_KERNEL); + if (charger == NULL) + return -ENOMEM; + + charger->bat_status = POWER_SUPPLY_STATUS_UNKNOWN; + charger->info = info; + charger->client = client; + i2c_set_clientdata(client, charger); + + mutex_init(&charger->work_lock); + + if (info->charge_gpio >= 0 && gpio_is_valid(info->charge_gpio)) { + ret = gpio_request(info->charge_gpio, "BATT CHRG"); + if (ret) + goto err; + + ret = gpio_direction_input(info->charge_gpio); + if (ret) + goto err2; + + set_irq_type(gpio_to_irq(info->charge_gpio), + IRQ_TYPE_EDGE_BOTH); + ret = request_irq(gpio_to_irq(info->charge_gpio), + z2_charge_switch_irq, IRQF_DISABLED, + "AC Detect", charger); + if (ret) + goto err3; + } + + ret = z2_batt_ps_init(charger, props); + if (ret) + goto err3; + + INIT_WORK(&charger->bat_work, z2_batt_work); + + ret = power_supply_register(&client->dev, &charger->batt_ps); + if (ret) + goto err4; + + schedule_work(&charger->bat_work); + + return 0; + +err4: + kfree(charger->batt_ps.properties); +err3: + if (info->charge_gpio >= 0 && gpio_is_valid(info->charge_gpio)) + free_irq(gpio_to_irq(info->charge_gpio), charger); +err2: + if (info->charge_gpio >= 0 && gpio_is_valid(info->charge_gpio)) + gpio_free(info->charge_gpio); +err: + kfree(charger); + return ret; +} + +static int __devexit z2_batt_remove(struct i2c_client *client) +{ + struct z2_charger *charger = i2c_get_clientdata(client); + struct z2_battery_info *info = charger->info; + + flush_scheduled_work(); + power_supply_unregister(&charger->batt_ps); + + kfree(charger->batt_ps.properties); + if (info->charge_gpio >= 0 && gpio_is_valid(info->charge_gpio)) { + free_irq(gpio_to_irq(info->charge_gpio), charger); + gpio_free(info->charge_gpio); + } + + kfree(charger); + + return 0; +} + +#ifdef CONFIG_PM +static int z2_batt_suspend(struct i2c_client *client, pm_message_t state) +{ + flush_scheduled_work(); + return 0; +} + +static int z2_batt_resume(struct i2c_client *client) +{ + struct z2_charger *charger = i2c_get_clientdata(client); + + schedule_work(&charger->bat_work); + return 0; +} +#else +#define z2_batt_suspend NULL +#define z2_batt_resume NULL +#endif + +static const struct i2c_device_id z2_batt_id[] = { + { "aer915", 0 }, + { } +}; + +static struct i2c_driver z2_batt_driver = { + .driver = { + .name = "z2-battery", + .owner = THIS_MODULE, + }, + .probe = z2_batt_probe, + .remove = z2_batt_remove, + .suspend = z2_batt_suspend, + .resume = z2_batt_resume, + .id_table = z2_batt_id, +}; + +static int __init z2_batt_init(void) +{ + return i2c_add_driver(&z2_batt_driver); +} + +static void __exit z2_batt_exit(void) +{ + i2c_del_driver(&z2_batt_driver); +} + +module_init(z2_batt_init); +module_exit(z2_batt_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Peter Edwards "); +MODULE_DESCRIPTION("Zipit Z2 battery driver"); diff --git a/include/linux/z2_battery.h b/include/linux/z2_battery.h new file mode 100644 index 000000000000..7b9750404d22 --- /dev/null +++ b/include/linux/z2_battery.h @@ -0,0 +1,17 @@ +#ifndef _LINUX_Z2_BATTERY_H +#define _LINUX_Z2_BATTERY_H + +struct z2_battery_info { + int batt_I2C_bus; + int batt_I2C_addr; + int batt_I2C_reg; + int charge_gpio; + int min_voltage; + int max_voltage; + int batt_div; + int batt_mult; + int batt_tech; + char *batt_name; +}; + +#endif From b5874f33bbaf00586d05de37706491ee37057e11 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 10 Mar 2010 18:27:40 +0000 Subject: [PATCH 0009/1337] wm831x_power: Use genirq Since the WM831x core has been converted to use genirq for the interrupt controller there is no longer any need for chip specific wrappers for IRQ operations. Convert to use genirq directly. Signed-off-by: Mark Brown Signed-off-by: Anton Vorontsov --- drivers/power/wm831x_power.c | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/drivers/power/wm831x_power.c b/drivers/power/wm831x_power.c index f85e80b1b400..bf2ff4132478 100644 --- a/drivers/power/wm831x_power.c +++ b/drivers/power/wm831x_power.c @@ -536,9 +536,9 @@ static __devinit int wm831x_power_probe(struct platform_device *pdev) goto err_battery; irq = platform_get_irq_byname(pdev, "SYSLO"); - ret = wm831x_request_irq(wm831x, irq, wm831x_syslo_irq, - IRQF_TRIGGER_RISING, "SYSLO", - power); + ret = request_threaded_irq(irq, NULL, wm831x_syslo_irq, + IRQF_TRIGGER_RISING, "System power low", + power); if (ret != 0) { dev_err(&pdev->dev, "Failed to request SYSLO IRQ %d: %d\n", irq, ret); @@ -546,9 +546,9 @@ static __devinit int wm831x_power_probe(struct platform_device *pdev) } irq = platform_get_irq_byname(pdev, "PWR SRC"); - ret = wm831x_request_irq(wm831x, irq, wm831x_pwr_src_irq, - IRQF_TRIGGER_RISING, "Power source", - power); + ret = request_threaded_irq(irq, NULL, wm831x_pwr_src_irq, + IRQF_TRIGGER_RISING, "Power source", + power); if (ret != 0) { dev_err(&pdev->dev, "Failed to request PWR SRC IRQ %d: %d\n", irq, ret); @@ -557,10 +557,10 @@ static __devinit int wm831x_power_probe(struct platform_device *pdev) for (i = 0; i < ARRAY_SIZE(wm831x_bat_irqs); i++) { irq = platform_get_irq_byname(pdev, wm831x_bat_irqs[i]); - ret = wm831x_request_irq(wm831x, irq, wm831x_bat_irq, - IRQF_TRIGGER_RISING, - wm831x_bat_irqs[i], - power); + ret = request_threaded_irq(irq, NULL, wm831x_bat_irq, + IRQF_TRIGGER_RISING, + wm831x_bat_irqs[i], + power); if (ret != 0) { dev_err(&pdev->dev, "Failed to request %s IRQ %d: %d\n", @@ -574,13 +574,13 @@ static __devinit int wm831x_power_probe(struct platform_device *pdev) err_bat_irq: for (; i >= 0; i--) { irq = platform_get_irq_byname(pdev, wm831x_bat_irqs[i]); - wm831x_free_irq(wm831x, irq, power); + free_irq(irq, power); } irq = platform_get_irq_byname(pdev, "PWR SRC"); - wm831x_free_irq(wm831x, irq, power); + free_irq(irq, power); err_syslo: irq = platform_get_irq_byname(pdev, "SYSLO"); - wm831x_free_irq(wm831x, irq, power); + free_irq(irq, power); err_usb: power_supply_unregister(usb); err_battery: @@ -595,19 +595,18 @@ err_kmalloc: static __devexit int wm831x_power_remove(struct platform_device *pdev) { struct wm831x_power *wm831x_power = platform_get_drvdata(pdev); - struct wm831x *wm831x = wm831x_power->wm831x; int irq, i; for (i = 0; i < ARRAY_SIZE(wm831x_bat_irqs); i++) { irq = platform_get_irq_byname(pdev, wm831x_bat_irqs[i]); - wm831x_free_irq(wm831x, irq, wm831x_power); + free_irq(irq, wm831x_power); } irq = platform_get_irq_byname(pdev, "PWR SRC"); - wm831x_free_irq(wm831x, irq, wm831x_power); + free_irq(irq, wm831x_power); irq = platform_get_irq_byname(pdev, "SYSLO"); - wm831x_free_irq(wm831x, irq, wm831x_power); + free_irq(irq, wm831x_power); power_supply_unregister(&wm831x_power->battery); power_supply_unregister(&wm831x_power->wall); From 8f9f8d9e8080a2ff46caa7decef47810d093d252 Mon Sep 17 00:00:00 2001 From: David Rientjes Date: Sat, 27 Mar 2010 19:40:47 -0700 Subject: [PATCH 0010/1337] slab: add memory hotplug support Slab lacks any memory hotplug support for nodes that are hotplugged without cpus being hotplugged. This is possible at least on x86 CONFIG_MEMORY_HOTPLUG_SPARSE kernels where SRAT entries are marked ACPI_SRAT_MEM_HOT_PLUGGABLE and the regions of RAM represent a seperate node. It can also be done manually by writing the start address to /sys/devices/system/memory/probe for kernels that have CONFIG_ARCH_MEMORY_PROBE set, which is how this patch was tested, and then onlining the new memory region. When a node is hotadded, a nodelist for that node is allocated and initialized for each slab cache. If this isn't completed due to a lack of memory, the hotadd is aborted: we have a reasonable expectation that kmalloc_node(nid) will work for all caches if nid is online and memory is available. Since nodelists must be allocated and initialized prior to the new node's memory actually being online, the struct kmem_list3 is allocated off-node due to kmalloc_node()'s fallback. When an entire node would be offlined, its nodelists are subsequently drained. If slab objects still exist and cannot be freed, the offline is aborted. It is possible that objects will be allocated between this drain and page isolation, so it's still possible that the offline will still fail, however. Acked-by: Christoph Lameter Signed-off-by: David Rientjes Signed-off-by: Pekka Enberg --- mm/slab.c | 157 +++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 125 insertions(+), 32 deletions(-) diff --git a/mm/slab.c b/mm/slab.c index a9f325b28bed..3230cd2c6b3b 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -115,6 +115,7 @@ #include #include #include +#include #include #include @@ -1102,6 +1103,52 @@ static inline int cache_free_alien(struct kmem_cache *cachep, void *objp) } #endif +/* + * Allocates and initializes nodelists for a node on each slab cache, used for + * either memory or cpu hotplug. If memory is being hot-added, the kmem_list3 + * will be allocated off-node since memory is not yet online for the new node. + * When hotplugging memory or a cpu, existing nodelists are not replaced if + * already in use. + * + * Must hold cache_chain_mutex. + */ +static int init_cache_nodelists_node(int node) +{ + struct kmem_cache *cachep; + struct kmem_list3 *l3; + const int memsize = sizeof(struct kmem_list3); + + list_for_each_entry(cachep, &cache_chain, next) { + /* + * Set up the size64 kmemlist for cpu before we can + * begin anything. Make sure some other cpu on this + * node has not already allocated this + */ + if (!cachep->nodelists[node]) { + l3 = kmalloc_node(memsize, GFP_KERNEL, node); + if (!l3) + return -ENOMEM; + kmem_list3_init(l3); + l3->next_reap = jiffies + REAPTIMEOUT_LIST3 + + ((unsigned long)cachep) % REAPTIMEOUT_LIST3; + + /* + * The l3s don't come and go as CPUs come and + * go. cache_chain_mutex is sufficient + * protection here. + */ + cachep->nodelists[node] = l3; + } + + spin_lock_irq(&cachep->nodelists[node]->list_lock); + cachep->nodelists[node]->free_limit = + (1 + nr_cpus_node(node)) * + cachep->batchcount + cachep->num; + spin_unlock_irq(&cachep->nodelists[node]->list_lock); + } + return 0; +} + static void __cpuinit cpuup_canceled(long cpu) { struct kmem_cache *cachep; @@ -1172,7 +1219,7 @@ static int __cpuinit cpuup_prepare(long cpu) struct kmem_cache *cachep; struct kmem_list3 *l3 = NULL; int node = cpu_to_node(cpu); - const int memsize = sizeof(struct kmem_list3); + int err; /* * We need to do this right in the beginning since @@ -1180,35 +1227,9 @@ static int __cpuinit cpuup_prepare(long cpu) * kmalloc_node allows us to add the slab to the right * kmem_list3 and not this cpu's kmem_list3 */ - - list_for_each_entry(cachep, &cache_chain, next) { - /* - * Set up the size64 kmemlist for cpu before we can - * begin anything. Make sure some other cpu on this - * node has not already allocated this - */ - if (!cachep->nodelists[node]) { - l3 = kmalloc_node(memsize, GFP_KERNEL, node); - if (!l3) - goto bad; - kmem_list3_init(l3); - l3->next_reap = jiffies + REAPTIMEOUT_LIST3 + - ((unsigned long)cachep) % REAPTIMEOUT_LIST3; - - /* - * The l3s don't come and go as CPUs come and - * go. cache_chain_mutex is sufficient - * protection here. - */ - cachep->nodelists[node] = l3; - } - - spin_lock_irq(&cachep->nodelists[node]->list_lock); - cachep->nodelists[node]->free_limit = - (1 + nr_cpus_node(node)) * - cachep->batchcount + cachep->num; - spin_unlock_irq(&cachep->nodelists[node]->list_lock); - } + err = init_cache_nodelists_node(node); + if (err < 0) + goto bad; /* * Now we can go ahead with allocating the shared arrays and @@ -1331,11 +1352,75 @@ static struct notifier_block __cpuinitdata cpucache_notifier = { &cpuup_callback, NULL, 0 }; +#if defined(CONFIG_NUMA) && defined(CONFIG_MEMORY_HOTPLUG) +/* + * Drains freelist for a node on each slab cache, used for memory hot-remove. + * Returns -EBUSY if all objects cannot be drained so that the node is not + * removed. + * + * Must hold cache_chain_mutex. + */ +static int __meminit drain_cache_nodelists_node(int node) +{ + struct kmem_cache *cachep; + int ret = 0; + + list_for_each_entry(cachep, &cache_chain, next) { + struct kmem_list3 *l3; + + l3 = cachep->nodelists[node]; + if (!l3) + continue; + + drain_freelist(cachep, l3, l3->free_objects); + + if (!list_empty(&l3->slabs_full) || + !list_empty(&l3->slabs_partial)) { + ret = -EBUSY; + break; + } + } + return ret; +} + +static int __meminit slab_memory_callback(struct notifier_block *self, + unsigned long action, void *arg) +{ + struct memory_notify *mnb = arg; + int ret = 0; + int nid; + + nid = mnb->status_change_nid; + if (nid < 0) + goto out; + + switch (action) { + case MEM_GOING_ONLINE: + mutex_lock(&cache_chain_mutex); + ret = init_cache_nodelists_node(nid); + mutex_unlock(&cache_chain_mutex); + break; + case MEM_GOING_OFFLINE: + mutex_lock(&cache_chain_mutex); + ret = drain_cache_nodelists_node(nid); + mutex_unlock(&cache_chain_mutex); + break; + case MEM_ONLINE: + case MEM_OFFLINE: + case MEM_CANCEL_ONLINE: + case MEM_CANCEL_OFFLINE: + break; + } +out: + return ret ? notifier_from_errno(ret) : NOTIFY_OK; +} +#endif /* CONFIG_NUMA && CONFIG_MEMORY_HOTPLUG */ + /* * swap the static kmem_list3 with kmalloced memory */ -static void init_list(struct kmem_cache *cachep, struct kmem_list3 *list, - int nodeid) +static void __init init_list(struct kmem_cache *cachep, struct kmem_list3 *list, + int nodeid) { struct kmem_list3 *ptr; @@ -1580,6 +1665,14 @@ void __init kmem_cache_init_late(void) */ register_cpu_notifier(&cpucache_notifier); +#ifdef CONFIG_NUMA + /* + * Register a memory hotplug callback that initializes and frees + * nodelists. + */ + hotplug_memory_notifier(slab_memory_callback, SLAB_CALLBACK_PRI); +#endif + /* * The reap timers are started later, with a module init call: That part * of the kernel is not yet operational. From 4a96b4fcd6b35e9233df07b3c9ab38091edcfe7e Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Sun, 4 Apr 2010 15:19:52 +0200 Subject: [PATCH 0011/1337] firewire: ohci: add a function for reading PHY registers Move the register reading code from ohci_update_phy_reg() into a function which can be used separately. Signed-off-by: Clemens Ladisch Signed-off-by: Stefan Richter --- drivers/firewire/ohci.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c index e33917bf97d2..8ebccda94df9 100644 --- a/drivers/firewire/ohci.c +++ b/drivers/firewire/ohci.c @@ -460,22 +460,36 @@ static inline void flush_writes(const struct fw_ohci *ohci) reg_read(ohci, OHCI1394_Version); } -static int ohci_update_phy_reg(struct fw_card *card, int addr, - int clear_bits, int set_bits) +static int read_phy_reg(struct fw_card *card, int addr, u32 *value) { struct fw_ohci *ohci = fw_ohci(card); - u32 val, old; + u32 val; reg_write(ohci, OHCI1394_PhyControl, OHCI1394_PhyControl_Read(addr)); flush_writes(ohci); msleep(2); val = reg_read(ohci, OHCI1394_PhyControl); if ((val & OHCI1394_PhyControl_ReadDone) == 0) { - fw_error("failed to set phy reg bits.\n"); + fw_error("failed to read phy reg bits\n"); return -EBUSY; } - old = OHCI1394_PhyControl_ReadData(val); + *value = OHCI1394_PhyControl_ReadData(val); + + return 0; +} + +static int ohci_update_phy_reg(struct fw_card *card, int addr, + int clear_bits, int set_bits) +{ + struct fw_ohci *ohci = fw_ohci(card); + u32 old; + int err; + + err = read_phy_reg(card, addr, &old); + if (err < 0) + return err; + old = (old & ~clear_bits) | set_bits; reg_write(ohci, OHCI1394_PhyControl, OHCI1394_PhyControl_Write(addr, old)); From e7014dada041982ae12ba7fd1967ca0ab0243e04 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Thu, 1 Apr 2010 16:40:18 +0200 Subject: [PATCH 0012/1337] firewire: ohci: do not clear PHY interrupt status inadvertently The interrupt status bits in PHY register 5 are cleared by writing a one bit. To avoid clearing them unadvertently, do not write them back when they were read as set, but only when they have been explicitly requested to be set. Signed-off-by: Clemens Ladisch Signed-off-by: Stefan Richter --- drivers/firewire/core.h | 1 + drivers/firewire/ohci.c | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/drivers/firewire/core.h b/drivers/firewire/core.h index fb0321300cce..b2a7b651473a 100644 --- a/drivers/firewire/core.h +++ b/drivers/firewire/core.h @@ -28,6 +28,7 @@ struct fw_packet; #define PHY_CONTENDER 0x40 #define PHY_BUS_RESET 0x40 #define PHY_BUS_SHORT_RESET 0x40 +#define PHY_INT_STATUS_BITS 0x3c #define BANDWIDTH_AVAILABLE_INITIAL 4915 #define BROADCAST_CHANNEL_INITIAL (1 << 31 | 31) diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c index 8ebccda94df9..525848f71c34 100644 --- a/drivers/firewire/ohci.c +++ b/drivers/firewire/ohci.c @@ -490,6 +490,13 @@ static int ohci_update_phy_reg(struct fw_card *card, int addr, if (err < 0) return err; + /* + * The interrupt status bits are cleared by writing a one bit. + * Avoid clearing them unless explicitly requested in set_bits. + */ + if (addr == 5) + clear_bits |= PHY_INT_STATUS_BITS; + old = (old & ~clear_bits) | set_bits; reg_write(ohci, OHCI1394_PhyControl, OHCI1394_PhyControl_Write(addr, old)); From 925e7a6504966b838c519f009086982c68e0666f Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Sun, 4 Apr 2010 15:19:54 +0200 Subject: [PATCH 0013/1337] firewire: ohci: enable 1394a enhancements The OHCI spec says that, if the programPhyEnable bit is set, the driver is responsible for configuring the IEEE1394a enhancements within the PHY and the link consistently. So do this. Also add a quirk to allow disabling these enhancements; this is needed for the TSB12LV22 where ack accelerations are buggy (erratum b). Signed-off-by: Clemens Ladisch Signed-off-by: Stefan Richter --- drivers/firewire/core.h | 4 ++ drivers/firewire/ohci.c | 83 ++++++++++++++++++++++++++++++++++++++++- drivers/firewire/ohci.h | 2 +- 3 files changed, 86 insertions(+), 3 deletions(-) diff --git a/drivers/firewire/core.h b/drivers/firewire/core.h index b2a7b651473a..7a9759bf6837 100644 --- a/drivers/firewire/core.h +++ b/drivers/firewire/core.h @@ -27,8 +27,12 @@ struct fw_packet; #define PHY_LINK_ACTIVE 0x80 #define PHY_CONTENDER 0x40 #define PHY_BUS_RESET 0x40 +#define PHY_EXTENDED_REGISTERS 0xe0 #define PHY_BUS_SHORT_RESET 0x40 #define PHY_INT_STATUS_BITS 0x3c +#define PHY_ENABLE_ACCEL 0x02 +#define PHY_ENABLE_MULTI 0x01 +#define PHY_PAGE_SELECT 0xe0 #define BANDWIDTH_AVAILABLE_INITIAL 4915 #define BROADCAST_CHANNEL_INITIAL (1 << 31 | 31) diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c index 525848f71c34..e934713f3fce 100644 --- a/drivers/firewire/ohci.c +++ b/drivers/firewire/ohci.c @@ -236,13 +236,15 @@ static char ohci_driver_name[] = KBUILD_MODNAME; #define QUIRK_CYCLE_TIMER 1 #define QUIRK_RESET_PACKET 2 #define QUIRK_BE_HEADERS 4 +#define QUIRK_NO_1394A 8 /* In case of multiple matches in ohci_quirks[], only the first one is used. */ static const struct { unsigned short vendor, device, flags; } ohci_quirks[] = { {PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_TSB12LV22, QUIRK_CYCLE_TIMER | - QUIRK_RESET_PACKET}, + QUIRK_RESET_PACKET | + QUIRK_NO_1394A}, {PCI_VENDOR_ID_TI, PCI_ANY_ID, QUIRK_RESET_PACKET}, {PCI_VENDOR_ID_AL, PCI_ANY_ID, QUIRK_CYCLE_TIMER}, {PCI_VENDOR_ID_NEC, PCI_ANY_ID, QUIRK_CYCLE_TIMER}, @@ -257,6 +259,7 @@ MODULE_PARM_DESC(quirks, "Chip quirks (default = 0" ", nonatomic cycle timer = " __stringify(QUIRK_CYCLE_TIMER) ", reset packet generation = " __stringify(QUIRK_RESET_PACKET) ", AR/selfID endianess = " __stringify(QUIRK_BE_HEADERS) + ", no 1394a enhancements = " __stringify(QUIRK_NO_1394A) ")"); #ifdef CONFIG_FIREWIRE_OHCI_DEBUG @@ -504,6 +507,27 @@ static int ohci_update_phy_reg(struct fw_card *card, int addr, return 0; } +static int read_paged_phy_reg(struct fw_card *card, + int page, int addr, u32 *value) +{ + struct fw_ohci *ohci = fw_ohci(card); + u32 reg; + int err; + + err = ohci_update_phy_reg(card, 7, PHY_PAGE_SELECT, page << 5); + if (err < 0) + return err; + flush_writes(ohci); + msleep(2); + reg = reg_read(ohci, OHCI1394_PhyControl); + if ((reg & OHCI1394_PhyControl_WritePending) != 0) { + fw_error("failed to write phy reg bits\n"); + return -EBUSY; + } + + return read_phy_reg(card, addr, value); +} + static int ar_context_add_page(struct ar_context *ctx) { struct device *dev = ctx->ohci->card.device; @@ -1511,13 +1535,64 @@ static void copy_config_rom(__be32 *dest, const __be32 *src, size_t length) memset(&dest[length], 0, CONFIG_ROM_SIZE - size); } +static int configure_1394a_enhancements(struct fw_ohci *ohci) +{ + bool enable_1394a; + u32 reg, phy_compliance; + int clear, set, offset; + + /* Check if the driver should configure link and PHY. */ + if (!(reg_read(ohci, OHCI1394_HCControlSet) & + OHCI1394_HCControl_programPhyEnable)) + return 0; + + /* Paranoia: check whether the PHY supports 1394a, too. */ + enable_1394a = false; + if (read_phy_reg(&ohci->card, 2, ®) < 0) + return -EIO; + if ((reg & PHY_EXTENDED_REGISTERS) == PHY_EXTENDED_REGISTERS) { + if (read_paged_phy_reg(&ohci->card, 1, 8, &phy_compliance) < 0) + return -EIO; + if (phy_compliance >= 1) + enable_1394a = true; + } + + if (ohci->quirks & QUIRK_NO_1394A) + enable_1394a = false; + + /* Configure PHY and link consistently. */ + if (enable_1394a) { + clear = 0; + set = PHY_ENABLE_ACCEL | PHY_ENABLE_MULTI; + } else { + clear = PHY_ENABLE_ACCEL | PHY_ENABLE_MULTI; + set = 0; + } + if (ohci_update_phy_reg(&ohci->card, 5, clear, set) < 0) + return -EIO; + flush_writes(ohci); + msleep(2); + + if (enable_1394a) + offset = OHCI1394_HCControlSet; + else + offset = OHCI1394_HCControlClear; + reg_write(ohci, offset, OHCI1394_HCControl_aPhyEnhanceEnable); + + /* Clean up: configuration has been taken care of. */ + reg_write(ohci, OHCI1394_HCControlClear, + OHCI1394_HCControl_programPhyEnable); + + return 0; +} + static int ohci_enable(struct fw_card *card, const __be32 *config_rom, size_t length) { struct fw_ohci *ohci = fw_ohci(card); struct pci_dev *dev = to_pci_dev(card->device); u32 lps; - int i; + int i, err; if (software_reset(ohci)) { fw_error("Failed to reset ohci card.\n"); @@ -1581,6 +1656,10 @@ static int ohci_enable(struct fw_card *card, if (param_debug & OHCI_PARAM_DEBUG_BUSRESETS) reg_write(ohci, OHCI1394_IntMaskSet, OHCI1394_busReset); + err = configure_1394a_enhancements(ohci); + if (err < 0) + return err; + /* Activate link_on bit and contender bit in our self ID packets.*/ if (ohci_update_phy_reg(card, 4, 0, PHY_LINK_ACTIVE | PHY_CONTENDER) < 0) diff --git a/drivers/firewire/ohci.h b/drivers/firewire/ohci.h index ba492d85c516..d49e1469a986 100644 --- a/drivers/firewire/ohci.h +++ b/drivers/firewire/ohci.h @@ -67,7 +67,7 @@ #define OHCI1394_PhyControl_ReadDone 0x80000000 #define OHCI1394_PhyControl_ReadData(r) (((r) & 0x00ff0000) >> 16) #define OHCI1394_PhyControl_Write(addr, data) (((addr) << 8) | (data) | 0x00004000) -#define OHCI1394_PhyControl_WriteDone 0x00004000 +#define OHCI1394_PhyControl_WritePending 0x00004000 #define OHCI1394_IsochronousCycleTimer 0x0F0 #define OHCI1394_AsReqFilterHiSet 0x100 #define OHCI1394_AsReqFilterHiClear 0x104 From 54672386ccf36ffa21d1de8e75624af83f9b0eeb Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Thu, 1 Apr 2010 16:43:59 +0200 Subject: [PATCH 0014/1337] firewire: ohci: fix up configuration of TI chips On TI chips (OHCI-Lynx and later), enable link enhancements features that TI recommends to be used. None of these are required for proper operation, but they are safe and nice to have. In theory, these bits should have been set by default, but in practice, some BIOS/EEPROM writers apparently do not read the datasheet, or get spooked by names like "unfair". Signed-off-by: Clemens Ladisch Signed-off-by: Stefan Richter --- drivers/firewire/ohci.c | 19 ++++++++++++++++++- drivers/firewire/ohci.h | 8 ++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c index e934713f3fce..6a27a0ef3b63 100644 --- a/drivers/firewire/ohci.c +++ b/drivers/firewire/ohci.c @@ -2431,7 +2431,7 @@ static int __devinit pci_probe(struct pci_dev *dev, const struct pci_device_id *ent) { struct fw_ohci *ohci; - u32 bus_options, max_receive, link_speed, version; + u32 bus_options, max_receive, link_speed, version, link_enh; u64 guid; int i, err, n_ir, n_it; size_t size; @@ -2484,6 +2484,23 @@ static int __devinit pci_probe(struct pci_dev *dev, if (param_quirks) ohci->quirks = param_quirks; + /* TI OHCI-Lynx and compatible: set recommended configuration bits. */ + if (dev->vendor == PCI_VENDOR_ID_TI) { + pci_read_config_dword(dev, PCI_CFG_TI_LinkEnh, &link_enh); + + /* adjust latency of ATx FIFO: use 1.7 KB threshold */ + link_enh &= ~TI_LinkEnh_atx_thresh_mask; + link_enh |= TI_LinkEnh_atx_thresh_1_7K; + + /* use priority arbitration for asynchronous responses */ + link_enh |= TI_LinkEnh_enab_unfair; + + /* required for aPhyEnhanceEnable to work */ + link_enh |= TI_LinkEnh_enab_accel; + + pci_write_config_dword(dev, PCI_CFG_TI_LinkEnh, link_enh); + } + ar_context_init(&ohci->ar_request_ctx, ohci, OHCI1394_AsReqRcvContextControlSet); diff --git a/drivers/firewire/ohci.h b/drivers/firewire/ohci.h index d49e1469a986..3bc9a5d744eb 100644 --- a/drivers/firewire/ohci.h +++ b/drivers/firewire/ohci.h @@ -154,4 +154,12 @@ #define OHCI1394_phy_tcode 0xe +/* TI extensions */ + +#define PCI_CFG_TI_LinkEnh 0xf4 +#define TI_LinkEnh_enab_accel 0x00000002 +#define TI_LinkEnh_enab_unfair 0x00000080 +#define TI_LinkEnh_atx_thresh_mask 0x00003000 +#define TI_LinkEnh_atx_thresh_1_7K 0x00001000 + #endif /* _FIREWIRE_OHCI_H */ From 35d999b12037b5ea0152889232629c25d45b0e26 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sat, 10 Apr 2010 16:04:56 +0200 Subject: [PATCH 0015/1337] firewire: ohci: wait for PHY register accesses to complete Rather than having the arbitrary msleep(2) pause, let read_phy_reg() loop until the link--phy access was finished. Factor write_phy_reg() out of ohci_update_phy_reg() and of read_paged_phy_reg() and let it loop too until the link--phy access was finished. Like in the older ohci1394 driver, a timeout of 100 milliseconds is chosen. Unlike the old driver, we sleep instead of busy-wait in each waiting loop iteration. Instead of a loop, the waiting could probably also be implemented interrupt driven, but why bother. It would require up and running interrupt handling before the link was fully configured and enabled. Also modify functions a bit: Error return and value return can be combined in read_phy_reg() since the domain of values is only u8. Likewise in read_paged_phy_reg(). Signed-off-by: Stefan Richter --- drivers/firewire/ohci.c | 112 ++++++++++++++++++++-------------------- 1 file changed, 57 insertions(+), 55 deletions(-) diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c index 6a27a0ef3b63..5bbf42eb3f9a 100644 --- a/drivers/firewire/ohci.c +++ b/drivers/firewire/ohci.c @@ -463,35 +463,51 @@ static inline void flush_writes(const struct fw_ohci *ohci) reg_read(ohci, OHCI1394_Version); } -static int read_phy_reg(struct fw_card *card, int addr, u32 *value) +static int read_phy_reg(struct fw_ohci *ohci, int addr) { - struct fw_ohci *ohci = fw_ohci(card); u32 val; + int i; reg_write(ohci, OHCI1394_PhyControl, OHCI1394_PhyControl_Read(addr)); - flush_writes(ohci); - msleep(2); - val = reg_read(ohci, OHCI1394_PhyControl); - if ((val & OHCI1394_PhyControl_ReadDone) == 0) { - fw_error("failed to read phy reg bits\n"); - return -EBUSY; + for (i = 0; i < 10; i++) { + val = reg_read(ohci, OHCI1394_PhyControl); + if (val & OHCI1394_PhyControl_ReadDone) + return OHCI1394_PhyControl_ReadData(val); + + msleep(1); } + fw_error("failed to read phy reg\n"); - *value = OHCI1394_PhyControl_ReadData(val); + return -EBUSY; +} - return 0; +static int write_phy_reg(const struct fw_ohci *ohci, int addr, u32 val) +{ + int i; + + reg_write(ohci, OHCI1394_PhyControl, + OHCI1394_PhyControl_Write(addr, val)); + for (i = 0; i < 100; i++) { + val = reg_read(ohci, OHCI1394_PhyControl); + if (!(val & OHCI1394_PhyControl_WritePending)) + return 0; + + msleep(1); + } + fw_error("failed to write phy reg\n"); + + return -EBUSY; } static int ohci_update_phy_reg(struct fw_card *card, int addr, int clear_bits, int set_bits) { struct fw_ohci *ohci = fw_ohci(card); - u32 old; - int err; + int ret; - err = read_phy_reg(card, addr, &old); - if (err < 0) - return err; + ret = read_phy_reg(ohci, addr); + if (ret < 0) + return ret; /* * The interrupt status bits are cleared by writing a one bit. @@ -500,32 +516,18 @@ static int ohci_update_phy_reg(struct fw_card *card, int addr, if (addr == 5) clear_bits |= PHY_INT_STATUS_BITS; - old = (old & ~clear_bits) | set_bits; - reg_write(ohci, OHCI1394_PhyControl, - OHCI1394_PhyControl_Write(addr, old)); - - return 0; + return write_phy_reg(ohci, addr, (ret & ~clear_bits) | set_bits); } -static int read_paged_phy_reg(struct fw_card *card, - int page, int addr, u32 *value) +static int read_paged_phy_reg(struct fw_ohci *ohci, int page, int addr) { - struct fw_ohci *ohci = fw_ohci(card); - u32 reg; - int err; + int ret; - err = ohci_update_phy_reg(card, 7, PHY_PAGE_SELECT, page << 5); - if (err < 0) - return err; - flush_writes(ohci); - msleep(2); - reg = reg_read(ohci, OHCI1394_PhyControl); - if ((reg & OHCI1394_PhyControl_WritePending) != 0) { - fw_error("failed to write phy reg bits\n"); - return -EBUSY; - } + ret = ohci_update_phy_reg(&ohci->card, 7, PHY_PAGE_SELECT, page << 5); + if (ret < 0) + return ret; - return read_phy_reg(card, addr, value); + return read_phy_reg(ohci, addr); } static int ar_context_add_page(struct ar_context *ctx) @@ -1538,8 +1540,7 @@ static void copy_config_rom(__be32 *dest, const __be32 *src, size_t length) static int configure_1394a_enhancements(struct fw_ohci *ohci) { bool enable_1394a; - u32 reg, phy_compliance; - int clear, set, offset; + int ret, clear, set, offset; /* Check if the driver should configure link and PHY. */ if (!(reg_read(ohci, OHCI1394_HCControlSet) & @@ -1548,12 +1549,14 @@ static int configure_1394a_enhancements(struct fw_ohci *ohci) /* Paranoia: check whether the PHY supports 1394a, too. */ enable_1394a = false; - if (read_phy_reg(&ohci->card, 2, ®) < 0) - return -EIO; - if ((reg & PHY_EXTENDED_REGISTERS) == PHY_EXTENDED_REGISTERS) { - if (read_paged_phy_reg(&ohci->card, 1, 8, &phy_compliance) < 0) - return -EIO; - if (phy_compliance >= 1) + ret = read_phy_reg(ohci, 2); + if (ret < 0) + return ret; + if ((ret & PHY_EXTENDED_REGISTERS) == PHY_EXTENDED_REGISTERS) { + ret = read_paged_phy_reg(ohci, 1, 8); + if (ret < 0) + return ret; + if (ret >= 1) enable_1394a = true; } @@ -1568,10 +1571,9 @@ static int configure_1394a_enhancements(struct fw_ohci *ohci) clear = PHY_ENABLE_ACCEL | PHY_ENABLE_MULTI; set = 0; } - if (ohci_update_phy_reg(&ohci->card, 5, clear, set) < 0) - return -EIO; - flush_writes(ohci); - msleep(2); + ret = ohci_update_phy_reg(&ohci->card, 5, clear, set); + if (ret < 0) + return ret; if (enable_1394a) offset = OHCI1394_HCControlSet; @@ -1592,7 +1594,7 @@ static int ohci_enable(struct fw_card *card, struct fw_ohci *ohci = fw_ohci(card); struct pci_dev *dev = to_pci_dev(card->device); u32 lps; - int i, err; + int i, ret; if (software_reset(ohci)) { fw_error("Failed to reset ohci card.\n"); @@ -1656,14 +1658,14 @@ static int ohci_enable(struct fw_card *card, if (param_debug & OHCI_PARAM_DEBUG_BUSRESETS) reg_write(ohci, OHCI1394_IntMaskSet, OHCI1394_busReset); - err = configure_1394a_enhancements(ohci); - if (err < 0) - return err; + ret = configure_1394a_enhancements(ohci); + if (ret < 0) + return ret; /* Activate link_on bit and contender bit in our self ID packets.*/ - if (ohci_update_phy_reg(card, 4, 0, - PHY_LINK_ACTIVE | PHY_CONTENDER) < 0) - return -EIO; + ret = ohci_update_phy_reg(card, 4, 0, PHY_LINK_ACTIVE | PHY_CONTENDER); + if (ret < 0) + return ret; /* * When the link is not yet enabled, the atomic config rom From 5da3dac8d99c9933f12286fd73fa18e26f768bea Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Fri, 2 Apr 2010 14:05:02 +0200 Subject: [PATCH 0016/1337] firewire: ohci: cleanups and fix for nonstandard build without debug facility 1) Clean up two function names: The ohci_ prefix is only used in names of fw_card_driver hooks. There were two unnecessary exceptions. 2) Replace empty macros by empty inline functions so that call parameter type checking is available in #ifndef'd builds. 3) CONFIG_FIREWIRE_OHCI_DEBUG is currently a hidden kconfig variable, hence is not going to be switched off by anybody. Still, it can be switched off but then compilation will fail in ohci_enable() at the expression param_debug & OHCI_PARAM_DEBUG_BUSRESETS. Add the necessary definitions in the nonstandard case. Signed-off-by: Stefan Richter --- drivers/firewire/ohci.c | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c index 5bbf42eb3f9a..07deac77bc13 100644 --- a/drivers/firewire/ohci.c +++ b/drivers/firewire/ohci.c @@ -262,13 +262,13 @@ MODULE_PARM_DESC(quirks, "Chip quirks (default = 0" ", no 1394a enhancements = " __stringify(QUIRK_NO_1394A) ")"); -#ifdef CONFIG_FIREWIRE_OHCI_DEBUG - #define OHCI_PARAM_DEBUG_AT_AR 1 #define OHCI_PARAM_DEBUG_SELFIDS 2 #define OHCI_PARAM_DEBUG_IRQS 4 #define OHCI_PARAM_DEBUG_BUSRESETS 8 /* only effective before chip init */ +#ifdef CONFIG_FIREWIRE_OHCI_DEBUG + static int param_debug; module_param_named(debug, param_debug, int, 0644); MODULE_PARM_DESC(debug, "Verbose logging (default = 0" @@ -441,9 +441,10 @@ static void log_ar_at_event(char dir, int speed, u32 *header, int evt) #else -#define log_irqs(evt) -#define log_selfids(node_id, generation, self_id_count, sid) -#define log_ar_at_event(dir, speed, header, evt) +#define param_debug 0 +static inline void log_irqs(u32 evt) {} +static inline void log_selfids(int node_id, int generation, int self_id_count, u32 *s) {} +static inline void log_ar_at_event(char dir, int speed, u32 *header, int evt) {} #endif /* CONFIG_FIREWIRE_OHCI_DEBUG */ @@ -2401,7 +2402,7 @@ static const struct fw_card_driver ohci_driver = { }; #ifdef CONFIG_PPC_PMAC -static void ohci_pmac_on(struct pci_dev *dev) +static void pmac_ohci_on(struct pci_dev *dev) { if (machine_is(powermac)) { struct device_node *ofn = pci_device_to_OF_node(dev); @@ -2413,7 +2414,7 @@ static void ohci_pmac_on(struct pci_dev *dev) } } -static void ohci_pmac_off(struct pci_dev *dev) +static void pmac_ohci_off(struct pci_dev *dev) { if (machine_is(powermac)) { struct device_node *ofn = pci_device_to_OF_node(dev); @@ -2425,8 +2426,8 @@ static void ohci_pmac_off(struct pci_dev *dev) } } #else -#define ohci_pmac_on(dev) -#define ohci_pmac_off(dev) +static inline void pmac_ohci_on(struct pci_dev *dev) {} +static inline void pmac_ohci_off(struct pci_dev *dev) {} #endif /* CONFIG_PPC_PMAC */ static int __devinit pci_probe(struct pci_dev *dev, @@ -2446,7 +2447,7 @@ static int __devinit pci_probe(struct pci_dev *dev, fw_card_initialize(&ohci->card, &ohci_driver, &dev->dev); - ohci_pmac_on(dev); + pmac_ohci_on(dev); err = pci_enable_device(dev); if (err) { @@ -2580,7 +2581,7 @@ static int __devinit pci_probe(struct pci_dev *dev, pci_disable_device(dev); fail_free: kfree(&ohci->card); - ohci_pmac_off(dev); + pmac_ohci_off(dev); fail: if (err == -ENOMEM) fw_error("Out of memory\n"); @@ -2623,7 +2624,7 @@ static void pci_remove(struct pci_dev *dev) pci_release_region(dev, 0); pci_disable_device(dev); kfree(&ohci->card); - ohci_pmac_off(dev); + pmac_ohci_off(dev); fw_notify("Removed fw-ohci device.\n"); } @@ -2644,7 +2645,7 @@ static int pci_suspend(struct pci_dev *dev, pm_message_t state) err = pci_set_power_state(dev, pci_choose_state(dev, state)); if (err) fw_error("pci_set_power_state failed with %d\n", err); - ohci_pmac_off(dev); + pmac_ohci_off(dev); return 0; } @@ -2654,7 +2655,7 @@ static int pci_resume(struct pci_dev *dev) struct fw_ohci *ohci = pci_get_drvdata(dev); int err; - ohci_pmac_on(dev); + pmac_ohci_on(dev); pci_set_power_state(dev, PCI_D0); pci_restore_state(dev); err = pci_enable_device(dev); From 3ac26b2ee30005930117fe6a180c139c5f300faf Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sat, 10 Apr 2010 16:38:05 +0100 Subject: [PATCH 0017/1337] firewire: cdev: mark char device files as not seekable The character device file ABI (i.e. /dev/fw* character device file interface) does not make any use of lseek(), pread(), pwrite() (or any kind of write() at all). Use nonseekable_open() and, redundantly, set file_operations.llseek to no_llseek to remove any doubt whether the BKL-grabbing default_llseek handler is used. (Also shuffle file_operations initialization according to the order of handler definitions.) Signed-off-by: Stefan Richter --- drivers/firewire/core-cdev.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c index 0d3df0927efc..9d1a1a1a83c9 100644 --- a/drivers/firewire/core-cdev.c +++ b/drivers/firewire/core-cdev.c @@ -226,7 +226,7 @@ static int fw_device_op_open(struct inode *inode, struct file *file) list_add_tail(&client->link, &device->client_list); mutex_unlock(&device->client_list_mutex); - return 0; + return nonseekable_open(inode, file); } static void queue_event(struct client *client, struct event *event, @@ -1495,13 +1495,13 @@ static unsigned int fw_device_op_poll(struct file *file, poll_table * pt) const struct file_operations fw_device_ops = { .owner = THIS_MODULE, + .llseek = no_llseek, .open = fw_device_op_open, .read = fw_device_op_read, .unlocked_ioctl = fw_device_op_ioctl, - .poll = fw_device_op_poll, - .release = fw_device_op_release, .mmap = fw_device_op_mmap, - + .release = fw_device_op_release, + .poll = fw_device_op_poll, #ifdef CONFIG_COMPAT .compat_ioctl = fw_device_op_compat_ioctl, #endif From 7cfe21aae155c26193fde617dc61d37a79a63f86 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sat, 10 Apr 2010 16:47:18 +0100 Subject: [PATCH 0018/1337] ieee1394: mark char device files as not seekable The - raw1394 (/dev/raw1394), - video1394 (/dev/video1394/*), - dv1394 (/dev/dv1394/*) character device file ABIs do not make any use of lseek(), pread(), or pwrite(). Therefore use nonseekable_open() and, redundantly, set file_operations.llseek to no_llseek to remove any doubt whether the BKL- grabbing default_llseek handler is used. Although all this is legacy code which should be left in peace until it is eventually removed (as it is superseded by firewire-core's ABI), this change seems still worth doing to further minimize the presence of BKL usage in the kernel. Signed-off-by: Stefan Richter --- drivers/ieee1394/dv1394.c | 11 ++++++----- drivers/ieee1394/raw1394.c | 3 ++- drivers/ieee1394/video1394.c | 5 +++-- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/drivers/ieee1394/dv1394.c b/drivers/ieee1394/dv1394.c index 9fd4a0d3206e..adaefabc40e9 100644 --- a/drivers/ieee1394/dv1394.c +++ b/drivers/ieee1394/dv1394.c @@ -1824,7 +1824,7 @@ static int dv1394_open(struct inode *inode, struct file *file) "and will not be available in the new firewire driver stack. " "Try libraw1394 based programs instead.\n", current->comm); - return 0; + return nonseekable_open(inode, file); } @@ -2153,17 +2153,18 @@ static struct cdev dv1394_cdev; static const struct file_operations dv1394_fops= { .owner = THIS_MODULE, - .poll = dv1394_poll, + .poll = dv1394_poll, .unlocked_ioctl = dv1394_ioctl, #ifdef CONFIG_COMPAT .compat_ioctl = dv1394_compat_ioctl, #endif .mmap = dv1394_mmap, .open = dv1394_open, - .write = dv1394_write, - .read = dv1394_read, + .write = dv1394_write, + .read = dv1394_read, .release = dv1394_release, - .fasync = dv1394_fasync, + .fasync = dv1394_fasync, + .llseek = no_llseek, }; diff --git a/drivers/ieee1394/raw1394.c b/drivers/ieee1394/raw1394.c index 8aa56ac07e29..b563d5e9fa2e 100644 --- a/drivers/ieee1394/raw1394.c +++ b/drivers/ieee1394/raw1394.c @@ -2834,7 +2834,7 @@ static int raw1394_open(struct inode *inode, struct file *file) file->private_data = fi; - return 0; + return nonseekable_open(inode, file); } static int raw1394_release(struct inode *inode, struct file *file) @@ -3035,6 +3035,7 @@ static const struct file_operations raw1394_fops = { .poll = raw1394_poll, .open = raw1394_open, .release = raw1394_release, + .llseek = no_llseek, }; static int __init init_raw1394(void) diff --git a/drivers/ieee1394/video1394.c b/drivers/ieee1394/video1394.c index 949064a05675..a42bd6893bcf 100644 --- a/drivers/ieee1394/video1394.c +++ b/drivers/ieee1394/video1394.c @@ -1239,7 +1239,7 @@ static int video1394_open(struct inode *inode, struct file *file) ctx->current_ctx = NULL; file->private_data = ctx; - return 0; + return nonseekable_open(inode, file); } static int video1394_release(struct inode *inode, struct file *file) @@ -1287,7 +1287,8 @@ static const struct file_operations video1394_fops= .poll = video1394_poll, .mmap = video1394_mmap, .open = video1394_open, - .release = video1394_release + .release = video1394_release, + .llseek = no_llseek, }; /*** HOTPLUG STUFF **********************************************************/ From ded518c60967793706f19b2c63dc43deac29ef6f Mon Sep 17 00:00:00 2001 From: Vladimir Zapolskiy Date: Wed, 24 Mar 2010 14:32:17 +0300 Subject: [PATCH 0019/1337] imx3: Add rtc platform device support This patch adds support for build-in RTC device found on Freescale imx31 and imx35 SoCs. Signed-off-by: Vladimir Zapolskiy Cc: Sascha Hauer Signed-off-by: Sascha Hauer --- arch/arm/mach-mx3/devices.c | 19 +++++++++++++++++++ arch/arm/mach-mx3/devices.h | 1 + 2 files changed, 20 insertions(+) diff --git a/arch/arm/mach-mx3/devices.c b/arch/arm/mach-mx3/devices.c index f8911154a9fa..1ffed283d6cd 100644 --- a/arch/arm/mach-mx3/devices.c +++ b/arch/arm/mach-mx3/devices.c @@ -588,6 +588,25 @@ struct platform_device imx_wdt_device0 = { .resource = imx_wdt_resources, }; +static struct resource imx_rtc_resources[] = { + { + .start = MX31_RTC_BASE_ADDR, + .end = MX31_RTC_BASE_ADDR + 0x3fff, + .flags = IORESOURCE_MEM, + }, + { + .start = MX31_INT_RTC, + .flags = IORESOURCE_IRQ, + }, +}; + +struct platform_device imx_rtc_device0 = { + .name = "mxc_rtc", + .id = -1, + .num_resources = ARRAY_SIZE(imx_rtc_resources), + .resource = imx_rtc_resources, +}; + static int __init mx3_devices_init(void) { if (cpu_is_mx31()) { diff --git a/arch/arm/mach-mx3/devices.h b/arch/arm/mach-mx3/devices.h index 4f77eb501274..b1687ad72052 100644 --- a/arch/arm/mach-mx3/devices.h +++ b/arch/arm/mach-mx3/devices.h @@ -27,3 +27,4 @@ extern struct platform_device imx_ssi_device0; extern struct platform_device imx_ssi_device1; extern struct platform_device imx_ssi_device1; extern struct platform_device imx_wdt_device0; +extern struct platform_device imx_rtc_device0; From 8bcc84ad61a601f4d8fc960d5e6495d6fc88177b Mon Sep 17 00:00:00 2001 From: Vladimir Zapolskiy Date: Wed, 24 Mar 2010 14:32:18 +0300 Subject: [PATCH 0020/1337] imx31: add rtc device on litekit board. This patch adds support for SoC build-in RTC device on litekit board. Signed-off-by: Vladimir Zapolskiy Cc: Sascha Hauer Signed-off-by: Sascha Hauer --- arch/arm/mach-mx3/mx31lite-db.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/mach-mx3/mx31lite-db.c b/arch/arm/mach-mx3/mx31lite-db.c index 093c595ca581..5f05bfbec380 100644 --- a/arch/arm/mach-mx3/mx31lite-db.c +++ b/arch/arm/mach-mx3/mx31lite-db.c @@ -206,5 +206,6 @@ void __init mx31lite_db_init(void) mxc_register_device(&mxc_spi_device0, &spi0_pdata); platform_device_register(&litekit_led_device); mxc_register_device(&imx_wdt_device0, NULL); + mxc_register_device(&imx_rtc_device0, NULL); } From 7422f27a8ad7f6a7474e324a61e5a7f8be166c25 Mon Sep 17 00:00:00 2001 From: Ivo Clarysse Date: Thu, 8 Apr 2010 16:14:44 +0200 Subject: [PATCH 0021/1337] MXC: mxc_nand: set NFC registers after reset This patch allows the mxc_nand driver to reset the NAND flash controller. NFC registers are (re-)set after completion of the reset, as a reset will have reverted the NFC registers to their default values. Signed-off-by: Ivo Clarysse Signed-off-by: Sascha Hauer --- drivers/mtd/nand/mxc_nand.c | 90 ++++++++++++++++++++----------------- 1 file changed, 48 insertions(+), 42 deletions(-) diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c index b2900d8406d3..ed27d38de27a 100644 --- a/drivers/mtd/nand/mxc_nand.c +++ b/drivers/mtd/nand/mxc_nand.c @@ -542,6 +542,41 @@ static void mxc_do_addr_cycle(struct mtd_info *mtd, int column, int page_addr) } } +static void preset(struct mtd_info *mtd) +{ + struct nand_chip *nand_chip = mtd->priv; + struct mxc_nand_host *host = nand_chip->priv; + uint16_t tmp; + + /* disable interrupt, disable spare enable */ + tmp = readw(host->regs + NFC_CONFIG1); + tmp |= NFC_INT_MSK; + tmp &= ~NFC_SP_EN; + if (nand_chip->ecc.mode == NAND_ECC_HW) { + tmp |= NFC_ECC_EN; + } else { + tmp &= ~NFC_ECC_EN; + } + writew(tmp, host->regs + NFC_CONFIG1); + /* preset operation */ + + /* Unlock the internal RAM Buffer */ + writew(0x2, host->regs + NFC_CONFIG); + + /* Blocks to be unlocked */ + if (nfc_is_v21()) { + writew(0x0, host->regs + NFC_V21_UNLOCKSTART_BLKADDR); + writew(0xffff, host->regs + NFC_V21_UNLOCKEND_BLKADDR); + } else if (nfc_is_v1()) { + writew(0x0, host->regs + NFC_V1_UNLOCKSTART_BLKADDR); + writew(0x4000, host->regs + NFC_V1_UNLOCKEND_BLKADDR); + } else + BUG(); + + /* Unlock Block Command for given address range */ + writew(0x4, host->regs + NFC_WRPROT); +} + /* Used by the upper layer to write command to NAND Flash for * different operations to be carried out on NAND Flash */ static void mxc_nand_command(struct mtd_info *mtd, unsigned command, @@ -559,6 +594,10 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command, /* Command pre-processing step */ switch (command) { + case NAND_CMD_RESET: + send_cmd(host, command, false); + preset(mtd); + break; case NAND_CMD_STATUS: host->buf_start = 0; @@ -679,7 +718,6 @@ static int __init mxcnd_probe(struct platform_device *pdev) struct mxc_nand_platform_data *pdata = pdev->dev.platform_data; struct mxc_nand_host *host; struct resource *res; - uint16_t tmp; int err = 0, nr_parts = 0; struct nand_ecclayout *oob_smallpage, *oob_largepage; @@ -743,51 +781,17 @@ static int __init mxcnd_probe(struct platform_device *pdev) host->spare_len = 64; oob_smallpage = &nandv2_hw_eccoob_smallpage; oob_largepage = &nandv2_hw_eccoob_largepage; + this->ecc.bytes = 9; } else if (nfc_is_v1()) { host->regs = host->base; host->spare0 = host->base + 0x800; host->spare_len = 16; oob_smallpage = &nandv1_hw_eccoob_smallpage; oob_largepage = &nandv1_hw_eccoob_largepage; - } else - BUG(); - - /* disable interrupt and spare enable */ - tmp = readw(host->regs + NFC_CONFIG1); - tmp |= NFC_INT_MSK; - tmp &= ~NFC_SP_EN; - writew(tmp, host->regs + NFC_CONFIG1); - - init_waitqueue_head(&host->irq_waitq); - - host->irq = platform_get_irq(pdev, 0); - - err = request_irq(host->irq, mxc_nfc_irq, 0, DRIVER_NAME, host); - if (err) - goto eirq; - - /* Reset NAND */ - this->cmdfunc(mtd, NAND_CMD_RESET, -1, -1); - - /* preset operation */ - /* Unlock the internal RAM Buffer */ - writew(0x2, host->regs + NFC_CONFIG); - - /* Blocks to be unlocked */ - if (nfc_is_v21()) { - writew(0x0, host->regs + NFC_V21_UNLOCKSTART_BLKADDR); - writew(0xffff, host->regs + NFC_V21_UNLOCKEND_BLKADDR); - this->ecc.bytes = 9; - } else if (nfc_is_v1()) { - writew(0x0, host->regs + NFC_V1_UNLOCKSTART_BLKADDR); - writew(0x4000, host->regs + NFC_V1_UNLOCKEND_BLKADDR); this->ecc.bytes = 3; } else BUG(); - /* Unlock Block Command for given address range */ - writew(0x4, host->regs + NFC_WRPROT); - this->ecc.size = 512; this->ecc.layout = oob_smallpage; @@ -796,14 +800,8 @@ static int __init mxcnd_probe(struct platform_device *pdev) this->ecc.hwctl = mxc_nand_enable_hwecc; this->ecc.correct = mxc_nand_correct_data; this->ecc.mode = NAND_ECC_HW; - tmp = readw(host->regs + NFC_CONFIG1); - tmp |= NFC_ECC_EN; - writew(tmp, host->regs + NFC_CONFIG1); } else { this->ecc.mode = NAND_ECC_SOFT; - tmp = readw(host->regs + NFC_CONFIG1); - tmp &= ~NFC_ECC_EN; - writew(tmp, host->regs + NFC_CONFIG1); } /* NAND bus width determines access funtions used by upper layer */ @@ -817,6 +815,14 @@ static int __init mxcnd_probe(struct platform_device *pdev) this->options |= NAND_USE_FLASH_BBT; } + init_waitqueue_head(&host->irq_waitq); + + host->irq = platform_get_irq(pdev, 0); + + err = request_irq(host->irq, mxc_nfc_irq, 0, DRIVER_NAME, host); + if (err) + goto eirq; + /* first scan to find the device and get the page size */ if (nand_scan_ident(mtd, 1)) { err = -ENXIO; From 63f4079b6a90e2a8ee64c5900a6d4d0bcb79bc65 Mon Sep 17 00:00:00 2001 From: Ivo Clarysse Date: Thu, 8 Apr 2010 16:16:51 +0200 Subject: [PATCH 0022/1337] MXC: mxc_nand: support i.MX21 On i.MX21 SoCs, if the NFC_CONFIG1:NFC_INT_MASK bit is set, NFC_CONFIG2:NFC_INT always reads out zero, even if an operation is completed. This patch uses enable_irq and disable_irq_nosync instead of NFC_CONFIG1:NFC_INT_MASK to mask NFC interrupts. This allows NFC_CONFIG2:NFC_INT to also be used to detect operation completion on i.MX21. The i.MX21 NFC does not signal reset completion using NFC_CONFIG1:NFC_INT_MASK, so instead reset completion is tested by checking if NFC_CONFIG2 becomes 0. Signed-off-by: Ivo Clarysse Signed-off-by: Sascha Hauer --- drivers/mtd/nand/mxc_nand.c | 41 ++++++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 16 deletions(-) diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c index ed27d38de27a..fb03aff8e83a 100644 --- a/drivers/mtd/nand/mxc_nand.c +++ b/drivers/mtd/nand/mxc_nand.c @@ -38,7 +38,7 @@ #define DRIVER_NAME "mxc_nand" #define nfc_is_v21() (cpu_is_mx25() || cpu_is_mx35()) -#define nfc_is_v1() (cpu_is_mx31() || cpu_is_mx27()) +#define nfc_is_v1() (cpu_is_mx31() || cpu_is_mx27() || cpu_is_mx21()) /* Addresses for NFC registers */ #define NFC_BUF_SIZE 0xE00 @@ -168,11 +168,7 @@ static irqreturn_t mxc_nfc_irq(int irq, void *dev_id) { struct mxc_nand_host *host = dev_id; - uint16_t tmp; - - tmp = readw(host->regs + NFC_CONFIG1); - tmp |= NFC_INT_MSK; /* Disable interrupt */ - writew(tmp, host->regs + NFC_CONFIG1); + disable_irq_nosync(irq); wake_up(&host->irq_waitq); @@ -184,15 +180,13 @@ static irqreturn_t mxc_nfc_irq(int irq, void *dev_id) */ static void wait_op_done(struct mxc_nand_host *host, int useirq) { - uint32_t tmp; - int max_retries = 2000; + uint16_t tmp; + int max_retries = 8000; if (useirq) { if ((readw(host->regs + NFC_CONFIG2) & NFC_INT) == 0) { - tmp = readw(host->regs + NFC_CONFIG1); - tmp &= ~NFC_INT_MSK; /* Enable interrupt */ - writew(tmp, host->regs + NFC_CONFIG1); + enable_irq(host->irq); wait_event(host->irq_waitq, readw(host->regs + NFC_CONFIG2) & NFC_INT); @@ -226,8 +220,23 @@ static void send_cmd(struct mxc_nand_host *host, uint16_t cmd, int useirq) writew(cmd, host->regs + NFC_FLASH_CMD); writew(NFC_CMD, host->regs + NFC_CONFIG2); - /* Wait for operation to complete */ - wait_op_done(host, useirq); + if (cpu_is_mx21() && (cmd == NAND_CMD_RESET)) { + int max_retries = 100; + /* Reset completion is indicated by NFC_CONFIG2 */ + /* being set to 0 */ + while (max_retries-- > 0) { + if (readw(host->regs + NFC_CONFIG2) == 0) { + break; + } + udelay(1); + } + if (max_retries < 0) + DEBUG(MTD_DEBUG_LEVEL0, "%s: RESET failed\n", + __func__); + } else { + /* Wait for operation to complete */ + wait_op_done(host, useirq); + } } /* This function sends an address (or partial address) to the @@ -548,9 +557,9 @@ static void preset(struct mtd_info *mtd) struct mxc_nand_host *host = nand_chip->priv; uint16_t tmp; - /* disable interrupt, disable spare enable */ + /* enable interrupt, disable spare enable */ tmp = readw(host->regs + NFC_CONFIG1); - tmp |= NFC_INT_MSK; + tmp &= ~NFC_INT_MSK; tmp &= ~NFC_SP_EN; if (nand_chip->ecc.mode == NAND_ECC_HW) { tmp |= NFC_ECC_EN; @@ -819,7 +828,7 @@ static int __init mxcnd_probe(struct platform_device *pdev) host->irq = platform_get_irq(pdev, 0); - err = request_irq(host->irq, mxc_nfc_irq, 0, DRIVER_NAME, host); + err = request_irq(host->irq, mxc_nfc_irq, IRQF_DISABLED, DRIVER_NAME, host); if (err) goto eirq; From 066fb8472036805e31ee002097f619815e25a127 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Tue, 13 Apr 2010 20:11:37 +0200 Subject: [PATCH 0023/1337] ARM: mx3/lilly1131: add USB support Signed-off-by: Daniel Mack Cc: Sascha Hauer Signed-off-by: Sascha Hauer --- arch/arm/mach-mx3/Kconfig | 1 + arch/arm/mach-mx3/mach-mx31lilly.c | 145 +++++++++++++++++++++++++++++ 2 files changed, 146 insertions(+) diff --git a/arch/arm/mach-mx3/Kconfig b/arch/arm/mach-mx3/Kconfig index 170f68e46dd5..344753fdf25e 100644 --- a/arch/arm/mach-mx3/Kconfig +++ b/arch/arm/mach-mx3/Kconfig @@ -82,6 +82,7 @@ config MACH_MX31MOBOARD config MACH_MX31LILLY bool "Support MX31 LILLY-1131 platforms (INCO startec)" select ARCH_MX31 + select MXC_ULPI if USB_ULPI help Include support for mx31 based LILLY1131 modules. This includes specific configurations for the board and its peripherals. diff --git a/arch/arm/mach-mx3/mach-mx31lilly.c b/arch/arm/mach-mx3/mach-mx31lilly.c index 80847b04c063..d3d5877c750e 100644 --- a/arch/arm/mach-mx3/mach-mx31lilly.c +++ b/arch/arm/mach-mx3/mach-mx31lilly.c @@ -27,12 +27,15 @@ #include #include #include +#include #include #include #include #include #include #include +#include +#include #include #include @@ -44,6 +47,8 @@ #include #include #include +#include +#include #include "devices.h" @@ -108,6 +113,137 @@ static struct platform_device physmap_flash_device = { .num_resources = 1, }; +/* USB */ + +#define USB_PAD_CFG (PAD_CTL_DRV_MAX | PAD_CTL_SRE_FAST | PAD_CTL_HYS_CMOS | \ + PAD_CTL_ODE_CMOS | PAD_CTL_100K_PU) + +static int usbotg_init(struct platform_device *pdev) +{ + unsigned int pins[] = { + MX31_PIN_USBOTG_DATA0__USBOTG_DATA0, + MX31_PIN_USBOTG_DATA1__USBOTG_DATA1, + MX31_PIN_USBOTG_DATA2__USBOTG_DATA2, + MX31_PIN_USBOTG_DATA3__USBOTG_DATA3, + MX31_PIN_USBOTG_DATA4__USBOTG_DATA4, + MX31_PIN_USBOTG_DATA5__USBOTG_DATA5, + MX31_PIN_USBOTG_DATA6__USBOTG_DATA6, + MX31_PIN_USBOTG_DATA7__USBOTG_DATA7, + MX31_PIN_USBOTG_CLK__USBOTG_CLK, + MX31_PIN_USBOTG_DIR__USBOTG_DIR, + MX31_PIN_USBOTG_NXT__USBOTG_NXT, + MX31_PIN_USBOTG_STP__USBOTG_STP, + }; + + mxc_iomux_setup_multiple_pins(pins, ARRAY_SIZE(pins), "USB OTG"); + + mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA0, USB_PAD_CFG); + mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA1, USB_PAD_CFG); + mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA2, USB_PAD_CFG); + mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA3, USB_PAD_CFG); + mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA4, USB_PAD_CFG); + mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA5, USB_PAD_CFG); + mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA6, USB_PAD_CFG); + mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA7, USB_PAD_CFG); + mxc_iomux_set_pad(MX31_PIN_USBOTG_CLK, USB_PAD_CFG); + mxc_iomux_set_pad(MX31_PIN_USBOTG_DIR, USB_PAD_CFG); + mxc_iomux_set_pad(MX31_PIN_USBOTG_NXT, USB_PAD_CFG); + mxc_iomux_set_pad(MX31_PIN_USBOTG_STP, USB_PAD_CFG); + + mxc_iomux_set_gpr(MUX_PGP_USB_4WIRE, true); + mxc_iomux_set_gpr(MUX_PGP_USB_COMMON, true); + + /* chip select */ + mxc_iomux_alloc_pin(IOMUX_MODE(MX31_PIN_DTR_DCE2, IOMUX_CONFIG_GPIO), + "USBOTG_CS"); + gpio_request(IOMUX_TO_GPIO(MX31_PIN_DTR_DCE2), "USBH1 CS"); + gpio_direction_output(IOMUX_TO_GPIO(MX31_PIN_DTR_DCE2), 0); + + return 0; +} + +static int usbh1_init(struct platform_device *pdev) +{ + int pins[] = { + MX31_PIN_CSPI1_MOSI__USBH1_RXDM, + MX31_PIN_CSPI1_MISO__USBH1_RXDP, + MX31_PIN_CSPI1_SS0__USBH1_TXDM, + MX31_PIN_CSPI1_SS1__USBH1_TXDP, + MX31_PIN_CSPI1_SS2__USBH1_RCV, + MX31_PIN_CSPI1_SCLK__USBH1_OEB, + MX31_PIN_CSPI1_SPI_RDY__USBH1_FS, + }; + + mxc_iomux_setup_multiple_pins(pins, ARRAY_SIZE(pins), "USB H1"); + + mxc_iomux_set_pad(MX31_PIN_CSPI1_MOSI, USB_PAD_CFG); + mxc_iomux_set_pad(MX31_PIN_CSPI1_MISO, USB_PAD_CFG); + mxc_iomux_set_pad(MX31_PIN_CSPI1_SS0, USB_PAD_CFG); + mxc_iomux_set_pad(MX31_PIN_CSPI1_SS1, USB_PAD_CFG); + mxc_iomux_set_pad(MX31_PIN_CSPI1_SS2, USB_PAD_CFG); + mxc_iomux_set_pad(MX31_PIN_CSPI1_SCLK, USB_PAD_CFG); + mxc_iomux_set_pad(MX31_PIN_CSPI1_SPI_RDY, USB_PAD_CFG); + + mxc_iomux_set_gpr(MUX_PGP_USB_SUSPEND, true); + + return 0; +} + +static int usbh2_init(struct platform_device *pdev) +{ + int pins[] = { + MX31_PIN_USBH2_DATA0__USBH2_DATA0, + MX31_PIN_USBH2_DATA1__USBH2_DATA1, + MX31_PIN_USBH2_CLK__USBH2_CLK, + MX31_PIN_USBH2_DIR__USBH2_DIR, + MX31_PIN_USBH2_NXT__USBH2_NXT, + MX31_PIN_USBH2_STP__USBH2_STP, + }; + + mxc_iomux_setup_multiple_pins(pins, ARRAY_SIZE(pins), "USB H2"); + + mxc_iomux_set_pad(MX31_PIN_USBH2_CLK, USB_PAD_CFG); + mxc_iomux_set_pad(MX31_PIN_USBH2_DIR, USB_PAD_CFG); + mxc_iomux_set_pad(MX31_PIN_USBH2_NXT, USB_PAD_CFG); + mxc_iomux_set_pad(MX31_PIN_USBH2_STP, USB_PAD_CFG); + mxc_iomux_set_pad(MX31_PIN_USBH2_DATA0, USB_PAD_CFG); + mxc_iomux_set_pad(MX31_PIN_USBH2_DATA1, USB_PAD_CFG); + mxc_iomux_set_pad(MX31_PIN_SRXD6, USB_PAD_CFG); + mxc_iomux_set_pad(MX31_PIN_STXD6, USB_PAD_CFG); + mxc_iomux_set_pad(MX31_PIN_SFS3, USB_PAD_CFG); + mxc_iomux_set_pad(MX31_PIN_SCK3, USB_PAD_CFG); + mxc_iomux_set_pad(MX31_PIN_SRXD3, USB_PAD_CFG); + mxc_iomux_set_pad(MX31_PIN_STXD3, USB_PAD_CFG); + + mxc_iomux_set_gpr(MUX_PGP_UH2, true); + + /* chip select */ + mxc_iomux_alloc_pin(IOMUX_MODE(MX31_PIN_DTR_DCE1, IOMUX_CONFIG_GPIO), + "USBH2_CS"); + gpio_request(IOMUX_TO_GPIO(MX31_PIN_DTR_DCE1), "USBH2 CS"); + gpio_direction_output(IOMUX_TO_GPIO(MX31_PIN_DTR_DCE1), 0); + + return 0; +} + +static struct mxc_usbh_platform_data usbotg_pdata = { + .init = usbotg_init, + .portsc = MXC_EHCI_MODE_ULPI | MXC_EHCI_UTMI_8BIT, + .flags = MXC_EHCI_POWER_PINS_ENABLED, +}; + +static struct mxc_usbh_platform_data usbh1_pdata = { + .init = usbh1_init, + .portsc = MXC_EHCI_MODE_UTMI | MXC_EHCI_SERIAL, + .flags = MXC_EHCI_POWER_PINS_ENABLED | MXC_EHCI_INTERFACE_SINGLE_UNI, +}; + +static struct mxc_usbh_platform_data usbh2_pdata = { + .init = usbh2_init, + .portsc = MXC_EHCI_MODE_ULPI | MXC_EHCI_UTMI_8BIT, + .flags = MXC_EHCI_POWER_PINS_ENABLED, +}; + static struct platform_device *devices[] __initdata = { &smsc91x_device, &physmap_flash_device, @@ -183,6 +319,15 @@ static void __init mx31lilly_board_init(void) spi_register_board_info(&mc13783_dev, 1); platform_add_devices(devices, ARRAY_SIZE(devices)); + + /* USB */ + usbotg_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops, + USB_OTG_DRV_VBUS | USB_OTG_DRV_VBUS_EXT); + usbh2_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops, + USB_OTG_DRV_VBUS | USB_OTG_DRV_VBUS_EXT); + + mxc_register_device(&mxc_usbh1, &usbh1_pdata); + mxc_register_device(&mxc_usbh2, &usbh2_pdata); } static void __init mx31lilly_timer_init(void) From 4725f6f17691f4602e3e31d785da5a461a16ccfe Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Thu, 1 Apr 2010 10:03:23 +0200 Subject: [PATCH 0024/1337] ARM: MXC: mxcmmc: misc cleanups MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Be more verbose on error messages and add one debug message. Signed-off-by: Daniel Mack Cc: Sascha Hauer Cc: Dan Williams Cc: Volker Ernst Cc: Jiri Kosina Cc: Michał Mirosław Signed-off-by: Sascha Hauer --- drivers/mmc/host/mxcmmc.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/drivers/mmc/host/mxcmmc.c b/drivers/mmc/host/mxcmmc.c index 2df90412abb5..44a53ee5e212 100644 --- a/drivers/mmc/host/mxcmmc.c +++ b/drivers/mmc/host/mxcmmc.c @@ -151,6 +151,8 @@ static void mxcmci_softreset(struct mxcmci_host *host) { int i; + dev_dbg(mmc_dev(host->mmc), "mxcmci_softreset\n"); + /* reset sequence */ writew(STR_STP_CLK_RESET, host->base + MMC_REG_STR_STP_CLK); writew(STR_STP_CLK_RESET | STR_STP_CLK_START_CLK, @@ -290,16 +292,25 @@ static int mxcmci_finish_data(struct mxcmci_host *host, unsigned int stat) dev_dbg(mmc_dev(host->mmc), "request failed. status: 0x%08x\n", stat); if (stat & STATUS_CRC_READ_ERR) { + dev_err(mmc_dev(host->mmc), "%s: -EILSEQ\n", __func__); data->error = -EILSEQ; } else if (stat & STATUS_CRC_WRITE_ERR) { u32 err_code = (stat >> 9) & 0x3; - if (err_code == 2) /* No CRC response */ + if (err_code == 2) { /* No CRC response */ + dev_err(mmc_dev(host->mmc), + "%s: No CRC -ETIMEDOUT\n", __func__); data->error = -ETIMEDOUT; - else + } else { + dev_err(mmc_dev(host->mmc), + "%s: -EILSEQ\n", __func__); data->error = -EILSEQ; + } } else if (stat & STATUS_TIME_OUT_READ) { + dev_err(mmc_dev(host->mmc), + "%s: read -ETIMEDOUT\n", __func__); data->error = -ETIMEDOUT; } else { + dev_err(mmc_dev(host->mmc), "%s: -EIO\n", __func__); data->error = -EIO; } } else { @@ -433,8 +444,6 @@ static int mxcmci_transfer_data(struct mxcmci_host *host) struct scatterlist *sg; int stat, i; - host->datasize = 0; - host->data = data; host->datasize = 0; From f441b993101d4ee95222ccbaad1e0dd53ea90b64 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Thu, 1 Apr 2010 10:03:24 +0200 Subject: [PATCH 0025/1337] ARM: MXC: mxcmmc: Teach the driver SDIO operations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Successfully tested on MX31 hardware using libertas SDIO peripherals. Signed-off-by: Daniel Mack Cc: Sascha Hauer Cc: Dan Williams Cc: Volker Ernst Cc: Jiri Kosina Cc: Michał Mirosław Signed-off-by: Sascha Hauer --- drivers/mmc/host/mxcmmc.c | 70 +++++++++++++++++++++++++++++++++------ 1 file changed, 59 insertions(+), 11 deletions(-) diff --git a/drivers/mmc/host/mxcmmc.c b/drivers/mmc/host/mxcmmc.c index 44a53ee5e212..51e880c8f193 100644 --- a/drivers/mmc/host/mxcmmc.c +++ b/drivers/mmc/host/mxcmmc.c @@ -119,6 +119,7 @@ struct mxcmci_host { int detect_irq; int dma; int do_dma; + int use_sdio; unsigned int power_mode; struct imxmmc_platform_data *pdata; @@ -138,6 +139,7 @@ struct mxcmci_host { int clock; struct work_struct datawork; + spinlock_t lock; }; static void mxcmci_set_clk_rate(struct mxcmci_host *host, unsigned int clk_ios); @@ -226,6 +228,9 @@ static int mxcmci_setup_data(struct mxcmci_host *host, struct mmc_data *data) static int mxcmci_start_cmd(struct mxcmci_host *host, struct mmc_command *cmd, unsigned int cmdat) { + u32 int_cntr; + unsigned long flags; + WARN_ON(host->cmd != NULL); host->cmd = cmd; @@ -249,12 +254,16 @@ static int mxcmci_start_cmd(struct mxcmci_host *host, struct mmc_command *cmd, return -EINVAL; } + int_cntr = INT_END_CMD_RES_EN; + if (mxcmci_use_dma(host)) - writel(INT_READ_OP_EN | INT_WRITE_OP_DONE_EN | - INT_END_CMD_RES_EN, - host->base + MMC_REG_INT_CNTR); - else - writel(INT_END_CMD_RES_EN, host->base + MMC_REG_INT_CNTR); + int_cntr |= INT_READ_OP_EN | INT_WRITE_OP_DONE_EN; + + spin_lock_irqsave(&host->lock, flags); + if (host->use_sdio) + int_cntr |= INT_SDIO_IRQ_EN; + writel(int_cntr, host->base + MMC_REG_INT_CNTR); + spin_unlock_irqrestore(&host->lock, flags); writew(cmd->opcode, host->base + MMC_REG_CMD); writel(cmd->arg, host->base + MMC_REG_ARG); @@ -266,7 +275,14 @@ static int mxcmci_start_cmd(struct mxcmci_host *host, struct mmc_command *cmd, static void mxcmci_finish_request(struct mxcmci_host *host, struct mmc_request *req) { - writel(0, host->base + MMC_REG_INT_CNTR); + u32 int_cntr = 0; + unsigned long flags; + + spin_lock_irqsave(&host->lock, flags); + if (host->use_sdio) + int_cntr |= INT_SDIO_IRQ_EN; + writel(int_cntr, host->base + MMC_REG_INT_CNTR); + spin_unlock_irqrestore(&host->lock, flags); host->req = NULL; host->cmd = NULL; @@ -532,15 +548,27 @@ static void mxcmci_cmd_done(struct mxcmci_host *host, unsigned int stat) static irqreturn_t mxcmci_irq(int irq, void *devid) { struct mxcmci_host *host = devid; + unsigned long flags; + bool sdio_irq; u32 stat; stat = readl(host->base + MMC_REG_STATUS); - writel(stat, host->base + MMC_REG_STATUS); + writel(stat & ~STATUS_SDIO_INT_ACTIVE, host->base + MMC_REG_STATUS); dev_dbg(mmc_dev(host->mmc), "%s: 0x%08x\n", __func__, stat); + spin_lock_irqsave(&host->lock, flags); + sdio_irq = (stat & STATUS_SDIO_INT_ACTIVE) && host->use_sdio; + spin_unlock_irqrestore(&host->lock, flags); + + if (sdio_irq) { + writel(STATUS_SDIO_INT_ACTIVE, host->base + MMC_REG_STATUS); + mmc_signal_sdio_irq(host->mmc); + } + if (stat & STATUS_END_CMD_RESP) mxcmci_cmd_done(host, stat); + #ifdef HAS_DMA if (mxcmci_use_dma(host) && (stat & (STATUS_DATA_TRANS_DONE | STATUS_WRITE_OP_DONE))) @@ -677,11 +705,30 @@ static int mxcmci_get_ro(struct mmc_host *mmc) return -ENOSYS; } +static void mxcmci_enable_sdio_irq(struct mmc_host *mmc, int enable) +{ + struct mxcmci_host *host = mmc_priv(mmc); + unsigned long flags; + u32 int_cntr; + + spin_lock_irqsave(&host->lock, flags); + host->use_sdio = enable; + int_cntr = readl(host->base + MMC_REG_INT_CNTR); + + if (enable) + int_cntr |= INT_SDIO_IRQ_EN; + else + int_cntr &= ~INT_SDIO_IRQ_EN; + + writel(int_cntr, host->base + MMC_REG_INT_CNTR); + spin_unlock_irqrestore(&host->lock, flags); +} static const struct mmc_host_ops mxcmci_ops = { - .request = mxcmci_request, - .set_ios = mxcmci_set_ios, - .get_ro = mxcmci_get_ro, + .request = mxcmci_request, + .set_ios = mxcmci_set_ios, + .get_ro = mxcmci_get_ro, + .enable_sdio_irq = mxcmci_enable_sdio_irq, }; static int mxcmci_probe(struct platform_device *pdev) @@ -709,7 +756,7 @@ static int mxcmci_probe(struct platform_device *pdev) } mmc->ops = &mxcmci_ops; - mmc->caps = MMC_CAP_4_BIT_DATA; + mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_SDIO_IRQ; /* MMC core transfer sizes tunable parameters */ mmc->max_hw_segs = 64; @@ -728,6 +775,7 @@ static int mxcmci_probe(struct platform_device *pdev) host->mmc = mmc; host->pdata = pdev->dev.platform_data; + spin_lock_init(&host->lock); if (host->pdata && host->pdata->ocr_avail) mmc->ocr_avail = host->pdata->ocr_avail; From 3fcb027d7fd749569665d34a79ce2a8e00bc2ed6 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Thu, 1 Apr 2010 10:03:25 +0200 Subject: [PATCH 0026/1337] ARM: MXC: mxcmmc: work around a bug in the SDHC busy line handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit MX3 SoCs have a silicon bug which corrupts CRC calculation of multi-block transfers when connected SDIO peripheral doesn't drive the BUSY line as required by the specs. One way to prevent this is to only allow 1-bit transfers. Another way is playing tricks with the DMA engine, but this isn't mainline yet. So for now, we live with the performance drawback of 1-bit transfers until a nicer solution is found. This patch introduces a new host controller callback 'init_card' which is for now only called from mmc_sdio_init_card(). Signed-off-by: Daniel Mack Cc: Sascha Hauer Cc: Dan Williams Cc: Volker Ernst Cc: Jiri Kosina Cc: Michał Mirosław Signed-off-by: Sascha Hauer --- drivers/mmc/core/sdio.c | 6 ++++++ drivers/mmc/host/mxcmmc.c | 16 ++++++++++++++++ include/linux/mmc/host.h | 3 +++ 3 files changed, 25 insertions(+) diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c index 2dd4cfe7ca17..b9dee28ee7d0 100644 --- a/drivers/mmc/core/sdio.c +++ b/drivers/mmc/core/sdio.c @@ -295,6 +295,12 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr, card->type = MMC_TYPE_SDIO; + /* + * Call the optional HC's init_card function to handle quirks. + */ + if (host->ops->init_card) + host->ops->init_card(host, card); + /* * For native busses: set card RCA and quit open drain mode. */ diff --git a/drivers/mmc/host/mxcmmc.c b/drivers/mmc/host/mxcmmc.c index 51e880c8f193..2c53024ee439 100644 --- a/drivers/mmc/host/mxcmmc.c +++ b/drivers/mmc/host/mxcmmc.c @@ -724,11 +724,27 @@ static void mxcmci_enable_sdio_irq(struct mmc_host *mmc, int enable) spin_unlock_irqrestore(&host->lock, flags); } +static void mxcmci_init_card(struct mmc_host *host, struct mmc_card *card) +{ + /* + * MX3 SoCs have a silicon bug which corrupts CRC calculation of + * multi-block transfers when connected SDIO peripheral doesn't + * drive the BUSY line as required by the specs. + * One way to prevent this is to only allow 1-bit transfers. + */ + + if (cpu_is_mx3() && card->type == MMC_TYPE_SDIO) + host->caps &= ~MMC_CAP_4_BIT_DATA; + else + host->caps |= MMC_CAP_4_BIT_DATA; +} + static const struct mmc_host_ops mxcmci_ops = { .request = mxcmci_request, .set_ios = mxcmci_set_ios, .get_ro = mxcmci_get_ro, .enable_sdio_irq = mxcmci_enable_sdio_irq, + .init_card = mxcmci_init_card, }; static int mxcmci_probe(struct platform_device *pdev) diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index 43eaf5ca5848..3196c84cc630 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h @@ -108,6 +108,9 @@ struct mmc_host_ops { int (*get_cd)(struct mmc_host *host); void (*enable_sdio_irq)(struct mmc_host *host, int enable); + + /* optional callback for HC quirks */ + void (*init_card)(struct mmc_host *host, struct mmc_card *card); }; struct mmc_card; From 5c5e3b33b7cb959a401f823707bee006caadd76e Mon Sep 17 00:00:00 2001 From: Shiyong Li Date: Mon, 12 Apr 2010 13:48:21 +0800 Subject: [PATCH 0027/1337] slab: Fix missing DEBUG_SLAB last user Even with SLAB_RED_ZONE and SLAB_STORE_USER enabled, kernel would NOT store redzone and last user data around allocated memory space if "arch cache line > sizeof(unsigned long long)". As a result, last user information is unexpectedly MISSED while dumping slab corruption log. This fix makes sure that redzone and last user tags get stored unless the required alignment breaks redzone's. Signed-off-by: Shiyong Li Signed-off-by: Pekka Enberg --- mm/slab.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/mm/slab.c b/mm/slab.c index bac0f4fcc216..525c66466469 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -2220,8 +2220,8 @@ kmem_cache_create (const char *name, size_t size, size_t align, if (ralign < align) { ralign = align; } - /* disable debug if necessary */ - if (ralign > __alignof__(unsigned long long)) + /* disable debug if not aligning with REDZONE_ALIGN */ + if (ralign & (__alignof__(unsigned long long) - 1)) flags &= ~(SLAB_RED_ZONE | SLAB_STORE_USER); /* * 4) Store it. @@ -2247,8 +2247,8 @@ kmem_cache_create (const char *name, size_t size, size_t align, */ if (flags & SLAB_RED_ZONE) { /* add space for red zone words */ - cachep->obj_offset += sizeof(unsigned long long); - size += 2 * sizeof(unsigned long long); + cachep->obj_offset += align; + size += align + sizeof(unsigned long long); } if (flags & SLAB_STORE_USER) { /* user store requires one word storage behind the end of From 54a4ec469dd6067f0b604bef8ca01a2b1fdb4dcd Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Thu, 15 Apr 2010 02:17:25 -0700 Subject: [PATCH 0028/1337] ide: fix comment typo in ide.h Fix typo in the comment to the 'dma_mode' field of the 'struct ide_drive_s' introduced by the commit 3fccaa192b9501e79a57e02e62b6bf420d2b461e (ide: add drive->dma_mode field). Whilt at it, convert spaces to a tab in the declaration of the neighbouring 'dn' field... Signed-off-by: Sergei Shtylyov Signed-off-by: David S. Miller --- include/linux/ide.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/linux/ide.h b/include/linux/ide.h index 3239d1c10acb..5acdbe51348a 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -516,8 +516,8 @@ struct ide_drive_s { u8 current_speed; /* current transfer rate set */ u8 desired_speed; /* desired transfer rate set */ u8 pio_mode; /* for ->set_pio_mode _only_ */ - u8 dma_mode; /* for ->dma_pio_mode _only_ */ - u8 dn; /* now wide spread use */ + u8 dma_mode; /* for ->set_dma_mode _only_ */ + u8 dn; /* now wide spread use */ u8 acoustic; /* acoustic management */ u8 media; /* disk, cdrom, tape, floppy, ... */ u8 ready_stat; /* min status value for drive ready */ From ec1a123afdbe6a14ee93df03e2a829ad9884693e Mon Sep 17 00:00:00 2001 From: Yegor Yefremov Date: Thu, 15 Apr 2010 14:20:53 -0700 Subject: [PATCH 0029/1337] IDE: pass IRQ flags to the IDE core This enables shared IRQs and other features to be used with platform devices Signed-off-by: Yegor Yefremov Signed-off-by: David S. Miller --- drivers/ide/ide_platform.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/ide/ide_platform.c b/drivers/ide/ide_platform.c index 42965b3e30b9..542603b394e4 100644 --- a/drivers/ide/ide_platform.c +++ b/drivers/ide/ide_platform.c @@ -95,6 +95,7 @@ static int __devinit plat_ide_probe(struct platform_device *pdev) plat_ide_setup_ports(&hw, base, alt_base, pdata, res_irq->start); hw.dev = &pdev->dev; + d.irq_flags = res_irq->flags; if (mmio) d.host_flags |= IDE_HFLAG_MMIO; From a3bcbbee83f55cbaec9b2ad748e7300c7feb2192 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Mon, 12 Apr 2010 23:33:22 +0200 Subject: [PATCH 0030/1337] pda_power: Add function callbacks for suspend and resume Add function prototypes for power management events so they can be handled and used by platform implementations. Signed-off-by: Daniel Mack Cc: Dmitry Baryshkov Cc: David Woodhouse Signed-off-by: Anton Vorontsov --- drivers/power/pda_power.c | 10 ++++++++++ include/linux/pda_power.h | 2 ++ 2 files changed, 12 insertions(+) diff --git a/drivers/power/pda_power.c b/drivers/power/pda_power.c index a232de6a5703..69f8aa3a6a4b 100644 --- a/drivers/power/pda_power.c +++ b/drivers/power/pda_power.c @@ -404,6 +404,13 @@ static int usb_wakeup_enabled; static int pda_power_suspend(struct platform_device *pdev, pm_message_t state) { + if (pdata->suspend) { + int ret = pdata->suspend(state); + + if (ret) + return ret; + } + if (device_may_wakeup(&pdev->dev)) { if (ac_irq) ac_wakeup_enabled = !enable_irq_wake(ac_irq->start); @@ -423,6 +430,9 @@ static int pda_power_resume(struct platform_device *pdev) disable_irq_wake(ac_irq->start); } + if (pdata->resume) + return pdata->resume(); + return 0; } #else diff --git a/include/linux/pda_power.h b/include/linux/pda_power.h index d4cf7a2ceb3e..c9e4d814ff77 100644 --- a/include/linux/pda_power.h +++ b/include/linux/pda_power.h @@ -24,6 +24,8 @@ struct pda_power_pdata { int (*is_usb_online)(void); void (*set_charge)(int flags); void (*exit)(struct device *dev); + int (*suspend)(pm_message_t state); + int (*resume)(void); char **supplied_to; size_t num_supplicants; From edd5bdaf128e04066caac84fcb21377197ea0d64 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Wed, 14 Apr 2010 22:30:18 +0200 Subject: [PATCH 0031/1337] firewire: core: clean up config ROM related defined constants Clemens Ladisch pointed out that - BIB_IMC is not named like the field is called in the standard, - readers of the code may get worried about the magic 0x0c0083c0, - a CSR_NODE_CAPABILITIES key is there in the header but not put to good use. So let's rename BIB_IMC, add a defined constant for Node_Capabilities and a comment which reassures people that somebody thought about it and they don't have to (or if they still do, tell them where they have to look for confirmation), and prune our incomplete and arbitrary set of defined constants of CSR key IDs. And there is a nother magic number, that of Bus_Information_Block.Bus_Name, to be defined and commented. Signed-off-by: Stefan Richter --- drivers/firewire/core-card.c | 11 ++++++----- include/linux/firewire.h | 2 -- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/drivers/firewire/core-card.c b/drivers/firewire/core-card.c index 5045156c5313..42cf911b73cf 100644 --- a/drivers/firewire/core-card.c +++ b/drivers/firewire/core-card.c @@ -63,7 +63,7 @@ static size_t config_rom_length = 1 + 4 + 1 + 1; #define BIB_CRC(v) ((v) << 0) #define BIB_CRC_LENGTH(v) ((v) << 16) #define BIB_INFO_LENGTH(v) ((v) << 24) - +#define BIB_BUS_NAME 0x31333934 /* "1394" */ #define BIB_LINK_SPEED(v) ((v) << 0) #define BIB_GENERATION(v) ((v) << 4) #define BIB_MAX_ROM(v) ((v) << 8) @@ -73,7 +73,8 @@ static size_t config_rom_length = 1 + 4 + 1 + 1; #define BIB_BMC ((1) << 28) #define BIB_ISC ((1) << 29) #define BIB_CMC ((1) << 30) -#define BIB_IMC ((1) << 31) +#define BIB_IRMC ((1) << 31) +#define NODE_CAPABILITIES 0x0c0083c0 /* per IEEE 1394 clause 8.3.2.6.5.2 */ static void generate_config_rom(struct fw_card *card, __be32 *config_rom) { @@ -91,18 +92,18 @@ static void generate_config_rom(struct fw_card *card, __be32 *config_rom) config_rom[0] = cpu_to_be32( BIB_CRC_LENGTH(4) | BIB_INFO_LENGTH(4) | BIB_CRC(0)); - config_rom[1] = cpu_to_be32(0x31333934); + config_rom[1] = cpu_to_be32(BIB_BUS_NAME); config_rom[2] = cpu_to_be32( BIB_LINK_SPEED(card->link_speed) | BIB_GENERATION(card->config_rom_generation++ % 14 + 2) | BIB_MAX_ROM(2) | BIB_MAX_RECEIVE(card->max_receive) | - BIB_BMC | BIB_ISC | BIB_CMC | BIB_IMC); + BIB_BMC | BIB_ISC | BIB_CMC | BIB_IRMC); config_rom[3] = cpu_to_be32(card->guid >> 32); config_rom[4] = cpu_to_be32(card->guid); /* Generate root directory. */ - config_rom[6] = cpu_to_be32(0x0c0083c0); /* node capabilities */ + config_rom[6] = cpu_to_be32(NODE_CAPABILITIES); i = 7; j = 7 + descriptor_count; diff --git a/include/linux/firewire.h b/include/linux/firewire.h index 4bd94bf5e739..a527d73f9966 100644 --- a/include/linux/firewire.h +++ b/include/linux/firewire.h @@ -55,13 +55,11 @@ #define CSR_DESCRIPTOR 0x01 #define CSR_VENDOR 0x03 #define CSR_HARDWARE_VERSION 0x04 -#define CSR_NODE_CAPABILITIES 0x0c #define CSR_UNIT 0x11 #define CSR_SPECIFIER_ID 0x12 #define CSR_VERSION 0x13 #define CSR_DEPENDENT_INFO 0x14 #define CSR_MODEL 0x17 -#define CSR_INSTANCE 0x18 #define CSR_DIRECTORY_ID 0x20 struct fw_csr_iterator { From 7906054f0d597246178b3154adca76de29913aa5 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Mon, 19 Apr 2010 17:29:14 +0200 Subject: [PATCH 0032/1337] firewire: core: make transaction label allocation more robust If one request is so long-lived that it does not get a response before the following 63 requests, its bit in tlabel_mask is still set when the next request tries to allocate a transaction label for that number. In this state, while the first request is not completed or timed out, no new requests can be submitted. To fix this, skip over any label still in use, and do not error out unless we have entirely run out of labels. Signed-off-by: Clemens Ladisch Signed-off-by: Stefan Richter --- drivers/firewire/core-transaction.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/drivers/firewire/core-transaction.c b/drivers/firewire/core-transaction.c index 673b03f8b4ec..9882240205cd 100644 --- a/drivers/firewire/core-transaction.c +++ b/drivers/firewire/core-transaction.c @@ -229,6 +229,23 @@ static void fw_fill_request(struct fw_packet *packet, int tcode, int tlabel, packet->payload_mapped = false; } +static int allocate_tlabel(struct fw_card *card) +{ + int tlabel; + + tlabel = card->current_tlabel; + while (card->tlabel_mask & (1ULL << tlabel)) { + tlabel = (tlabel + 1) & 0x3f; + if (tlabel == card->current_tlabel) + return -EBUSY; + } + + card->current_tlabel = (tlabel + 1) & 0x3f; + card->tlabel_mask |= 1ULL << tlabel; + + return tlabel; +} + /** * This function provides low-level access to the IEEE1394 transaction * logic. Most C programs would use either fw_read(), fw_write() or @@ -290,16 +307,13 @@ void fw_send_request(struct fw_card *card, struct fw_transaction *t, int tcode, spin_lock_irqsave(&card->lock, flags); - tlabel = card->current_tlabel; - if (card->tlabel_mask & (1ULL << tlabel)) { + tlabel = allocate_tlabel(card); + if (tlabel < 0) { spin_unlock_irqrestore(&card->lock, flags); callback(card, RCODE_SEND_ERROR, NULL, 0, callback_data); return; } - card->current_tlabel = (card->current_tlabel + 1) & 0x3f; - card->tlabel_mask |= (1ULL << tlabel); - t->node_id = destination_id; t->tlabel = tlabel; t->callback = callback; From e92a716240258989f19c7345e8b135e6d214431a Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Tue, 12 Jan 2010 14:17:03 -0500 Subject: [PATCH 0033/1337] ACPI: Export EDID blocks to the kernel The ACPI spec includes a provision for hardware to provide EDID via the ACPI video extension. In the KMS world it's necessary for a way to obtain this from within the kernel. Add a function that either returns the EDID for the provided ACPI display ID or the first display of the provided type. Also add support for ensuring that devices with legacy IDs are supported. Signed-off-by: Matthew Garrett Acked-by: Zhang Rui Signed-off-by: Len Brown --- drivers/acpi/video.c | 110 +++++++++++++++++++++++++++++++++++++++---- include/acpi/video.h | 16 +++++++ 2 files changed, 118 insertions(+), 8 deletions(-) diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index a0c93b321482..4b8bda1154db 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -45,6 +45,7 @@ #include #include #include +#include #define PREFIX "ACPI: " @@ -65,11 +66,6 @@ #define MAX_NAME_LEN 20 -#define ACPI_VIDEO_DISPLAY_CRT 1 -#define ACPI_VIDEO_DISPLAY_TV 2 -#define ACPI_VIDEO_DISPLAY_DVI 3 -#define ACPI_VIDEO_DISPLAY_LCD 4 - #define _COMPONENT ACPI_VIDEO_COMPONENT ACPI_MODULE_NAME("video"); @@ -1747,12 +1743,28 @@ acpi_video_get_device_attr(struct acpi_video_bus *video, unsigned long device_id return NULL; } +static int +acpi_video_get_device_type(struct acpi_video_bus *video, + unsigned long device_id) +{ + struct acpi_video_enumerated_device *ids; + int i; + + for (i = 0; i < video->attached_count; i++) { + ids = &video->attached_array[i]; + if ((ids->value.int_val & 0xffff) == device_id) + return ids->value.int_val; + } + + return 0; +} + static int acpi_video_bus_get_one_device(struct acpi_device *device, struct acpi_video_bus *video) { unsigned long long device_id; - int status; + int status, device_type; struct acpi_video_device *data; struct acpi_video_device_attrib* attribute; @@ -1797,8 +1809,25 @@ acpi_video_bus_get_one_device(struct acpi_device *device, } if(attribute->bios_can_detect) data->flags.bios = 1; - } else - data->flags.unknown = 1; + } else { + /* Check for legacy IDs */ + device_type = acpi_video_get_device_type(video, + device_id); + /* Ignore bits 16 and 18-20 */ + switch (device_type & 0xffe2ffff) { + case ACPI_VIDEO_DISPLAY_LEGACY_MONITOR: + data->flags.crt = 1; + break; + case ACPI_VIDEO_DISPLAY_LEGACY_PANEL: + data->flags.lcd = 1; + break; + case ACPI_VIDEO_DISPLAY_LEGACY_TV: + data->flags.tvout = 1; + break; + default: + data->flags.unknown = 1; + } + } acpi_video_device_bind(video, data); acpi_video_device_find_cap(data); @@ -2032,6 +2061,71 @@ out: return result; } +int acpi_video_get_edid(struct acpi_device *device, int type, int device_id, + void **edid) +{ + struct acpi_video_bus *video; + struct acpi_video_device *video_device; + union acpi_object *buffer = NULL; + acpi_status status; + int i, length; + + if (!device || !acpi_driver_data(device)) + return -EINVAL; + + video = acpi_driver_data(device); + + for (i = 0; i < video->attached_count; i++) { + video_device = video->attached_array[i].bind_info; + length = 256; + + if (!video_device) + continue; + + if (type) { + switch (type) { + case ACPI_VIDEO_DISPLAY_CRT: + if (!video_device->flags.crt) + continue; + break; + case ACPI_VIDEO_DISPLAY_TV: + if (!video_device->flags.tvout) + continue; + break; + case ACPI_VIDEO_DISPLAY_DVI: + if (!video_device->flags.dvi) + continue; + break; + case ACPI_VIDEO_DISPLAY_LCD: + if (!video_device->flags.lcd) + continue; + break; + } + } else if (video_device->device_id != device_id) { + continue; + } + + status = acpi_video_device_EDID(video_device, &buffer, length); + + if (ACPI_FAILURE(status) || !buffer || + buffer->type != ACPI_TYPE_BUFFER) { + length = 128; + status = acpi_video_device_EDID(video_device, &buffer, + length); + if (ACPI_FAILURE(status) || !buffer || + buffer->type != ACPI_TYPE_BUFFER) { + continue; + } + } + + *edid = buffer->buffer.pointer; + return length; + } + + return -ENODEV; +} +EXPORT_SYMBOL(acpi_video_get_edid); + static int acpi_video_bus_get_devices(struct acpi_video_bus *video, struct acpi_device *device) diff --git a/include/acpi/video.h b/include/acpi/video.h index cf7be3dd157b..551793c9b6e8 100644 --- a/include/acpi/video.h +++ b/include/acpi/video.h @@ -1,12 +1,28 @@ #ifndef __ACPI_VIDEO_H #define __ACPI_VIDEO_H +#define ACPI_VIDEO_DISPLAY_CRT 1 +#define ACPI_VIDEO_DISPLAY_TV 2 +#define ACPI_VIDEO_DISPLAY_DVI 3 +#define ACPI_VIDEO_DISPLAY_LCD 4 + +#define ACPI_VIDEO_DISPLAY_LEGACY_MONITOR 0x0100 +#define ACPI_VIDEO_DISPLAY_LEGACY_PANEL 0x0110 +#define ACPI_VIDEO_DISPLAY_LEGACY_TV 0x0200 + #if (defined CONFIG_ACPI_VIDEO || defined CONFIG_ACPI_VIDEO_MODULE) extern int acpi_video_register(void); extern void acpi_video_unregister(void); +extern int acpi_video_get_edid(struct acpi_device *device, int type, + int device_id, void **edid); #else static inline int acpi_video_register(void) { return 0; } static inline void acpi_video_unregister(void) { return; } +static inline int acpi_video_get_edid(struct acpi_device *device, int type, + int device_id, void **edid) +{ + return -ENODEV; +} #endif #endif From 38a66f51e71c8d3e24c221614c57b9e8b37a46b3 Mon Sep 17 00:00:00 2001 From: Amit Kucheria Date: Wed, 21 Apr 2010 21:34:36 +0300 Subject: [PATCH 0034/1337] mxc: Change gpt timer code to be more generic by using V2 instead of MX3 Replace mx3_ with v2_ since the register layout is the same for all SoCs using version 2 of the timer (mx25, mx31, mx37 and now mx51) Signed-off-by: Amit Kucheria Signed-off-by: Sascha Hauer --- arch/arm/plat-mxc/time.c | 44 ++++++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/arch/arm/plat-mxc/time.c b/arch/arm/plat-mxc/time.c index c1ce51abdba6..714bdeffbe57 100644 --- a/arch/arm/plat-mxc/time.c +++ b/arch/arm/plat-mxc/time.c @@ -54,14 +54,14 @@ #define MX2_TSTAT_COMP (1 << 0) /* MX31, MX35, MX25, MXC91231, MX5 */ -#define MX3_TCTL_WAITEN (1 << 3) /* Wait enable mode */ -#define MX3_TCTL_CLK_IPG (1 << 6) -#define MX3_TCTL_FRR (1 << 9) -#define MX3_IR 0x0c -#define MX3_TSTAT 0x08 -#define MX3_TSTAT_OF1 (1 << 0) -#define MX3_TCN 0x24 -#define MX3_TCMP 0x10 +#define V2_TCTL_WAITEN (1 << 3) /* Wait enable mode */ +#define V2_TCTL_CLK_IPG (1 << 6) +#define V2_TCTL_FRR (1 << 9) +#define V2_IR 0x0c +#define V2_TSTAT 0x08 +#define V2_TSTAT_OF1 (1 << 0) +#define V2_TCN 0x24 +#define V2_TCMP 0x10 #define timer_is_v1() (cpu_is_mx1() || cpu_is_mx21() || cpu_is_mx27()) #define timer_is_v2() (!timer_is_v1()) @@ -76,7 +76,7 @@ static inline void gpt_irq_disable(void) unsigned int tmp; if (timer_is_v2()) - __raw_writel(0, timer_base + MX3_IR); + __raw_writel(0, timer_base + V2_IR); else { tmp = __raw_readl(timer_base + MXC_TCTL); __raw_writel(tmp & ~MX1_2_TCTL_IRQEN, timer_base + MXC_TCTL); @@ -86,7 +86,7 @@ static inline void gpt_irq_disable(void) static inline void gpt_irq_enable(void) { if (timer_is_v2()) - __raw_writel(1<<0, timer_base + MX3_IR); + __raw_writel(1<<0, timer_base + V2_IR); else { __raw_writel(__raw_readl(timer_base + MXC_TCTL) | MX1_2_TCTL_IRQEN, timer_base + MXC_TCTL); @@ -110,9 +110,9 @@ static cycle_t mx1_2_get_cycles(struct clocksource *cs) return __raw_readl(timer_base + MX1_2_TCN); } -static cycle_t mx3_get_cycles(struct clocksource *cs) +static cycle_t v2_get_cycles(struct clocksource *cs) { - return __raw_readl(timer_base + MX3_TCN); + return __raw_readl(timer_base + V2_TCN); } static struct clocksource clocksource_mxc = { @@ -129,7 +129,7 @@ static int __init mxc_clocksource_init(struct clk *timer_clk) unsigned int c = clk_get_rate(timer_clk); if (timer_is_v2()) - clocksource_mxc.read = mx3_get_cycles; + clocksource_mxc.read = v2_get_cycles; clocksource_mxc.mult = clocksource_hz2mult(c, clocksource_mxc.shift); @@ -153,16 +153,16 @@ static int mx1_2_set_next_event(unsigned long evt, -ETIME : 0; } -static int mx3_set_next_event(unsigned long evt, +static int v2_set_next_event(unsigned long evt, struct clock_event_device *unused) { unsigned long tcmp; - tcmp = __raw_readl(timer_base + MX3_TCN) + evt; + tcmp = __raw_readl(timer_base + V2_TCN) + evt; - __raw_writel(tcmp, timer_base + MX3_TCMP); + __raw_writel(tcmp, timer_base + V2_TCMP); - return (int)(tcmp - __raw_readl(timer_base + MX3_TCN)) < 0 ? + return (int)(tcmp - __raw_readl(timer_base + V2_TCN)) < 0 ? -ETIME : 0; } @@ -192,8 +192,8 @@ static void mxc_set_mode(enum clock_event_mode mode, if (mode != clockevent_mode) { /* Set event time into far-far future */ if (timer_is_v2()) - __raw_writel(__raw_readl(timer_base + MX3_TCN) - 3, - timer_base + MX3_TCMP); + __raw_writel(__raw_readl(timer_base + V2_TCN) - 3, + timer_base + V2_TCMP); else __raw_writel(__raw_readl(timer_base + MX1_2_TCN) - 3, timer_base + MX1_2_TCMP); @@ -245,7 +245,7 @@ static irqreturn_t mxc_timer_interrupt(int irq, void *dev_id) uint32_t tstat; if (timer_is_v2()) - tstat = __raw_readl(timer_base + MX3_TSTAT); + tstat = __raw_readl(timer_base + V2_TSTAT); else tstat = __raw_readl(timer_base + MX1_2_TSTAT); @@ -276,7 +276,7 @@ static int __init mxc_clockevent_init(struct clk *timer_clk) unsigned int c = clk_get_rate(timer_clk); if (timer_is_v2()) - clockevent_mxc.set_next_event = mx3_set_next_event; + clockevent_mxc.set_next_event = v2_set_next_event; clockevent_mxc.mult = div_sc(c, NSEC_PER_SEC, clockevent_mxc.shift); @@ -308,7 +308,7 @@ void __init mxc_timer_init(struct clk *timer_clk, void __iomem *base, int irq) __raw_writel(0, timer_base + MXC_TPRER); /* see datasheet note */ if (timer_is_v2()) - tctl_val = MX3_TCTL_CLK_IPG | MX3_TCTL_FRR | MX3_TCTL_WAITEN | MXC_TCTL_TEN; + tctl_val = V2_TCTL_CLK_IPG | V2_TCTL_FRR | V2_TCTL_WAITEN | MXC_TCTL_TEN; else tctl_val = MX1_2_TCTL_FRR | MX1_2_TCTL_CLK_PCLK1 | MXC_TCTL_TEN; From e24798e637f5d5222f9fd767aefbea15de456e4a Mon Sep 17 00:00:00 2001 From: Dinh Nguyen Date: Thu, 22 Apr 2010 16:28:42 +0300 Subject: [PATCH 0035/1337] mx5: Add registration of GPIOs for MX5 devices Register the gpio irqs on Freescale's MX51 Babbage HW. Signed-off-by: Dinh Nguyen Signed-off-by: Amit Kucheria Signed-off-by: Sascha Hauer --- arch/arm/mach-mx5/devices.c | 33 +++++++++++++++++++++++++++++++-- arch/arm/plat-mxc/gpio.c | 5 ++--- arch/arm/plat-mxc/tzic.c | 4 +++- 3 files changed, 36 insertions(+), 6 deletions(-) diff --git a/arch/arm/mach-mx5/devices.c b/arch/arm/mach-mx5/devices.c index d6fd3961ade9..5070ae1f94c6 100644 --- a/arch/arm/mach-mx5/devices.c +++ b/arch/arm/mach-mx5/devices.c @@ -1,5 +1,6 @@ /* * Copyright 2009 Amit Kucheria + * Copyright (C) 2010 Freescale Semiconductor, Inc. * * The code contained herein is licensed under the GNU General Public * License. You may obtain a copy of the GNU General Public License @@ -10,8 +11,10 @@ */ #include +#include #include #include +#include static struct resource uart0[] = { { @@ -89,8 +92,34 @@ struct platform_device mxc_fec_device = { .resource = mxc_fec_resources, }; -/* Dummy definition to allow compiling in AVIC and TZIC simultaneously */ +static struct mxc_gpio_port mxc_gpio_ports[] = { + { + .chip.label = "gpio-0", + .base = MX51_IO_ADDRESS(MX51_GPIO1_BASE_ADDR), + .irq = MX51_MXC_INT_GPIO1_LOW, + .virtual_irq_start = MXC_GPIO_IRQ_START + }, + { + .chip.label = "gpio-1", + .base = MX51_IO_ADDRESS(MX51_GPIO2_BASE_ADDR), + .irq = MX51_MXC_INT_GPIO2_LOW, + .virtual_irq_start = MXC_GPIO_IRQ_START + 32 * 1 + }, + { + .chip.label = "gpio-2", + .base = MX51_IO_ADDRESS(MX51_GPIO3_BASE_ADDR), + .irq = MX51_MXC_INT_GPIO3_LOW, + .virtual_irq_start = MXC_GPIO_IRQ_START + 32 * 2 + }, + { + .chip.label = "gpio-3", + .base = MX51_IO_ADDRESS(MX51_GPIO4_BASE_ADDR), + .irq = MX51_MXC_INT_GPIO4_LOW, + .virtual_irq_start = MXC_GPIO_IRQ_START + 32 * 3 + }, +}; + int __init mxc_register_gpios(void) { - return 0; + return mxc_gpio_init(mxc_gpio_ports, ARRAY_SIZE(mxc_gpio_ports)); } diff --git a/arch/arm/plat-mxc/gpio.c b/arch/arm/plat-mxc/gpio.c index 70b23893f094..71437c61cfd7 100644 --- a/arch/arm/plat-mxc/gpio.c +++ b/arch/arm/plat-mxc/gpio.c @@ -3,7 +3,7 @@ * Copyright 2008 Juergen Beisert, kernel@pengutronix.de * * Based on code from Freescale, - * Copyright 2004-2006 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright (C) 2004-2010 Freescale Semiconductor, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -38,7 +38,6 @@ static int gpio_table_size; #define GPIO_ICR2 (cpu_is_mx1_mx2() ? 0x2C : 0x10) #define GPIO_IMR (cpu_is_mx1_mx2() ? 0x30 : 0x14) #define GPIO_ISR (cpu_is_mx1_mx2() ? 0x34 : 0x18) -#define GPIO_ISR (cpu_is_mx1_mx2() ? 0x34 : 0x18) #define GPIO_INT_LOW_LEV (cpu_is_mx1_mx2() ? 0x3 : 0x0) #define GPIO_INT_HIGH_LEV (cpu_is_mx1_mx2() ? 0x2 : 0x1) @@ -289,7 +288,7 @@ int __init mxc_gpio_init(struct mxc_gpio_port *port, int cnt) /* its a serious configuration bug when it fails */ BUG_ON( gpiochip_add(&port[i].chip) < 0 ); - if (cpu_is_mx1() || cpu_is_mx3() || cpu_is_mx25()) { + if (cpu_is_mx1() || cpu_is_mx3() || cpu_is_mx25() || cpu_is_mx51()) { /* setup one handler for each entry */ set_irq_chained_handler(port[i].irq, mx3_gpio_irq_handler); set_irq_data(port[i].irq, &port[i]); diff --git a/arch/arm/plat-mxc/tzic.c b/arch/arm/plat-mxc/tzic.c index afa6709db0b3..9b86d2a60d43 100644 --- a/arch/arm/plat-mxc/tzic.c +++ b/arch/arm/plat-mxc/tzic.c @@ -1,5 +1,5 @@ /* - * Copyright 2004-2009 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright (C)2004-2010 Freescale Semiconductor, Inc. All Rights Reserved. * * The code contained herein is licensed under the GNU General Public * License. You may obtain a copy of the GNU General Public License @@ -19,6 +19,7 @@ #include #include +#include /* ***************************************** @@ -144,6 +145,7 @@ void __init tzic_init_irq(void __iomem *irqbase) set_irq_handler(i, handle_level_irq); set_irq_flags(i, IRQF_VALID); } + mxc_register_gpios(); pr_info("TrustZone Interrupt Controller (TZIC) initialized\n"); } From 63e7cf910542383591318941cb62a246ac191cfe Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Wed, 14 Apr 2010 05:50:26 +0000 Subject: [PATCH 0036/1337] pdc202xx_old: wire test_irq() method for PDC2026x In the commit e0321fbe6d34b4bb514fb6daff9e0859e5d76001 (pdc202xx_old: implement test_irq() method (take 2)) I forgot to modify 'pdc2026x_port_ops'... :-/ Signed-off-by: Sergei Shtylyov Signed-off-by: David S. Miller --- drivers/ide/pdc202xx_old.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/ide/pdc202xx_old.c b/drivers/ide/pdc202xx_old.c index c5f3841af360..42ad794dfaae 100644 --- a/drivers/ide/pdc202xx_old.c +++ b/drivers/ide/pdc202xx_old.c @@ -241,6 +241,7 @@ static const struct ide_port_ops pdc20246_port_ops = { static const struct ide_port_ops pdc2026x_port_ops = { .set_pio_mode = pdc202xx_set_pio_mode, .set_dma_mode = pdc202xx_set_mode, + .test_irq = pdc202xx_test_irq, .cable_detect = pdc2026x_cable_detect, }; From f693be4d8a00431b53a59d74aefdb3f7ae92f662 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Wed, 14 Apr 2010 05:52:59 +0000 Subject: [PATCH 0037/1337] pdc202xx_old: ignore "FIFO empty" bit in test_irq() method The driver takes into account not only the interrupt status bit but also "FIFO empty" bit in its test_irq() method. This actually is a superfluous check since for the DMA commands calling the dma_test_irq() method further in the interrupt handler makes sure FIFO is emptied. Signed-off-by: Sergei Shtylyov Signed-off-by: David S. Miller --- drivers/ide/pdc202xx_old.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/ide/pdc202xx_old.c b/drivers/ide/pdc202xx_old.c index 42ad794dfaae..3a35ec6193d2 100644 --- a/drivers/ide/pdc202xx_old.c +++ b/drivers/ide/pdc202xx_old.c @@ -93,13 +93,13 @@ static int pdc202xx_test_irq(ide_hwif_t *hwif) * bit 7: error, bit 6: interrupting, * bit 5: FIFO full, bit 4: FIFO empty */ - return ((sc1d & 0x50) == 0x50) ? 1 : 0; + return (sc1d & 0x40) ? 1 : 0; } else { /* * bit 3: error, bit 2: interrupting, * bit 1: FIFO full, bit 0: FIFO empty */ - return ((sc1d & 0x05) == 0x05) ? 1 : 0; + return (sc1d & 0x04) ? 1 : 0; } } From d943f2c82144b0fb8aaebfbc6659c02cc3340527 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Fri, 23 Apr 2010 06:49:43 +0200 Subject: [PATCH 0038/1337] arm/plat-mxc: Fix forgotten renaming in timer.c Commit "mxc: Change gpt timer code to be more generic by using V2 instead of MX3" forgot to replace one occurence causing a build failure. Signed-off-by: Wolfram Sang Cc: Amit Kucheria Cc: Sascha Hauer Signed-off-by: Sascha Hauer --- arch/arm/plat-mxc/time.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/plat-mxc/time.c b/arch/arm/plat-mxc/time.c index 714bdeffbe57..f9a1b059a76c 100644 --- a/arch/arm/plat-mxc/time.c +++ b/arch/arm/plat-mxc/time.c @@ -102,7 +102,7 @@ static void gpt_irq_acknowledge(void) __raw_writel(MX2_TSTAT_CAPT | MX2_TSTAT_COMP, timer_base + MX1_2_TSTAT); } else if (timer_is_v2()) - __raw_writel(MX3_TSTAT_OF1, timer_base + MX3_TSTAT); + __raw_writel(V2_TSTAT_OF1, timer_base + V2_TSTAT); } static cycle_t mx1_2_get_cycles(struct clocksource *cs) From 9b9ade6b612e562c4a5bd02ef38cc32e10f3f9ba Mon Sep 17 00:00:00 2001 From: Yulia Vilensky Date: Mon, 26 Apr 2010 14:05:25 +0300 Subject: [PATCH 0039/1337] ds2782_battery: Add support for ds2786 battery gas gauge Signed-off-by: Yulia Vilensky Signed-off-by: Mike Rapoport Signed-off-by: Anton Vorontsov --- drivers/power/Kconfig | 4 +- drivers/power/ds2782_battery.c | 184 ++++++++++++++++++++++++--------- include/linux/ds2782_battery.h | 8 ++ 3 files changed, 146 insertions(+), 50 deletions(-) create mode 100644 include/linux/ds2782_battery.h diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig index 22f2fa912127..c59bcb7c6eb0 100644 --- a/drivers/power/Kconfig +++ b/drivers/power/Kconfig @@ -65,10 +65,10 @@ config BATTERY_DS2760 Say Y here to enable support for batteries with ds2760 chip. config BATTERY_DS2782 - tristate "DS2782 standalone gas-gauge" + tristate "DS2782/DS2786 standalone gas-gauge" depends on I2C help - Say Y here to enable support for the DS2782 standalone battery + Say Y here to enable support for the DS2782/DS2786 standalone battery gas-gauge. config BATTERY_PMU diff --git a/drivers/power/ds2782_battery.c b/drivers/power/ds2782_battery.c index ba1bd1a545be..c665e8007235 100644 --- a/drivers/power/ds2782_battery.c +++ b/drivers/power/ds2782_battery.c @@ -5,6 +5,8 @@ * * Author: Ryan Mallon * + * DS2786 added by Yulia Vilensky + * * 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. @@ -20,12 +22,13 @@ #include #include #include +#include #define DS2782_REG_RARC 0x06 /* Remaining active relative capacity */ -#define DS2782_REG_VOLT_MSB 0x0c -#define DS2782_REG_TEMP_MSB 0x0a -#define DS2782_REG_CURRENT_MSB 0x0e +#define DS278x_REG_VOLT_MSB 0x0c +#define DS278x_REG_TEMP_MSB 0x0a +#define DS278x_REG_CURRENT_MSB 0x0e /* EEPROM Block */ #define DS2782_REG_RSNSP 0x69 /* Sense resistor value */ @@ -33,18 +36,33 @@ /* Current unit measurement in uA for a 1 milli-ohm sense resistor */ #define DS2782_CURRENT_UNITS 1563 -#define to_ds2782_info(x) container_of(x, struct ds2782_info, battery) +#define DS2786_REG_RARC 0x02 /* Remaining active relative capacity */ -struct ds2782_info { +#define DS2786_CURRENT_UNITS 25 + +struct ds278x_info; + +struct ds278x_battery_ops { + int (*get_current)(struct ds278x_info *info, int *current_uA); + int (*get_voltage)(struct ds278x_info *info, int *voltage_uA); + int (*get_capacity)(struct ds278x_info *info, int *capacity_uA); + +}; + +#define to_ds278x_info(x) container_of(x, struct ds278x_info, battery) + +struct ds278x_info { struct i2c_client *client; struct power_supply battery; + struct ds278x_battery_ops *ops; int id; + int rsns; }; static DEFINE_IDR(battery_id); static DEFINE_MUTEX(battery_lock); -static inline int ds2782_read_reg(struct ds2782_info *info, int reg, u8 *val) +static inline int ds278x_read_reg(struct ds278x_info *info, int reg, u8 *val) { int ret; @@ -58,7 +76,7 @@ static inline int ds2782_read_reg(struct ds2782_info *info, int reg, u8 *val) return 0; } -static inline int ds2782_read_reg16(struct ds2782_info *info, int reg_msb, +static inline int ds278x_read_reg16(struct ds278x_info *info, int reg_msb, s16 *val) { int ret; @@ -73,7 +91,7 @@ static inline int ds2782_read_reg16(struct ds2782_info *info, int reg_msb, return 0; } -static int ds2782_get_temp(struct ds2782_info *info, int *temp) +static int ds278x_get_temp(struct ds278x_info *info, int *temp) { s16 raw; int err; @@ -84,14 +102,14 @@ static int ds2782_get_temp(struct ds2782_info *info, int *temp) * celsius. The temperature value is stored as a 10 bit number, plus * sign in the upper bits of a 16 bit register. */ - err = ds2782_read_reg16(info, DS2782_REG_TEMP_MSB, &raw); + err = ds278x_read_reg16(info, DS278x_REG_TEMP_MSB, &raw); if (err) return err; *temp = ((raw / 32) * 125) / 100; return 0; } -static int ds2782_get_current(struct ds2782_info *info, int *current_uA) +static int ds2782_get_current(struct ds278x_info *info, int *current_uA) { int sense_res; int err; @@ -102,7 +120,7 @@ static int ds2782_get_current(struct ds2782_info *info, int *current_uA) * The units of measurement for current are dependent on the value of * the sense resistor. */ - err = ds2782_read_reg(info, DS2782_REG_RSNSP, &sense_res_raw); + err = ds278x_read_reg(info, DS2782_REG_RSNSP, &sense_res_raw); if (err) return err; if (sense_res_raw == 0) { @@ -113,14 +131,14 @@ static int ds2782_get_current(struct ds2782_info *info, int *current_uA) dev_dbg(&info->client->dev, "sense resistor = %d milli-ohms\n", sense_res); - err = ds2782_read_reg16(info, DS2782_REG_CURRENT_MSB, &raw); + err = ds278x_read_reg16(info, DS278x_REG_CURRENT_MSB, &raw); if (err) return err; *current_uA = raw * (DS2782_CURRENT_UNITS / sense_res); return 0; } -static int ds2782_get_voltage(struct ds2782_info *info, int *voltage_uA) +static int ds2782_get_voltage(struct ds278x_info *info, int *voltage_uA) { s16 raw; int err; @@ -129,36 +147,77 @@ static int ds2782_get_voltage(struct ds2782_info *info, int *voltage_uA) * Voltage is measured in units of 4.88mV. The voltage is stored as * a 10-bit number plus sign, in the upper bits of a 16-bit register */ - err = ds2782_read_reg16(info, DS2782_REG_VOLT_MSB, &raw); + err = ds278x_read_reg16(info, DS278x_REG_VOLT_MSB, &raw); if (err) return err; *voltage_uA = (raw / 32) * 4800; return 0; } -static int ds2782_get_capacity(struct ds2782_info *info, int *capacity) +static int ds2782_get_capacity(struct ds278x_info *info, int *capacity) { int err; u8 raw; - err = ds2782_read_reg(info, DS2782_REG_RARC, &raw); + err = ds278x_read_reg(info, DS2782_REG_RARC, &raw); if (err) return err; *capacity = raw; return raw; } -static int ds2782_get_status(struct ds2782_info *info, int *status) +static int ds2786_get_current(struct ds278x_info *info, int *current_uA) +{ + int err; + s16 raw; + + err = ds278x_read_reg16(info, DS278x_REG_CURRENT_MSB, &raw); + if (err) + return err; + *current_uA = (raw / 16) * (DS2786_CURRENT_UNITS / info->rsns); + return 0; +} + +static int ds2786_get_voltage(struct ds278x_info *info, int *voltage_uA) +{ + s16 raw; + int err; + + /* + * Voltage is measured in units of 1.22mV. The voltage is stored as + * a 10-bit number plus sign, in the upper bits of a 16-bit register + */ + err = ds278x_read_reg16(info, DS278x_REG_VOLT_MSB, &raw); + if (err) + return err; + *voltage_uA = (raw / 8) * 1220; + return 0; +} + +static int ds2786_get_capacity(struct ds278x_info *info, int *capacity) +{ + int err; + u8 raw; + + err = ds278x_read_reg(info, DS2786_REG_RARC, &raw); + if (err) + return err; + /* Relative capacity is displayed with resolution 0.5 % */ + *capacity = raw/2 ; + return 0; +} + +static int ds278x_get_status(struct ds278x_info *info, int *status) { int err; int current_uA; int capacity; - err = ds2782_get_current(info, ¤t_uA); + err = info->ops->get_current(info, ¤t_uA); if (err) return err; - err = ds2782_get_capacity(info, &capacity); + err = info->ops->get_capacity(info, &capacity); if (err) return err; @@ -174,32 +233,32 @@ static int ds2782_get_status(struct ds2782_info *info, int *status) return 0; } -static int ds2782_battery_get_property(struct power_supply *psy, +static int ds278x_battery_get_property(struct power_supply *psy, enum power_supply_property prop, union power_supply_propval *val) { - struct ds2782_info *info = to_ds2782_info(psy); + struct ds278x_info *info = to_ds278x_info(psy); int ret; switch (prop) { case POWER_SUPPLY_PROP_STATUS: - ret = ds2782_get_status(info, &val->intval); + ret = ds278x_get_status(info, &val->intval); break; case POWER_SUPPLY_PROP_CAPACITY: - ret = ds2782_get_capacity(info, &val->intval); + ret = info->ops->get_capacity(info, &val->intval); break; case POWER_SUPPLY_PROP_VOLTAGE_NOW: - ret = ds2782_get_voltage(info, &val->intval); + ret = info->ops->get_voltage(info, &val->intval); break; case POWER_SUPPLY_PROP_CURRENT_NOW: - ret = ds2782_get_current(info, &val->intval); + ret = info->ops->get_current(info, &val->intval); break; case POWER_SUPPLY_PROP_TEMP: - ret = ds2782_get_temp(info, &val->intval); + ret = ds278x_get_temp(info, &val->intval); break; default: @@ -209,7 +268,7 @@ static int ds2782_battery_get_property(struct power_supply *psy, return ret; } -static enum power_supply_property ds2782_battery_props[] = { +static enum power_supply_property ds278x_battery_props[] = { POWER_SUPPLY_PROP_STATUS, POWER_SUPPLY_PROP_CAPACITY, POWER_SUPPLY_PROP_VOLTAGE_NOW, @@ -217,18 +276,18 @@ static enum power_supply_property ds2782_battery_props[] = { POWER_SUPPLY_PROP_TEMP, }; -static void ds2782_power_supply_init(struct power_supply *battery) +static void ds278x_power_supply_init(struct power_supply *battery) { battery->type = POWER_SUPPLY_TYPE_BATTERY; - battery->properties = ds2782_battery_props; - battery->num_properties = ARRAY_SIZE(ds2782_battery_props); - battery->get_property = ds2782_battery_get_property; + battery->properties = ds278x_battery_props; + battery->num_properties = ARRAY_SIZE(ds278x_battery_props); + battery->get_property = ds278x_battery_get_property; battery->external_power_changed = NULL; } -static int ds2782_battery_remove(struct i2c_client *client) +static int ds278x_battery_remove(struct i2c_client *client) { - struct ds2782_info *info = i2c_get_clientdata(client); + struct ds278x_info *info = i2c_get_clientdata(client); power_supply_unregister(&info->battery); kfree(info->battery.name); @@ -241,13 +300,36 @@ static int ds2782_battery_remove(struct i2c_client *client) return 0; } -static int ds2782_battery_probe(struct i2c_client *client, +static struct ds278x_battery_ops ds278x_ops[] = { + [0] = { + .get_current = ds2782_get_current, + .get_voltage = ds2782_get_voltage, + .get_capacity = ds2782_get_capacity, + }, + [1] = { + .get_current = ds2786_get_current, + .get_voltage = ds2786_get_voltage, + .get_capacity = ds2786_get_capacity, + } +}; + +static int ds278x_battery_probe(struct i2c_client *client, const struct i2c_device_id *id) { - struct ds2782_info *info; + struct ds278x_platform_data *pdata = client->dev.platform_data; + struct ds278x_info *info; int ret; int num; + /* + * ds2786 should have the sense resistor value set + * in the platform data + */ + if (id->driver_data == 1 && !pdata) { + dev_err(&client->dev, "missing platform data for ds2786\n"); + return -EINVAL; + } + /* Get an ID for this battery */ ret = idr_pre_get(&battery_id, GFP_KERNEL); if (ret == 0) { @@ -267,15 +349,20 @@ static int ds2782_battery_probe(struct i2c_client *client, goto fail_info; } - info->battery.name = kasprintf(GFP_KERNEL, "ds2782-%d", num); + info->battery.name = kasprintf(GFP_KERNEL, "%s-%d", client->name, num); if (!info->battery.name) { ret = -ENOMEM; goto fail_name; } + if (id->driver_data == 1) + info->rsns = pdata->rsns; + i2c_set_clientdata(client, info); info->client = client; - ds2782_power_supply_init(&info->battery); + info->id = num; + info->ops = &ds278x_ops[id->driver_data]; + ds278x_power_supply_init(&info->battery); ret = power_supply_register(&client->dev, &info->battery); if (ret) { @@ -297,31 +384,32 @@ fail_id: return ret; } -static const struct i2c_device_id ds2782_id[] = { +static const struct i2c_device_id ds278x_id[] = { {"ds2782", 0}, + {"ds2786", 1}, {}, }; -static struct i2c_driver ds2782_battery_driver = { +static struct i2c_driver ds278x_battery_driver = { .driver = { .name = "ds2782-battery", }, - .probe = ds2782_battery_probe, - .remove = ds2782_battery_remove, - .id_table = ds2782_id, + .probe = ds278x_battery_probe, + .remove = ds278x_battery_remove, + .id_table = ds278x_id, }; -static int __init ds2782_init(void) +static int __init ds278x_init(void) { - return i2c_add_driver(&ds2782_battery_driver); + return i2c_add_driver(&ds278x_battery_driver); } -module_init(ds2782_init); +module_init(ds278x_init); -static void __exit ds2782_exit(void) +static void __exit ds278x_exit(void) { - i2c_del_driver(&ds2782_battery_driver); + i2c_del_driver(&ds278x_battery_driver); } -module_exit(ds2782_exit); +module_exit(ds278x_exit); MODULE_AUTHOR("Ryan Mallon "); MODULE_DESCRIPTION("Maxim/Dallas DS2782 Stand-Alone Fuel Gauage IC driver"); diff --git a/include/linux/ds2782_battery.h b/include/linux/ds2782_battery.h new file mode 100644 index 000000000000..b4e281f65c15 --- /dev/null +++ b/include/linux/ds2782_battery.h @@ -0,0 +1,8 @@ +#ifndef __LINUX_DS2782_BATTERY_H +#define __LINUX_DS2782_BATTERY_H + +struct ds278x_platform_data { + int rsns; +}; + +#endif From cf32eb89cb4e674f88e4af5025839d85d02485c6 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Tue, 13 Apr 2010 16:12:25 -0700 Subject: [PATCH 0040/1337] of/flattree: make of_fdt.h safe to unconditionally include. If CONFIG_OF_FLATTREE is not set, then don't process the body of linux/of_fdt.h Signed-off-by: Grant Likely --- include/linux/of_fdt.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/linux/of_fdt.h b/include/linux/of_fdt.h index a1ca92ccb0ff..f0fdd1f43688 100644 --- a/include/linux/of_fdt.h +++ b/include/linux/of_fdt.h @@ -57,6 +57,7 @@ struct boot_param_header { __be32 dt_struct_size; /* size of the DT structure block */ }; +#if defined(CONFIG_OF_FLATTREE) /* TBD: Temporary export of fdt globals - remove when code fully merged */ extern int __initdata dt_root_addr_cells; extern int __initdata dt_root_size_cells; @@ -98,6 +99,7 @@ extern int early_init_dt_scan_root(unsigned long node, const char *uname, /* Other Prototypes */ extern void unflatten_device_tree(void); extern void early_init_devtree(void *); +#endif /* CONFIG_OF_FLATTREE */ #endif /* __ASSEMBLY__ */ #endif /* _LINUX_OF_FDT_H */ From 8bfe9b5c3a684fe39eb58a65e466c103d1c32c9a Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Tue, 13 Apr 2010 16:12:26 -0700 Subject: [PATCH 0041/1337] of/flattree: Make unflatten_device_tree() safe to call from any arch This patch makes unflatten_device_tree() safe to call from any arch setup code with the following changes: - Make sure initial_boot_params actually points to a device tree blob before unflattening - Make sure the initial_boot_params->magic field is correct - If CONFIG_OF_FLATTREE is not set, then make unflatten_device_tree() an empty static inline function. This patch also adds some additional debug output to the top of unflatten_device_tree(). Signed-off-by: Grant Likely --- drivers/of/fdt.c | 15 +++++++++++++++ include/linux/of_fdt.h | 2 ++ 2 files changed, 17 insertions(+) diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index dee4fb56b094..b6987bba8556 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -556,6 +556,21 @@ void __init unflatten_device_tree(void) pr_debug(" -> unflatten_device_tree()\n"); + if (!initial_boot_params) { + pr_debug("No device tree pointer\n"); + return; + } + + pr_debug("Unflattening device tree:\n"); + pr_debug("magic: %08x\n", be32_to_cpu(initial_boot_params->magic)); + pr_debug("size: %08x\n", be32_to_cpu(initial_boot_params->totalsize)); + pr_debug("version: %08x\n", be32_to_cpu(initial_boot_params->version)); + + if (be32_to_cpu(initial_boot_params->magic) != OF_DT_HEADER) { + pr_err("Invalid device tree blob header\n"); + return; + } + /* First pass, scan for size */ start = ((unsigned long)initial_boot_params) + be32_to_cpu(initial_boot_params->off_dt_struct); diff --git a/include/linux/of_fdt.h b/include/linux/of_fdt.h index f0fdd1f43688..71e1a916d3fa 100644 --- a/include/linux/of_fdt.h +++ b/include/linux/of_fdt.h @@ -99,6 +99,8 @@ extern int early_init_dt_scan_root(unsigned long node, const char *uname, /* Other Prototypes */ extern void unflatten_device_tree(void); extern void early_init_devtree(void *); +#else /* CONFIG_OF_FLATTREE */ +static inline void unflatten_device_tree(void) {} #endif /* CONFIG_OF_FLATTREE */ #endif /* __ASSEMBLY__ */ From efb2e014fc4f2675011b802e1a84bf9a58756004 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Tue, 13 Apr 2010 16:12:27 -0700 Subject: [PATCH 0042/1337] of: protect contents of of_platform.h and of_device.h Only process contents of of_platform.h and of_device.h if CONFIG_OF_DEVICE is set. Signed-off-by: Grant Likely --- include/linux/of_device.h | 2 ++ include/linux/of_platform.h | 2 ++ 2 files changed, 4 insertions(+) diff --git a/include/linux/of_device.h b/include/linux/of_device.h index d3a74e00a3e1..e7904a9cd3a3 100644 --- a/include/linux/of_device.h +++ b/include/linux/of_device.h @@ -1,6 +1,7 @@ #ifndef _LINUX_OF_DEVICE_H #define _LINUX_OF_DEVICE_H +#ifdef CONFIG_OF_DEVICE #include #include #include @@ -26,5 +27,6 @@ static inline void of_device_free(struct of_device *dev) extern ssize_t of_device_get_modalias(struct of_device *ofdev, char *str, ssize_t len); +#endif /* CONFIG_OF_DEVICE */ #endif /* _LINUX_OF_DEVICE_H */ diff --git a/include/linux/of_platform.h b/include/linux/of_platform.h index 908406651330..ac3ae0758fbe 100644 --- a/include/linux/of_platform.h +++ b/include/linux/of_platform.h @@ -11,6 +11,7 @@ * */ +#ifdef CONFIG_OF_DEVICE #include #include #include @@ -66,5 +67,6 @@ static inline void of_unregister_platform_driver(struct of_platform_driver *drv) extern struct of_device *of_find_device_by_node(struct device_node *np); extern int of_bus_type_init(struct bus_type *bus, const char *name); +#endif /* CONFIG_OF_DEVICE */ #endif /* _LINUX_OF_PLATFORM_H */ From d706c1b050274b3bf97d7cb0542c0d070c9ccb8b Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Tue, 13 Apr 2010 16:12:28 -0700 Subject: [PATCH 0043/1337] driver-core: Add device node pointer to struct device Currently, platforms using CONFIG_OF add a 'struct device_node *of_node' to dev->archdata. However, with CONFIG_OF becoming generic for all architectures, it makes sense for commonality to move it out of archdata and into struct device proper. This patch adds a struct device_node *of_node member to struct device and updates all locations which currently write the device_node pointer into archdata to also update dev->of_node. Subsequent patches will modify callers to use the archdata location and ultimately remove the archdata member entirely. Signed-off-by: Grant Likely Acked-by: Greg Kroah-Hartman CC: Michal Simek CC: Greg Kroah-Hartman CC: Benjamin Herrenschmidt CC: "David S. Miller" CC: Stephen Rothwell CC: Jeremy Kerr CC: microblaze-uclinux@itee.uq.edu.au CC: linux-kernel@vger.kernel.org CC: linuxppc-dev@ozlabs.org CC: sparclinux@vger.kernel.org --- arch/microblaze/kernel/of_device.c | 1 + arch/powerpc/kernel/of_device.c | 1 + arch/powerpc/kernel/pci-common.c | 3 ++- arch/powerpc/kernel/vio.c | 3 ++- arch/powerpc/platforms/ps3/system-bus.c | 1 + arch/sparc/kernel/of_device_32.c | 1 + arch/sparc/kernel/of_device_64.c | 1 + arch/sparc/kernel/pci.c | 1 + drivers/of/of_mdio.c | 1 + drivers/of/of_spi.c | 1 + include/linux/device.h | 4 ++++ 11 files changed, 16 insertions(+), 2 deletions(-) diff --git a/arch/microblaze/kernel/of_device.c b/arch/microblaze/kernel/of_device.c index 9a0f7632c47c..f6c521898ebf 100644 --- a/arch/microblaze/kernel/of_device.c +++ b/arch/microblaze/kernel/of_device.c @@ -54,6 +54,7 @@ struct of_device *of_device_alloc(struct device_node *np, dev->dev.parent = parent; dev->dev.release = of_release_dev; dev->dev.archdata.of_node = np; + dev->dev.of_node = np; if (bus_id) dev_set_name(&dev->dev, bus_id); diff --git a/arch/powerpc/kernel/of_device.c b/arch/powerpc/kernel/of_device.c index a359cb08e900..9577e6f4e3bf 100644 --- a/arch/powerpc/kernel/of_device.c +++ b/arch/powerpc/kernel/of_device.c @@ -74,6 +74,7 @@ struct of_device *of_device_alloc(struct device_node *np, dev->dev.parent = parent; dev->dev.release = of_release_dev; dev->dev.archdata.of_node = np; + dev->dev.of_node = np; if (bus_id) dev_set_name(&dev->dev, "%s", bus_id); diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c index 0c0567e58409..88da282047c3 100644 --- a/arch/powerpc/kernel/pci-common.c +++ b/arch/powerpc/kernel/pci-common.c @@ -1097,8 +1097,9 @@ void __devinit pcibios_setup_bus_devices(struct pci_bus *bus) if (dev->is_added) continue; - /* Setup OF node pointer in archdata */ + /* Setup OF node pointer in the device */ sd->of_node = pci_device_to_OF_node(dev); + dev->dev.of_node = pci_device_to_OF_node(dev); /* Fixup NUMA node as it may not be setup yet by the generic * code and is needed by the DMA init diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c index 82237176a2a3..d6708da114ee 100644 --- a/arch/powerpc/kernel/vio.c +++ b/arch/powerpc/kernel/vio.c @@ -1230,7 +1230,8 @@ struct vio_dev *vio_register_device_node(struct device_node *of_node) if (unit_address != NULL) viodev->unit_address = *unit_address; } - viodev->dev.archdata.of_node = of_node_get(of_node); + viodev->dev.of_node = of_node_get(of_node); + viodev->dev.archdata.of_node = viodev->dev.of_node; if (firmware_has_feature(FW_FEATURE_CMO)) vio_cmo_set_dma_ops(viodev); diff --git a/arch/powerpc/platforms/ps3/system-bus.c b/arch/powerpc/platforms/ps3/system-bus.c index 6d09f5e3e7e4..e546c86a539b 100644 --- a/arch/powerpc/platforms/ps3/system-bus.c +++ b/arch/powerpc/platforms/ps3/system-bus.c @@ -766,6 +766,7 @@ int ps3_system_bus_device_register(struct ps3_system_bus_device *dev) BUG(); }; + dev->core.of_node = NULL; dev->core.archdata.of_node = NULL; set_dev_node(&dev->core, 0); diff --git a/arch/sparc/kernel/of_device_32.c b/arch/sparc/kernel/of_device_32.c index da527b33ebc7..4926c1babd84 100644 --- a/arch/sparc/kernel/of_device_32.c +++ b/arch/sparc/kernel/of_device_32.c @@ -348,6 +348,7 @@ static struct of_device * __init scan_one_device(struct device_node *dp, sd->prom_node = dp; sd->op = op; + op->dev.of_node = dp; op->node = dp; op->clock_freq = of_getintprop_default(dp, "clock-frequency", diff --git a/arch/sparc/kernel/of_device_64.c b/arch/sparc/kernel/of_device_64.c index b3d4cb5d21b3..5bc74161667c 100644 --- a/arch/sparc/kernel/of_device_64.c +++ b/arch/sparc/kernel/of_device_64.c @@ -643,6 +643,7 @@ static struct of_device * __init scan_one_device(struct device_node *dp, sd->prom_node = dp; sd->op = op; + op->dev.of_node = dp; op->node = dp; op->clock_freq = of_getintprop_default(dp, "clock-frequency", diff --git a/arch/sparc/kernel/pci.c b/arch/sparc/kernel/pci.c index 5ac539a5930f..0c920147b4ef 100644 --- a/arch/sparc/kernel/pci.c +++ b/arch/sparc/kernel/pci.c @@ -262,6 +262,7 @@ static struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm, sd->stc = &pbm->stc; sd->host_controller = pbm; sd->prom_node = node; + dev->dev.of_node = node; sd->op = op = of_find_device_by_node(node); sd->numa_node = pbm->numa_node; diff --git a/drivers/of/of_mdio.c b/drivers/of/of_mdio.c index 18ecae4a4375..12090f57dc87 100644 --- a/drivers/of/of_mdio.c +++ b/drivers/of/of_mdio.c @@ -80,6 +80,7 @@ int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np) * can be looked up later */ of_node_get(child); dev_archdata_set_node(&phy->dev.archdata, child); + phy->dev.of_node = child; /* All data is now stored in the phy struct; register it */ rc = phy_device_register(phy); diff --git a/drivers/of/of_spi.c b/drivers/of/of_spi.c index f65f48b98448..f3119a0836af 100644 --- a/drivers/of/of_spi.c +++ b/drivers/of/of_spi.c @@ -79,6 +79,7 @@ void of_register_spi_devices(struct spi_master *master, struct device_node *np) /* Store a pointer to the node in the device structure */ of_node_get(nc); + spi->dev.of_node = nc; spi->dev.archdata.of_node = nc; /* Register the new device */ diff --git a/include/linux/device.h b/include/linux/device.h index 182192892d45..7a968bdb02e2 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -34,6 +34,7 @@ struct class; struct class_private; struct bus_type; struct bus_type_private; +struct device_node; struct bus_attribute { struct attribute attr; @@ -433,6 +434,9 @@ struct device { override */ /* arch specific additions */ struct dev_archdata archdata; +#ifdef CONFIG_OF + struct device_node *of_node; +#endif dev_t devt; /* dev_t, creates the sysfs "dev" */ From d12d42f744f805a9ccc33cd76f04b237cd83ce56 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Tue, 13 Apr 2010 16:12:28 -0700 Subject: [PATCH 0044/1337] i2c/of: Allow device node to be passed via i2c_board_info The struct device_node *of_node pointer is moving out of dev->archdata and into the struct device proper. of_i2c.c needs to set the of_node pointer before the device is registered. Since the i2c subsystem doesn't allow 2 stage allocation and registration of i2c devices, the of_node pointer needs to be passed via the i2c_board_info structure so that it is set prior to registration. This patch adds of_node to struct i2c_board_info (conditional on CONFIG_OF), sets of_node in i2c_new_device(), and modifies of_i2c.c to use the new parameter. The calling of dev_archdata_set_node() from of_i2c will be removed in a subsequent patch when of_node is removed from archdata and all users are converted over. Signed-off-by: Grant Likely --- drivers/i2c/i2c-core.c | 3 +++ drivers/of/of_i2c.c | 1 + include/linux/i2c.h | 4 ++++ 3 files changed, 8 insertions(+) diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 3202a86f420e..4099b2b8c392 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -387,6 +387,9 @@ i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info) client->dev.parent = &client->adapter->dev; client->dev.bus = &i2c_bus_type; client->dev.type = &i2c_client_type; +#ifdef CONFIG_OF + client->dev.of_node = info->of_node; +#endif dev_set_name(&client->dev, "%d-%04x", i2c_adapter_id(adap), client->addr); diff --git a/drivers/of/of_i2c.c b/drivers/of/of_i2c.c index a3a708e590d0..e690a2aa6fef 100644 --- a/drivers/of/of_i2c.c +++ b/drivers/of/of_i2c.c @@ -43,6 +43,7 @@ void of_register_i2c_devices(struct i2c_adapter *adap, info.addr = be32_to_cpup(addr); dev_archdata_set_node(&dev_ad, node); + info.of_node = node; info.archdata = &dev_ad; request_module("%s", info.type); diff --git a/include/linux/i2c.h b/include/linux/i2c.h index 0a5da639b327..4f37ff1de7e1 100644 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h @@ -34,6 +34,7 @@ #include /* for struct device */ #include /* for completion */ #include +#include /* for struct device_node */ extern struct bus_type i2c_bus_type; @@ -251,6 +252,9 @@ struct i2c_board_info { unsigned short addr; void *platform_data; struct dev_archdata *archdata; +#ifdef CONFIG_OF + struct device_node *of_node; +#endif int irq; }; From ab6cc8f9b716a3d0a41b42cd81d392183211a7f2 Mon Sep 17 00:00:00 2001 From: Anton Vorontsov Date: Mon, 26 Apr 2010 22:10:52 +0400 Subject: [PATCH 0045/1337] ds2782_battery: Get rid of magic numbers in driver_data Constructions like 'if (id->driver_data == 1)' look quite weird. This patch introduces 'enum ds278x_num_id', which makes things much more understandable, i.e. 'if (id->driver_data == DS2786)'. Signed-off-by: Anton Vorontsov Acked-by: Mike Rapoport --- drivers/power/ds2782_battery.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/drivers/power/ds2782_battery.c b/drivers/power/ds2782_battery.c index c665e8007235..d762a0cbc6af 100644 --- a/drivers/power/ds2782_battery.c +++ b/drivers/power/ds2782_battery.c @@ -300,13 +300,18 @@ static int ds278x_battery_remove(struct i2c_client *client) return 0; } +enum ds278x_num_id { + DS2782 = 0, + DS2786, +}; + static struct ds278x_battery_ops ds278x_ops[] = { - [0] = { + [DS2782] = { .get_current = ds2782_get_current, .get_voltage = ds2782_get_voltage, .get_capacity = ds2782_get_capacity, }, - [1] = { + [DS2786] = { .get_current = ds2786_get_current, .get_voltage = ds2786_get_voltage, .get_capacity = ds2786_get_capacity, @@ -325,7 +330,7 @@ static int ds278x_battery_probe(struct i2c_client *client, * ds2786 should have the sense resistor value set * in the platform data */ - if (id->driver_data == 1 && !pdata) { + if (id->driver_data == DS2786 && !pdata) { dev_err(&client->dev, "missing platform data for ds2786\n"); return -EINVAL; } @@ -355,7 +360,7 @@ static int ds278x_battery_probe(struct i2c_client *client, goto fail_name; } - if (id->driver_data == 1) + if (id->driver_data == DS2786) info->rsns = pdata->rsns; i2c_set_clientdata(client, info); @@ -385,8 +390,8 @@ fail_id: } static const struct i2c_device_id ds278x_id[] = { - {"ds2782", 0}, - {"ds2786", 1}, + {"ds2782", DS2782}, + {"ds2786", DS2786}, {}, }; From b1458fb57de03b19296cac70e9455b05912782b5 Mon Sep 17 00:00:00 2001 From: Anton Vorontsov Date: Sun, 2 May 2010 23:50:38 +0400 Subject: [PATCH 0046/1337] wm97xx_battery: Quieten sparse warning (bat_set_pdata not declared) This patch fixes following sparse warning: drivers/power/wm97xx_battery.c:311:6: warning: symbol 'wm97xx_bat_set_pdata' was not declared. Should it be static? Note that we can't just include linux/wm97xx_batt.h because the header is deprecated, and so this pops up: In file included from drivers/power/wm97xx_battery.c:22: include/linux/wm97xx_batt.h:6: warning: #warning This file will be removed soon, use wm97xx.h instead! Since wm97xx_bat_set_pdata() is also deprecated (in favour of pdata passed via AC97 bus), just workaround the issue by declaring the function in wm97xx_battery.c. Signed-off-by: Anton Vorontsov --- drivers/power/wm97xx_battery.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/power/wm97xx_battery.c b/drivers/power/wm97xx_battery.c index 94c70650aafc..4e8afce0c818 100644 --- a/drivers/power/wm97xx_battery.c +++ b/drivers/power/wm97xx_battery.c @@ -308,6 +308,9 @@ static void __exit wm97xx_bat_exit(void) platform_driver_unregister(&wm97xx_bat_driver); } +/* The interface is deprecated, as well as linux/wm97xx_batt.h */ +void wm97xx_bat_set_pdata(struct wm97xx_batt_info *data); + void wm97xx_bat_set_pdata(struct wm97xx_batt_info *data) { gpdata = data; From 06b9e650ce5eaf14ac1486b2f05baaf2ba22ad22 Mon Sep 17 00:00:00 2001 From: Dmitry Eremin-Solenikov Date: Tue, 27 Apr 2010 17:18:22 +0400 Subject: [PATCH 0047/1337] tosa_battery: Fix build error due to direct driver_data usage The driver isn't buildable since 2.6.32 (i.e. commit b4028437 "Driver core: move dev_get/set_drvdata to drivers/base/dd.c"): CC tosa_battery.o tosa_battery.c: In function 'tosa_read_bat': tosa_battery.c:64: error: 'struct device' has no member named 'driver_data' tosa_battery.c: In function 'tosa_read_temp': tosa_battery.c:84: error: 'struct device' has no member named 'driver_data' Nowadays we must not access driver_data directly, use dev_get_drvdata() instead. Signed-off-by: Dmitry Eremin-Solenikov Signed-off-by: Andrew Morton Signed-off-by: Anton Vorontsov --- drivers/power/tosa_battery.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/power/tosa_battery.c b/drivers/power/tosa_battery.c index 2eab35aab311..ee04936b2db5 100644 --- a/drivers/power/tosa_battery.c +++ b/drivers/power/tosa_battery.c @@ -61,7 +61,7 @@ static unsigned long tosa_read_bat(struct tosa_bat *bat) mutex_lock(&bat_lock); gpio_set_value(bat->gpio_bat, 1); msleep(5); - value = wm97xx_read_aux_adc(bat->psy.dev->parent->driver_data, + value = wm97xx_read_aux_adc(dev_get_drvdata(bat->psy.dev->parent), bat->adc_bat); gpio_set_value(bat->gpio_bat, 0); mutex_unlock(&bat_lock); @@ -81,7 +81,7 @@ static unsigned long tosa_read_temp(struct tosa_bat *bat) mutex_lock(&bat_lock); gpio_set_value(bat->gpio_temp, 1); msleep(5); - value = wm97xx_read_aux_adc(bat->psy.dev->parent->driver_data, + value = wm97xx_read_aux_adc(dev_get_drvdata(bat->psy.dev->parent), bat->adc_temp); gpio_set_value(bat->gpio_temp, 0); mutex_unlock(&bat_lock); From 282f152219020c14064efa78374309e1df6a23a2 Mon Sep 17 00:00:00 2001 From: Dinh Nguyen Date: Fri, 30 Apr 2010 15:48:23 -0500 Subject: [PATCH 0048/1337] mxc: Update GPIO for USB support on Freescale MX51 Babbage HW This patch is part of enabling USB for Freescale MX51 Babbage HW. This patch updates the iomux pins for USB, and gpio line for reset the USB hub on the MX51 Babbage HW. This patch applies to 2.6.34-rc6. Signed-off-by: Dinh Nguyen Signed-off-by: Sascha Hauer --- arch/arm/plat-mxc/include/mach/iomux-mx51.h | 33 +++++++++++++-------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/arch/arm/plat-mxc/include/mach/iomux-mx51.h b/arch/arm/plat-mxc/include/mach/iomux-mx51.h index b4f975e6a665..80528cc3b557 100644 --- a/arch/arm/plat-mxc/include/mach/iomux-mx51.h +++ b/arch/arm/plat-mxc/include/mach/iomux-mx51.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2009-2010 Amit Kucheria + * Copyright (C) 2010 Freescale Semiconductor, Inc. * * The code contained herein is licensed under the GNU General Public * License. You may obtain a copy of the GNU General Public License @@ -37,6 +38,11 @@ typedef enum iomux_config { PAD_CTL_SRE_FAST) #define MX51_UART3_PAD_CTRL (PAD_CTL_PKE | PAD_CTL_DSE_HIGH | \ PAD_CTL_SRE_FAST) +#define MX51_USBH1_PAD_CTRL (PAD_CTL_SRE_FAST | PAD_CTL_DSE_HIGH | \ + PAD_CTL_PUS_100K_UP | PAD_CTL_PUE | \ + PAD_CTL_PKE | PAD_CTL_HYS) +#define MX51_GPIO_PAD_CTRL (PAD_CTL_DSE_HIGH | PAD_CTL_PKE | \ + PAD_CTL_SRE_FAST) /* * The naming convention for the pad modes is MX51_PAD___ @@ -208,18 +214,19 @@ typedef enum iomux_config { #define MX51_PAD_KEY_COL3__KEY_COL3 IOMUX_PAD(0x658, 0x268, 0, 0x0, 0, NO_PAD_CTRL) #define MX51_PAD_KEY_COL4__KEY_COL4 IOMUX_PAD(0x65C, 0x26C, 0, 0x0, 0, NO_PAD_CTRL) #define MX51_PAD_KEY_COL5__KEY_COL5 IOMUX_PAD(0x660, 0x270, 0, 0x0, 0, NO_PAD_CTRL) -#define MX51_PAD_GPIO_1_25__USBH1_CLK IOMUX_PAD(0x678, 0x278, 2, 0x0, 0, NO_PAD_CTRL) -#define MX51_PAD_GPIO_1_26__USBH1_DIR IOMUX_PAD(0x67C, 0x27C, 2, 0x0, 0, NO_PAD_CTRL) -#define MX51_PAD_GPIO_1_27__USBH1_STP IOMUX_PAD(0x680, 0x280, 2, 0x0, 0, NO_PAD_CTRL) -#define MX51_PAD_GPIO_1_28__USBH1_NXT IOMUX_PAD(0x684, 0x284, 2, 0x0, 0, NO_PAD_CTRL) -#define MX51_PAD_GPIO_1_11__USBH1_DATA0 IOMUX_PAD(0x688, 0x288, 2, 0x0, 0, NO_PAD_CTRL) -#define MX51_PAD_GPIO_1_12__USBH1_DATA1 IOMUX_PAD(0x68C, 0x28C, 2, 0x0, 0, NO_PAD_CTRL) -#define MX51_PAD_GPIO_1_13__USBH1_DATA2 IOMUX_PAD(0x690, 0x290, 2, 0x0, 0, NO_PAD_CTRL) -#define MX51_PAD_GPIO_1_14__USBH1_DATA3 IOMUX_PAD(0x694, 0x294, 2, 0x0, 0, NO_PAD_CTRL) -#define MX51_PAD_GPIO_1_15__USBH1_DATA4 IOMUX_PAD(0x698, 0x298, 2, 0x0, 0, NO_PAD_CTRL) -#define MX51_PAD_GPIO_1_16__USBH1_DATA5 IOMUX_PAD(0x69C, 0x29C, 2, 0x0, 0, NO_PAD_CTRL) -#define MX51_PAD_GPIO_1_17__USBH1_DATA6 IOMUX_PAD(0x6A0, 0x2A0, 2, 0x0, 0, NO_PAD_CTRL) -#define MX51_PAD_GPIO_1_18__USBH1_DATA7 IOMUX_PAD(0x6A4, 0x2A4, 2, 0x0, 0, NO_PAD_CTRL) +#define MX51_PAD_USBH1_CLK__USBH1_CLK IOMUX_PAD(0x678, 0x278, IOMUX_CONFIG_ALT0, 0x0, 0, MX51_USBH1_PAD_CTRL) +#define MX51_PAD_USBH1_DIR__USBH1_DIR IOMUX_PAD(0x67C, 0x27C, IOMUX_CONFIG_ALT0, 0x0, 0, MX51_USBH1_PAD_CTRL) +#define MX51_PAD_USBH1_STP__USBH1_STP IOMUX_PAD(0x680, 0x280, IOMUX_CONFIG_ALT0, 0x0, 0, MX51_USBH1_PAD_CTRL) +#define MX51_PAD_USBH1_STP__GPIO_1_27 IOMUX_PAD(0x680, 0x280, IOMUX_CONFIG_GPIO, 0x0, 0, MX51_USBH1_PAD_CTRL) +#define MX51_PAD_USBH1_NXT__USBH1_NXT IOMUX_PAD(0x684, 0x284, IOMUX_CONFIG_ALT0, 0x0, 0, MX51_USBH1_PAD_CTRL) +#define MX51_PAD_USBH1_DATA0__USBH1_DATA0 IOMUX_PAD(0x688, 0x288, IOMUX_CONFIG_ALT0, 0x0, 0, MX51_USBH1_PAD_CTRL) +#define MX51_PAD_USBH1_DATA1__USBH1_DATA1 IOMUX_PAD(0x68C, 0x28C, IOMUX_CONFIG_ALT0, 0x0, 0, MX51_USBH1_PAD_CTRL) +#define MX51_PAD_USBH1_DATA2__USBH1_DATA2 IOMUX_PAD(0x690, 0x290, IOMUX_CONFIG_ALT0, 0x0, 0, MX51_USBH1_PAD_CTRL) +#define MX51_PAD_USBH1_DATA3__USBH1_DATA3 IOMUX_PAD(0x694, 0x294, IOMUX_CONFIG_ALT0, 0x0, 0, MX51_USBH1_PAD_CTRL) +#define MX51_PAD_USBH1_DATA4__USBH1_DATA4 IOMUX_PAD(0x698, 0x298, IOMUX_CONFIG_ALT0, 0x0, 0, MX51_USBH1_PAD_CTRL) +#define MX51_PAD_USBH1_DATA5__USBH1_DATA5 IOMUX_PAD(0x69C, 0x29C, IOMUX_CONFIG_ALT0, 0x0, 0, MX51_USBH1_PAD_CTRL) +#define MX51_PAD_USBH1_DATA6__USBH1_DATA6 IOMUX_PAD(0x6A0, 0x2A0, IOMUX_CONFIG_ALT0, 0x0, 0, MX51_USBH1_PAD_CTRL) +#define MX51_PAD_USBH1_DATA7__USBH1_DATA7 IOMUX_PAD(0x6A4, 0x2A4, IOMUX_CONFIG_ALT0, 0x0, 0, MX51_USBH1_PAD_CTRL) #define MX51_PAD_GPIO_3_0__DI1_PIN11 IOMUX_PAD(0x6A8, 0x2A8, 4, 0x0, 0, NO_PAD_CTRL) #define MX51_PAD_GPIO_3_1__DI1_PIN12 IOMUX_PAD(0x6AC, 0x2AC, 4, 0x0, 0, NO_PAD_CTRL) #define MX51_PAD_GPIO_3_2__DI1_PIN13 IOMUX_PAD(0x6B0, 0x2B0, 4, 0x0, 0, NO_PAD_CTRL) @@ -299,7 +306,7 @@ typedef enum iomux_config { #define MX51_PAD_GPIO_1_4__GPIO1_4 IOMUX_PAD(0x804, 0x3D8, 0, 0x0, 0, NO_PAD_CTRL) #define MX51_PAD_GPIO_1_5__GPIO1_5 IOMUX_PAD(0x808, 0x3DC, 0, 0x0, 0, NO_PAD_CTRL) #define MX51_PAD_GPIO_1_6__GPIO1_6 IOMUX_PAD(0x80C, 0x3E0, 0, 0x0, 0, NO_PAD_CTRL) -#define MX51_PAD_GPIO_1_7__GPIO1_7 IOMUX_PAD(0x810, 0x3E4, 0, 0x0, 0, NO_PAD_CTRL) +#define MX51_PAD_GPIO_1_7__GPIO1_7 IOMUX_PAD(0x810, 0x3E4, 0, 0x0, 0, MX51_GPIO_PAD_CTRL) #define MX51_PAD_GPIO_1_8__GPIO1_8 IOMUX_PAD(0x814, 0x3E8, 0, 0x0, 1, \ (PAD_CTL_SRE_SLOW | PAD_CTL_DSE_MED | PAD_CTL_PUS_100K_UP | PAD_CTL_HYS)) #define MX51_PAD_GPIO_1_9__GPIO1_9 IOMUX_PAD(0x818, 0x3EC, 0, 0x0, 0, NO_PAD_CTRL) From c53bdf1c4488ce196e9a0056285e7b4a36f6f76a Mon Sep 17 00:00:00 2001 From: Dinh Nguyen Date: Fri, 30 Apr 2010 15:48:24 -0500 Subject: [PATCH 0049/1337] mx5: Add USB device definitions for Freescale MX51 Babbage HW This patch is part of enabling USB for Freescale MX51 Babbage HW. This patch adds device structures for USB Host1 and OTG port, and adds clocking information for USB HW. This patch applies to 2.6.34-rc6. Signed-off-by: Dinh Nguyen Signed-off-by: Sascha Hauer --- arch/arm/mach-mx5/clock-mx51.c | 8 ++++++ arch/arm/mach-mx5/devices.c | 49 ++++++++++++++++++++++++++++++++++ arch/arm/mach-mx5/devices.h | 2 ++ 3 files changed, 59 insertions(+) diff --git a/arch/arm/mach-mx5/clock-mx51.c b/arch/arm/mach-mx5/clock-mx51.c index 8f85f73b83a8..dcca330addc9 100644 --- a/arch/arm/mach-mx5/clock-mx51.c +++ b/arch/arm/mach-mx5/clock-mx51.c @@ -761,6 +761,10 @@ DEFINE_CLOCK(gpt_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG9_OFFSET, DEFINE_CLOCK(gpt_ipg_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG10_OFFSET, NULL, NULL, &ipg_clk, NULL); +/* USB */ +DEFINE_CLOCK(usboh3_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG14_OFFSET, + NULL, NULL, &pll3_sw_clk, NULL); + /* FEC */ DEFINE_CLOCK(fec_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG12_OFFSET, NULL, NULL, &ipg_clk, NULL); @@ -778,6 +782,10 @@ static struct clk_lookup lookups[] = { _REGISTER_CLOCK("imx-uart.2", NULL, uart3_clk) _REGISTER_CLOCK(NULL, "gpt", gpt_clk) _REGISTER_CLOCK("fec.0", NULL, fec_clk) + _REGISTER_CLOCK("mxc-ehci.0", "usb", usboh3_clk) + _REGISTER_CLOCK("mxc-ehci.0", "usb_ahb", ahb_clk) + _REGISTER_CLOCK("mxc-ehci.1", "usb", usboh3_clk) + _REGISTER_CLOCK("mxc-ehci.1", "usb_ahb", ahb_clk) }; static void clk_tree_init(void) diff --git a/arch/arm/mach-mx5/devices.c b/arch/arm/mach-mx5/devices.c index 5070ae1f94c6..e6262f31ed8f 100644 --- a/arch/arm/mach-mx5/devices.c +++ b/arch/arm/mach-mx5/devices.c @@ -11,6 +11,7 @@ */ #include +#include #include #include #include @@ -92,6 +93,54 @@ struct platform_device mxc_fec_device = { .resource = mxc_fec_resources, }; +static u64 usb_dma_mask = DMA_BIT_MASK(32); + +static struct resource usbotg_resources[] = { + { + .start = MX51_OTG_BASE_ADDR, + .end = MX51_OTG_BASE_ADDR + 0x1ff, + .flags = IORESOURCE_MEM, + }, + { + .start = MX51_MXC_INT_USB_OTG, + .flags = IORESOURCE_IRQ, + }, +}; + +struct platform_device mxc_usbdr_host_device = { + .name = "mxc-ehci", + .id = 0, + .num_resources = ARRAY_SIZE(usbotg_resources), + .resource = usbotg_resources, + .dev = { + .dma_mask = &usb_dma_mask, + .coherent_dma_mask = DMA_BIT_MASK(32), + }, +}; + +static struct resource usbh1_resources[] = { + { + .start = MX51_OTG_BASE_ADDR + 0x200, + .end = MX51_OTG_BASE_ADDR + 0x200 + 0x1ff, + .flags = IORESOURCE_MEM, + }, + { + .start = MX51_MXC_INT_USB_H1, + .flags = IORESOURCE_IRQ, + }, +}; + +struct platform_device mxc_usbh1_device = { + .name = "mxc-ehci", + .id = 1, + .num_resources = ARRAY_SIZE(usbh1_resources), + .resource = usbh1_resources, + .dev = { + .dma_mask = &usb_dma_mask, + .coherent_dma_mask = DMA_BIT_MASK(32), + }, +}; + static struct mxc_gpio_port mxc_gpio_ports[] = { { .chip.label = "gpio-0", diff --git a/arch/arm/mach-mx5/devices.h b/arch/arm/mach-mx5/devices.h index f339ab8c19be..95c45f9e46ca 100644 --- a/arch/arm/mach-mx5/devices.h +++ b/arch/arm/mach-mx5/devices.h @@ -2,3 +2,5 @@ extern struct platform_device mxc_uart_device0; extern struct platform_device mxc_uart_device1; extern struct platform_device mxc_uart_device2; extern struct platform_device mxc_fec_device; +extern struct platform_device mxc_usbdr_host_device; +extern struct platform_device mxc_usbh1_device; From 231637f5f2c7f3795d1b0c9b59fda27a23ffdc3e Mon Sep 17 00:00:00 2001 From: Dinh Nguyen Date: Fri, 30 Apr 2010 15:48:25 -0500 Subject: [PATCH 0050/1337] mx5: Enable board specific functions for enabling USB host on Babbage This patch enables USB host functionality for Host1 and OTG port on Freescale MX51 Babbage HW. This patch contains the board specific HW initialization of the USB HW. This patch applies to 2.6.34-rc6. Signed-off-by: Dinh Nguyen Reviewed-by: Daniel Mack Signed-off-by: Sascha Hauer --- arch/arm/mach-mx5/board-mx51_babbage.c | 129 +++++++++++++++++++++++++ 1 file changed, 129 insertions(+) diff --git a/arch/arm/mach-mx5/board-mx51_babbage.c b/arch/arm/mach-mx5/board-mx51_babbage.c index ee67a71db80d..99f7ea903a51 100644 --- a/arch/arm/mach-mx5/board-mx51_babbage.c +++ b/arch/arm/mach-mx5/board-mx51_babbage.c @@ -12,11 +12,15 @@ #include #include +#include +#include +#include #include #include #include #include +#include #include #include @@ -26,6 +30,17 @@ #include "devices.h" +#define BABBAGE_USB_HUB_RESET (0*32 + 7) /* GPIO_1_7 */ +#define BABBAGE_USBH1_STP (0*32 + 27) /* GPIO_1_27 */ + +/* USB_CTRL_1 */ +#define MX51_USB_CTRL_1_OFFSET 0x10 +#define MX51_USB_CTRL_UH1_EXT_CLK_EN (1 << 25) + +#define MX51_USB_PLLDIV_12_MHZ 0x00 +#define MX51_USB_PLL_DIV_19_2_MHZ 0x01 +#define MX51_USB_PLL_DIV_24_MHZ 0x02 + static struct platform_device *devices[] __initdata = { &mxc_fec_device, }; @@ -46,6 +61,22 @@ static struct pad_desc mx51babbage_pads[] = { MX51_PAD_EIM_D26__UART3_TXD, MX51_PAD_EIM_D27__UART3_RTS, MX51_PAD_EIM_D24__UART3_CTS, + + /* USB HOST1 */ + MX51_PAD_USBH1_CLK__USBH1_CLK, + MX51_PAD_USBH1_DIR__USBH1_DIR, + MX51_PAD_USBH1_NXT__USBH1_NXT, + MX51_PAD_USBH1_DATA0__USBH1_DATA0, + MX51_PAD_USBH1_DATA1__USBH1_DATA1, + MX51_PAD_USBH1_DATA2__USBH1_DATA2, + MX51_PAD_USBH1_DATA3__USBH1_DATA3, + MX51_PAD_USBH1_DATA4__USBH1_DATA4, + MX51_PAD_USBH1_DATA5__USBH1_DATA5, + MX51_PAD_USBH1_DATA6__USBH1_DATA6, + MX51_PAD_USBH1_DATA7__USBH1_DATA7, + + /* USB HUB reset line*/ + MX51_PAD_GPIO_1_7__GPIO1_7, }; /* Serial ports */ @@ -66,15 +97,113 @@ static inline void mxc_init_imx_uart(void) } #endif /* SERIAL_IMX */ +static int gpio_usbh1_active(void) +{ + struct pad_desc usbh1stp_gpio = MX51_PAD_USBH1_STP__GPIO_1_27; + int ret; + + /* Set USBH1_STP to GPIO and toggle it */ + mxc_iomux_v3_setup_pad(&usbh1stp_gpio); + ret = gpio_request(BABBAGE_USBH1_STP, "usbh1_stp"); + + if (ret) { + pr_debug("failed to get MX51_PAD_USBH1_STP__GPIO_1_27: %d\n", ret); + return ret; + } + gpio_direction_output(BABBAGE_USBH1_STP, 0); + gpio_set_value(BABBAGE_USBH1_STP, 1); + msleep(100); + gpio_free(BABBAGE_USBH1_STP); + return 0; +} + +static inline void babbage_usbhub_reset(void) +{ + int ret; + + /* Bring USB hub out of reset */ + ret = gpio_request(BABBAGE_USB_HUB_RESET, "GPIO1_7"); + if (ret) { + printk(KERN_ERR"failed to get GPIO_USB_HUB_RESET: %d\n", ret); + return; + } + gpio_direction_output(BABBAGE_USB_HUB_RESET, 0); + + /* USB HUB RESET - De-assert USB HUB RESET_N */ + msleep(1); + gpio_set_value(BABBAGE_USB_HUB_RESET, 0); + msleep(1); + gpio_set_value(BABBAGE_USB_HUB_RESET, 1); +} + +/* This function is board specific as the bit mask for the plldiv will also +be different for other Freescale SoCs, thus a common bitmask is not +possible and cannot get place in /plat-mxc/ehci.c.*/ +static int initialize_otg_port(struct platform_device *pdev) +{ + u32 v; + void __iomem *usb_base; + u32 usbother_base; + + usb_base = ioremap(MX51_OTG_BASE_ADDR, SZ_4K); + usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET; + + /* Set the PHY clock to 19.2MHz */ + v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET); + v &= ~MX5_USB_UTMI_PHYCTRL1_PLLDIV_MASK; + v |= MX51_USB_PLL_DIV_19_2_MHZ; + __raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET); + iounmap(usb_base); + return 0; +} + +static int initialize_usbh1_port(struct platform_device *pdev) +{ + u32 v; + void __iomem *usb_base; + u32 usbother_base; + + usb_base = ioremap(MX51_OTG_BASE_ADDR, SZ_4K); + usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET; + + /* The clock for the USBH1 ULPI port will come externally from the PHY. */ + v = __raw_readl(usbother_base + MX51_USB_CTRL_1_OFFSET); + __raw_writel(v | MX51_USB_CTRL_UH1_EXT_CLK_EN, usbother_base + MX51_USB_CTRL_1_OFFSET); + iounmap(usb_base); + return 0; +} + +static struct mxc_usbh_platform_data dr_utmi_config = { + .init = initialize_otg_port, + .portsc = MXC_EHCI_UTMI_16BIT, + .flags = MXC_EHCI_INTERNAL_PHY, +}; + +static struct mxc_usbh_platform_data usbh1_config = { + .init = initialize_usbh1_port, + .portsc = MXC_EHCI_MODE_ULPI, + .flags = (MXC_EHCI_POWER_PINS_ENABLED | MXC_EHCI_ITC_NO_THRESHOLD), +}; + /* * Board specific initialization. */ static void __init mxc_board_init(void) { + struct pad_desc usbh1stp = MX51_PAD_USBH1_STP__USBH1_STP; + mxc_iomux_v3_setup_multiple_pads(mx51babbage_pads, ARRAY_SIZE(mx51babbage_pads)); mxc_init_imx_uart(); platform_add_devices(devices, ARRAY_SIZE(devices)); + + mxc_register_device(&mxc_usbdr_host_device, &dr_utmi_config); + + gpio_usbh1_active(); + mxc_register_device(&mxc_usbh1_device, &usbh1_config); + /* setback USBH1_STP to be function */ + mxc_iomux_v3_setup_pad(&usbh1stp); + babbage_usbhub_reset(); } static void __init mx51_babbage_timer_init(void) From 5a25ad84e01173bb225285eb50f9af48ed1a7598 Mon Sep 17 00:00:00 2001 From: Dinh Nguyen Date: Fri, 30 Apr 2010 15:48:26 -0500 Subject: [PATCH 0051/1337] mxc: Add generic USB HW initialization for MX51 This patch adds USB HW initializiation code to /plat-mxc/ehci.c. -Sets some specific PHY settings Renames mxc_set_usbcontrol to mxc_initialize_usb_hw. Adds new register bit defines for the USB HW on Freescale SoCs. This patch applies to 2.6.34-rc6. Signed-off-by: Dinh Nguyen Reviewed-by: Daniel Mack Signed-off-by: Sascha Hauer --- arch/arm/plat-mxc/ehci.c | 100 +++++++++++++++++++++- arch/arm/plat-mxc/include/mach/mxc_ehci.h | 14 ++- drivers/usb/host/ehci-mxc.c | 4 +- 3 files changed, 113 insertions(+), 5 deletions(-) diff --git a/arch/arm/plat-mxc/ehci.c b/arch/arm/plat-mxc/ehci.c index cb0b63874482..2a8646173c2f 100644 --- a/arch/arm/plat-mxc/ehci.c +++ b/arch/arm/plat-mxc/ehci.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2009 Daniel Mack + * Copyright (C) 2010 Freescale Semiconductor, Inc. * * 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 @@ -50,7 +51,26 @@ #define MX35_H1_TLL_BIT (1 << 5) #define MX35_H1_USBTE_BIT (1 << 4) -int mxc_set_usbcontrol(int port, unsigned int flags) +#define MXC_OTG_OFFSET 0 +#define MXC_H1_OFFSET 0x200 + +/* USB_CTRL */ +#define MXC_OTG_UCTRL_OWIE_BIT (1 << 27) /* OTG wakeup intr enable */ +#define MXC_OTG_UCTRL_OPM_BIT (1 << 24) /* OTG power mask */ +#define MXC_H1_UCTRL_H1UIE_BIT (1 << 12) /* Host1 ULPI interrupt enable */ +#define MXC_H1_UCTRL_H1WIE_BIT (1 << 11) /* HOST1 wakeup intr enable */ +#define MXC_H1_UCTRL_H1PM_BIT (1 << 8) /* HOST1 power mask */ + +/* USB_PHY_CTRL_FUNC */ +#define MXC_OTG_PHYCTRL_OC_DIS_BIT (1 << 8) /* OTG Disable Overcurrent Event */ +#define MXC_H1_OC_DIS_BIT (1 << 5) /* UH1 Disable Overcurrent Event */ + +#define MXC_USBCMD_OFFSET 0x140 + +/* USBCMD */ +#define MXC_UCMD_ITC_NO_THRESHOLD_MASK (~(0xff << 16)) /* Interrupt Threshold Control */ + +int mxc_initialize_usb_hw(int port, unsigned int flags) { unsigned int v; #ifdef CONFIG_ARCH_MX3 @@ -186,9 +206,85 @@ int mxc_set_usbcontrol(int port, unsigned int flags) return 0; } #endif /* CONFIG_MACH_MX27 */ +#ifdef CONFIG_ARCH_MX51 + if (cpu_is_mx51()) { + void __iomem *usb_base; + u32 usbotg_base; + u32 usbother_base; + int ret = 0; + + usb_base = ioremap(MX51_OTG_BASE_ADDR, SZ_4K); + + switch (port) { + case 0: /* OTG port */ + usbotg_base = usb_base + MXC_OTG_OFFSET; + break; + case 1: /* Host 1 port */ + usbotg_base = usb_base + MXC_H1_OFFSET; + break; + default: + printk(KERN_ERR"%s no such port %d\n", __func__, port); + ret = -ENOENT; + goto error; + } + usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET; + + switch (port) { + case 0: /*OTG port */ + if (flags & MXC_EHCI_INTERNAL_PHY) { + v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET); + + if (flags & MXC_EHCI_POWER_PINS_ENABLED) + v |= (MXC_OTG_PHYCTRL_OC_DIS_BIT | MXC_OTG_UCTRL_OPM_BIT); /* OC/USBPWR is not used */ + else + v &= ~(MXC_OTG_PHYCTRL_OC_DIS_BIT | MXC_OTG_UCTRL_OPM_BIT); /* OC/USBPWR is used */ + __raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET); + + v = __raw_readl(usbother_base + MXC_USBCTRL_OFFSET); + if (flags & MXC_EHCI_WAKEUP_ENABLED) + v |= MXC_OTG_UCTRL_OWIE_BIT;/* OTG wakeup enable */ + else + v &= ~MXC_OTG_UCTRL_OWIE_BIT;/* OTG wakeup disable */ + __raw_writel(v, usbother_base + MXC_USBCTRL_OFFSET); + } + break; + case 1: /* Host 1 */ + /*Host ULPI */ + v = __raw_readl(usbother_base + MXC_USBCTRL_OFFSET); + if (flags & MXC_EHCI_WAKEUP_ENABLED) + v &= ~(MXC_H1_UCTRL_H1WIE_BIT | MXC_H1_UCTRL_H1UIE_BIT);/* HOST1 wakeup/ULPI intr disable */ + else + v &= ~(MXC_H1_UCTRL_H1WIE_BIT | MXC_H1_UCTRL_H1UIE_BIT);/* HOST1 wakeup/ULPI intr disable */ + + if (flags & MXC_EHCI_POWER_PINS_ENABLED) + v &= ~MXC_H1_UCTRL_H1PM_BIT; /* HOST1 power mask used*/ + else + v |= MXC_H1_UCTRL_H1PM_BIT; /* HOST1 power mask used*/ + __raw_writel(v, usbother_base + MXC_USBCTRL_OFFSET); + + v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET); + if (flags & MXC_EHCI_POWER_PINS_ENABLED) + v &= ~MXC_H1_OC_DIS_BIT; /* OC is used */ + else + v |= MXC_H1_OC_DIS_BIT; /* OC is not used */ + __raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET); + + v = __raw_readl(usbotg_base + MXC_USBCMD_OFFSET); + if (flags & MXC_EHCI_ITC_NO_THRESHOLD) + /* Interrupt Threshold Control:Immediate (no threshold) */ + v &= MXC_UCMD_ITC_NO_THRESHOLD_MASK; + __raw_writel(v, usbotg_base + MXC_USBCMD_OFFSET); + break; + } + +error: + iounmap(usb_base); + return ret; + } +#endif printk(KERN_WARNING "%s() unable to setup USBCONTROL for this CPU\n", __func__); return -EINVAL; } -EXPORT_SYMBOL(mxc_set_usbcontrol); +EXPORT_SYMBOL(mxc_initialize_usb_hw); diff --git a/arch/arm/plat-mxc/include/mach/mxc_ehci.h b/arch/arm/plat-mxc/include/mach/mxc_ehci.h index 4b9b8368c0c0..7fc5f9946199 100644 --- a/arch/arm/plat-mxc/include/mach/mxc_ehci.h +++ b/arch/arm/plat-mxc/include/mach/mxc_ehci.h @@ -25,6 +25,18 @@ #define MXC_EHCI_INTERNAL_PHY (1 << 7) #define MXC_EHCI_IPPUE_DOWN (1 << 8) #define MXC_EHCI_IPPUE_UP (1 << 9) +#define MXC_EHCI_WAKEUP_ENABLED (1 << 10) +#define MXC_EHCI_ITC_NO_THRESHOLD (1 << 11) + +#define MXC_USBCTRL_OFFSET 0 +#define MXC_USB_PHY_CTR_FUNC_OFFSET 0x8 +#define MXC_USB_PHY_CTR_FUNC2_OFFSET 0xc + +#define MX5_USBOTHER_REGS_OFFSET 0x800 + +/* USB_PHY_CTRL_FUNC2*/ +#define MX5_USB_UTMI_PHYCTRL1_PLLDIV_MASK 0x3 +#define MX5_USB_UTMI_PHYCTRL1_PLLDIV_SHIFT 0 struct mxc_usbh_platform_data { int (*init)(struct platform_device *pdev); @@ -35,7 +47,7 @@ struct mxc_usbh_platform_data { struct otg_transceiver *otg; }; -int mxc_set_usbcontrol(int port, unsigned int flags); +int mxc_initialize_usb_hw(int port, unsigned int flags); #endif /* __INCLUDE_ASM_ARCH_MXC_EHCI_H */ diff --git a/drivers/usb/host/ehci-mxc.c b/drivers/usb/host/ehci-mxc.c index ead59f42e69b..544ccfd7056e 100644 --- a/drivers/usb/host/ehci-mxc.c +++ b/drivers/usb/host/ehci-mxc.c @@ -199,8 +199,8 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev) writel(pdata->portsc, hcd->regs + PORTSC_OFFSET); mdelay(10); - /* setup USBCONTROL. */ - ret = mxc_set_usbcontrol(pdev->id, pdata->flags); + /* setup specific usb hw */ + ret = mxc_initialize_usb_hw(pdev->id, pdata->flags); if (ret < 0) goto err_init; From 28a2afe0df1078d479923142a708adfe65fbf8b7 Mon Sep 17 00:00:00 2001 From: Dinh Nguyen Date: Fri, 30 Apr 2010 15:48:27 -0500 Subject: [PATCH 0052/1337] mx5: Add USB to Freescale MX51 defconfig Update mx51_defconfig to include USB EHCI by default. This patch applies to 2.6.34-rc6. Signed-off-by: Dinh Nguyen Signed-off-by: Sascha Hauer --- arch/arm/configs/mx51_defconfig | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/arch/arm/configs/mx51_defconfig b/arch/arm/configs/mx51_defconfig index c88e9527a8ec..a708fd6d6ffe 100644 --- a/arch/arm/configs/mx51_defconfig +++ b/arch/arm/configs/mx51_defconfig @@ -809,7 +809,22 @@ CONFIG_SSB_POSSIBLE=y CONFIG_DUMMY_CONSOLE=y # CONFIG_SOUND is not set # CONFIG_HID_SUPPORT is not set -# CONFIG_USB_SUPPORT is not set +CONFIG_USB_SUPPORT=y +CONFIG_USB_ARCH_HAS_HCD=y +# CONFIG_USB_ARCH_HAS_OHCI is not set +CONFIG_USB_ARCH_HAS_EHCI=y +CONFIG_USB=y + +# +# USB Host Controller Drivers +# +# CONFIG_USB_C67X00_HCD is not set +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_ROOT_HUB_TT=y +# CONFIG_USB_EHCI_TT_NEWSCHED is not set +CONFIG_USB_EHCI_MXC=y + + CONFIG_MMC=y # CONFIG_MMC_DEBUG is not set # CONFIG_MMC_UNSAFE_RESUME is not set From 7176441b95b4a04ad7cbac71d0d3614a7634d727 Mon Sep 17 00:00:00 2001 From: Valentin Longchamp Date: Wed, 5 May 2010 11:34:21 +0200 Subject: [PATCH 0053/1337] mx31smartbot: change the config of a gpio Since it is finally used on the handbot as a configuration input for the translator. Signed-off-by: Valentin Longchamp Signed-off-by: Sascha Hauer --- arch/arm/mach-mx3/mx31moboard-smartbot.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-mx3/mx31moboard-smartbot.c b/arch/arm/mach-mx3/mx31moboard-smartbot.c index 52a69fc8b14f..83d2b9f42cec 100644 --- a/arch/arm/mach-mx3/mx31moboard-smartbot.c +++ b/arch/arm/mach-mx3/mx31moboard-smartbot.c @@ -119,7 +119,7 @@ static int __init smartbot_cam_init(void) #define POWER_EN IOMUX_TO_GPIO(MX31_PIN_DTR_DCE1) #define DSPIC_RST_B IOMUX_TO_GPIO(MX31_PIN_DSR_DCE1) #define TRSLAT_RST_B IOMUX_TO_GPIO(MX31_PIN_RI_DCE1) -#define SEL3 IOMUX_TO_GPIO(MX31_PIN_DCD_DCE1) +#define TRSLAT_SRC_CHOICE IOMUX_TO_GPIO(MX31_PIN_DCD_DCE1) static void smartbot_resets_init(void) { @@ -138,9 +138,9 @@ static void smartbot_resets_init(void) gpio_export(TRSLAT_RST_B, false); } - if (!gpio_request(SEL3, "sel3")) { - gpio_direction_input(SEL3); - gpio_export(SEL3, true); + if (!gpio_request(TRSLAT_SRC_CHOICE, "translator-src-choice")) { + gpio_direction_output(TRSLAT_SRC_CHOICE, 0); + gpio_export(TRSLAT_SRC_CHOICE, false); } } /* From 0671e704658b9f26f85e78d51176daa861f955c7 Mon Sep 17 00:00:00 2001 From: Dmitry Monakhov Date: Mon, 10 May 2010 00:00:00 -0400 Subject: [PATCH 0054/1337] ext4: check missed return value in ext4_sync_file() Signed-off-by: Dmitry Monakhov Signed-off-by: "Theodore Ts'o" --- fs/ext4/fsync.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/ext4/fsync.c b/fs/ext4/fsync.c index 0d0c3239c1cd..42bd94a942c9 100644 --- a/fs/ext4/fsync.c +++ b/fs/ext4/fsync.c @@ -101,7 +101,7 @@ int ext4_sync_file(struct file *file, struct dentry *dentry, int datasync) (journal->j_fs_dev != journal->j_dev) && (journal->j_flags & JBD2_BARRIER)) blkdev_issue_flush(inode->i_sb->s_bdev, NULL); - jbd2_log_wait_commit(journal, commit_tid); + ret = jbd2_log_wait_commit(journal, commit_tid); } else if (journal->j_flags & JBD2_BARRIER) blkdev_issue_flush(inode->i_sb->s_bdev, NULL); return ret; From c26d0bad3d0e951487e5dee36632dd3817f42b10 Mon Sep 17 00:00:00 2001 From: Steven Liu Date: Tue, 11 May 2010 00:00:00 -0400 Subject: [PATCH 0055/1337] ext4: Fix coding style in fs/ext4/move_extent.c Making sure ee_block is initialized to zero to prevent gcc from kvetching. It's harmless (although it's not obvious that it's harmless) from code inspection: fs/ext4/move_extent.c:478: warning: 'start_ext.ee_block' may be used uninitialized in this function Thanks to Stefan Richter for first bringing this to the attention of linux-ext4@vger.kernel.org. Signed-off-by: LiuQi Signed-off-by: "Theodore Ts'o" Cc: Stefan Richter --- fs/ext4/move_extent.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/ext4/move_extent.c b/fs/ext4/move_extent.c index d1fc662cc311..82621a360932 100644 --- a/fs/ext4/move_extent.c +++ b/fs/ext4/move_extent.c @@ -482,6 +482,7 @@ mext_leaf_block(handle_t *handle, struct inode *orig_inode, int depth = ext_depth(orig_inode); int ret; + start_ext.ee_block = end_ext.ee_block = 0; o_start = o_end = oext = orig_path[depth].p_ext; oext_alen = ext4_ext_get_actual_len(oext); start_ext.ee_len = end_ext.ee_len = 0; From c79504e73a0e84c4db7a2315dcdd6987b0c52566 Mon Sep 17 00:00:00 2001 From: Dinh Nguyen Date: Mon, 10 May 2010 13:45:58 -0500 Subject: [PATCH 0056/1337] mx5: change usb clock source from pll3 to pll2 For power management reasons, pll2 should be used to source the USBOH3 clock for mx51. PLL3 can be completely gated off when USB is not used. This patch applies to 2.6.34-rc7. Signed-off-by: Dinh Nguyen Signed-off-by: Sascha Hauer --- arch/arm/mach-mx5/clock-mx51.c | 43 ++++++++++++++++++++++++++++++---- 1 file changed, 39 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-mx5/clock-mx51.c b/arch/arm/mach-mx5/clock-mx51.c index dcca330addc9..566cfda6185e 100644 --- a/arch/arm/mach-mx5/clock-mx51.c +++ b/arch/arm/mach-mx5/clock-mx51.c @@ -36,6 +36,7 @@ static struct clk lp_apm_clk; static struct clk periph_apm_clk; static struct clk ahb_clk; static struct clk ipg_clk; +static struct clk usboh3_clk; #define MAX_DPLL_WAIT_TRIES 1000 /* 1000 * udelay(1) = 1ms */ @@ -569,6 +570,35 @@ static int _clk_uart_set_parent(struct clk *clk, struct clk *parent) return 0; } +static unsigned long clk_usboh3_get_rate(struct clk *clk) +{ + u32 reg, prediv, podf; + unsigned long parent_rate; + + parent_rate = clk_get_rate(clk->parent); + + reg = __raw_readl(MXC_CCM_CSCDR1); + prediv = ((reg & MXC_CCM_CSCDR1_USBOH3_CLK_PRED_MASK) >> + MXC_CCM_CSCDR1_USBOH3_CLK_PRED_OFFSET) + 1; + podf = ((reg & MXC_CCM_CSCDR1_USBOH3_CLK_PODF_MASK) >> + MXC_CCM_CSCDR1_USBOH3_CLK_PODF_OFFSET) + 1; + + return parent_rate / (prediv * podf); +} + +static int _clk_usboh3_set_parent(struct clk *clk, struct clk *parent) +{ + u32 reg, mux; + + mux = _get_mux(parent, &pll1_sw_clk, &pll2_sw_clk, &pll3_sw_clk, + &lp_apm_clk); + reg = __raw_readl(MXC_CCM_CSCMR1) & ~MXC_CCM_CSCMR1_USBOH3_CLK_SEL_MASK; + reg |= mux << MXC_CCM_CSCMR1_USBOH3_CLK_SEL_OFFSET; + __raw_writel(reg, MXC_CCM_CSCMR1); + + return 0; +} + static unsigned long get_high_reference_clock_rate(struct clk *clk) { return external_high_reference; @@ -690,6 +720,12 @@ static struct clk uart_root_clk = { .set_parent = _clk_uart_set_parent, }; +static struct clk usboh3_clk = { + .parent = &pll2_sw_clk, + .get_rate = clk_usboh3_get_rate, + .set_parent = _clk_usboh3_set_parent, +}; + static struct clk ahb_max_clk = { .parent = &ahb_clk, .enable_reg = MXC_CCM_CCGR0, @@ -761,10 +797,6 @@ DEFINE_CLOCK(gpt_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG9_OFFSET, DEFINE_CLOCK(gpt_ipg_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG10_OFFSET, NULL, NULL, &ipg_clk, NULL); -/* USB */ -DEFINE_CLOCK(usboh3_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG14_OFFSET, - NULL, NULL, &pll3_sw_clk, NULL); - /* FEC */ DEFINE_CLOCK(fec_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG12_OFFSET, NULL, NULL, &ipg_clk, NULL); @@ -826,6 +858,9 @@ int __init mx51_clocks_init(unsigned long ckil, unsigned long osc, clk_enable(&cpu_clk); clk_enable(&main_bus_clk); + /* set the usboh3_clk parent to pll2_sw_clk */ + clk_set_parent(&usboh3_clk, &pll2_sw_clk); + /* System timer */ mxc_timer_init(&gpt_clk, MX51_IO_ADDRESS(MX51_GPT1_BASE_ADDR), MX51_MXC_INT_GPT); From 2ba5a2c0d8e0f62916a885170f28786141f08f76 Mon Sep 17 00:00:00 2001 From: Dinh Nguyen Date: Mon, 10 May 2010 13:45:59 -0500 Subject: [PATCH 0057/1337] mx5: enable usb gadget for freescale mx51 babbage board This patch enables usb gadget for freescale mx51 babbage hw. By default, the OTG port will be in device mode. To put the OTG port into Host mode, pass "otg_mode=host" in the exec command. This patch applies to 2.6.34-rc7. Signed-off-by: Dinh Nguyen Signed-off-by: Sascha Hauer --- arch/arm/mach-mx5/board-mx51_babbage.c | 28 +++++++++++++++++++++++++- arch/arm/mach-mx5/clock-mx51.c | 2 ++ arch/arm/mach-mx5/devices.c | 12 +++++++++++ arch/arm/mach-mx5/devices.h | 1 + 4 files changed, 42 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-mx5/board-mx51_babbage.c b/arch/arm/mach-mx5/board-mx51_babbage.c index 99f7ea903a51..dacf506f18ba 100644 --- a/arch/arm/mach-mx5/board-mx51_babbage.c +++ b/arch/arm/mach-mx5/board-mx51_babbage.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -179,12 +180,32 @@ static struct mxc_usbh_platform_data dr_utmi_config = { .flags = MXC_EHCI_INTERNAL_PHY, }; +static struct fsl_usb2_platform_data usb_pdata = { + .operating_mode = FSL_USB2_DR_DEVICE, + .phy_mode = FSL_USB2_PHY_UTMI_WIDE, +}; + static struct mxc_usbh_platform_data usbh1_config = { .init = initialize_usbh1_port, .portsc = MXC_EHCI_MODE_ULPI, .flags = (MXC_EHCI_POWER_PINS_ENABLED | MXC_EHCI_ITC_NO_THRESHOLD), }; +static int otg_mode_host; + +static int __init babbage_otg_mode(char *options) +{ + if (!strcmp(options, "host")) + otg_mode_host = 1; + else if (!strcmp(options, "device")) + otg_mode_host = 0; + else + pr_info("otg_mode neither \"host\" nor \"device\". " + "Defaulting to device\n"); + return 0; +} +__setup("otg_mode=", babbage_otg_mode); + /* * Board specific initialization. */ @@ -197,7 +218,12 @@ static void __init mxc_board_init(void) mxc_init_imx_uart(); platform_add_devices(devices, ARRAY_SIZE(devices)); - mxc_register_device(&mxc_usbdr_host_device, &dr_utmi_config); + if (otg_mode_host) + mxc_register_device(&mxc_usbdr_host_device, &dr_utmi_config); + else { + initialize_otg_port(NULL); + mxc_register_device(&mxc_usbdr_udc_device, &usb_pdata); + } gpio_usbh1_active(); mxc_register_device(&mxc_usbh1_device, &usbh1_config); diff --git a/arch/arm/mach-mx5/clock-mx51.c b/arch/arm/mach-mx5/clock-mx51.c index 566cfda6185e..9b93de36cf25 100644 --- a/arch/arm/mach-mx5/clock-mx51.c +++ b/arch/arm/mach-mx5/clock-mx51.c @@ -818,6 +818,8 @@ static struct clk_lookup lookups[] = { _REGISTER_CLOCK("mxc-ehci.0", "usb_ahb", ahb_clk) _REGISTER_CLOCK("mxc-ehci.1", "usb", usboh3_clk) _REGISTER_CLOCK("mxc-ehci.1", "usb_ahb", ahb_clk) + _REGISTER_CLOCK("fsl-usb2-udc", "usb", usboh3_clk) + _REGISTER_CLOCK("fsl-usb2-udc", "usb_ahb", ahb_clk) }; static void clk_tree_init(void) diff --git a/arch/arm/mach-mx5/devices.c b/arch/arm/mach-mx5/devices.c index e6262f31ed8f..23850e637dc3 100644 --- a/arch/arm/mach-mx5/devices.c +++ b/arch/arm/mach-mx5/devices.c @@ -107,6 +107,18 @@ static struct resource usbotg_resources[] = { }, }; +/* OTG gadget device */ +struct platform_device mxc_usbdr_udc_device = { + .name = "fsl-usb2-udc", + .id = -1, + .num_resources = ARRAY_SIZE(usbotg_resources), + .resource = usbotg_resources, + .dev = { + .dma_mask = &usb_dma_mask, + .coherent_dma_mask = DMA_BIT_MASK(32), + }, +}; + struct platform_device mxc_usbdr_host_device = { .name = "mxc-ehci", .id = 0, diff --git a/arch/arm/mach-mx5/devices.h b/arch/arm/mach-mx5/devices.h index 95c45f9e46ca..0494d6bbcc5f 100644 --- a/arch/arm/mach-mx5/devices.h +++ b/arch/arm/mach-mx5/devices.h @@ -4,3 +4,4 @@ extern struct platform_device mxc_uart_device2; extern struct platform_device mxc_fec_device; extern struct platform_device mxc_usbdr_host_device; extern struct platform_device mxc_usbh1_device; +extern struct platform_device mxc_usbdr_udc_device; From a9ddabc52ce3757a4331d6c1e8bf4065333cc51b Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Tue, 11 May 2010 00:08:03 -0700 Subject: [PATCH 0058/1337] cmd640: fix kernel oops in test_irq() method When implementing the test_iqr() method, I forgot that this driver is not an ordinary PCI driver and also needs to support VLB variant of the chip. Moreover, 'hwif->dev' should be NULL, potentially causing oops in pci_read_config_byte(). Signed-off-by: Sergei Shtylyov Signed-off-by: David S. Miller --- drivers/ide/cmd640.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/ide/cmd640.c b/drivers/ide/cmd640.c index d2b8b272bc27..cb10201a15ed 100644 --- a/drivers/ide/cmd640.c +++ b/drivers/ide/cmd640.c @@ -633,12 +633,10 @@ static void __init cmd640_init_dev(ide_drive_t *drive) static int cmd640_test_irq(ide_hwif_t *hwif) { - struct pci_dev *dev = to_pci_dev(hwif->dev); int irq_reg = hwif->channel ? ARTTIM23 : CFR; - u8 irq_stat, irq_mask = hwif->channel ? ARTTIM23_IDE23INTR : + u8 irq_mask = hwif->channel ? ARTTIM23_IDE23INTR : CFR_IDE01INTR; - - pci_read_config_byte(dev, irq_reg, &irq_stat); + u8 irq_stat = get_cmd640_reg(irq_reg); return (irq_stat & irq_mask) ? 1 : 0; } From b720303df7352d4a7a1f61e467e0a124913c0d41 Mon Sep 17 00:00:00 2001 From: Jing Zhang Date: Wed, 12 May 2010 00:00:00 -0400 Subject: [PATCH 0059/1337] ext4: fix memory leaks in error path handling of ext4_ext_zeroout() When EIO occurs after bio is submitted, there is no memory free operation for bio, which results in memory leakage. And there is also no check against bio_alloc() for bio. Acked-by: Dave Kleikamp Signed-off-by: Jing Zhang Signed-off-by: "Theodore Ts'o" --- fs/ext4/extents.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 236b834b4ca8..228eeaf2dccf 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -2544,7 +2544,7 @@ static void bi_complete(struct bio *bio, int error) /* FIXME!! we need to try to merge to left or right after zero-out */ static int ext4_ext_zeroout(struct inode *inode, struct ext4_extent *ex) { - int ret = -EIO; + int ret; struct bio *bio; int blkbits, blocksize; sector_t ee_pblock; @@ -2568,6 +2568,9 @@ static int ext4_ext_zeroout(struct inode *inode, struct ext4_extent *ex) len = ee_len; bio = bio_alloc(GFP_NOIO, len); + if (!bio) + return -ENOMEM; + bio->bi_sector = ee_pblock; bio->bi_bdev = inode->i_sb->s_bdev; @@ -2595,17 +2598,15 @@ static int ext4_ext_zeroout(struct inode *inode, struct ext4_extent *ex) submit_bio(WRITE, bio); wait_for_completion(&event); - if (test_bit(BIO_UPTODATE, &bio->bi_flags)) - ret = 0; - else { - ret = -EIO; - break; + if (!test_bit(BIO_UPTODATE, &bio->bi_flags)) { + bio_put(bio); + return -EIO; } bio_put(bio); ee_len -= done; ee_pblock += done << (blkbits - 9); } - return ret; + return 0; } #define EXT4_EXT_ZERO_LEN 7 From b430acbd7c4b919886fa7fd92eeb7a695f1940d3 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Thu, 6 May 2010 17:41:08 -0400 Subject: [PATCH 0060/1337] ACPICA: simplify SCI_EN workaround acpi_hw_set_mode() double checks its effectiveness by calling acpi_hw_get_mode() -- polling up to 3 seconds. It would be more logical for its caller, acpi_enable() acpi_enable() to do the double-checking. (lets assume that acpi_disable() isn't interesting) The ACPI specification is unclear on this point. Some parts say that the BIOS sets SCI_EN and then returns to the OS, but one part says "OSPM polls the SCI_EN bit until it is sampled SET". The systems I have on hand do the former, SCI_EN is observed to be set upon return from the BIOS. So we move the check up out of acpi_hw_set_mode() up into acpi_enable() where it makes logical sense. Then we replace the 3-second polling loop with a single check. If this check fails, we'll see: "Hardware did not enter ACPI mode" and the system will bail out of ACPI initialization and likely fail to boot. If we see that in practice, we can restore the polling, but put it into acpi_enable. This patch is important if acpi_enable() is used in the resume from S3 path. Many systems today are seen coming back from S3 with SCI_EN off, and then failing to set SCI_EN in response to acpi_enable(). Those systems will take 3 seconds longer to resume due to this loop. However, it is possible that we will not use acpi_enable() in the S3 resume path, and bang SCI_EN directly, which would make the loop harmless, as it would be invisible to all systems except those that need it. Signed-off-by: Len Brown --- drivers/acpi/acpica/evxfevnt.c | 37 +++++++++++++++++++++------------- drivers/acpi/acpica/hwacpi.c | 20 +----------------- 2 files changed, 24 insertions(+), 33 deletions(-) diff --git a/drivers/acpi/acpica/evxfevnt.c b/drivers/acpi/acpica/evxfevnt.c index 5ff32c78ea2d..bfbe291d572e 100644 --- a/drivers/acpi/acpica/evxfevnt.c +++ b/drivers/acpi/acpica/evxfevnt.c @@ -69,7 +69,7 @@ acpi_ev_get_gpe_device(struct acpi_gpe_xrupt_info *gpe_xrupt_info, acpi_status acpi_enable(void) { - acpi_status status = AE_OK; + acpi_status status; ACPI_FUNCTION_TRACE(acpi_enable); @@ -84,21 +84,30 @@ acpi_status acpi_enable(void) if (acpi_hw_get_mode() == ACPI_SYS_MODE_ACPI) { ACPI_DEBUG_PRINT((ACPI_DB_INIT, "System is already in ACPI mode\n")); - } else { - /* Transition to ACPI mode */ - - status = acpi_hw_set_mode(ACPI_SYS_MODE_ACPI); - if (ACPI_FAILURE(status)) { - ACPI_ERROR((AE_INFO, - "Could not transition to ACPI mode")); - return_ACPI_STATUS(status); - } - - ACPI_DEBUG_PRINT((ACPI_DB_INIT, - "Transition to ACPI mode successful\n")); + return_ACPI_STATUS(AE_OK); } - return_ACPI_STATUS(status); + /* Transition to ACPI mode */ + + status = acpi_hw_set_mode(ACPI_SYS_MODE_ACPI); + if (ACPI_FAILURE(status)) { + ACPI_ERROR((AE_INFO, + "Could not transition to ACPI mode")); + return_ACPI_STATUS(status); + } + + /* Sanity check that transition succeeded */ + + if (acpi_hw_get_mode() != ACPI_SYS_MODE_ACPI) { + ACPI_ERROR((AE_INFO, + "Hardware did not enter ACPI mode")); + return_ACPI_STATUS(AE_NO_HARDWARE_RESPONSE); + } + + ACPI_DEBUG_PRINT((ACPI_DB_INIT, + "Transition to ACPI mode successful\n")); + + return_ACPI_STATUS(AE_OK); } ACPI_EXPORT_SYMBOL(acpi_enable) diff --git a/drivers/acpi/acpica/hwacpi.c b/drivers/acpi/acpica/hwacpi.c index 679a112a7d26..b44274a0b62c 100644 --- a/drivers/acpi/acpica/hwacpi.c +++ b/drivers/acpi/acpica/hwacpi.c @@ -63,7 +63,6 @@ acpi_status acpi_hw_set_mode(u32 mode) { acpi_status status; - u32 retry; ACPI_FUNCTION_TRACE(hw_set_mode); @@ -125,24 +124,7 @@ acpi_status acpi_hw_set_mode(u32 mode) return_ACPI_STATUS(status); } - /* - * Some hardware takes a LONG time to switch modes. Give them 3 sec to - * do so, but allow faster systems to proceed more quickly. - */ - retry = 3000; - while (retry) { - if (acpi_hw_get_mode() == mode) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Mode %X successfully enabled\n", - mode)); - return_ACPI_STATUS(AE_OK); - } - acpi_os_stall(1000); - retry--; - } - - ACPI_ERROR((AE_INFO, "Hardware did not change modes")); - return_ACPI_STATUS(AE_NO_HARDWARE_RESPONSE); + return_ACPI_STATUS(AE_OK); } /******************************************************************************* From b6dacf63e9fb2e7a1369843d6cef332f76fca6a3 Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Tue, 11 May 2010 13:49:25 -0400 Subject: [PATCH 0061/1337] ACPI: Unconditionally set SCI_EN on resume The ACPI spec tells us that the firmware will reenable SCI_EN on resume. Reality disagrees in some cases. The ACPI spec tells us that the only way to set SCI_EN is via an SMM call. https://bugzilla.kernel.org/show_bug.cgi?id=13745 shows us that doing so may break machines. Tracing the ACPI calls made by Windows shows that it unconditionally sets SCI_EN on resume with a direct register write, and therefore the overwhelming probability is that everything is fine with this behaviour. Signed-off-by: Matthew Garrett Tested-by: Rafael J. Wysocki Signed-off-by: Len Brown --- arch/x86/kernel/acpi/sleep.c | 2 - drivers/acpi/sleep.c | 157 +---------------------------------- include/linux/acpi.h | 1 - 3 files changed, 2 insertions(+), 158 deletions(-) diff --git a/arch/x86/kernel/acpi/sleep.c b/arch/x86/kernel/acpi/sleep.c index f9961034e557..82e508677b91 100644 --- a/arch/x86/kernel/acpi/sleep.c +++ b/arch/x86/kernel/acpi/sleep.c @@ -162,8 +162,6 @@ static int __init acpi_sleep_setup(char *str) #endif if (strncmp(str, "old_ordering", 12) == 0) acpi_old_suspend_ordering(); - if (strncmp(str, "sci_force_enable", 16) == 0) - acpi_set_sci_en_on_resume(); str = strchr(str, ','); if (str != NULL) str += strspn(str, ", \t"); diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index baa76bbf244a..4ab2275b4461 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -80,22 +80,6 @@ static int acpi_sleep_prepare(u32 acpi_state) #ifdef CONFIG_ACPI_SLEEP static u32 acpi_target_sleep_state = ACPI_STATE_S0; -/* - * According to the ACPI specification the BIOS should make sure that ACPI is - * enabled and SCI_EN bit is set on wake-up from S1 - S3 sleep states. Still, - * some BIOSes don't do that and therefore we use acpi_enable() to enable ACPI - * on such systems during resume. Unfortunately that doesn't help in - * particularly pathological cases in which SCI_EN has to be set directly on - * resume, although the specification states very clearly that this flag is - * owned by the hardware. The set_sci_en_on_resume variable will be set in such - * cases. - */ -static bool set_sci_en_on_resume; - -void __init acpi_set_sci_en_on_resume(void) -{ - set_sci_en_on_resume = true; -} /* * ACPI 1.0 wants us to execute _PTS before suspending devices, so we allow the @@ -253,11 +237,8 @@ static int acpi_suspend_enter(suspend_state_t pm_state) break; } - /* If ACPI is not enabled by the BIOS, we need to enable it here. */ - if (set_sci_en_on_resume) - acpi_write_bit_register(ACPI_BITREG_SCI_ENABLE, 1); - else - acpi_enable(); + /* This violates the spec but is required for bug compatibility. */ + acpi_write_bit_register(ACPI_BITREG_SCI_ENABLE, 1); /* Reprogram control registers and execute _BFS */ acpi_leave_sleep_state_prep(acpi_state); @@ -346,12 +327,6 @@ static int __init init_old_suspend_ordering(const struct dmi_system_id *d) return 0; } -static int __init init_set_sci_en_on_resume(const struct dmi_system_id *d) -{ - set_sci_en_on_resume = true; - return 0; -} - static struct dmi_system_id __initdata acpisleep_dmi_table[] = { { .callback = init_old_suspend_ordering, @@ -370,22 +345,6 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = { }, }, { - .callback = init_set_sci_en_on_resume, - .ident = "Apple MacBook 1,1", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Apple Computer, Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "MacBook1,1"), - }, - }, - { - .callback = init_set_sci_en_on_resume, - .ident = "Apple MacMini 1,1", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Apple Computer, Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "Macmini1,1"), - }, - }, - { .callback = init_old_suspend_ordering, .ident = "Asus Pundit P1-AH2 (M2N8L motherboard)", .matches = { @@ -394,94 +353,6 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = { }, }, { - .callback = init_set_sci_en_on_resume, - .ident = "Toshiba Satellite L300", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), - DMI_MATCH(DMI_PRODUCT_NAME, "Satellite L300"), - }, - }, - { - .callback = init_set_sci_en_on_resume, - .ident = "Hewlett-Packard HP G7000 Notebook PC", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), - DMI_MATCH(DMI_PRODUCT_NAME, "HP G7000 Notebook PC"), - }, - }, - { - .callback = init_set_sci_en_on_resume, - .ident = "Hewlett-Packard HP Pavilion dv3 Notebook PC", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), - DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv3 Notebook PC"), - }, - }, - { - .callback = init_set_sci_en_on_resume, - .ident = "Hewlett-Packard Pavilion dv4", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), - DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv4"), - }, - }, - { - .callback = init_set_sci_en_on_resume, - .ident = "Hewlett-Packard Pavilion dv7", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), - DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv7"), - }, - }, - { - .callback = init_set_sci_en_on_resume, - .ident = "Hewlett-Packard Compaq Presario C700 Notebook PC", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), - DMI_MATCH(DMI_PRODUCT_NAME, "Compaq Presario C700 Notebook PC"), - }, - }, - { - .callback = init_set_sci_en_on_resume, - .ident = "Hewlett-Packard Compaq Presario CQ40 Notebook PC", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), - DMI_MATCH(DMI_PRODUCT_NAME, "Compaq Presario CQ40 Notebook PC"), - }, - }, - { - .callback = init_set_sci_en_on_resume, - .ident = "Lenovo ThinkPad T410", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T410"), - }, - }, - { - .callback = init_set_sci_en_on_resume, - .ident = "Lenovo ThinkPad T510", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T510"), - }, - }, - { - .callback = init_set_sci_en_on_resume, - .ident = "Lenovo ThinkPad W510", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad W510"), - }, - }, - { - .callback = init_set_sci_en_on_resume, - .ident = "Lenovo ThinkPad X201[s]", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X201"), - }, - }, - { .callback = init_old_suspend_ordering, .ident = "Panasonic CF51-2L", .matches = { @@ -490,30 +361,6 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = { DMI_MATCH(DMI_BOARD_NAME, "CF51-2L"), }, }, - { - .callback = init_set_sci_en_on_resume, - .ident = "Dell Studio 1558", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "Studio 1558"), - }, - }, - { - .callback = init_set_sci_en_on_resume, - .ident = "Dell Studio 1557", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "Studio 1557"), - }, - }, - { - .callback = init_set_sci_en_on_resume, - .ident = "Dell Studio 1555", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "Studio 1555"), - }, - }, {}, }; #endif /* CONFIG_SUSPEND */ diff --git a/include/linux/acpi.h b/include/linux/acpi.h index b926afe8c03e..87ca4913294c 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -251,7 +251,6 @@ int acpi_check_mem_region(resource_size_t start, resource_size_t n, void __init acpi_no_s4_hw_signature(void); void __init acpi_old_suspend_ordering(void); void __init acpi_s4_no_nvs(void); -void __init acpi_set_sci_en_on_resume(void); #endif /* CONFIG_PM_SLEEP */ struct acpi_osc_context { From 62e823a2cba18509ee826d775270e8ef9071b5bc Mon Sep 17 00:00:00 2001 From: Jing Zhang Date: Thu, 13 May 2010 00:00:00 -0400 Subject: [PATCH 0062/1337] ext4: Remove unnecessary call to ext4_get_group_desc() in mballoc Signed-off-by: Jing Zhang Signed-off-by: "Theodore Ts'o" --- fs/ext4/mballoc.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index b423a364dca3..0550ea3532f9 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c @@ -2025,7 +2025,6 @@ repeat: for (i = 0; i < ngroups; group++, i++) { struct ext4_group_info *grp; - struct ext4_group_desc *desc; if (group == ngroups) group = 0; @@ -2048,7 +2047,6 @@ repeat: } ac->ac_groups_scanned++; - desc = ext4_get_group_desc(sb, group, NULL); if (cr == 0) ext4_mb_simple_scan_group(ac, &e4b); else if (cr == 1 && From e39e07fdfd98be8650385f12a7b81d6adc547510 Mon Sep 17 00:00:00 2001 From: Jing Zhang Date: Fri, 14 May 2010 00:00:00 -0400 Subject: [PATCH 0063/1337] ext4: rename ext4_mb_release_desc() to ext4_mb_unload_buddy() This function cleans up after ext4_mb_load_buddy(), so the renaming makes the code clearer. Signed-off-by: Jing Zhang Signed-off-by: "Theodore Ts'o" --- fs/ext4/mballoc.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index 0550ea3532f9..8639d5a637b2 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c @@ -1150,7 +1150,7 @@ err: return ret; } -static void ext4_mb_release_desc(struct ext4_buddy *e4b) +static void ext4_mb_unload_buddy(struct ext4_buddy *e4b) { if (e4b->bd_bitmap_page) page_cache_release(e4b->bd_bitmap_page); @@ -1617,7 +1617,7 @@ int ext4_mb_try_best_found(struct ext4_allocation_context *ac, } ext4_unlock_group(ac->ac_sb, group); - ext4_mb_release_desc(e4b); + ext4_mb_unload_buddy(e4b); return 0; } @@ -1672,7 +1672,7 @@ int ext4_mb_find_by_goal(struct ext4_allocation_context *ac, ext4_mb_use_best_found(ac, e4b); } ext4_unlock_group(ac->ac_sb, group); - ext4_mb_release_desc(e4b); + ext4_mb_unload_buddy(e4b); return 0; } @@ -2042,7 +2042,7 @@ repeat: if (!ext4_mb_good_group(ac, group, cr)) { /* someone did allocation from this group */ ext4_unlock_group(sb, group); - ext4_mb_release_desc(&e4b); + ext4_mb_unload_buddy(&e4b); continue; } @@ -2056,7 +2056,7 @@ repeat: ext4_mb_complex_scan_group(ac, &e4b); ext4_unlock_group(sb, group); - ext4_mb_release_desc(&e4b); + ext4_mb_unload_buddy(&e4b); if (ac->ac_status != AC_STATUS_CONTINUE) break; @@ -2146,7 +2146,7 @@ static int ext4_mb_seq_groups_show(struct seq_file *seq, void *v) ext4_lock_group(sb, group); memcpy(&sg, ext4_get_group_info(sb, group), i); ext4_unlock_group(sb, group); - ext4_mb_release_desc(&e4b); + ext4_mb_unload_buddy(&e4b); seq_printf(seq, "#%-5u: %-5u %-5u %-5u [", group, sg.info.bb_free, sg.info.bb_fragments, sg.info.bb_first_free); @@ -2566,7 +2566,7 @@ static void release_blocks_on_commit(journal_t *journal, transaction_t *txn) } ext4_unlock_group(sb, entry->group); kmem_cache_free(ext4_free_ext_cachep, entry); - ext4_mb_release_desc(&e4b); + ext4_mb_unload_buddy(&e4b); } mb_debug(1, "freed %u blocks in %u structures\n", count, count2); @@ -3695,7 +3695,7 @@ out: ext4_unlock_group(sb, group); if (ac) kmem_cache_free(ext4_ac_cachep, ac); - ext4_mb_release_desc(&e4b); + ext4_mb_unload_buddy(&e4b); put_bh(bitmap_bh); return free; } @@ -3799,7 +3799,7 @@ repeat: if (bitmap_bh == NULL) { ext4_error(sb, "Error reading block bitmap for %u", group); - ext4_mb_release_desc(&e4b); + ext4_mb_unload_buddy(&e4b); continue; } @@ -3808,7 +3808,7 @@ repeat: ext4_mb_release_inode_pa(&e4b, bitmap_bh, pa, ac); ext4_unlock_group(sb, group); - ext4_mb_release_desc(&e4b); + ext4_mb_unload_buddy(&e4b); put_bh(bitmap_bh); list_del(&pa->u.pa_tmp_list); @@ -4072,7 +4072,7 @@ ext4_mb_discard_lg_preallocations(struct super_block *sb, ext4_mb_release_group_pa(&e4b, pa, ac); ext4_unlock_group(sb, group); - ext4_mb_release_desc(&e4b); + ext4_mb_unload_buddy(&e4b); list_del(&pa->u.pa_tmp_list); call_rcu(&(pa)->u.pa_rcu, ext4_mb_pa_callback); } @@ -4608,7 +4608,7 @@ do_more: atomic_add(count, &sbi->s_flex_groups[flex_group].free_blocks); } - ext4_mb_release_desc(&e4b); + ext4_mb_unload_buddy(&e4b); freed += count; From 8f0820183056ad26dabc0202115848a92f1143fc Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Tue, 20 Apr 2010 10:47:33 -0400 Subject: [PATCH 0064/1337] tracing: Create class struct for events This patch creates a ftrace_event_class struct that event structs point to. This class struct will be made to hold information to modify the events. Currently the class struct only holds the events system name. This patch slightly increases the size, but this change lays the ground work of other changes to make the footprint of tracepoints smaller. With 82 standard tracepoints, and 618 system call tracepoints (two tracepoints per syscall: enter and exit): text data bss dec hex filename 4913961 1088356 861512 6863829 68bbd5 vmlinux.orig 4914025 1088868 861512 6864405 68be15 vmlinux.class This patch also cleans up some stale comments in ftrace.h. v2: Fixed missing semi-colon in macro. Acked-by: Frederic Weisbecker Acked-by: Mathieu Desnoyers Acked-by: Masami Hiramatsu Signed-off-by: Steven Rostedt --- include/linux/ftrace_event.h | 6 +++- include/linux/syscalls.h | 6 ++-- include/trace/ftrace.h | 44 +++++++++++++----------------- kernel/trace/trace_events.c | 20 +++++++------- kernel/trace/trace_events_filter.c | 6 ++-- kernel/trace/trace_export.c | 6 +++- kernel/trace/trace_kprobe.c | 12 ++++---- kernel/trace/trace_syscalls.c | 4 +++ 8 files changed, 56 insertions(+), 48 deletions(-) diff --git a/include/linux/ftrace_event.h b/include/linux/ftrace_event.h index 39e71b0a3bfd..496eea898ee4 100644 --- a/include/linux/ftrace_event.h +++ b/include/linux/ftrace_event.h @@ -113,10 +113,14 @@ void tracing_record_cmdline(struct task_struct *tsk); struct event_filter; +struct ftrace_event_class { + char *system; +}; + struct ftrace_event_call { struct list_head list; + struct ftrace_event_class *class; char *name; - char *system; struct dentry *dir; struct trace_event *event; int enabled; diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h index 057929b0a651..ac5791df2506 100644 --- a/include/linux/syscalls.h +++ b/include/linux/syscalls.h @@ -134,6 +134,8 @@ struct perf_event_attr; #define __SC_STR_TDECL5(t, a, ...) #t, __SC_STR_TDECL4(__VA_ARGS__) #define __SC_STR_TDECL6(t, a, ...) #t, __SC_STR_TDECL5(__VA_ARGS__) +extern struct ftrace_event_class event_class_syscalls; + #define SYSCALL_TRACE_ENTER_EVENT(sname) \ static const struct syscall_metadata __syscall_meta_##sname; \ static struct ftrace_event_call \ @@ -146,7 +148,7 @@ struct perf_event_attr; __attribute__((section("_ftrace_events"))) \ event_enter_##sname = { \ .name = "sys_enter"#sname, \ - .system = "syscalls", \ + .class = &event_class_syscalls, \ .event = &enter_syscall_print_##sname, \ .raw_init = init_syscall_trace, \ .define_fields = syscall_enter_define_fields, \ @@ -168,7 +170,7 @@ struct perf_event_attr; __attribute__((section("_ftrace_events"))) \ event_exit_##sname = { \ .name = "sys_exit"#sname, \ - .system = "syscalls", \ + .class = &event_class_syscalls, \ .event = &exit_syscall_print_##sname, \ .raw_init = init_syscall_trace, \ .define_fields = syscall_exit_define_fields, \ diff --git a/include/trace/ftrace.h b/include/trace/ftrace.h index 75dd7787fb37..7dcdfd824aab 100644 --- a/include/trace/ftrace.h +++ b/include/trace/ftrace.h @@ -62,7 +62,10 @@ struct trace_entry ent; \ tstruct \ char __data[0]; \ - }; + }; \ + \ + static struct ftrace_event_class event_class_##name; + #undef DEFINE_EVENT #define DEFINE_EVENT(template, name, proto, args) \ static struct ftrace_event_call \ @@ -430,22 +433,6 @@ perf_trace_disable_##name(struct ftrace_event_call *unused) \ * * Override the macros in to include the following: * - * static void ftrace_event_(proto) - * { - * event_trace_printk(_RET_IP_, ": " ); - * } - * - * static int ftrace_reg_event_(struct ftrace_event_call *unused) - * { - * return register_trace_(ftrace_event_); - * } - * - * static void ftrace_unreg_event_(struct ftrace_event_call *unused) - * { - * unregister_trace_(ftrace_event_); - * } - * - * * For those macros defined with TRACE_EVENT: * * static struct ftrace_event_call event_; @@ -497,17 +484,21 @@ perf_trace_disable_##name(struct ftrace_event_call *unused) \ * * static const char print_fmt_[] = ; * + * static struct ftrace_event_class __used event_class_