示例#1
0
__initfunc(void prom_init(void *cif_handler, void *cif_stack))
{
	char buffer[80], *p;
	int ints[3];
	int node;
	int i = 0;

	prom_vers = PROM_P1275;

	prom_cif_init(cif_handler, cif_stack);

	prom_root_node = prom_getsibling(0);
	if((prom_root_node == 0) || (prom_root_node == -1))
		prom_halt();

	prom_chosen_node = prom_finddevice("/chosen");
	if (!prom_chosen_node || prom_chosen_node == -1)
		prom_halt();

	prom_stdin = prom_getint (prom_chosen_node, "stdin");
	prom_stdout = prom_getint (prom_chosen_node, "stdout");

	node = prom_finddevice("/openprom");
	if (!node || node == -1)
		prom_halt();

	prom_getstring (node, "version", buffer, sizeof (buffer));

	prom_printf ("\n");

	if (strncmp (buffer, "OBP ", 4))
		goto strange_version;

	/* Version field is expected to be 'OBP xx.yy.zz date...' */

	p = buffer + 4;
	while (p && isdigit(*p) && i < 3) {
		ints[i++] = simple_strtoul(p, NULL, 0);
		if ((p = strchr(p, '.')) != NULL)
			p++;
	}
	if (i != 3)
		goto strange_version;

	prom_rev = ints[1];
	prom_prev = (ints[0] << 16) | (ints[1] << 8) | ints[2];

	printk ("PROMLIB: Sun IEEE Boot Prom %s\n", buffer + 4);

	prom_meminit();

	prom_ranges_init();

	/* Initialization successful. */
	return;

strange_version:
	prom_printf ("Strange OBP version `%s'.\n", buffer);
	prom_halt ();
}
示例#2
0
/* Acquire an integer property, upon error return the passed default
 * integer.
 */
