Commit 0e2ffbf6 authored by Linus Torvalds's avatar Linus Torvalds

Merge commit master.kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6 of HEAD

* HEAD:
  [SPARC]: Fix OF register translations under sub-PCI busses.
  [SPARC64]: Refine Sabre wsync logic.
  [SERIAL] sunsu: Handle keyboard and mouse ports directly.
  [SPARC64]: Fix 2 bugs in sabre_irq_build()
  [SPARC64]: Update defconfig.
  [SPARC64]: Fix make headers_install
  [SPARC64]: of_device_register() error checking fix
parents 1b0f06d0 a83f9823
...@@ -183,7 +183,7 @@ struct bus_type of_bus_type = { ...@@ -183,7 +183,7 @@ struct bus_type of_bus_type = {
}; };
EXPORT_SYMBOL(of_bus_type); EXPORT_SYMBOL(of_bus_type);
static inline u64 of_read_addr(u32 *cell, int size) static inline u64 of_read_addr(const u32 *cell, int size)
{ {
u64 r = 0; u64 r = 0;
while (size--) while (size--)
...@@ -209,8 +209,8 @@ struct of_bus { ...@@ -209,8 +209,8 @@ struct of_bus {
int (*match)(struct device_node *parent); int (*match)(struct device_node *parent);
void (*count_cells)(struct device_node *child, void (*count_cells)(struct device_node *child,
int *addrc, int *sizec); int *addrc, int *sizec);
u64 (*map)(u32 *addr, u32 *range, int na, int ns, int pna); int (*map)(u32 *addr, const u32 *range,
int (*translate)(u32 *addr, u64 offset, int na); int na, int ns, int pna);
unsigned int (*get_flags)(u32 *addr); unsigned int (*get_flags)(u32 *addr);
}; };
...@@ -224,27 +224,49 @@ static void of_bus_default_count_cells(struct device_node *dev, ...@@ -224,27 +224,49 @@ static void of_bus_default_count_cells(struct device_node *dev,
get_cells(dev, addrc, sizec); get_cells(dev, addrc, sizec);
} }
static u64 of_bus_default_map(u32 *addr, u32 *range, int na, int ns, int pna) /* Make sure the least significant 64-bits are in-range. Even
* for 3 or 4 cell values it is a good enough approximation.
*/
static int of_out_of_range(const u32 *addr, const u32 *base,
const u32 *size, int na, int ns)
{ {
u64 cp, s, da; u64 a = of_read_addr(addr, na);
u64 b = of_read_addr(base, na);
if (a < b)
return 1;
cp = of_read_addr(range, na); b += of_read_addr(size, ns);
s = of_read_addr(range + na + pna, ns); if (a >= b)
da = of_read_addr(addr, na); return 1;
if (da < cp || da >= (cp + s)) return 0;
return OF_BAD_ADDR;
return da - cp;
} }
static int of_bus_default_translate(u32 *addr, u64 offset, int na) static int of_bus_default_map(u32 *addr, const u32 *range,
int na, int ns, int pna)
{ {
u64 a = of_read_addr(addr, na); u32 result[OF_MAX_ADDR_CELLS];
memset(addr, 0, na * 4); int i;
a += offset;
if (na > 1) if (ns > 2) {
addr[na - 2] = a >> 32; printk("of_device: Cannot handle size cells (%d) > 2.", ns);
addr[na - 1] = a & 0xffffffffu; return -EINVAL;
}
if (of_out_of_range(addr, range, range + na + pna, na, ns))
return -EINVAL;
/* Start with the parent range base. */
memcpy(result, range + na, pna * 4);
/* Add in the child address offset. */
for (i = 0; i < na; i++)
result[pna - 1 - i] +=
(addr[na - 1 - i] -
range[na - 1 - i]);
memcpy(addr, result, pna * 4);
return 0; return 0;
} }
...@@ -254,14 +276,26 @@ static unsigned int of_bus_default_get_flags(u32 *addr) ...@@ -254,14 +276,26 @@ static unsigned int of_bus_default_get_flags(u32 *addr)
return IORESOURCE_MEM; return IORESOURCE_MEM;
} }
/* /*
* PCI bus specific translator * PCI bus specific translator
*/ */
static int of_bus_pci_match(struct device_node *np) static int of_bus_pci_match(struct device_node *np)
{ {
return !strcmp(np->type, "pci") || !strcmp(np->type, "pciex"); if (!strcmp(np->type, "pci") || !strcmp(np->type, "pciex")) {
/* Do not do PCI specific frobbing if the
* PCI bridge lacks a ranges property. We
* want to pass it through up to the next
* parent as-is, not with the PCI translate
* method which chops off the top address cell.
*/
if (!of_find_property(np, "ranges", NULL))
return 0;
return 1;
}
return 0;
} }
static void of_bus_pci_count_cells(struct device_node *np, static void of_bus_pci_count_cells(struct device_node *np,
...@@ -273,27 +307,32 @@ static void of_bus_pci_count_cells(struct device_node *np, ...@@ -273,27 +307,32 @@ static void of_bus_pci_count_cells(struct device_node *np,
*sizec = 2; *sizec = 2;
} }
static u64 of_bus_pci_map(u32 *addr, u32 *range, int na, int ns, int pna) static int of_bus_pci_map(u32 *addr, const u32 *range,
int na, int ns, int pna)
{ {
u64 cp, s, da; u32 result[OF_MAX_ADDR_CELLS];
int i;
/* Check address type match */ /* Check address type match */
if ((addr[0] ^ range[0]) & 0x03000000) if ((addr[0] ^ range[0]) & 0x03000000)
return OF_BAD_ADDR; return -EINVAL;
/* Read address values, skipping high cell */ if (of_out_of_range(addr + 1, range + 1, range + na + pna,
cp = of_read_addr(range + 1, na - 1); na - 1, ns))
s = of_read_addr(range + na + pna, ns); return -EINVAL;
da = of_read_addr(addr + 1, na - 1);
if (da < cp || da >= (cp + s)) /* Start with the parent range base. */
return OF_BAD_ADDR; memcpy(result, range + na, pna * 4);
return da - cp;
}
static int of_bus_pci_translate(u32 *addr, u64 offset, int na) /* Add in the child address offset, skipping high cell. */
{ for (i = 0; i < na - 1; i++)
return of_bus_default_translate(addr + 1, offset, na - 1); result[pna - 1 - i] +=
(addr[na - 1 - i] -
range[na - 1 - i]);
memcpy(addr, result, pna * 4);
return 0;
} }
static unsigned int of_bus_pci_get_flags(u32 *addr) static unsigned int of_bus_pci_get_flags(u32 *addr)
...@@ -332,16 +371,11 @@ static void of_bus_sbus_count_cells(struct device_node *child, ...@@ -332,16 +371,11 @@ static void of_bus_sbus_count_cells(struct device_node *child,
*sizec = 1; *sizec = 1;
} }
static u64 of_bus_sbus_map(u32 *addr, u32 *range, int na, int ns, int pna) static int of_bus_sbus_map(u32 *addr, const u32 *range, int na, int ns, int pna)
{ {
return of_bus_default_map(addr, range, na, ns, pna); return of_bus_default_map(addr, range, na, ns, pna);
} }
static int of_bus_sbus_translate(u32 *addr, u64 offset, int na)
{
return of_bus_default_translate(addr, offset, na);
}
static unsigned int of_bus_sbus_get_flags(u32 *addr) static unsigned int of_bus_sbus_get_flags(u32 *addr)
{ {
return IORESOURCE_MEM; return IORESOURCE_MEM;
...@@ -360,7 +394,6 @@ static struct of_bus of_busses[] = { ...@@ -360,7 +394,6 @@ static struct of_bus of_busses[] = {
.match = of_bus_pci_match, .match = of_bus_pci_match,
.count_cells = of_bus_pci_count_cells, .count_cells = of_bus_pci_count_cells,
.map = of_bus_pci_map, .map = of_bus_pci_map,
.translate = of_bus_pci_translate,
.get_flags = of_bus_pci_get_flags, .get_flags = of_bus_pci_get_flags,
}, },
/* SBUS */ /* SBUS */
...@@ -370,7 +403,6 @@ static struct of_bus of_busses[] = { ...@@ -370,7 +403,6 @@ static struct of_bus of_busses[] = {
.match = of_bus_sbus_match, .match = of_bus_sbus_match,
.count_cells = of_bus_sbus_count_cells, .count_cells = of_bus_sbus_count_cells,
.map = of_bus_sbus_map, .map = of_bus_sbus_map,
.translate = of_bus_sbus_translate,
.get_flags = of_bus_sbus_get_flags, .get_flags = of_bus_sbus_get_flags,
}, },
/* Default */ /* Default */
...@@ -380,7 +412,6 @@ static struct of_bus of_busses[] = { ...@@ -380,7 +412,6 @@ static struct of_bus of_busses[] = {
.match = NULL, .match = NULL,
.count_cells = of_bus_default_count_cells, .count_cells = of_bus_default_count_cells,
.map = of_bus_default_map, .map = of_bus_default_map,
.translate = of_bus_default_translate,
.get_flags = of_bus_default_get_flags, .get_flags = of_bus_default_get_flags,
}, },
}; };
...@@ -405,33 +436,34 @@ static int __init build_one_resource(struct device_node *parent, ...@@ -405,33 +436,34 @@ static int __init build_one_resource(struct device_node *parent,
u32 *ranges; u32 *ranges;
unsigned int rlen; unsigned int rlen;
int rone; int rone;
u64 offset = OF_BAD_ADDR;
ranges = of_get_property(parent, "ranges", &rlen); ranges = of_get_property(parent, "ranges", &rlen);
if (ranges == NULL || rlen == 0) { if (ranges == NULL || rlen == 0) {
offset = of_read_addr(addr, na); u32 result[OF_MAX_ADDR_CELLS];
memset(addr, 0, pna * 4); int i;
goto finish;
memset(result, 0, pna * 4);
for (i = 0; i < na; i++)
result[pna - 1 - i] =
addr[na - 1 - i];
memcpy(addr, result, pna * 4);
return 0;
} }
/* Now walk through the ranges */ /* Now walk through the ranges */
rlen /= 4; rlen /= 4;
rone = na + pna + ns; rone = na + pna + ns;
for (; rlen >= rone; rlen -= rone, ranges += rone) { for (; rlen >= rone; rlen -= rone, ranges += rone) {
offset = bus->map(addr, ranges, na, ns, pna); if (!bus->map(addr, ranges, na, ns, pna))
if (offset != OF_BAD_ADDR) return 0;
break;
} }
if (offset == OF_BAD_ADDR)
return 1;
memcpy(addr, ranges + na, 4 * pna); return 1;
finish:
/* Translate it into parent bus space */
return pbus->translate(addr, offset, pna);
} }
static int of_resource_verbose;
static void __init build_device_resources(struct of_device *op, static void __init build_device_resources(struct of_device *op,
struct device *parent) struct device *parent)
{ {
...@@ -497,7 +529,8 @@ static void __init build_device_resources(struct of_device *op, ...@@ -497,7 +529,8 @@ static void __init build_device_resources(struct of_device *op,
pbus = of_match_bus(pp); pbus = of_match_bus(pp);
pbus->count_cells(dp, &pna, &pns); pbus->count_cells(dp, &pna, &pns);
if (build_one_resource(dp, bus, pbus, addr, dna, dns, pna)) if (build_one_resource(dp, bus, pbus, addr,
dna, dns, pna))
break; break;
dna = pna; dna = pna;
...@@ -507,6 +540,12 @@ static void __init build_device_resources(struct of_device *op, ...@@ -507,6 +540,12 @@ static void __init build_device_resources(struct of_device *op,
build_res: build_res:
memset(r, 0, sizeof(*r)); memset(r, 0, sizeof(*r));
if (of_resource_verbose)
printk("%s reg[%d] -> %llx\n",
op->node->full_name, index,
result);
if (result != OF_BAD_ADDR) { if (result != OF_BAD_ADDR) {
r->start = result & 0xffffffff; r->start = result & 0xffffffff;
r->end = result + size - 1; r->end = result + size - 1;
...@@ -643,6 +682,18 @@ static int __init of_bus_driver_init(void) ...@@ -643,6 +682,18 @@ static int __init of_bus_driver_init(void)
postcore_initcall(of_bus_driver_init); postcore_initcall(of_bus_driver_init);
static int __init of_debug(char *str)
{
int val = 0;
get_option(&str, &val);
if (val & 1)
of_resource_verbose = 1;
return 1;
}
__setup("of_debug=", of_debug);
int of_register_driver(struct of_platform_driver *drv, struct bus_type *bus) int of_register_driver(struct of_platform_driver *drv, struct bus_type *bus)
{ {
/* initialize common driver fields */ /* initialize common driver fields */
...@@ -695,9 +746,11 @@ int of_device_register(struct of_device *ofdev) ...@@ -695,9 +746,11 @@ int of_device_register(struct of_device *ofdev)
if (rc) if (rc)
return rc; return rc;
device_create_file(&ofdev->dev, &dev_attr_devspec); rc = device_create_file(&ofdev->dev, &dev_attr_devspec);
if (rc)
device_unregister(&ofdev->dev);
return 0; return rc;
} }
void of_device_unregister(struct of_device *ofdev) void of_device_unregister(struct of_device *ofdev)
......
# #
# Automatically generated make config: don't edit # Automatically generated make config: don't edit
# Linux kernel version: 2.6.17 # Linux kernel version: 2.6.18-rc1
# Fri Jun 23 23:17:09 2006 # Wed Jul 12 14:00:58 2006
# #
CONFIG_SPARC=y CONFIG_SPARC=y
CONFIG_SPARC64=y CONFIG_SPARC64=y
...@@ -18,6 +18,7 @@ CONFIG_SECCOMP=y ...@@ -18,6 +18,7 @@ CONFIG_SECCOMP=y
CONFIG_HZ_250=y CONFIG_HZ_250=y
# CONFIG_HZ_1000 is not set # CONFIG_HZ_1000 is not set
CONFIG_HZ=250 CONFIG_HZ=250
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
# #
# Code maturity level options # Code maturity level options
...@@ -51,10 +52,12 @@ CONFIG_PRINTK=y ...@@ -51,10 +52,12 @@ CONFIG_PRINTK=y
CONFIG_BUG=y CONFIG_BUG=y
CONFIG_ELF_CORE=y CONFIG_ELF_CORE=y
CONFIG_BASE_FULL=y CONFIG_BASE_FULL=y
CONFIG_RT_MUTEXES=y
CONFIG_FUTEX=y CONFIG_FUTEX=y
CONFIG_EPOLL=y CONFIG_EPOLL=y
CONFIG_SHMEM=y CONFIG_SHMEM=y
CONFIG_SLAB=y CONFIG_SLAB=y
CONFIG_VM_EVENT_COUNTERS=y
# CONFIG_TINY_SHMEM is not set # CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0 CONFIG_BASE_SMALL=0
# CONFIG_SLOB is not set # CONFIG_SLOB is not set
...@@ -127,8 +130,8 @@ CONFIG_SPARSEMEM=y ...@@ -127,8 +130,8 @@ CONFIG_SPARSEMEM=y
CONFIG_HAVE_MEMORY_PRESENT=y CONFIG_HAVE_MEMORY_PRESENT=y
# CONFIG_SPARSEMEM_STATIC is not set # CONFIG_SPARSEMEM_STATIC is not set
CONFIG_SPARSEMEM_EXTREME=y CONFIG_SPARSEMEM_EXTREME=y
CONFIG_MEMORY_HOTPLUG=y
CONFIG_SPLIT_PTLOCK_CPUS=4 CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_RESOURCES_64BIT=y
CONFIG_GENERIC_ISA_DMA=y CONFIG_GENERIC_ISA_DMA=y
CONFIG_SBUS=y CONFIG_SBUS=y
CONFIG_SBUSCHAR=y CONFIG_SBUSCHAR=y
...@@ -203,7 +206,6 @@ CONFIG_TCP_CONG_VEGAS=m ...@@ -203,7 +206,6 @@ CONFIG_TCP_CONG_VEGAS=m
CONFIG_TCP_CONG_SCALABLE=m CONFIG_TCP_CONG_SCALABLE=m
CONFIG_TCP_CONG_LP=m CONFIG_TCP_CONG_LP=m
CONFIG_TCP_CONG_VENO=m CONFIG_TCP_CONG_VENO=m
CONFIG_TCP_CONG_COMPOUND=m
CONFIG_IPV6=m CONFIG_IPV6=m
CONFIG_IPV6_PRIVACY=y CONFIG_IPV6_PRIVACY=y
CONFIG_IPV6_ROUTER_PREF=y CONFIG_IPV6_ROUTER_PREF=y
...@@ -461,9 +463,8 @@ CONFIG_MD_LINEAR=m ...@@ -461,9 +463,8 @@ CONFIG_MD_LINEAR=m
CONFIG_MD_RAID0=m CONFIG_MD_RAID0=m
CONFIG_MD_RAID1=m CONFIG_MD_RAID1=m
CONFIG_MD_RAID10=m CONFIG_MD_RAID10=m
CONFIG_MD_RAID5=m CONFIG_MD_RAID456=m
# CONFIG_MD_RAID5_RESHAPE is not set # CONFIG_MD_RAID5_RESHAPE is not set
CONFIG_MD_RAID6=m
CONFIG_MD_MULTIPATH=m CONFIG_MD_MULTIPATH=m
# CONFIG_MD_FAULTY is not set # CONFIG_MD_FAULTY is not set
CONFIG_BLK_DEV_DM=m CONFIG_BLK_DEV_DM=m
...@@ -663,6 +664,7 @@ CONFIG_SERIO_RAW=m ...@@ -663,6 +664,7 @@ CONFIG_SERIO_RAW=m
CONFIG_VT=y CONFIG_VT=y
CONFIG_VT_CONSOLE=y CONFIG_VT_CONSOLE=y
CONFIG_HW_CONSOLE=y CONFIG_HW_CONSOLE=y
# CONFIG_VT_HW_CONSOLE_BINDING is not set
# CONFIG_SERIAL_NONSTANDARD is not set # CONFIG_SERIAL_NONSTANDARD is not set
# #
...@@ -693,6 +695,7 @@ CONFIG_UNIX98_PTYS=y ...@@ -693,6 +695,7 @@ CONFIG_UNIX98_PTYS=y
# Watchdog Cards # Watchdog Cards
# #
# CONFIG_WATCHDOG is not set # CONFIG_WATCHDOG is not set
# CONFIG_HW_RANDOM is not set
CONFIG_RTC=y CONFIG_RTC=y
# CONFIG_DTLK is not set # CONFIG_DTLK is not set
# CONFIG_R3964 is not set # CONFIG_R3964 is not set
...@@ -839,12 +842,13 @@ CONFIG_VIDEO_V4L2=y ...@@ -839,12 +842,13 @@ CONFIG_VIDEO_V4L2=y
# #
# Graphics support # Graphics support
# #
# CONFIG_FIRMWARE_EDID is not set
CONFIG_FB=y CONFIG_FB=y
CONFIG_FB_CFB_FILLRECT=y CONFIG_FB_CFB_FILLRECT=y
CONFIG_FB_CFB_COPYAREA=y CONFIG_FB_CFB_COPYAREA=y
CONFIG_FB_CFB_IMAGEBLIT=y CONFIG_FB_CFB_IMAGEBLIT=y
# CONFIG_FB_MACMODES is not set # CONFIG_FB_MACMODES is not set
# CONFIG_FB_FIRMWARE_EDID is not set # CONFIG_FB_BACKLIGHT is not set
CONFIG_FB_MODE_HELPERS=y CONFIG_FB_MODE_HELPERS=y
CONFIG_FB_TILEBLITTING=y CONFIG_FB_TILEBLITTING=y
# CONFIG_FB_CIRRUS is not set # CONFIG_FB_CIRRUS is not set
...@@ -954,6 +958,18 @@ CONFIG_SND_ALI5451=m ...@@ -954,6 +958,18 @@ CONFIG_SND_ALI5451=m
# CONFIG_SND_CMIPCI is not set # CONFIG_SND_CMIPCI is not set
# CONFIG_SND_CS4281 is not set # CONFIG_SND_CS4281 is not set
# CONFIG_SND_CS46XX is not set # CONFIG_SND_CS46XX is not set
# CONFIG_SND_DARLA20 is not set
# CONFIG_SND_GINA20 is not set
# CONFIG_SND_LAYLA20 is not set
# CONFIG_SND_DARLA24 is not set
# CONFIG_SND_GINA24 is not set
# CONFIG_SND_LAYLA24 is not set
# CONFIG_SND_MONA is not set
# CONFIG_SND_MIA is not set
# CONFIG_SND_ECHO3G is not set
# CONFIG_SND_INDIGO is not set
# CONFIG_SND_INDIGOIO is not set
# CONFIG_SND_INDIGODJ is not set
# CONFIG_SND_EMU10K1 is not set # CONFIG_SND_EMU10K1 is not set
# CONFIG_SND_EMU10K1X is not set # CONFIG_SND_EMU10K1X is not set
# CONFIG_SND_ENS1370 is not set # CONFIG_SND_ENS1370 is not set
...@@ -1263,6 +1279,7 @@ CONFIG_RAMFS=y ...@@ -1263,6 +1279,7 @@ CONFIG_RAMFS=y
# CONFIG_NFSD is not set # CONFIG_NFSD is not set
# CONFIG_SMB_FS is not set # CONFIG_SMB_FS is not set
# CONFIG_CIFS is not set # CONFIG_CIFS is not set
# CONFIG_CIFS_DEBUG2 is not set
# CONFIG_NCP_FS is not set # CONFIG_NCP_FS is not set
# CONFIG_CODA_FS is not set # CONFIG_CODA_FS is not set
# CONFIG_AFS_FS is not set # CONFIG_AFS_FS is not set
...@@ -1331,14 +1348,19 @@ CONFIG_KPROBES=y ...@@ -1331,14 +1348,19 @@ CONFIG_KPROBES=y
# #
CONFIG_PRINTK_TIME=y CONFIG_PRINTK_TIME=y
CONFIG_MAGIC_SYSRQ=y CONFIG_MAGIC_SYSRQ=y
# CONFIG_UNUSED_SYMBOLS is not set
CONFIG_DEBUG_KERNEL=y CONFIG_DEBUG_KERNEL=y
CONFIG_LOG_BUF_SHIFT=18 CONFIG_LOG_BUF_SHIFT=18
CONFIG_DETECT_SOFTLOCKUP=y CONFIG_DETECT_SOFTLOCKUP=y
CONFIG_SCHEDSTATS=y CONFIG_SCHEDSTATS=y
# CONFIG_DEBUG_SLAB is not set # CONFIG_DEBUG_SLAB is not set
# CONFIG_DEBUG_MUTEXES is not set # CONFIG_DEBUG_RT_MUTEXES is not set
# CONFIG_RT_MUTEX_TESTER is not set
# CONFIG_DEBUG_SPINLOCK is not set # CONFIG_DEBUG_SPINLOCK is not set
# CONFIG_DEBUG_MUTEXES is not set
# CONFIG_DEBUG_RWSEMS is not set
# CONFIG_DEBUG_SPINLOCK_SLEEP is not set # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
# CONFIG_DEBUG_KOBJECT is not set # CONFIG_DEBUG_KOBJECT is not set
CONFIG_DEBUG_BUGVERBOSE=y CONFIG_DEBUG_BUGVERBOSE=y
# CONFIG_DEBUG_INFO is not set # CONFIG_DEBUG_INFO is not set
...@@ -1402,3 +1424,4 @@ CONFIG_CRC32=y ...@@ -1402,3 +1424,4 @@ CONFIG_CRC32=y
CONFIG_LIBCRC32C=m CONFIG_LIBCRC32C=m
CONFIG_ZLIB_INFLATE=y CONFIG_ZLIB_INFLATE=y
CONFIG_ZLIB_DEFLATE=y CONFIG_ZLIB_DEFLATE=y
CONFIG_PLIST=y
This diff is collapsed.
...@@ -539,6 +539,45 @@ static unsigned long __sabre_onboard_imap_off[] = { ...@@ -539,6 +539,45 @@ static unsigned long __sabre_onboard_imap_off[] = {
((ino & 0x20) ? (SABRE_ICLR_SCSI + (((ino) & 0x1f) << 3)) : \ ((ino & 0x20) ? (SABRE_ICLR_SCSI + (((ino) & 0x1f) << 3)) : \
(SABRE_ICLR_A_SLOT0 + (((ino) & 0x1f)<<3))) (SABRE_ICLR_A_SLOT0 + (((ino) & 0x1f)<<3)))
static int sabre_device_needs_wsync(struct device_node *dp)
{
struct device_node *parent = dp->parent;
char *parent_model, *parent_compat;
/* This traversal up towards the root is meant to
* handle two cases:
*
* 1) non-PCI bus sitting under PCI, such as 'ebus'
* 2) the PCI controller interrupts themselves, which
* will use the sabre_irq_build but do not need
* the DMA synchronization handling
*/
while (parent) {
if (!strcmp(parent->type, "pci"))
break;
parent = parent->parent;
}
if (!parent)
return 0;
parent_model = of_get_property(parent,
"model", NULL);
if (parent_model &&
(!strcmp(parent_model, "SUNW,sabre") ||
!strcmp(parent_model, "SUNW,simba")))
return 0;
parent_compat = of_get_property(parent,
"compatible", NULL);
if (parent_compat &&
(!strcmp(parent_compat, "pci108e,a000") ||
!strcmp(parent_compat, "pci108e,a001")))
return 0;
return 1;
}
static unsigned int sabre_irq_build(struct device_node *dp, static unsigned int sabre_irq_build(struct device_node *dp,
unsigned int ino, unsigned int ino,
void *_data) void *_data)
...@@ -577,15 +616,17 @@ static unsigned int sabre_irq_build(struct device_node *dp, ...@@ -577,15 +616,17 @@ static unsigned int sabre_irq_build(struct device_node *dp,
virt_irq = build_irq(inofixup, iclr, imap); virt_irq = build_irq(inofixup, iclr, imap);
/* If the parent device is a PCI<->PCI bridge other than
* APB, we have to install a pre-handler to ensure that
* all pending DMA is drained before the interrupt handler
* is run.
*/
regs = of_get_property(dp, "reg", NULL); regs = of_get_property(dp, "reg", NULL);
if (regs && if (regs && sabre_device_needs_wsync(dp)) {
((regs->phys_hi >> 16) & 0xff) != irq_data->pci_first_busno) {
irq_install_pre_handler(virt_irq, irq_install_pre_handler(virt_irq,
sabre_wsync_handler, sabre_wsync_handler,
(void *) (long) regs->phys_hi, (void *) (long) regs->phys_hi,
(void *) (void *) irq_data);
controller_regs +
SABRE_WRSYNC);
} }
return virt_irq; return virt_irq;
......
...@@ -1406,25 +1406,35 @@ static int __devinit su_probe(struct of_device *op, const struct of_device_id *m ...@@ -1406,25 +1406,35 @@ static int __devinit su_probe(struct of_device *op, const struct of_device_id *m
struct device_node *dp = op->node; struct device_node *dp = op->node;
struct uart_sunsu_port *up; struct uart_sunsu_port *up;
struct resource *rp; struct resource *rp;
enum su_type type;
int err; int err;
if (inst >= UART_NR) type = su_get_type(dp);
return -EINVAL; if (type == SU_PORT_PORT) {
if (inst >= UART_NR)
return -EINVAL;
up = &sunsu_ports[inst];
} else {
up = kzalloc(sizeof(*up), GFP_KERNEL);
if (!up)
return -ENOMEM;
}
up = &sunsu_ports[inst];
up->port.line = inst; up->port.line = inst;
spin_lock_init(&up->port.lock); spin_lock_init(&up->port.lock);
up->su_type = su_get_type(dp); up->su_type = type;
rp = &op->resource[0]; rp = &op->resource[0];
up->port.mapbase = op->resource[0].start; up->port.mapbase = rp->start;
up->reg_size = (rp->end - rp->start) + 1; up->reg_size = (rp->end - rp->start) + 1;
up->port.membase = of_ioremap(rp, 0, up->reg_size, "su"); up->port.membase = of_ioremap(rp, 0, up->reg_size, "su");
if (!up->port.membase) if (!up->port.membase) {
if (type != SU_PORT_PORT)
kfree(up);
return -ENOMEM; return -ENOMEM;
}
up->port.irq = op->irqs[0]; up->port.irq = op->irqs[0];
...@@ -1436,8 +1446,11 @@ static int __devinit su_probe(struct of_device *op, const struct of_device_id *m ...@@ -1436,8 +1446,11 @@ static int __devinit su_probe(struct of_device *op, const struct of_device_id *m
err = 0; err = 0;
if (up->su_type == SU_PORT_KBD || up->su_type == SU_PORT_MS) { if (up->su_type == SU_PORT_KBD || up->su_type == SU_PORT_MS) {
err = sunsu_kbd_ms_init(up); err = sunsu_kbd_ms_init(up);
if (err) if (err) {
kfree(up);
goto out_unmap; goto out_unmap;
}
dev_set_drvdata(&op->dev, up);
return 0; return 0;
} }
...@@ -1476,8 +1489,12 @@ static int __devexit su_remove(struct of_device *dev) ...@@ -1476,8 +1489,12 @@ static int __devexit su_remove(struct of_device *dev)
#ifdef CONFIG_SERIO #ifdef CONFIG_SERIO
serio_unregister_port(&up->serio); serio_unregister_port(&up->serio);
#endif #endif
} else if (up->port.type != PORT_UNKNOWN) kfree(up);
} else if (up->port.type != PORT_UNKNOWN) {
uart_remove_one_port(&sunsu_reg, &up->port); uart_remove_one_port(&sunsu_reg, &up->port);
}
dev_set_drvdata(&dev->dev, NULL);
return 0; return 0;
} }
......
...@@ -4,7 +4,7 @@ ALTARCH := sparc ...@@ -4,7 +4,7 @@ ALTARCH := sparc
ARCHDEF := defined __sparc__ && defined __arch64__ ARCHDEF := defined __sparc__ && defined __arch64__
ALTARCHDEF := defined __sparc__ && !defined __arch64__ ALTARCHDEF := defined __sparc__ && !defined __arch64__
unifdef-y := fbio.h perfctr.h unifdef-y += fbio.h perfctr.h
header-y += apb.h asi.h bbc.h bpp.h display7seg.h envctrl.h floppy.h \ header-y += apb.h asi.h bbc.h bpp.h display7seg.h envctrl.h floppy.h \
ipc.h kdebug.h mostek.h openprom.h openpromio.h parport.h \ ipc.h kdebug.h mostek.h openprom.h openpromio.h parport.h \
pconf.h psrcompat.h pstate.h reg.h uctx.h utrap.h watchdog.h pconf.h psrcompat.h pstate.h reg.h uctx.h utrap.h watchdog.h
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment