Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+113 −60
Original line number Diff line number Diff line
@@ -183,7 +183,7 @@ struct bus_type 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;
	while (size--)
@@ -209,8 +209,8 @@ struct of_bus {
	int		(*match)(struct device_node *parent);
	void		(*count_cells)(struct device_node *child,
				       int *addrc, int *sizec);
	u64		(*map)(u32 *addr, u32 *range, int na, int ns, int pna);
	int		(*translate)(u32 *addr, u64 offset, int na);
	int		(*map)(u32 *addr, const u32 *range,
			       int na, int ns, int pna);
	unsigned int	(*get_flags)(u32 *addr);
};

@@ -224,27 +224,49 @@ static void of_bus_default_count_cells(struct device_node *dev,
	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);

	cp = of_read_addr(range, na);
	s  = of_read_addr(range + na + pna, ns);
	da = of_read_addr(addr, na);
	if (a < b)
		return 1;

	if (da < cp || da >= (cp + s))
		return OF_BAD_ADDR;
	return da - cp;
	b += of_read_addr(size, ns);
	if (a >= b)
		return 1;

	return 0;
}

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);
	memset(addr, 0, na * 4);
	a += offset;
	if (na > 1)
		addr[na - 2] = a >> 32;
	addr[na - 1] = a & 0xffffffffu;
	u32 result[OF_MAX_ADDR_CELLS];
	int i;

	if (ns > 2) {
		printk("of_device: Cannot handle size cells (%d) > 2.", ns);
		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;
}
@@ -254,14 +276,26 @@ static unsigned int of_bus_default_get_flags(u32 *addr)
	return IORESOURCE_MEM;
}


/*
 * PCI bus specific translator
 */

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,
@@ -273,27 +307,32 @@ static void of_bus_pci_count_cells(struct device_node *np,
		*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 */
	if ((addr[0] ^ range[0]) & 0x03000000)
		return OF_BAD_ADDR;
		return -EINVAL;

	/* Read address values, skipping high cell */
	cp = of_read_addr(range + 1, na - 1);
	s  = of_read_addr(range + na + pna, ns);
	da = of_read_addr(addr + 1, na - 1);
	if (of_out_of_range(addr + 1, range + 1, range + na + pna,
			    na - 1, ns))
		return -EINVAL;

	if (da < cp || da >= (cp + s))
		return OF_BAD_ADDR;
	return da - cp;
}
	/* Start with the parent range base.  */
	memcpy(result, range + na, pna * 4);

static int of_bus_pci_translate(u32 *addr, u64 offset, int na)
{
	return of_bus_default_translate(addr + 1, offset, na - 1);
	/* Add in the child address offset, skipping high cell.  */
	for (i = 0; i < na - 1; i++)
		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)
@@ -332,16 +371,11 @@ static void of_bus_sbus_count_cells(struct device_node *child,
		*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);
}

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)
{
	return IORESOURCE_MEM;
@@ -360,7 +394,6 @@ static struct of_bus of_busses[] = {
		.match = of_bus_pci_match,
		.count_cells = of_bus_pci_count_cells,
		.map = of_bus_pci_map,
		.translate = of_bus_pci_translate,
		.get_flags = of_bus_pci_get_flags,
	},
	/* SBUS */
@@ -370,7 +403,6 @@ static struct of_bus of_busses[] = {
		.match = of_bus_sbus_match,
		.count_cells = of_bus_sbus_count_cells,
		.map = of_bus_sbus_map,
		.translate = of_bus_sbus_translate,
		.get_flags = of_bus_sbus_get_flags,
	},
	/* Default */
@@ -380,7 +412,6 @@ static struct of_bus of_busses[] = {
		.match = NULL,
		.count_cells = of_bus_default_count_cells,
		.map = of_bus_default_map,
		.translate = of_bus_default_translate,
		.get_flags = of_bus_default_get_flags,
	},
};
@@ -405,33 +436,34 @@ static int __init build_one_resource(struct device_node *parent,
	u32 *ranges;
	unsigned int rlen;
	int rone;
	u64 offset = OF_BAD_ADDR;

	ranges = of_get_property(parent, "ranges", &rlen);
	if (ranges == NULL || rlen == 0) {
		offset = of_read_addr(addr, na);
		memset(addr, 0, pna * 4);
		goto finish;
		u32 result[OF_MAX_ADDR_CELLS];
		int i;

		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 */
	rlen /= 4;
	rone = na + pna + ns;
	for (; rlen >= rone; rlen -= rone, ranges += rone) {
		offset = bus->map(addr, ranges, na, ns, pna);
		if (offset != OF_BAD_ADDR)
			break;
		if (!bus->map(addr, ranges, na, ns, pna))
			return 0;
	}
	if (offset == OF_BAD_ADDR)
		return 1;

	memcpy(addr, ranges + na, 4 * pna);

finish:
	/* Translate it into parent bus space */
	return pbus->translate(addr, offset, pna);
	return 1;
}

static int of_resource_verbose;

static void __init build_device_resources(struct of_device *op,
					  struct device *parent)
{
@@ -497,7 +529,8 @@ static void __init build_device_resources(struct of_device *op,
			pbus = of_match_bus(pp);
			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;

			dna = pna;
@@ -507,6 +540,12 @@ static void __init build_device_resources(struct of_device *op,

	build_res:
		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) {
			r->start = result & 0xffffffff;
			r->end = result + size - 1;
@@ -643,6 +682,18 @@ static int __init of_bus_driver_init(void)

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)
{
	/* initialize common driver fields */
@@ -695,9 +746,11 @@ int of_device_register(struct of_device *ofdev)
	if (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)
+31 −8
Original line number Diff line number Diff line
#
# Automatically generated make config: don't edit
# Linux kernel version: 2.6.17
# Fri Jun 23 23:17:09 2006
# Linux kernel version: 2.6.18-rc1
# Wed Jul 12 14:00:58 2006
#
CONFIG_SPARC=y
CONFIG_SPARC64=y
@@ -18,6 +18,7 @@ CONFIG_SECCOMP=y
CONFIG_HZ_250=y
# CONFIG_HZ_1000 is not set
CONFIG_HZ=250
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"

#
# Code maturity level options
@@ -51,10 +52,12 @@ CONFIG_PRINTK=y
CONFIG_BUG=y
CONFIG_ELF_CORE=y
CONFIG_BASE_FULL=y
CONFIG_RT_MUTEXES=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
CONFIG_SLAB=y
CONFIG_VM_EVENT_COUNTERS=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
# CONFIG_SLOB is not set
@@ -127,8 +130,8 @@ CONFIG_SPARSEMEM=y
CONFIG_HAVE_MEMORY_PRESENT=y
# CONFIG_SPARSEMEM_STATIC is not set
CONFIG_SPARSEMEM_EXTREME=y
CONFIG_MEMORY_HOTPLUG=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_RESOURCES_64BIT=y
CONFIG_GENERIC_ISA_DMA=y
CONFIG_SBUS=y
CONFIG_SBUSCHAR=y
@@ -203,7 +206,6 @@ CONFIG_TCP_CONG_VEGAS=m
CONFIG_TCP_CONG_SCALABLE=m
CONFIG_TCP_CONG_LP=m
CONFIG_TCP_CONG_VENO=m
CONFIG_TCP_CONG_COMPOUND=m
CONFIG_IPV6=m
CONFIG_IPV6_PRIVACY=y
CONFIG_IPV6_ROUTER_PREF=y
@@ -461,9 +463,8 @@ CONFIG_MD_LINEAR=m
CONFIG_MD_RAID0=m
CONFIG_MD_RAID1=m
CONFIG_MD_RAID10=m
CONFIG_MD_RAID5=m
CONFIG_MD_RAID456=m
# CONFIG_MD_RAID5_RESHAPE is not set
CONFIG_MD_RAID6=m
CONFIG_MD_MULTIPATH=m
# CONFIG_MD_FAULTY is not set
CONFIG_BLK_DEV_DM=m
@@ -663,6 +664,7 @@ CONFIG_SERIO_RAW=m
CONFIG_VT=y
CONFIG_VT_CONSOLE=y
CONFIG_HW_CONSOLE=y
# CONFIG_VT_HW_CONSOLE_BINDING is not set
# CONFIG_SERIAL_NONSTANDARD is not set

#
@@ -693,6 +695,7 @@ CONFIG_UNIX98_PTYS=y
# Watchdog Cards
#
# CONFIG_WATCHDOG is not set
# CONFIG_HW_RANDOM is not set
CONFIG_RTC=y
# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
@@ -839,12 +842,13 @@ CONFIG_VIDEO_V4L2=y
#
# Graphics support
#
# CONFIG_FIRMWARE_EDID is not set
CONFIG_FB=y
CONFIG_FB_CFB_FILLRECT=y
CONFIG_FB_CFB_COPYAREA=y
CONFIG_FB_CFB_IMAGEBLIT=y
# 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_TILEBLITTING=y
# CONFIG_FB_CIRRUS is not set
@@ -954,6 +958,18 @@ CONFIG_SND_ALI5451=m
# CONFIG_SND_CMIPCI is not set
# CONFIG_SND_CS4281 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_EMU10K1X is not set
# CONFIG_SND_ENS1370 is not set
@@ -1263,6 +1279,7 @@ CONFIG_RAMFS=y
# CONFIG_NFSD is not set
# CONFIG_SMB_FS is not set
# CONFIG_CIFS is not set
# CONFIG_CIFS_DEBUG2 is not set
# CONFIG_NCP_FS is not set
# CONFIG_CODA_FS is not set
# CONFIG_AFS_FS is not set
@@ -1331,14 +1348,19 @@ CONFIG_KPROBES=y
#
CONFIG_PRINTK_TIME=y
CONFIG_MAGIC_SYSRQ=y
# CONFIG_UNUSED_SYMBOLS is not set
CONFIG_DEBUG_KERNEL=y
CONFIG_LOG_BUF_SHIFT=18
CONFIG_DETECT_SOFTLOCKUP=y
CONFIG_SCHEDSTATS=y
# 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_MUTEXES is not set
# CONFIG_DEBUG_RWSEMS 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_BUGVERBOSE=y
# CONFIG_DEBUG_INFO is not set
@@ -1402,3 +1424,4 @@ CONFIG_CRC32=y
CONFIG_LIBCRC32C=m
CONFIG_ZLIB_INFLATE=y
CONFIG_ZLIB_DEFLATE=y
CONFIG_PLIST=y
+166 −148
Original line number Diff line number Diff line
@@ -210,7 +210,7 @@ struct bus_type 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;
	while (size--)
@@ -236,8 +236,8 @@ struct of_bus {
	int		(*match)(struct device_node *parent);
	void		(*count_cells)(struct device_node *child,
				       int *addrc, int *sizec);
	u64		(*map)(u32 *addr, u32 *range, int na, int ns, int pna);
	int		(*translate)(u32 *addr, u64 offset, int na);
	int		(*map)(u32 *addr, const u32 *range,
			       int na, int ns, int pna);
	unsigned int	(*get_flags)(u32 *addr);
};

@@ -251,27 +251,49 @@ static void of_bus_default_count_cells(struct device_node *dev,
	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);
	s  = of_read_addr(range + na + pna, ns);
	da = of_read_addr(addr, na);
	b += of_read_addr(size, ns);
	if (a >= b)
		return 1;

	if (da < cp || da >= (cp + s))
		return OF_BAD_ADDR;
	return da - cp;
	return 0;
}

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);
	memset(addr, 0, na * 4);
	a += offset;
	if (na > 1)
		addr[na - 2] = a >> 32;
	addr[na - 1] = a & 0xffffffffu;
	u32 result[OF_MAX_ADDR_CELLS];
	int i;

	if (ns > 2) {
		printk("of_device: Cannot handle size cells (%d) > 2.", ns);
		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;
}
@@ -287,7 +309,20 @@ static unsigned int of_bus_default_get_flags(u32 *addr)

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,
@@ -299,27 +334,32 @@ static void of_bus_pci_count_cells(struct device_node *np,
		*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 */
	if ((addr[0] ^ range[0]) & 0x03000000)
		return OF_BAD_ADDR;
		return -EINVAL;

	/* Read address values, skipping high cell */
	cp = of_read_addr(range + 1, na - 1);
	s  = of_read_addr(range + na + pna, ns);
	da = of_read_addr(addr + 1, na - 1);
	if (of_out_of_range(addr + 1, range + 1, range + na + pna,
			    na - 1, ns))
		return -EINVAL;

	if (da < cp || da >= (cp + s))
		return OF_BAD_ADDR;
	return da - cp;
}
	/* Start with the parent range base.  */
	memcpy(result, range + na, pna * 4);

static int of_bus_pci_translate(u32 *addr, u64 offset, int na)
{
	return of_bus_default_translate(addr + 1, offset, na - 1);
	/* Add in the child address offset, skipping high cell.  */
	for (i = 0; i < na - 1; i++)
		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)
@@ -339,59 +379,6 @@ static unsigned int of_bus_pci_get_flags(u32 *addr)
	return flags;
}

/*
 * ISA bus specific translator
 */

static int of_bus_isa_match(struct device_node *np)
{
	return !strcmp(np->name, "isa");
}

static void of_bus_isa_count_cells(struct device_node *child,
				   int *addrc, int *sizec)
{
	if (addrc)
		*addrc = 2;
	if (sizec)
		*sizec = 1;
}

static u64 of_bus_isa_map(u32 *addr, u32 *range, int na, int ns, int pna)
{
	u64 cp, s, da;

	/* Check address type match */
	if ((addr[0] ^ range[0]) & 0x00000001)
		return OF_BAD_ADDR;

	/* Read address values, skipping high cell */
	cp = of_read_addr(range + 1, na - 1);
	s  = of_read_addr(range + na + pna, ns);
	da = of_read_addr(addr + 1, na - 1);

	if (da < cp || da >= (cp + s))
		return OF_BAD_ADDR;
	return da - cp;
}

static int of_bus_isa_translate(u32 *addr, u64 offset, int na)
{
	return of_bus_default_translate(addr + 1, offset, na - 1);
}

static unsigned int of_bus_isa_get_flags(u32 *addr)
{
	unsigned int flags = 0;
	u32 w = addr[0];

	if (w & 1)
		flags |= IORESOURCE_IO;
	else
		flags |= IORESOURCE_MEM;
	return flags;
}

/*
 * SBUS bus specific translator
 */
@@ -411,16 +398,11 @@ static void of_bus_sbus_count_cells(struct device_node *child,
		*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);
}

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)
{
	return IORESOURCE_MEM;
@@ -439,19 +421,8 @@ static struct of_bus of_busses[] = {
		.match = of_bus_pci_match,
		.count_cells = of_bus_pci_count_cells,
		.map = of_bus_pci_map,
		.translate = of_bus_pci_translate,
		.get_flags = of_bus_pci_get_flags,
	},
	/* ISA */
	{
		.name = "isa",
		.addr_prop_name = "reg",
		.match = of_bus_isa_match,
		.count_cells = of_bus_isa_count_cells,
		.map = of_bus_isa_map,
		.translate = of_bus_isa_translate,
		.get_flags = of_bus_isa_get_flags,
	},
	/* SBUS */
	{
		.name = "sbus",
@@ -459,7 +430,6 @@ static struct of_bus of_busses[] = {
		.match = of_bus_sbus_match,
		.count_cells = of_bus_sbus_count_cells,
		.map = of_bus_sbus_map,
		.translate = of_bus_sbus_translate,
		.get_flags = of_bus_sbus_get_flags,
	},
	/* Default */
@@ -469,7 +439,6 @@ static struct of_bus of_busses[] = {
		.match = NULL,
		.count_cells = of_bus_default_count_cells,
		.map = of_bus_default_map,
		.translate = of_bus_default_translate,
		.get_flags = of_bus_default_get_flags,
	},
};
@@ -494,33 +463,62 @@ static int __init build_one_resource(struct device_node *parent,
	u32 *ranges;
	unsigned int rlen;
	int rone;
	u64 offset = OF_BAD_ADDR;

	ranges = of_get_property(parent, "ranges", &rlen);
	if (ranges == NULL || rlen == 0) {
		offset = of_read_addr(addr, na);
		memset(addr, 0, pna * 4);
		goto finish;
		u32 result[OF_MAX_ADDR_CELLS];
		int i;

		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 */
	rlen /= 4;
	rone = na + pna + ns;
	for (; rlen >= rone; rlen -= rone, ranges += rone) {
		offset = bus->map(addr, ranges, na, ns, pna);
		if (offset != OF_BAD_ADDR)
			break;
		if (!bus->map(addr, ranges, na, ns, pna))
			return 0;
	}
	if (offset == OF_BAD_ADDR)

	return 1;
}

static int __init use_1to1_mapping(struct device_node *pp)
{
	char *model;

	/* If this is on the PMU bus, don't try to translate it even
	 * if a ranges property exists.
	 */
	if (!strcmp(pp->name, "pmu"))
		return 1;

	memcpy(addr, ranges + na, 4 * pna);
	/* If we have a ranges property in the parent, use it.  */
	if (of_find_property(pp, "ranges", NULL) != NULL)
		return 0;

	/* If the parent is the dma node of an ISA bus, pass
	 * the translation up to the root.
	 */
	if (!strcmp(pp->name, "dma"))
		return 0;

	/* Similarly for Simba PCI bridges.  */
	model = of_get_property(pp, "model", NULL);
	if (model && !strcmp(model, "SUNW,simba"))
		return 0;

finish:
	/* Translate it into parent bus space */
	return pbus->translate(addr, offset, pna);
	return 1;
}

static int of_resource_verbose;

static void __init build_device_resources(struct of_device *op,
					  struct device *parent)
{
@@ -564,15 +562,7 @@ static void __init build_device_resources(struct of_device *op,

		memcpy(addr, reg, na * 4);

		/* If the immediate parent has no ranges property to apply,
		 * just use a 1<->1 mapping.  Unless it is the 'dma' child
		 * of an isa bus, which must be passed up towards the root.
		 *
		 * Also, don't try to translate PMU bus device registers.
		 */
		if ((of_find_property(pp, "ranges", NULL) == NULL &&
		     strcmp(pp->name, "dma") != 0) ||
		    !strcmp(pp->name, "pmu")) {
		if (use_1to1_mapping(pp)) {
			result = of_read_addr(addr, na);
			goto build_res;
		}
@@ -591,7 +581,8 @@ static void __init build_device_resources(struct of_device *op,
			pbus = of_match_bus(pp);
			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;

			dna = pna;
@@ -601,6 +592,12 @@ static void __init build_device_resources(struct of_device *op,

	build_res:
		memset(r, 0, sizeof(*r));

		if (of_resource_verbose)
			printk("%s reg[%d] -> %lx\n",
			       op->node->full_name, index,
			       result);

		if (result != OF_BAD_ADDR) {
			if (tlb_type == hypervisor)
				result &= 0x0fffffffffffffffUL;
@@ -684,6 +681,8 @@ static unsigned int __init pci_irq_swizzle(struct device_node *dp,
	return ret;
}

static int of_irq_verbose;

static unsigned int __init build_one_device_irq(struct of_device *op,
						struct device *parent,
						unsigned int irq)
@@ -698,10 +697,11 @@ static unsigned int __init build_one_device_irq(struct of_device *op,
	if (dp->irq_trans) {
		irq = dp->irq_trans->irq_build(dp, irq,
					       dp->irq_trans->data);
#if 1

		if (of_irq_verbose)
			printk("%s: direct translate %x --> %x\n",
			       dp->full_name, orig_irq, irq);
#endif

		return irq;
	}

@@ -728,12 +728,13 @@ static unsigned int __init build_one_device_irq(struct of_device *op,
			iret = apply_interrupt_map(dp, pp,
						   imap, imlen, imsk,
						   &irq);
#if 1

			if (of_irq_verbose)
				printk("%s: Apply [%s:%x] imap --> [%s:%x]\n",
				       op->node->full_name,
				       pp->full_name, this_orig_irq,
				       (iret ? iret->full_name : "NULL"), irq);
#endif

			if (!iret)
				break;

@@ -747,11 +748,13 @@ static unsigned int __init build_one_device_irq(struct of_device *op,
				unsigned int this_orig_irq = irq;

				irq = pci_irq_swizzle(dp, pp, irq);
#if 1
				printk("%s: PCI swizzle [%s] %x --> %x\n",
				if (of_irq_verbose)
					printk("%s: PCI swizzle [%s] "
					       "%x --> %x\n",
					       op->node->full_name,
				       pp->full_name, this_orig_irq, irq);
#endif
					       pp->full_name, this_orig_irq,
					       irq);

			}

			if (pp->irq_trans) {
@@ -767,10 +770,9 @@ static unsigned int __init build_one_device_irq(struct of_device *op,

	irq = ip->irq_trans->irq_build(op->node, irq,
				       ip->irq_trans->data);
#if 1
	if (of_irq_verbose)
		printk("%s: Apply IRQ trans [%s] %x --> %x\n",
		       op->node->full_name, ip->full_name, orig_irq, irq);
#endif

	return irq;
}
@@ -870,6 +872,20 @@ static int __init of_bus_driver_init(void)

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;
	if (val & 2)
		of_irq_verbose = 1;
	return 1;
}

__setup("of_debug=", of_debug);

int of_register_driver(struct of_platform_driver *drv, struct bus_type *bus)
{
	/* initialize common driver fields */
@@ -922,9 +938,11 @@ int of_device_register(struct of_device *ofdev)
	if (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)
+46 −5
Original line number Diff line number Diff line
@@ -539,6 +539,45 @@ static unsigned long __sabre_onboard_imap_off[] = {
	((ino & 0x20) ? (SABRE_ICLR_SCSI + (((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,
				    unsigned int ino,
				    void *_data)
@@ -577,15 +616,17 @@ static unsigned int sabre_irq_build(struct device_node *dp,

	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);
	if (regs &&
	    ((regs->phys_hi >> 16) & 0xff) != irq_data->pci_first_busno) {
	if (regs && sabre_device_needs_wsync(dp)) {
		irq_install_pre_handler(virt_irq,
					sabre_wsync_handler,
					(void *) (long) regs->phys_hi,
					(void *)
					controller_regs +
					SABRE_WRSYNC);
					(void *) irq_data);
	}

	return virt_irq;
+26 −9
Original line number Diff line number Diff line
@@ -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 uart_sunsu_port *up;
	struct resource *rp;
	enum su_type type;
	int err;

	type = su_get_type(dp);
	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->port.line = inst;

	spin_lock_init(&up->port.lock);

	up->su_type = su_get_type(dp);
	up->su_type = type;

	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->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;
	}

	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
	err = 0;
	if (up->su_type == SU_PORT_KBD || up->su_type == SU_PORT_MS) {
		err = sunsu_kbd_ms_init(up);
		if (err)
		if (err) {
			kfree(up);
			goto out_unmap;
		}
		dev_set_drvdata(&op->dev, up);

		return 0;
	}
@@ -1476,8 +1489,12 @@ static int __devexit su_remove(struct of_device *dev)
#ifdef CONFIG_SERIO
		serio_unregister_port(&up->serio);
#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);
	}

	dev_set_drvdata(&dev->dev, NULL);

	return 0;
}
Loading