int prom_getintdefault(int node, char *property, int deflt)
{
	int retval;

	retval = prom_getint(node, property);
	if(retval == -1) return deflt;

	return retval;
}
示例#3
0
文件: init.c 项目: mobilipia/iods
void __init prom_init(void *cif_handler, void *cif_stack)
{
	int node;

	prom_cif_init(cif_handler, cif_stack);

	prom_chosen_node = prom_finddevice(prom_chosen_path);
	if (!prom_chosen_node || prom_chosen_node == -1)
		prom_halt();

	prom_stdin = prom_getint(prom_chosen_node, "stdin");
	prom_stdout = prom_getint(prom_chosen_node, "stdout");

	node = prom_finddevice("/openprom");
	if (!node || node == -1)
		prom_halt();

	prom_getstring(node, "version", prom_version, sizeof(prom_version));

	prom_printf("\n");
}
示例#4
0
static int __devinit apbuart_probe(struct of_device *op, const struct of_device_id *match)
{
	struct console co;
	int node;
	int freq_khz;
	int baud_rates[UART_NR];
	unsigned long clk;
	struct device_node *dp = op->node; int v = 0, d = 0; unsigned int addr;
	struct uart_leon_port *port; struct amba_prom_registers *regs; int irq, line, *irqs;
	int *vendor = of_get_property(dp, "vendor", NULL);
	int *device = of_get_property(dp, "device", NULL);
	regs = of_get_property(dp, "reg", NULL);
	irqs = of_get_property(dp, "interrupts", NULL);
	if (vendor)
		v = *vendor;
	if (device)
		d = *device;
	
	if (LEON3_GpTimer_Regs == 0 || irqs == 0 || regs == 0 || !(v == VENDOR_GAISLER && d == GAISLER_APBUART)) {
		return -ENODEV;
	}
	addr = regs->phys_addr ;
	irq = *irqs;
	
	port = kzalloc(sizeof(struct uart_leon_port), GFP_KERNEL);
	if (unlikely(!port))
		return -ENOMEM;

	node = prom_getchild(prom_root_node);
	freq_khz = prom_getint(node, "clock-frequency");
	clk = ((unsigned long)(((LEON3_BYPASS_LOAD_PA(&LEON3_GpTimer_Regs->scalar_reload)) + 1)));
	
	port->port.membase = (void *)addr;
	port->port.mapbase = addr;
	port->port.irq = irq;
	port->port.iotype = SERIAL_IO_MEM;
	port->port.uartclk = clk * 1000 * 1000;
	port->port.fifosize = 1;
	port->port.ops = &leon_pops;
	port->port.flags = ASYNC_BOOT_AUTOCONF;
	port->port.line = line = leon_line_nr++;

	port->port.uartclk = freq_khz * 1000;
	uart_add_one_port(&leon_reg, port);
	uart_set_options(port, &co, line >= UART_NR ? 9600 : baud_rates[line], 'n', 8, 'n');
	port->port.fifosize = apbuart_scan_fifo_size(port, line);
	apbuart_flush_fifo(port);
	
	printk("---------------- Match %d: 0x%x@%d : %s ----------------\n",line,addr, irq,dp->path_component_name);
	return 0;
}
示例#5
0
文件: tree.c 项目: andreiw/mkunity
int
prom_getintdefault(int node, char *property, int deflt)
{
	int retval;

#if CONFIG_AP1000
        printk("prom_getintdefault(%s) -> 0\n",property);
        return 0;
#endif
	retval = prom_getint(node, property);
	if(retval == -1) return deflt;

	return retval;
}
示例#6
0
int prom_get_mmu_ihandle(void)
{
	int node, ret;

	if (prom_mmu_ihandle_cache != 0)
		return prom_mmu_ihandle_cache;

	node = prom_finddevice(prom_chosen_path);
	ret = prom_getint(node, prom_mmu_name);
	if (ret == -1 || ret == 0)
		prom_mmu_ihandle_cache = -1;
	else
		prom_mmu_ihandle_cache = ret;

	return ret;
}
示例#7
0
int prom_get_mmu_ihandle(void)
{
    int node, ret;

    if (mmu_ihandle_cache != 0)
        return mmu_ihandle_cache;

    node = prom_finddevice("/chosen");
    ret = prom_getint(node, "mmu");
    if(ret == -1 || ret == 0)
        mmu_ihandle_cache = -1;
    else
        mmu_ihandle_cache = ret;

    return ret;
}
示例#8
0
static int prom_get_memory_ihandle(void)
{
	static int memory_ihandle_cache;
	int node, ret;

	if (memory_ihandle_cache != 0)
		return memory_ihandle_cache;

	node = prom_finddevice("/chosen");
	ret = prom_getint(node, "memory");
	if (ret == -1 || ret == 0)
		memory_ihandle_cache = -1;
	else
		memory_ihandle_cache = ret;

	return ret;
}
示例#9
0
static int __init leonuart_init(void)
{
	int ret;
	int i;
	int node;
	int freq_khz;
	int baud_rates[UART_NR];

	printk(KERN_INFO
	       "Serial: Leon driver, author: Konrad Eisele<*****@*****.**>\n");

	node = prom_getchild(prom_root_node);
	freq_khz = prom_getint(node, "clock-frequency");
	baud_rates[0] = prom_getintdefault(node, "uart1_baud", 9600);
	baud_rates[1] = prom_getintdefault(node, "uart2_baud", 9600);

	printk(KERN_INFO
	       "Serial: system frequency: %i khz, baud rates: %i %i\n",
	       freq_khz, baud_rates[0], baud_rates[1]);

	ret = uart_register_driver(&leon_reg);
	leon_reg.tty_driver->init_termios.c_cflag =
	    (leon_reg.tty_driver->init_termios.c_cflag & ~CBAUD) | B38400;

	if (ret)
		return ret;

	for (i = 0; i < UART_NR; i++) {
		struct console co;
		leon_ports[i].port.uartclk = freq_khz * 1000;
		uart_add_one_port(&leon_reg, &leon_ports[i].port);
		uart_set_options(&leon_ports[i].port, &co,
				 baud_rates[i], 'n', 8, 'n');
	}

	return ret;
}
示例#10
0
static int __init myri_ether_init(struct net_device *dev, struct sbus_dev *sdev, int num)
{
	static unsigned version_printed = 0;
	struct myri_eth *mp;
	unsigned char prop_buf[32];
	int i;

	DET(("myri_ether_init(%p,%p,%d):\n", dev, sdev, num));
	dev = init_etherdev(0, sizeof(struct myri_eth));

	if (version_printed++ == 0)
		printk(version);

	printk("%s: MyriCOM MyriNET Ethernet ", dev->name);

	mp = (struct myri_eth *) dev->priv;
	mp->myri_sdev = sdev;

	/* Clean out skb arrays. */
	for (i = 0; i < (RX_RING_SIZE + 1); i++)
		mp->rx_skbs[i] = NULL;

	for (i = 0; i < TX_RING_SIZE; i++)
		mp->tx_skbs[i] = NULL;

	/* First check for EEPROM information. */
	i = prom_getproperty(sdev->prom_node, "myrinet-eeprom-info",
			     (char *)&mp->eeprom, sizeof(struct myri_eeprom));
	DET(("prom_getprop(myrinet-eeprom-info) returns %d\n", i));
	if (i == 0 || i == -1) {
		/* No eeprom property, must cook up the values ourselves. */
		DET(("No EEPROM: "));
		mp->eeprom.bus_type = BUS_TYPE_SBUS;
		mp->eeprom.cpuvers = prom_getintdefault(sdev->prom_node,"cpu_version",0);
		mp->eeprom.cval = prom_getintdefault(sdev->prom_node,"clock_value",0);
		mp->eeprom.ramsz = prom_getintdefault(sdev->prom_node,"sram_size",0);
		DET(("cpuvers[%d] cval[%d] ramsz[%d]\n", mp->eeprom.cpuvers,
		     mp->eeprom.cval, mp->eeprom.ramsz));
		if (mp->eeprom.cpuvers == 0) {
			DET(("EEPROM: cpuvers was zero, setting to %04x\n",CPUVERS_2_3));
			mp->eeprom.cpuvers = CPUVERS_2_3;
		}
		if (mp->eeprom.cpuvers < CPUVERS_3_0) {
			DET(("EEPROM: cpuvers < CPUVERS_3_0, clockval set to zero.\n"));
			mp->eeprom.cval = 0;
		}
		if (mp->eeprom.ramsz == 0) {
			DET(("EEPROM: ramsz == 0, setting to 128k\n"));
			mp->eeprom.ramsz = (128 * 1024);
		}
		i = prom_getproperty(sdev->prom_node, "myrinet-board-id",
				     &prop_buf[0], 10);
		DET(("EEPROM: prom_getprop(myrinet-board-id) returns %d\n", i));
		if ((i != 0) && (i != -1))
			memcpy(&mp->eeprom.id[0], &prop_buf[0], 6);
		else
			set_boardid_from_idprom(mp, num);
		i = prom_getproperty(sdev->prom_node, "fpga_version",
				     &mp->eeprom.fvers[0], 32);
		DET(("EEPROM: prom_getprop(fpga_version) returns %d\n", i));
		if (i == 0 || i == -1)
			memset(&mp->eeprom.fvers[0], 0, 32);

		if (mp->eeprom.cpuvers == CPUVERS_4_1) {
			DET(("EEPROM: cpuvers CPUVERS_4_1, "));
			if (mp->eeprom.ramsz == (128 * 1024)) {
				DET(("ramsize 128k, setting to 256k, "));
				mp->eeprom.ramsz = (256 * 1024);
			}
			if ((mp->eeprom.cval==0x40414041)||(mp->eeprom.cval==0x90449044)){
				DET(("changing cval from %08x to %08x ",
				     mp->eeprom.cval, 0x50e450e4));
				mp->eeprom.cval = 0x50e450e4;
			}
			DET(("\n"));
		}
	}
#ifdef DEBUG_DETECT
	dump_eeprom(mp);
#endif

	for (i = 0; i < 6; i++)
		printk("%2.2x%c",
		       dev->dev_addr[i] = mp->eeprom.id[i],
		       i == 5 ? ' ' : ':');
	printk("\n");

	determine_reg_space_size(mp);

	/* Map in the MyriCOM register/localram set. */
	if (mp->eeprom.cpuvers < CPUVERS_4_0) {
		/* XXX Makes no sense, if control reg is non-existant this
		 * XXX driver cannot function at all... maybe pre-4.0 is
		 * XXX only a valid version for PCI cards?  Ask feldy...
		 */
		DET(("Mapping regs for cpuvers < CPUVERS_4_0\n"));
		mp->regs = sbus_ioremap(&sdev->resource[0], 0,
					mp->reg_size, "MyriCOM Regs");
		if (!mp->regs) {
			printk("MyriCOM: Cannot map MyriCOM registers.\n");
			return -ENODEV;
		}
		mp->lanai = (unsigned short *) (mp->regs + (256 * 1024));
		mp->lanai3 = (unsigned int *) mp->lanai;
		mp->lregs = (unsigned long) &mp->lanai[0x10000];
	} else {
		DET(("Mapping regs for cpuvers >= CPUVERS_4_0\n"));
		mp->cregs = sbus_ioremap(&sdev->resource[0], 0,
					 PAGE_SIZE, "MyriCOM Control Regs");
		mp->lregs = sbus_ioremap(&sdev->resource[0], (256 * 1024),
					 PAGE_SIZE, "MyriCOM LANAI Regs");
		mp->lanai = (unsigned short *)
			sbus_ioremap(&sdev->resource[0], (512 * 1024),
				     mp->eeprom.ramsz, "MyriCOM SRAM");
		mp->lanai3 = (unsigned int *) mp->lanai;
	}
	DET(("Registers mapped: cregs[%lx] lregs[%lx] lanai[%p] lanai3[%p]\n",
	     mp->cregs, mp->lregs, mp->lanai, mp->lanai3));

	if (mp->eeprom.cpuvers >= CPUVERS_4_0)
		mp->shmem_base = 0xf000;
	else
		mp->shmem_base = 0x8000;

	DET(("Shared memory base is %04x, ", mp->shmem_base));

	mp->shmem = (struct myri_shmem *) &mp->lanai[mp->shmem_base];
	DET(("shmem mapped at %p\n", mp->shmem));

	mp->rqack	= &mp->shmem->channel.recvqa;
	mp->rq		= &mp->shmem->channel.recvq;
	mp->sq		= &mp->shmem->channel.sendq;

	/* Reset the board. */
	DET(("Resetting LANAI\n"));
	myri_reset_off(mp->lregs, mp->cregs);
	myri_reset_on(mp->cregs);

	/* Turn IRQ's off. */
	myri_disable_irq(mp->lregs, mp->cregs);

	/* Reset once more. */
	myri_reset_on(mp->cregs);

	/* Get the supported DVMA burst sizes from our SBUS. */
	mp->myri_bursts = prom_getintdefault(mp->myri_sdev->bus->prom_node,
					     "burst-sizes", 0x00);

	if (!sbus_can_burst64(sdev))
		mp->myri_bursts &= ~(DMA_BURST64);

	DET(("MYRI bursts %02x\n", mp->myri_bursts));

	/* Encode SBUS interrupt level in second control register. */
	i = prom_getint(sdev->prom_node, "interrupts");
	if (i == 0)
		i = 4;
	DET(("prom_getint(interrupts)==%d, irqlvl set to %04x\n",
	     i, (1 << i)));

	sbus_writel((1 << i), mp->cregs + MYRICTRL_IRQLVL);

	mp->dev = dev;
	dev->open = &myri_open;
	dev->stop = &myri_close;
	dev->hard_start_xmit = &myri_start_xmit;
	dev->tx_timeout = &myri_tx_timeout;
	dev->watchdog_timeo = 5*HZ;
	dev->get_stats = &myri_get_stats;
	dev->set_multicast_list = &myri_set_multicast;
	dev->irq = sdev->irqs[0];

	/* Register interrupt handler now. */
	DET(("Requesting MYRIcom IRQ line.\n"));
	if (request_irq(dev->irq, &myri_interrupt,
			SA_SHIRQ, "MyriCOM Ethernet", (void *) dev)) {
		printk("MyriCOM: Cannot register interrupt handler.\n");
		return -ENODEV;
	}

	DET(("ether_setup()\n"));
	ether_setup(dev);

	dev->mtu		= MYRINET_MTU;
	dev->change_mtu		= myri_change_mtu;
	dev->hard_header	= myri_header;
	dev->rebuild_header	= myri_rebuild_header;
	dev->hard_header_len	= (ETH_HLEN + MYRI_PAD_LEN);
	dev->hard_header_cache 	= myri_header_cache;
	dev->header_cache_update= myri_header_cache_update;

	/* Load code onto the LANai. */
	DET(("Loading LANAI firmware\n"));
	myri_load_lanai(mp);

#ifdef MODULE
	dev->ifindex = dev_new_index();
	mp->next_module = root_myri_dev;
	root_myri_dev = mp;
#endif
	return 0;
}
示例#11
0
static void __init fill_sbus_device(int prom_node, struct sbus_dev *sdev)
{
	unsigned long address, base;
	int len;

	sdev->prom_node = prom_node;
	prom_getstring(prom_node, "name",
		       sdev->prom_name, sizeof(sdev->prom_name));
	address = prom_getint(prom_node, "address");
	len = prom_getproperty(prom_node, "reg",
			       (char *) sdev->reg_addrs,
			       sizeof(sdev->reg_addrs));
	if (len == -1) {
		sdev->num_registers = 0;
		goto no_regs;
	}

	if (len % sizeof(struct linux_prom_registers)) {
		prom_printf("fill_sbus_device: proplen for regs of %s "
			    " was %d, need multiple of %d\n",
			    sdev->prom_name, len,
			    (int) sizeof(struct linux_prom_registers));
		prom_halt();
	}
	if (len > (sizeof(struct linux_prom_registers) * PROMREG_MAX)) {
		prom_printf("fill_sbus_device: Too many register properties "
			    "for device %s, len=%d\n",
			    sdev->prom_name, len);
		prom_halt();
	}
	sdev->num_registers = len / sizeof(struct linux_prom_registers);
	sdev->ranges_applied = 0;

	base = (unsigned long) sdev->reg_addrs[0].phys_addr;

	/* Compute the slot number. */
	if (base >= SUN_SBUS_BVADDR && sparc_cpu_model == sun4m) {
		sdev->slot = sbus_dev_slot(base);
	} else {
		sdev->slot = sdev->reg_addrs[0].which_io;
	}

no_regs:
	len = prom_getproperty(prom_node, "ranges",
			       (char *)sdev->device_ranges,
			       sizeof(sdev->device_ranges));
	if (len == -1) {
		sdev->num_device_ranges = 0;
		goto no_ranges;
	}
	if (len % sizeof(struct linux_prom_ranges)) {
		prom_printf("fill_sbus_device: proplen for ranges of %s "
			    " was %d, need multiple of %d\n",
			    sdev->prom_name, len,
			    (int) sizeof(struct linux_prom_ranges));
		prom_halt();
	}
	if (len > (sizeof(struct linux_prom_ranges) * PROMREG_MAX)) {
		prom_printf("fill_sbus_device: Too many range properties "
			    "for device %s, len=%d\n",
			    sdev->prom_name, len);
		prom_halt();
	}
	sdev->num_device_ranges =
		len / sizeof(struct linux_prom_ranges);

no_ranges:
	/* XXX Unfortunately, IRQ issues are very arch specific.
	 * XXX Pull this crud out into an arch specific area
	 * XXX at some point. -DaveM
	 */
#ifdef __sparc_v9__
	len = prom_getproperty(prom_node, "interrupts",
			       (char *) irqs, sizeof(irqs));
	if (len == -1 || len == 0) {
		sdev->irqs[0] = 0;
		sdev->num_irqs = 0;
	} else {
		unsigned int pri = irqs[0].pri;

		sdev->num_irqs = 1;
		if (pri < 0x20)
			pri += sdev->slot * 8;

		sdev->irqs[0] =	sbus_build_irq(sdev->bus, pri);
	}
#else
	len = prom_getproperty(prom_node, "intr",
			       (char *)irqs, sizeof(irqs));
	if (len == -1)
		len = 0;
	sdev->num_irqs = len / 8;
	if (sdev->num_irqs == 0) {
		sdev->irqs[0] = 0;
	} else if (sparc_cpu_model == sun4d) {
		extern unsigned int sun4d_build_irq(struct sbus_dev *sdev, int irq);

		for (len = 0; len < sdev->num_irqs; len++)
			sdev->irqs[len] = sun4d_build_irq(sdev, irqs[len].pri);
	} else {
		for (len = 0; len < sdev->num_irqs; len++)
			sdev->irqs[len] = irqs[len].pri;
	}
#endif /* !__sparc_v9__ */
}
示例#12
0
void __init sbus_init(void)
{
	int nd, this_sbus, sbus_devs, topnd, iommund;
	unsigned int sbus_clock;
	struct sbus_bus *sbus;
	struct sbus_dev *this_dev;
	int num_sbus = 0;  /* How many did we find? */

#ifndef __sparc_v9__
	register_proc_sparc_ioport();
#endif

#ifdef CONFIG_SUN4
	return sun4_dvma_init();
#endif

	topnd = prom_getchild(prom_root_node);
	
	/* Finding the first sbus is a special case... */
	iommund = 0;
	if(sparc_cpu_model == sun4u) {
		nd = prom_searchsiblings(topnd, "sbus");
		if(nd == 0) {
#ifdef CONFIG_PCI
			if (!pcibios_present()) {	
				prom_printf("Neither SBUS nor PCI found.\n");
				prom_halt();
			} else {
#ifdef __sparc_v9__
				firetruck_init();
#endif
			}
			return;
#else
			prom_printf("YEEE, UltraSparc sbus not found\n");
			prom_halt();
#endif
		}
	} else if(sparc_cpu_model == sun4d) {
		if((iommund = prom_searchsiblings(topnd, "io-unit")) == 0 ||
		   (nd = prom_getchild(iommund)) == 0 ||
		   (nd = prom_searchsiblings(nd, "sbi")) == 0) {
		   	panic("sbi not found");
		}
	} else if((nd = prom_searchsiblings(topnd, "sbus")) == 0) {
		if((iommund = prom_searchsiblings(topnd, "iommu")) == 0 ||
		   (nd = prom_getchild(iommund)) == 0 ||
		   (nd = prom_searchsiblings(nd, "sbus")) == 0) {
#ifdef CONFIG_PCI
                        if (!pcibios_present()) {       
                                prom_printf("Neither SBUS nor PCI found.\n");
                                prom_halt();
                        }
                        return;
#else
			/* No reason to run further - the data access trap will occur. */
			panic("sbus not found");
#endif
		}
	}

	/* Ok, we've found the first one, allocate first SBus struct
	 * and place in chain.
	 */
	sbus = sbus_root = kmalloc(sizeof(struct sbus_bus), GFP_ATOMIC);
	sbus->next = NULL;
	sbus->prom_node = nd;
	this_sbus = nd;

	if(iommund && sparc_cpu_model != sun4u && sparc_cpu_model != sun4d)
		iommu_init(iommund, sbus);

	/* Loop until we find no more SBUS's */
	while(this_sbus) {
#ifdef __sparc_v9__						  
		/* IOMMU hides inside SBUS/SYSIO prom node on Ultra. */
		if(sparc_cpu_model == sun4u) {
			extern void sbus_iommu_init(int prom_node, struct sbus_bus *sbus);

			sbus_iommu_init(this_sbus, sbus);
		}
#endif
#ifndef __sparc_v9__						  
		if (sparc_cpu_model == sun4d)
			iounit_init(this_sbus, iommund, sbus);
#endif						   
		printk("sbus%d: ", num_sbus);
		sbus_clock = prom_getint(this_sbus, "clock-frequency");
		if(sbus_clock == -1)
			sbus_clock = (25*1000*1000);
		printk("Clock %d.%d MHz\n", (int) ((sbus_clock/1000)/1000),
		       (int) (((sbus_clock/1000)%1000 != 0) ? 
			      (((sbus_clock/1000)%1000) + 1000) : 0));

		prom_getstring(this_sbus, "name",
			       sbus->prom_name, sizeof(sbus->prom_name));
		sbus->clock_freq = sbus_clock;
#ifndef __sparc_v9__		
		if (sparc_cpu_model == sun4d) {
			sbus->devid = prom_getint(iommund, "device-id");
			sbus->board = prom_getint(iommund, "board#");
		}
#endif
		
		sbus_bus_ranges_init(iommund, sbus);

		sbus_devs = prom_getchild(this_sbus);
		if (!sbus_devs) {
			sbus->devices = NULL;
			goto next_bus;
		}

		sbus->devices = kmalloc(sizeof(struct sbus_dev), GFP_ATOMIC);

		this_dev = sbus->devices;
		this_dev->next = NULL;

		this_dev->bus = sbus;
		this_dev->parent = NULL;
		fill_sbus_device(sbus_devs, this_dev);

		/* Should we traverse for children? */
		if(prom_getchild(sbus_devs)) {
			/* Allocate device node */
			this_dev->child = kmalloc(sizeof(struct sbus_dev),
						  GFP_ATOMIC);
			/* Fill it */
			this_dev->child->bus = sbus;
			this_dev->child->next = 0;
			fill_sbus_device(prom_getchild(sbus_devs),
					 this_dev->child);
			sbus_do_child_siblings(prom_getchild(sbus_devs),
					       this_dev->child,
					       this_dev,
					       sbus);
		} else {
			this_dev->child = NULL;
		}

		while((sbus_devs = prom_getsibling(sbus_devs)) != 0) {
			/* Allocate device node */
			this_dev->next = kmalloc(sizeof(struct sbus_dev),
						 GFP_ATOMIC);
			this_dev = this_dev->next;
			this_dev->next = NULL;

			/* Fill it */
			this_dev->bus = sbus;
			this_dev->parent = NULL;
			fill_sbus_device(sbus_devs, this_dev);

			/* Is there a child node hanging off of us? */
			if(prom_getchild(sbus_devs)) {
				/* Get new device struct */
				this_dev->child = kmalloc(sizeof(struct sbus_dev),
							  GFP_ATOMIC);
				/* Fill it */
				this_dev->child->bus = sbus;
				this_dev->child->next = 0;
				fill_sbus_device(prom_getchild(sbus_devs),
						 this_dev->child);
				sbus_do_child_siblings(prom_getchild(sbus_devs),
						       this_dev->child,
						       this_dev,
						       sbus);
			} else {
				this_dev->child = NULL;
			}
		}

		/* Walk all devices and apply parent ranges. */
		sbus_fixup_all_regs(sbus->devices);

		dvma_init(sbus);
	next_bus:
		num_sbus++;
		if(sparc_cpu_model == sun4u) {
			this_sbus = prom_getsibling(this_sbus);
			if(!this_sbus)
				break;
			this_sbus = prom_searchsiblings(this_sbus, "sbus");
		} else if(sparc_cpu_model == sun4d) {
			iommund = prom_getsibling(iommund);
			if(!iommund)
				break;
			iommund = prom_searchsiblings(iommund, "io-unit");
			if(!iommund)
				break;
			this_sbus = prom_searchsiblings(prom_getchild(iommund), "sbi");
		} else {
			this_sbus = prom_getsibling(this_sbus);
			if(!this_sbus)
				break;
			this_sbus = prom_searchsiblings(this_sbus, "sbus");
		}
		if(this_sbus) {
			sbus->next = kmalloc(sizeof(struct sbus_bus), GFP_ATOMIC);
			sbus = sbus->next;
			sbus->next = NULL;
			sbus->prom_node = this_sbus;
		} else {
			break;
		}
	} /* while(this_sbus) */

	if (sparc_cpu_model == sun4d) {
		extern void sun4d_init_sbi_irq(void);
		sun4d_init_sbi_irq();
	}
	
	rs_init();

#ifdef __sparc_v9__
	if (sparc_cpu_model == sun4u) {
		firetruck_init();
	}
#endif
#ifdef CONFIG_SUN_AUXIO
	if (sparc_cpu_model == sun4u)
		auxio_probe ();
#endif
#ifdef __sparc_v9__
	if (sparc_cpu_model == sun4u) {
		extern void clock_probe(void);

		clock_probe();
	}
#endif
}
示例#13
0
void __init prom_init(void *cif_handler, void *cif_stack)
{
	char buffer[80], *p;
	int ints[3];
	int node;
	int i = 0;
	int bufadjust;

	prom_vers = PROM_P1275;

	prom_cif_init(cif_handler, cif_stack);

	prom_root_node = prom_getsibling(0);
	if((prom_root_node == 0) || (prom_root_node == -1))
		prom_halt();

	prom_chosen_node = prom_finddevice("/chosen");
	if (!prom_chosen_node || prom_chosen_node == -1)
		prom_halt();

	prom_stdin = prom_getint (prom_chosen_node, "stdin");
	prom_stdout = prom_getint (prom_chosen_node, "stdout");

	node = prom_finddevice("/openprom");
	if (!node || node == -1)
		prom_halt();

	prom_getstring (node, "version", buffer, sizeof (buffer));

	prom_printf ("\n");

	if (strncmp (buffer, "OBP ", 4))
		goto strange_version;

	/*
	 * Version field is expected to be 'OBP xx.yy.zz date...'
	 * However, Sun can't stick to this format very well, so
	 * we need to check for 'OBP  xx.yy.zz date...' and adjust
	 * accordingly. -spot
	 */

	if (strncmp (buffer, "OBP  ", 5))
		bufadjust = 4;
	else
		bufadjust = 5;

	p = buffer + bufadjust;
	while (p && isdigit(*p) && i < 3) {
		ints[i++] = simple_strtoul(p, NULL, 0);
		if ((p = strchr(p, '.')) != NULL)
			p++;
	}
	if (i != 3)
		goto strange_version;

	prom_rev = ints[1];
	prom_prev = (ints[0] << 16) | (ints[1] << 8) | ints[2];

	printk ("PROMLIB: Sun IEEE Boot Prom %s\n", buffer + bufadjust);

	prom_meminit();

	/* Initialization successful. */
	return;

strange_version:
	prom_printf ("Strange OBP version `%s'.\n", buffer);
	prom_halt ();
}
示例#14
0
__initfunc(static void
fill_sbus_device(int nd, struct linux_sbus_device *sbus_dev))
{
	int grrr, len;
	unsigned long dev_base_addr, base;

	sbus_dev->prom_node = nd;
	prom_getstring(nd, "name", lbuf, sizeof(lbuf));
	strcpy(sbus_dev->prom_name, lbuf);

	dev_base_addr = prom_getint(nd, "address");
	if(dev_base_addr != -1)
		sbus_dev->sbus_addr = dev_base_addr;

	len = prom_getproperty(nd, "reg", (void *) sbus_dev->reg_addrs,
			       sizeof(sbus_dev->reg_addrs));
	if(len == -1)
		goto no_regs;
	if(len%sizeof(struct linux_prom_registers)) {
		prom_printf("WHOOPS:  proplen for %s was %d, need multiple of %d\n",
		       sbus_dev->prom_name, len,
		       (int) sizeof(struct linux_prom_registers));
		panic("fill_sbus_device");
	}
	sbus_dev->num_registers = (len/sizeof(struct linux_prom_registers));
	sbus_dev->ranges_applied = 0;

	base = (unsigned long) sbus_dev->reg_addrs[0].phys_addr;
	if(base>=SUN_SBUS_BVADDR ||
	   (sparc_cpu_model != sun4c &&
	   sparc_cpu_model != sun4)) {
		/* Ahh, we can determine the slot and offset */
		if(sparc_cpu_model == sun4u) {
			/* A bit tricky on the SYSIO. */
			sbus_dev->slot = sbus_dev->reg_addrs[0].which_io;
			sbus_dev->offset = sbus_dev_offset(base);
		} else if (sparc_cpu_model == sun4d) {
			sbus_dev->slot = sbus_dev->reg_addrs[0].which_io;
			sbus_dev->offset = base;
		} else {
			sbus_dev->slot = sbus_dev_slot(base);
			sbus_dev->offset = sbus_dev_offset(base);
		}
	} else {   /* Grrr, gotta do calculations to fix things up */
		sbus_dev->slot = sbus_dev->reg_addrs[0].which_io;
		sbus_dev->offset = base;
		sbus_dev->reg_addrs[0].phys_addr = 
			sbus_devaddr(sbus_dev->slot, base);
		for(grrr=1; grrr<sbus_dev->num_registers; grrr++) {
			base = (unsigned long) sbus_dev->reg_addrs[grrr].phys_addr;
			sbus_dev->reg_addrs[grrr].phys_addr =
				sbus_devaddr(sbus_dev->slot, base);
		}
		/* That surely sucked */
	}
	sbus_dev->sbus_addr = (unsigned long) sbus_dev->reg_addrs[0].phys_addr;
	if(len>(sizeof(struct linux_prom_registers)*PROMREG_MAX)) {
		prom_printf("WHOOPS:  I got too many register addresses for %s  len=%d\n",
		       sbus_dev->prom_name, len);
		panic("sbus device register overflow");
	}

no_regs:
	len = prom_getproperty(nd, "address", (void *) sbus_dev->sbus_vaddrs,
			       sizeof(sbus_dev->sbus_vaddrs));
	if(len == -1) len=0;
	if(len&3) {
		prom_printf("Grrr, I didn't get a multiple of 4 proplen "
		       "for device %s got %d\n", sbus_dev->prom_name, len);
		len=0;
	}
	sbus_dev->num_vaddrs = (len/4);

#ifdef __sparc_v9__  
	len = prom_getproperty(nd, "interrupts", (void *)irqs, sizeof(irqs));
	if((len == -1) || (len == 0)) {
		sbus_dev->irqs[0] = 0;
		sbus_dev->num_irqs = 0;
	} else {
		sbus_dev->num_irqs = 1;
		if (irqs[0].pri < 0x20)
			sbus_dev->irqs[0] = sbus_build_irq(sbus_dev->my_bus, 
					irqs[0].pri + (sbus_dev->slot * 8));
		else
			sbus_dev->irqs[0] = sbus_build_irq(sbus_dev->my_bus, 
					irqs[0].pri);
	}
#else
	len = prom_getproperty(nd, "intr", (void *)irqs, sizeof(irqs));
	if (len == -1) len=0;
	if (len&7) {
		prom_printf("Grrr, I didn't get a multiple of 8 proplen for "
			    "device %s got %d\n", sbus_dev->prom_name, len);
		len=0;
	}
	if (len > 4 * 8) {
		prom_printf("Device %s has more than 4 interrupts\n", sbus_dev->prom_name);
		len = 4 * 8;
	}
	sbus_dev->num_irqs=(len/8);
	if(sbus_dev->num_irqs == 0)
		sbus_dev->irqs[0]=0;
	else if (sparc_cpu_model != sun4d)
		for (len = 0; len < sbus_dev->num_irqs; len++)
			sbus_dev->irqs[len] = irqs[len].pri;
	else {
		extern unsigned int sun4d_build_irq(struct linux_sbus_device *sdev, int irq);
		
		for (len = 0; len < sbus_dev->num_irqs; len++)
			sbus_dev->irqs[len] = sun4d_build_irq(sbus_dev, irqs[len].pri);
	}
#endif

#ifdef DEBUG_FILL
#ifdef __sparc_v9__
	prom_printf("Found %s at SBUS slot %x offset %016lx ",
	       sbus_dev->prom_name, sbus_dev->slot, sbus_dev->offset);
	if (sbus_dev->irqs[0])
		prom_printf("irq %s\n", __irq_itoa(sbus_dev->irqs[0]));
	else
		prom_printf("\n");
	prom_printf("Base address %016lx\n", sbus_dev->sbus_addr);
#else
	prom_printf("Found %s at SBUS slot %x offset %08lx irq-level %d\n",
	       sbus_dev->prom_name, sbus_dev->slot, sbus_dev->offset,
	       sbus_dev->irqs[0]);
	prom_printf("Base address %08lx\n", sbus_dev->sbus_addr);
#endif
	prom_printf("REGISTERS: Probed %d register(s)\n", sbus_dev->num_registers);
	for(len=0; len<sbus_dev->num_registers; len++)
#ifdef __sparc_v9__
		prom_printf("Regs<%d> at address<%08lx> IO-space<%d> size<%d "
		       "bytes, %d words>\n", (int) len,
		       (unsigned long) sbus_dev->reg_addrs[len].phys_addr,
		       sbus_dev->reg_addrs[len].which_io,
		       sbus_dev->reg_addrs[len].reg_size,
		       (sbus_dev->reg_addrs[len].reg_size/4));
#else
		prom_printf("Regs<%d> at address<%016lx> IO-space<%d> size<%d "
		       "bytes, %d words>\n", (int) len,
		       (unsigned long) sbus_dev->reg_addrs[len].phys_addr,
		       sbus_dev->reg_addrs[len].which_io,
		       sbus_dev->reg_addrs[len].reg_size,
		       (sbus_dev->reg_addrs[len].reg_size/4));
#endif
#endif
}
示例#15
0
int __init gaisler_apbuart_init(void)
{
	int ret;
	int i;
	int node;
	int freq_khz;
	int baud_rates[UART_NR];

	_apbuart_init_bases();
	node = prom_getchild(prom_root_node);
	freq_khz = prom_getint(node, "clock-frequency");

	printk(KERN_INFO "grlib apbuart: %i serial driver(s) at [",
	       leon_ports_nr);
	for (i = 0; i < UART_NR; i++) {
		baud_rates[i] = 9600;
	}
	for (i = 0; i < leon_ports_nr; i++) {
		baud_rates[i] = prom_getintdefault(node, "uart1_baud", 9600);
		if (i != 0) {
			printk(",");
		}
		printk("0x%x", (unsigned int)leon_ports[i].port.mapbase);
		printk("(irq %i)", leon_ports[i].port.irq);
	}
	printk("]\n");

	baud_rates[0] = prom_getintdefault(node, "uart1_baud", 9600);
	baud_rates[1] = prom_getintdefault(node, "uart2_baud", 9600);

	printk(KERN_INFO 
	       "grlib apbuart: system frequency: %i khz, baud rates: %i %i\n",
	       freq_khz, baud_rates[0], baud_rates[1]);

	ret = uart_register_driver(&leon_reg);
	leon_reg.tty_driver->init_termios.c_cflag =
	    (leon_reg.tty_driver->init_termios.c_cflag & ~CBAUD) | B38400;

	if (ret)
		return ret;

	/*
 	 * Set the FIFO size after the baud rates are set so it'll be done at an
 	 * appropriate rate. Also flush the FIFOs just in case they have lingering
 	 * data.
 	 */

	of_register_driver(&apbuart_driver, &of_platform_bus_type);
	
	/*for (i = 0; i < leon_ports_nr; i++) {
		struct console co;
		leon_ports[i].port.uartclk = freq_khz * 1000;
		uart_add_one_port(&leon_reg, &leon_ports[i].port);
		uart_set_options(&leon_ports[i].port, &co,
				 baud_rates[i], 'n', 8, 'n');
		leon_ports[i].port.fifosize = apbuart_scan_fifo_size(i);
		apbuart_flush_fifo(&leon_ports[i].port);
		}*/
	
	
	return ret;
}