Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 21439
b: refs/heads/master
c: f4266ab
h: refs/heads/master
i:
  21437: 5239faa
  21435: 2d8389c
  21431: 5fc6df2
  21423: 5f9c22c
  21407: bcdc1b9
  21375: d3aa889
v: v3
  • Loading branch information
David S. Miller committed Mar 20, 2006
1 parent 2f07e2c commit e0a5992
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 7 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: e77227eb4e17591a6a511b9c0ff6e8ad7350c575
refs/heads/master: f4266ab45a3f08bd76c2d414a2d7a1a9dc2501c0
73 changes: 67 additions & 6 deletions trunk/drivers/serial/sunhv.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@

#include <asm/hypervisor.h>
#include <asm/spitfire.h>
#include <asm/vdev.h>
#include <asm/irq.h>

#if defined(CONFIG_MAGIC_SYSRQ)
#define SUPPORT_SYSRQ
Expand Down Expand Up @@ -407,6 +409,60 @@ static void __init sunhv_console_init(void)
register_console(&sunhv_console);
}

static int __init hv_console_compatible(char *buf, int len)
{
while (len) {
int this_len;

if (!strcmp(buf, "qcn"))
return 1;

this_len = strlen(buf) + 1;

buf += this_len;
len -= this_len;
}

return 0;
}

static unsigned int __init get_interrupt(void)
{
const char *cons_str = "console";
const char *compat_str = "compatible";
int node = prom_getchild(sun4v_vdev_root);
unsigned int irq;
char buf[64];
int err, len;

node = prom_searchsiblings(node, cons_str);
if (!node)
return 0;

len = prom_getproplen(node, compat_str);
if (len == 0 || len == -1)
return 0;

err = prom_getproperty(node, compat_str, buf, 64);
if (err == -1)
return 0;

if (!hv_console_compatible(buf, len))
return 0;

/* Ok, the this is the OBP node for the sun4v hypervisor
* console device. Decode the interrupt.
*/
err = prom_getproperty(node, "interrupts",
(char *) &irq, sizeof(irq));
if (err == -1)
return 0;

return sun4v_build_irq(sun4v_vdev_devhandle, irq, 4, 0);
}

static u32 sunhv_irq;

static int __init sunhv_init(void)
{
struct uart_port *port;
Expand All @@ -415,6 +471,10 @@ static int __init sunhv_init(void)
if (tlb_type != hypervisor)
return -ENODEV;

sunhv_irq = get_interrupt();
if (!sunhv_irq)
return -ENODEV;

port = kmalloc(sizeof(struct uart_port), GFP_KERNEL);
if (unlikely(!port))
return -ENOMEM;
Expand All @@ -424,22 +484,23 @@ static int __init sunhv_init(void)
port->type = PORT_SUNHV;
port->uartclk = ( 29491200 / 16 ); /* arbitrary */

/* XXX Get interrupt. XXX */
if (request_irq(0 /* XXX */, sunhv_interrupt,
if (request_irq(sunhv_irq, sunhv_interrupt,
SA_SHIRQ, "serial(sunhv)", port)) {
printk("sunhv: Cannot get IRQ %x\n",
0 /* XXX */);
printk("sunhv: Cannot get IRQ %x\n", sunhv_irq);
kfree(port);
return -ENODEV;
}

printk("SUNHV: SUN4V virtual console, IRQ[%08x]\n",
sunhv_irq);

sunhv_reg.minor = sunserial_current_minor;
sunhv_reg.nr = 1;
sunhv_reg.cons = &sunhv_console;

ret = uart_register_driver(&sunhv_reg);
if (ret < 0) {
free_irq(0 /* XXX */, up);
free_irq(sunhv_irq, up);
kfree(port);

return ret;
Expand All @@ -463,7 +524,7 @@ static void __exit sunhv_exit(void)
BUG_ON(!port);

uart_remove_one_port(&sunhv_reg, port);
free_irq(0 /* XXX */, port);
free_irq(sunhv_irq, port);

sunserial_current_minor -= 1;

Expand Down

0 comments on commit e0a5992

Please sign in to comment.