summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/input/serio/i8042-sparcio.h108
-rw-r--r--drivers/net/sunhme.c10
-rw-r--r--drivers/serial/sunsab.c299
-rw-r--r--drivers/serial/sunsu.c497
-rw-r--r--drivers/serial/sunzilog.c793
-rw-r--r--drivers/video/bw2.c213
-rw-r--r--drivers/video/cg14.c326
-rw-r--r--drivers/video/cg3.c217
-rw-r--r--drivers/video/cg6.c337
-rw-r--r--drivers/video/ffb.c466
-rw-r--r--drivers/video/leo.c294
-rw-r--r--drivers/video/p9100.c251
-rw-r--r--drivers/video/tcx.c224
13 files changed, 1829 insertions, 2206 deletions
diff --git a/drivers/input/serio/i8042-sparcio.h b/drivers/input/serio/i8042-sparcio.h
index 6d66351805a2..9cad197a4e68 100644
--- a/drivers/input/serio/i8042-sparcio.h
+++ b/drivers/input/serio/i8042-sparcio.h
@@ -3,11 +3,9 @@
#include <linux/config.h>
#include <asm/io.h>
-
-#ifdef CONFIG_PCI
#include <asm/oplib.h>
-#include <asm/ebus.h>
-#endif
+#include <asm/prom.h>
+#include <asm/of_device.h>
static int i8042_kbd_irq = -1;
static int i8042_aux_irq = -1;
@@ -48,54 +46,83 @@ static inline void i8042_write_command(int val)
#define OBP_PS2MS_NAME1 "kdmouse"
#define OBP_PS2MS_NAME2 "mouse"
+static int __devinit sparc_i8042_probe(struct of_device *op, const struct of_device_id *match)
+{
+ struct device_node *dp = op->node;
+
+ dp = dp->child;
+ while (dp) {
+ if (!strcmp(dp->name, OBP_PS2KBD_NAME1) ||
+ !strcmp(dp->name, OBP_PS2KBD_NAME2)) {
+ struct of_device *kbd = of_find_device_by_node(dp);
+ unsigned int irq = kbd->irqs[0];
+ if (irq == 0xffffffff)
+ irq = op->irqs[0];
+ i8042_kbd_irq = irq;
+ kbd_iobase = of_ioremap(&kbd->resource[0],
+ 0, 8, "kbd");
+ } else if (!strcmp(dp->name, OBP_PS2MS_NAME1) ||
+ !strcmp(dp->name, OBP_PS2MS_NAME2)) {
+ struct of_device *ms = of_find_device_by_node(dp);
+ unsigned int irq = ms->irqs[0];
+ if (irq == 0xffffffff)
+ irq = op->irqs[0];
+ i8042_aux_irq = irq;
+ }
+
+ dp = dp->sibling;
+ }
+
+ return 0;
+}
+
+static int __devexit sparc_i8042_remove(struct of_device *op)
+{
+ of_iounmap(kbd_iobase, 8);
+
+ return 0;
+}
+
+static struct of_device_id sparc_i8042_match[] = {
+ {
+ .name = "8042",
+ },
+ {},
+};
+MODULE_DEVICE_TABLE(of, i8042_match);
+
+static struct of_platform_driver sparc_i8042_driver = {
+ .name = "i8042",
+ .match_table = sparc_i8042_match,
+ .probe = sparc_i8042_probe,
+ .remove = __devexit_p(sparc_i8042_remove),
+};
+
static int __init i8042_platform_init(void)
{
#ifndef CONFIG_PCI
return -ENODEV;
#else
- char prop[128];
- int len;
+ struct device_node *root = of_find_node_by_path("/");
- len = prom_getproperty(prom_root_node, "name", prop, sizeof(prop));
- if (len < 0) {
- printk("i8042: Cannot get name property of root OBP node.\n");
- return -ENODEV;
- }
- if (strncmp(prop, "SUNW,JavaStation-1", len) == 0) {
+ if (!strcmp(root->name, "SUNW,JavaStation-1")) {
/* Hardcoded values for MrCoffee. */
i8042_kbd_irq = i8042_aux_irq = 13 | 0x20;
kbd_iobase = ioremap(0x71300060, 8);
if (!kbd_iobase)
return -ENODEV;
} else {
- struct linux_ebus *ebus;
- struct linux_ebus_device *edev;
- struct linux_ebus_child *child;
-
- for_each_ebus(ebus) {
- for_each_ebusdev(edev, ebus) {
- if (!strcmp(edev->prom_node->name, "8042"))
- goto edev_found;
- }
- }
- return -ENODEV;
-
- edev_found:
- for_each_edevchild(edev, child) {
- if (!strcmp(child->prom_node->name, OBP_PS2KBD_NAME1) ||
- !strcmp(child->prom_node->name, OBP_PS2KBD_NAME2)) {
- i8042_kbd_irq = child->irqs[0];
- kbd_iobase =
- ioremap(child->resource[0].start, 8);
- }
- if (!strcmp(child->prom_node->name, OBP_PS2MS_NAME1) ||
- !strcmp(child->prom_node->name, OBP_PS2MS_NAME2))
- i8042_aux_irq = child->irqs[0];
- }
+ int err = of_register_driver(&sparc_i8042_driver,
+ &of_bus_type);
+ if (err)
+ return err;
+
if (i8042_kbd_irq == -1 ||
i8042_aux_irq == -1) {
- printk("i8042: Error, 8042 device lacks both kbd and "
- "mouse nodes.\n");
+ if (kbd_iobase) {
+ of_iounmap(kbd_iobase, 8);
+ kbd_iobase = (void __iomem *) NULL;
+ }
return -ENODEV;
}
}
@@ -109,7 +136,10 @@ static int __init i8042_platform_init(void)
static inline void i8042_platform_exit(void)
{
#ifdef CONFIG_PCI
- iounmap(kbd_iobase);
+ struct device_node *root = of_find_node_by_path("/");
+
+ if (strcmp(root->name, "SUNW,JavaStation-1"))
+ of_unregister_driver(&sparc_i8042_driver);
#endif
}
diff --git a/drivers/net/sunhme.c b/drivers/net/sunhme.c
index c33ead3470db..9b246e44f756 100644
--- a/drivers/net/sunhme.c
+++ b/drivers/net/sunhme.c
@@ -2523,7 +2523,7 @@ static struct ethtool_ops hme_ethtool_ops = {
static int hme_version_printed;
#ifdef CONFIG_SBUS
-void __init quattro_get_ranges(struct quattro *qp)
+void __devinit quattro_get_ranges(struct quattro *qp)
{
struct sbus_dev *sdev = qp->quattro_dev;
int err;
@@ -2539,7 +2539,7 @@ void __init quattro_get_ranges(struct quattro *qp)
qp->nranges = (err / sizeof(struct linux_prom_ranges));
}
-static void __init quattro_apply_ranges(struct quattro *qp, struct happy_meal *hp)
+static void __devinit quattro_apply_ranges(struct quattro *qp, struct happy_meal *hp)
{
struct sbus_dev *sdev = hp->happy_dev;
int rng;
@@ -2566,7 +2566,7 @@ static void __init quattro_apply_ranges(struct quattro *qp, struct happy_meal *h
*
* Return NULL on failure.
*/
-static struct quattro * __init quattro_sbus_find(struct sbus_dev *goal_sdev)
+static struct quattro * __devinit quattro_sbus_find(struct sbus_dev *goal_sdev)
{
struct sbus_dev *sdev;
struct quattro *qp;
@@ -2618,7 +2618,7 @@ static void __init quattro_sbus_register_irqs(void)
}
}
-static void __devexit quattro_sbus_free_irqs(void)
+static void quattro_sbus_free_irqs(void)
{
struct quattro *qp;
@@ -2662,7 +2662,7 @@ static struct quattro * __init quattro_pci_find(struct pci_dev *pdev)
#endif /* CONFIG_PCI */
#ifdef CONFIG_SBUS
-static int __init happy_meal_sbus_probe_one(struct sbus_dev *sdev, int is_qfe)
+static int __devinit happy_meal_sbus_probe_one(struct sbus_dev *sdev, int is_qfe)
{
struct device_node *dp = sdev->ofdev.node;
struct quattro *qp = NULL;
diff --git a/drivers/serial/sunsab.c b/drivers/serial/sunsab.c
index 7da02d11c364..141fedbefbc4 100644
--- a/drivers/serial/sunsab.c
+++ b/drivers/serial/sunsab.c
@@ -1,7 +1,7 @@
/* sunsab.c: ASYNC Driver for the SIEMENS SAB82532 DUSCC.
*
* Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be)
- * Copyright (C) 2002 David S. Miller (davem@redhat.com)
+ * Copyright (C) 2002, 2006 David S. Miller (davem@davemloft.net)
*
* Rewrote buffer handling to use CIRC(Circular Buffer) macros.
* Maxim Krasnyanskiy <maxk@qualcomm.com>
@@ -12,7 +12,7 @@
* Theodore Ts'o <tytso@mit.edu>, 2001-Oct-12
*
* Ported to new 2.5.x UART layer.
- * David S. Miller <davem@redhat.com>
+ * David S. Miller <davem@davemloft.net>
*/
#include <linux/config.h>
@@ -37,8 +37,8 @@
#include <asm/io.h>
#include <asm/irq.h>
-#include <asm/oplib.h>
-#include <asm/ebus.h>
+#include <asm/prom.h>
+#include <asm/of_device.h>
#if defined(CONFIG_SERIAL_SUNZILOG_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
#define SUPPORT_SYSRQ
@@ -976,199 +976,188 @@ static inline struct console *SUNSAB_CONSOLE(void)
#define sunsab_console_init() do { } while (0)
#endif
-static void __init for_each_sab_edev(void (*callback)(struct linux_ebus_device *, void *), void *arg)
+static int __devinit sunsab_init_one(struct uart_sunsab_port *up,
+ struct of_device *op,
+ unsigned long offset,
+ int line)
{
- struct linux_ebus *ebus;
- struct linux_ebus_device *edev = NULL;
-
- for_each_ebus(ebus) {
- for_each_ebusdev(edev, ebus) {
- if (!strcmp(edev->prom_node->name, "se")) {
- callback(edev, arg);
- continue;
- } else if (!strcmp(edev->prom_node->name, "serial")) {
- char *compat;
- int clen;
-
- /* On RIO this can be an SE, check it. We could
- * just check ebus->is_rio, but this is more portable.
- */
- compat = of_get_property(edev->prom_node,
- "compatible", &clen);
- if (compat && clen > 0) {
- if (strncmp(compat, "sab82532", 8) == 0) {
- callback(edev, arg);
- continue;
- }
- }
- }
- }
- }
-}
+ up->port.line = line;
+ up->port.dev = &op->dev;
+
+ up->port.mapbase = op->resource[0].start + offset;
+ up->port.membase = of_ioremap(&op->resource[0], offset,
+ sizeof(union sab82532_async_regs),
+ "sab");
+ if (!up->port.membase)
+ return -ENOMEM;
+ up->regs = (union sab82532_async_regs __iomem *) up->port.membase;
-static void __init sab_count_callback(struct linux_ebus_device *edev, void *arg)
-{
- int *count_p = arg;
+ up->port.irq = op->irqs[0];
- (*count_p)++;
-}
+ up->port.fifosize = SAB82532_XMIT_FIFO_SIZE;
+ up->port.iotype = UPIO_MEM;
-static void __init sab_attach_callback(struct linux_ebus_device *edev, void *arg)
-{
- int *instance_p = arg;
- struct uart_sunsab_port *up;
- unsigned long regs, offset;
- int i;
+ writeb(SAB82532_IPC_IC_ACT_LOW, &up->regs->w.ipc);
- /* Note: ports are located in reverse order */
- regs = edev->resource[0].start;
- offset = sizeof(union sab82532_async_regs);
- for (i = 0; i < 2; i++) {
- up = &sunsab_ports[(*instance_p * 2) + 1 - i];
+ up->port.ops = &sunsab_pops;
+ up->port.type = PORT_SUNSAB;
+ up->port.uartclk = SAB_BASE_BAUD;
- memset(up, 0, sizeof(*up));
- up->regs = ioremap(regs + offset, sizeof(union sab82532_async_regs));
- up->port.irq = edev->irqs[0];
- up->port.fifosize = SAB82532_XMIT_FIFO_SIZE;
- up->port.mapbase = (unsigned long)up->regs;
- up->port.iotype = UPIO_MEM;
+ up->type = readb(&up->regs->r.vstr) & 0x0f;
+ writeb(~((1 << 1) | (1 << 2) | (1 << 4)), &up->regs->w.pcr);
+ writeb(0xff, &up->regs->w.pim);
+ if ((up->port.line & 0x1) == 0) {
+ up->pvr_dsr_bit = (1 << 0);
+ up->pvr_dtr_bit = (1 << 1);
+ } else {
+ up->pvr_dsr_bit = (1 << 3);
+ up->pvr_dtr_bit = (1 << 2);
+ }
+ up->cached_pvr = (1 << 1) | (1 << 2) | (1 << 4);
+ writeb(up->cached_pvr, &up->regs->w.pvr);
+ up->cached_mode = readb(&up->regs->rw.mode);
+ up->cached_mode |= SAB82532_MODE_FRTS;
+ writeb(up->cached_mode, &up->regs->rw.mode);
+ up->cached_mode |= SAB82532_MODE_RTS;
+ writeb(up->cached_mode, &up->regs->rw.mode);
- writeb(SAB82532_IPC_IC_ACT_LOW, &up->regs->w.ipc);
+ up->tec_timeout = SAB82532_MAX_TEC_TIMEOUT;
+ up->cec_timeout = SAB82532_MAX_CEC_TIMEOUT;
- offset -= sizeof(union sab82532_async_regs);
+ if (!(up->port.line & 0x01)) {
+ int err;
+
+ err = request_irq(up->port.irq, sunsab_interrupt,
+ SA_SHIRQ, "sab", up);
+ if (err) {
+ of_iounmap(up->port.membase,
+ sizeof(union sab82532_async_regs));
+ return err;
+ }
}
-
- (*instance_p)++;
+
+ return 0;
}
-static int __init probe_for_sabs(void)
+static int __devinit sab_probe(struct of_device *op, const struct of_device_id *match)
{
- int this_sab = 0;
+ static int inst;
+ struct uart_sunsab_port *up;
+ int err;
+
+ up = &sunsab_ports[inst * 2];
+
+ err = sunsab_init_one(&up[0], op,
+ sizeof(union sab82532_async_regs),
+ (inst * 2) + 0);
+ if (err)
+ return err;
+
+ err = sunsab_init_one(&up[0], op, 0,
+ (inst * 2) + 1);
+ if (err) {
+ of_iounmap(up[0].port.membase,
+ sizeof(union sab82532_async_regs));
+ free_irq(up[0].port.irq, &up[0]);
+ return err;
+ }
- /* Find device instances. */
- for_each_sab_edev(&sab_count_callback, &this_sab);
- if (!this_sab)
- return -ENODEV;
+ uart_add_one_port(&sunsab_reg, &up[0].port);
+ uart_add_one_port(&sunsab_reg, &up[1].port);
- /* Allocate tables. */
- sunsab_ports = kmalloc(sizeof(struct uart_sunsab_port) * this_sab * 2,
- GFP_KERNEL);
- if (!sunsab_ports)
- return -ENOMEM;
+ dev_set_drvdata(&op->dev, &up[0]);
- num_channels = this_sab * 2;
+ inst++;
- this_sab = 0;
- for_each_sab_edev(&sab_attach_callback, &this_sab);
return 0;
}
-static void __init sunsab_init_hw(void)
+static void __devexit sab_remove_one(struct uart_sunsab_port *up)
{
- int i;
-
- for (i = 0; i < num_channels; i++) {
- struct uart_sunsab_port *up = &sunsab_ports[i];
-
- up->port.line = i;
- up->port.ops = &sunsab_pops;
- up->port.type = PORT_SUNSAB;
- up->port.uartclk = SAB_BASE_BAUD;
-
- up->type = readb(&up->regs->r.vstr) & 0x0f;
- writeb(~((1 << 1) | (1 << 2) | (1 << 4)), &up->regs->w.pcr);
- writeb(0xff, &up->regs->w.pim);
- if (up->port.line == 0) {
- up->pvr_dsr_bit = (1 << 0);
- up->pvr_dtr_bit = (1 << 1);
- } else {
- up->pvr_dsr_bit = (1 << 3);
- up->pvr_dtr_bit = (1 << 2);
- }
- up->cached_pvr = (1 << 1) | (1 << 2) | (1 << 4);
- writeb(up->cached_pvr, &up->regs->w.pvr);
- up->cached_mode = readb(&up->regs->rw.mode);
- up->cached_mode |= SAB82532_MODE_FRTS;
- writeb(up->cached_mode, &up->regs->rw.mode);
- up->cached_mode |= SAB82532_MODE_RTS;
- writeb(up->cached_mode, &up->regs->rw.mode);
-
- up->tec_timeout = SAB82532_MAX_TEC_TIMEOUT;
- up->cec_timeout = SAB82532_MAX_CEC_TIMEOUT;
-
- if (!(up->port.line & 0x01)) {
- if (request_irq(up->port.irq, sunsab_interrupt,
- SA_SHIRQ, "serial(sab82532)", up)) {
- printk("sunsab%d: can't get IRQ %x\n",
- i, up->port.irq);
- continue;
- }
- }
- }
+ uart_remove_one_port(&sunsab_reg, &up->port);
+ if (!(up->port.line & 1))
+ free_irq(up->port.irq, up);
+ of_iounmap(up->port.membase,
+ sizeof(union sab82532_async_regs));
}
-static int __init sunsab_init(void)
+static int __devexit sab_remove(struct of_device *op)
{
- int ret = probe_for_sabs();
- int i;
-
- if (ret < 0)
- return ret;
+ struct uart_sunsab_port *up = dev_get_drvdata(&op->dev);
- sunsab_init_hw();
+ sab_remove_one(&up[0]);
+ sab_remove_one(&up[1]);
- sunsab_reg.minor = sunserial_current_minor;
- sunsab_reg.nr = num_channels;
+ dev_set_drvdata(&op->dev, NULL);
- ret = uart_register_driver(&sunsab_reg);
- if (ret < 0) {
- int i;
+ return 0;
+}
- for (i = 0; i < num_channels; i++) {
- struct uart_sunsab_port *up = &sunsab_ports[i];
+static struct of_device_id sab_match[] = {
+ {
+ .name = "se",
+ },
+ {
+ .name = "serial",
+ .compatible = "sab82532",
+ },
+ {},
+};
+MODULE_DEVICE_TABLE(of, sab_match);
- if (!(up->port.line & 0x01))
- free_irq(up->port.irq, up);
- iounmap(up->regs);
- }
- kfree(sunsab_ports);
- sunsab_ports = NULL;
+static struct of_platform_driver sab_driver = {
+ .name = "sab",
+ .match_table = sab_match,
+ .probe = sab_probe,
+ .remove = __devexit_p(sab_remove),
+};
- return ret;
+static int __init sunsab_init(void)
+{
+ struct device_node *dp;
+ int err;
+
+ num_channels = 0;
+ for_each_node_by_name(dp, "su")
+ num_channels += 2;
+ for_each_node_by_name(dp, "serial") {
+ if (of_device_is_compatible(dp, "sab82532"))
+ num_channels += 2;
}
- sunsab_reg.tty_driver->name_base = sunsab_reg.minor - 64;
+ if (num_channels) {
+ sunsab_ports = kzalloc(sizeof(struct uart_sunsab_port) *
+ num_channels, GFP_KERNEL);
+ if (!sunsab_ports)
+ return -ENOMEM;
- sunsab_reg.cons = SUNSAB_CONSOLE();
+ sunsab_reg.minor = sunserial_current_minor;
+ sunsab_reg.nr = num_channels;
- sunserial_current_minor += num_channels;
-
- for (i = 0; i < num_channels; i++) {
- struct uart_sunsab_port *up = &sunsab_ports[i];
+ err = uart_register_driver(&sunsab_reg);
+ if (err) {
+ kfree(sunsab_ports);
+ sunsab_ports = NULL;
- uart_add_one_port(&sunsab_reg, &up->port);
+ return err;
+ }
+
+ sunsab_reg.tty_driver->name_base = sunsab_reg.minor - 64;
+ sunsab_reg.cons = SUNSAB_CONSOLE();
+ sunserial_current_minor += num_channels;
}
- return 0;
+ return of_register_driver(&sab_driver, &of_bus_type);
}
static void __exit sunsab_exit(void)
{
- int i;
-
- for (i = 0; i < num_channels; i++) {
- struct uart_sunsab_port *up = &sunsab_ports[i];
-
- uart_remove_one_port(&sunsab_reg, &up->port);
-
- if (!(up->port.line & 0x01))
- free_irq(up->port.irq, up);
- iounmap(up->regs);
+ of_unregister_driver(&sab_driver);
+ if (num_channels) {
+ sunserial_current_minor -= num_channels;
+ uart_unregister_driver(&sunsab_reg);
}
- sunserial_current_minor -= num_channels;
- uart_unregister_driver(&sunsab_reg);
-
kfree(sunsab_ports);
sunsab_ports = NULL;
}
diff --git a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c
index 6e28c25138cf..73a043b914ef 100644
--- a/drivers/serial/sunsu.c
+++ b/drivers/serial/sunsu.c
@@ -12,7 +12,7 @@
* Theodore Ts'o <tytso@mit.edu>, 2001-Oct-12
*
* Converted to new 2.5.x UART layer.
- * David S. Miller (davem@redhat.com), 2002-Jul-29
+ * David S. Miller (davem@davemloft.net), 2002-Jul-29
*/
#include <linux/config.h>
@@ -40,11 +40,8 @@
#include <asm/io.h>
#include <asm/irq.h>
-#include <asm/oplib.h>
-#include <asm/ebus.h>
-#ifdef CONFIG_SPARC64
-#include <asm/isa.h>
-#endif
+#include <asm/prom.h>
+#include <asm/of_device.h>
#if defined(CONFIG_SERIAL_SUNSU_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
#define SUPPORT_SYSRQ
@@ -94,10 +91,10 @@ struct uart_sunsu_port {
/* Probing information. */
enum su_type su_type;
unsigned int type_probed; /* XXX Stupid */
- int port_node;
+ unsigned long reg_size;
#ifdef CONFIG_SERIO
- struct serio *serio;
+ struct serio serio;
int serio_open;
#endif
};
@@ -509,7 +506,7 @@ static void receive_kbd_ms_chars(struct uart_sunsu_port *up, struct pt_regs *reg
/* Stop-A is handled by drivers/char/keyboard.c now. */
if (up->su_type == SU_PORT_KBD) {
#ifdef CONFIG_SERIO
- serio_interrupt(up->serio, ch, 0, regs);
+ serio_interrupt(&up->serio, ch, 0, regs);
#endif
} else if (up->su_type == SU_PORT_MS) {
int ret = suncore_mouse_baud_detection(ch, is_break);
@@ -523,7 +520,7 @@ static void receive_kbd_ms_chars(struct uart_sunsu_port *up, struct pt_regs *reg
case 0:
#ifdef CONFIG_SERIO
- serio_interrupt(up->serio, ch, 0, regs);
+ serio_interrupt(&up->serio, ch, 0, regs);
#endif
break;
};
@@ -1031,99 +1028,14 @@ static void sunsu_autoconfig(struct uart_sunsu_port *up)
{
unsigned char status1, status2, scratch, scratch2, scratch3;
unsigned char save_lcr, save_mcr;
- struct linux_ebus_device *dev = NULL;
- struct linux_ebus *ebus;
-#ifdef CONFIG_SPARC64
- struct sparc_isa_bridge *isa_br;
- struct sparc_isa_device *isa_dev;
-#endif
-#ifndef CONFIG_SPARC64
- struct linux_prom_registers reg0;
-#endif
unsigned long flags;
- if (!up->port_node || !up->su_type)
+ if (up->su_type == SU_PORT_NONE)
return;
up->type_probed = PORT_UNKNOWN;
up->port.iotype = UPIO_MEM;
- /*
- * First we look for Ebus-bases su's
- */
- for_each_ebus(ebus) {
- for_each_ebusdev(dev, ebus) {
- if (dev->prom_node->node == up->port_node) {
- /*
- * The EBus is broken on sparc; it delivers
- * virtual addresses in resources. Oh well...
- * This is correct on sparc64, though.
- */
- up->port.membase = (char *) dev->resource[0].start;
- /*
- * This is correct on both architectures.
- */
- up->port.mapbase = dev->resource[0].start;
- up->port.irq = dev->irqs[0];
- goto ebus_done;
- }
- }
- }
-
-#ifdef CONFIG_SPARC64
- for_each_isa(isa_br) {
- for_each_isadev(isa_dev, isa_br) {
- if (isa_dev->prom_node->node == up->port_node) {
- /* Same on sparc64. Cool architecure... */
- up->port.membase = (char *) isa_dev->resource.start;
- up->port.mapbase = isa_dev->resource.start;
- up->port.irq = isa_dev->irq;
- goto ebus_done;
- }
- }
- }
-#endif
-
-#ifdef CONFIG_SPARC64
- /*
- * Not on Ebus, bailing.
- */
- return;
-#else
- /*
- * Not on Ebus, must be OBIO.
- */
- if (prom_getproperty(up->port_node, "reg",
- (char *)&reg0, sizeof(reg0)) == -1) {
- prom_printf("sunsu: no \"reg\" property\n");
- return;
- }
- prom_apply_obio_ranges(&reg0, 1);
- if (reg0.which_io != 0) { /* Just in case... */
- prom_printf("sunsu: bus number nonzero: 0x%x:%x\n",
- reg0.which_io, reg0.phys_addr);
- return;
- }
- up->port.mapbase = reg0.phys_addr;
- if ((up->port.membase = ioremap(reg0.phys_addr, reg0.reg_size)) == 0) {
- prom_printf("sunsu: Cannot map registers.\n");
- return;
- }
-
- /*
- * 0x20 is sun4m thing, Dave Redman heritage.
- * See arch/sparc/kernel/irq.c.
- */
-#define IRQ_4M(n) ((n)|0x20)
-
- /*
- * There is no intr property on MrCoffee, so hardwire it.
- */
- up->port.irq = IRQ_4M(13);
-#endif
-
-ebus_done:
-
spin_lock_irqsave(&up->port.lock, flags);
if (!(up->port.flags & UPF_BUGGY_UART)) {
@@ -1269,18 +1181,13 @@ static struct uart_driver sunsu_reg = {
.major = TTY_MAJOR,
};
-static int __init sunsu_kbd_ms_init(struct uart_sunsu_port *up, int channel)
+static int __init sunsu_kbd_ms_init(struct uart_sunsu_port *up)
{
int quot, baud;
#ifdef CONFIG_SERIO
struct serio *serio;
#endif
- spin_lock_init(&up->port.lock);
- up->port.line = channel;
- up->port.type = PORT_UNKNOWN;
- up->port.uartclk = (SU_BASE_BAUD * 16);
-
if (up->su_type == SU_PORT_KBD) {
up->cflag = B1200 | CS8 | CLOCAL | CREAD;
baud = 1200;
@@ -1292,41 +1199,31 @@ static int __init sunsu_kbd_ms_init(struct uart_sunsu_port *up, int channel)
sunsu_autoconfig(up);
if (up->port.type == PORT_UNKNOWN)
- return -1;
-
- printk(KERN_INFO "su%d at 0x%p (irq = %d) is a %s\n",
- channel,
- up->port.membase, up->port.irq,
- sunsu_type(&up->port));
+ return -ENODEV;
#ifdef CONFIG_SERIO
- up->serio = serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
- if (serio) {
- memset(serio, 0, sizeof(*serio));
-
- serio->port_data = up;
-
- serio->id.type = SERIO_RS232;
- if (up->su_type == SU_PORT_KBD) {
- serio->id.proto = SERIO_SUNKBD;
- strlcpy(serio->name, "sukbd", sizeof(serio->name));
- } else {
- serio->id.proto = SERIO_SUN;
- serio->id.extra = 1;
- strlcpy(serio->name, "sums", sizeof(serio->name));
- }
- strlcpy(serio->phys, (channel == 0 ? "su/serio0" : "su/serio1"),
- sizeof(serio->phys));
-
- serio->write = sunsu_serio_write;
- serio->open = sunsu_serio_open;
- serio->close = sunsu_serio_close;
+ serio = &up->serio;
+ serio->port_data = up;
- serio_register_port(serio);
+ serio->id.type = SERIO_RS232;
+ if (up->su_type == SU_PORT_KBD) {
+ serio->id.proto = SERIO_SUNKBD;
+ strlcpy(serio->name, "sukbd", sizeof(serio->name));
} else {
- printk(KERN_WARNING "su%d: not enough memory for serio port\n",
- channel);
+ serio->id.proto = SERIO_SUN;
+ serio->id.extra = 1;
+ strlcpy(serio->name, "sums", sizeof(serio->name));
}
+ strlcpy(serio->phys,
+ (!(up->port.line & 1) ? "su/serio0" : "su/serio1"),
+ sizeof(serio->phys));
+
+ serio->write = sunsu_serio_write;
+ serio->open = sunsu_serio_open;
+ serio->close = sunsu_serio_close;
+ serio->dev.parent = up->port.dev;
+
+ serio_register_port(serio);
#endif
sunsu_change_speed(&up->port, up->cflag, 0, quot);
@@ -1458,22 +1355,20 @@ static struct console sunsu_cons = {
* Register console.
*/
-static inline struct console *SUNSU_CONSOLE(void)
+static inline struct console *SUNSU_CONSOLE(int num_uart)
{
int i;
if (con_is_present())
return NULL;
- for (i = 0; i < UART_NR; i++) {
+ for (i = 0; i < num_uart; i++) {
int this_minor = sunsu_reg.minor + i;
if ((this_minor - 64) == (serial_console - 1))
break;
}
- if (i == UART_NR)
- return NULL;
- if (sunsu_ports[i].port_node == 0)
+ if (i == num_uart)
return NULL;
sunsu_cons.index = i;
@@ -1481,252 +1376,184 @@ static inline struct console *SUNSU_CONSOLE(void)
return &sunsu_cons;
}
#else
-#define SUNSU_CONSOLE() (NULL)
+#define SUNSU_CONSOLE(num_uart) (NULL)
#define sunsu_serial_console_init() do { } while (0)
#endif
-static int __init sunsu_serial_init(void)
+static enum su_type __devinit su_get_type(struct device_node *dp)
{
- int instance, ret, i;
+ struct device_node *ap = of_find_node_by_path("/aliases");
- /* How many instances do we need? */
- instance = 0;
- for (i = 0; i < UART_NR; i++) {
- struct uart_sunsu_port *up = &sunsu_ports[i];
+ if (ap) {
+ char *keyb = of_get_property(ap, "keyboard", NULL);
+ char *ms = of_get_property(ap, "mouse", NULL);
- if (up->su_type == SU_PORT_MS ||
- up->su_type == SU_PORT_KBD)
- continue;
-
- spin_lock_init(&up->port.lock);
- up->port.flags |= UPF_BOOT_AUTOCONF;
- up->port.type = PORT_UNKNOWN;
- up->port.uartclk = (SU_BASE_BAUD * 16);
+ if (keyb) {
+ if (dp == of_find_node_by_path(keyb))
+ return SU_PORT_KBD;
+ }
+ if (ms) {
+ if (dp == of_find_node_by_path(ms))
+ return SU_PORT_MS;
+ }
+ }
- sunsu_autoconfig(up);
- if (up->port.type == PORT_UNKNOWN)
- continue;
+ return SU_PORT_PORT;
+}
- up->port.line = instance++;
- up->port.ops = &sunsu_pops;
- }
+static int __devinit su_probe(struct of_device *op, const struct of_device_id *match)
+{
+ static int inst;
+ struct device_node *dp = op->node;
+ struct uart_sunsu_port *up;
+ struct resource *rp;
+ int err;
- sunsu_reg.minor = sunserial_current_minor;
+ if (inst >= UART_NR)
+ return -EINVAL;
- sunsu_reg.nr = instance;
+ up = &sunsu_ports[inst];
+ up->port.line = inst;
- ret = uart_register_driver(&sunsu_reg);
- if (ret < 0)
- return ret;
+ spin_lock_init(&up->port.lock);
- sunsu_reg.tty_driver->name_base = sunsu_reg.minor - 64;
+ up->su_type = su_get_type(dp);
- sunserial_current_minor += instance;
+ rp = &op->resource[0];
+ up->port.mapbase = op->resource[0].start;
- sunsu_reg.cons = SUNSU_CONSOLE();
+ up->reg_size = (rp->end - rp->start) + 1;
+ up->port.membase = of_ioremap(rp, 0, up->reg_size, "su");
+ if (!up->port.membase)
+ return -ENOMEM;
- for (i = 0; i < UART_NR; i++) {
- struct uart_sunsu_port *up = &sunsu_ports[i];
+ up->port.irq = op->irqs[0];
- /* Do not register Keyboard/Mouse lines with UART
- * layer.
- */
- if (up->su_type == SU_PORT_MS ||
- up->su_type == SU_PORT_KBD)
- continue;
+ up->port.dev = &op->dev;
- if (up->port.type == PORT_UNKNOWN)
- continue;
+ up->port.type = PORT_UNKNOWN;
+ up->port.uartclk = (SU_BASE_BAUD * 16);
- uart_add_one_port(&sunsu_reg, &up->port);
+ err = 0;
+ if (up->su_type == SU_PORT_KBD || up->su_type == SU_PORT_MS) {
+ err = sunsu_kbd_ms_init(up);
+ if (err)
+ goto out_unmap;
}
- return 0;
-}
+ up->port.flags |= UPF_BOOT_AUTOCONF;
-static int su_node_ok(int node, char *name, int namelen)
-{
- if (strncmp(name, "su", namelen) == 0 ||
- strncmp(name, "su_pnp", namelen) == 0)
- return 1;
-
- if (strncmp(name, "serial", namelen) == 0) {
- char compat[32];
- int clen;
-
- /* Is it _really_ a 'su' device? */
- clen = prom_getproperty(node, "compatible", compat, sizeof(compat));
- if (clen > 0) {
- if (strncmp(compat, "sab82532", 8) == 0) {
- /* Nope, Siemens serial, not for us. */
- return 0;
- }
- }
- return 1;
- }
+ sunsu_autoconfig(up);
- return 0;
-}
+ err = -ENODEV;
+ if (up->port.type == PORT_UNKNOWN)
+ goto out_unmap;
-#define SU_PROPSIZE 128
+ up->port.ops = &sunsu_pops;
-/*
- * Scan status structure.
- * "prop" is a local variable but it eats stack to keep it in each
- * stack frame of a recursive procedure.
- */
-struct su_probe_scan {
- int msnode, kbnode; /* PROM nodes for mouse and keyboard */
- int msx, kbx; /* minors for mouse and keyboard */
- int devices; /* scan index */
- char prop[SU_PROPSIZE];
-};
+ err = uart_add_one_port(&sunsu_reg, &up->port);
+ if (err)
+ goto out_unmap;
-/*
- * We have several platforms which present 'su' in different parts
- * of the device tree. 'su' may be found under obio, ebus, isa and pci.
- * We walk over the tree and find them wherever PROM hides them.
- */
-static void __init su_probe_any(struct su_probe_scan *t, int sunode)
-{
- struct uart_sunsu_port *up;
- int len;
+ dev_set_drvdata(&op->dev, up);
- if (t->devices >= UART_NR)
- return;
+ inst++;
- for (; sunode != 0; sunode = prom_getsibling(sunode)) {
- len = prom_getproperty(sunode, "name", t->prop, SU_PROPSIZE);
- if (len <= 1)
- continue; /* Broken PROM node */
-
- if (su_node_ok(sunode, t->prop, len)) {
- up = &sunsu_ports[t->devices];
- if (t->kbnode != 0 && sunode == t->kbnode) {
- t->kbx = t->devices;
- up->su_type = SU_PORT_KBD;
- } else if (t->msnode != 0 && sunode == t->msnode) {
- t->msx = t->devices;
- up->su_type = SU_PORT_MS;
- } else {
-#ifdef CONFIG_SPARC64
- /*
- * Do not attempt to use the truncated
- * keyboard/mouse ports as serial ports
- * on Ultras with PC keyboard attached.
- */
- if (prom_getbool(sunode, "mouse"))
- continue;
- if (prom_getbool(sunode, "keyboard"))
- continue;
-#endif
- up->su_type = SU_PORT_PORT;
- }
- up->port_node = sunode;
- ++t->devices;
- } else {
- su_probe_any(t, prom_getchild(sunode));
- }
- }
+ return 0;
+
+out_unmap:
+ of_iounmap(up->port.membase, up->reg_size);
+ return err;
}
-static int __init sunsu_probe(void)
+static int __devexit su_remove(struct of_device *dev)
{
- int node;
- int len;
- struct su_probe_scan scan;
+ struct uart_sunsu_port *up = dev_get_drvdata(&dev->dev);;
- /*
- * First, we scan the tree.
- */
- scan.devices = 0;
- scan.msx = -1;
- scan.kbx = -1;
- scan.kbnode = 0;
- scan.msnode = 0;
+ if (up->su_type == SU_PORT_MS ||
+ up->su_type == SU_PORT_KBD) {
+#ifdef CONFIG_SERIO
+ serio_unregister_port(&up->serio);
+#endif
+ } else if (up->port.type != PORT_UNKNOWN)
+ uart_remove_one_port(&sunsu_reg, &up->port);
- /*
- * Get the nodes for keyboard and mouse from 'aliases'...
- */
- node = prom_getchild(prom_root_node);
- node = prom_searchsiblings(node, "aliases");
- if (node != 0) {
- len = prom_getproperty(node, "keyboard", scan.prop, SU_PROPSIZE);
- if (len > 0) {
- scan.prop[len] = 0;
- scan.kbnode = prom_finddevice(scan.prop);
- }
+ return 0;
+}
- len = prom_getproperty(node, "mouse", scan.prop, SU_PROPSIZE);
- if (len > 0) {
- scan.prop[len] = 0;
- scan.msnode = prom_finddevice(scan.prop);
- }
- }
+static struct of_device_id su_match[] = {
+ {
+ .name = "su",
+ },
+ {
+ .name = "su_pnp",
+ },
+ {
+ .name = "serial",
+ .compatible = "su",
+ },
+ {},
+};
+MODULE_DEVICE_TABLE(of, su_match);
- su_probe_any(&scan, prom_getchild(prom_root_node));
+static struct of_platform_driver su_driver = {
+ .name = "su",
+ .match_table = su_match,
+ .probe = su_probe,
+ .remove = __devexit_p(su_remove),
+};
- /*
- * Second, we process the special case of keyboard and mouse.
- *
- * Currently if we got keyboard and mouse hooked to "su" ports
- * we do not use any possible remaining "su" as a serial port.
- * Thus, we ignore values of .msx and .kbx, then compact ports.
- */
- if (scan.msx != -1 && scan.kbx != -1) {
- sunsu_ports[0].su_type = SU_PORT_MS;
- sunsu_ports[0].port_node = scan.msnode;
- sunsu_kbd_ms_init(&sunsu_ports[0], 0);
+static int num_uart;
- sunsu_ports[1].su_type = SU_PORT_KBD;
- sunsu_ports[1].port_node = scan.kbnode;
- sunsu_kbd_ms_init(&sunsu_ports[1], 1);
+static int __init sunsu_init(void)
+{
+ struct device_node *dp;
+ int err;
- return 0;
+ num_uart = 0;
+ for_each_node_by_name(dp, "su") {
+ if (su_get_type(dp) == SU_PORT_PORT)
+ num_uart++;
}
-
- if (scan.msx != -1 || scan.kbx != -1) {
- printk("sunsu_probe: cannot match keyboard and mouse, confused\n");
- return -ENODEV;
+ for_each_node_by_name(dp, "su_pnp") {
+ if (su_get_type(dp) == SU_PORT_PORT)
+ num_uart++;
+ }
+ for_each_node_by_name(dp, "serial") {
+ if (of_device_is_compatible(dp, "su")) {
+ if (su_get_type(dp) == SU_PORT_PORT)
+ num_uart++;
+ }
}
- if (scan.devices == 0)
- return -ENODEV;
+ if (num_uart) {
+ sunsu_reg.minor = sunserial_current_minor;
+ sunsu_reg.nr = num_uart;
+ err = uart_register_driver(&sunsu_reg);
+ if (err)
+ return err;
+ sunsu_reg.tty_driver->name_base = sunsu_reg.minor - 64;
+ sunserial_current_minor += num_uart;
+ sunsu_reg.cons = SUNSU_CONSOLE(num_uart);
+ }
- /*
- * Console must be initiated after the generic initialization.
- */
- sunsu_serial_init();
+ err = of_register_driver(&su_driver, &of_bus_type);
+ if (err && num_uart)
+ uart_unregister_driver(&sunsu_reg);
- return 0;
+ return err;
}
static void __exit sunsu_exit(void)
{
- int i, saw_uart;
-
- saw_uart = 0;
- for (i = 0; i < UART_NR; i++) {
- struct uart_sunsu_port *up = &sunsu_ports[i];
-
- if (up->su_type == SU_PORT_MS ||
- up->su_type == SU_PORT_KBD) {
-#ifdef CONFIG_SERIO
- if (up->serio) {
- serio_unregister_port(up->serio);
- up->serio = NULL;
- }
-#endif
- } else if (up->port.type != PORT_UNKNOWN) {
- uart_remove_one_port(&sunsu_reg, &up->port);
- saw_uart++;
- }
- }
-
- if (saw_uart)
+ if (num_uart)
uart_unregister_driver(&sunsu_reg);
}
-module_init(sunsu_probe);
+module_init(sunsu_init);
module_exit(sunsu_exit);
+
+MODULE_AUTHOR("Eddie C. Dost, Peter Zaitcev, and David S. Miller");
+MODULE_DESCRIPTION("Sun SU serial port driver");
+MODULE_VERSION("2.0");
MODULE_LICENSE("GPL");
diff --git a/drivers/serial/sunzilog.c b/drivers/serial/sunzilog.c
index 9f42677287ad..1caa286a6be6 100644
--- a/drivers/serial/sunzilog.c
+++ b/drivers/serial/sunzilog.c
@@ -1,5 +1,4 @@
-/*
- * sunzilog.c
+/* sunzilog.c: Zilog serial driver for Sparc systems.
*
* Driver for Zilog serial chips found on Sun workstations and
* servers. This driver could actually be made more generic.
@@ -10,7 +9,7 @@
* C. Dost, Pete Zaitcev, Ted Ts'o and Alex Buell for their
* work there.
*
- * Copyright (C) 2002 David S. Miller (davem@redhat.com)
+ * Copyright (C) 2002, 2006 David S. Miller (davem@davemloft.net)
*/
#include <linux/config.h>
@@ -38,10 +37,8 @@
#include <asm/io.h>
#include <asm/irq.h>
-#ifdef CONFIG_SPARC64
-#include <asm/fhc.h>
-#endif
-#include <asm/sbus.h>
+#include <asm/prom.h>
+#include <asm/of_device.h>
#if defined(CONFIG_SERIAL_SUNZILOG_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
#define SUPPORT_SYSRQ
@@ -65,7 +62,7 @@
#define ZSDELAY()
#define ZSDELAY_LONG()
#define ZS_WSYNC(__channel) \
- sbus_readb(&((__channel)->control))
+ readb(&((__channel)->control))
#endif
static int num_sunzilog;
@@ -107,7 +104,7 @@ struct uart_sunzilog_port {
unsigned char prev_status;
#ifdef CONFIG_SERIO
- struct serio *serio;
+ struct serio serio;
int serio_open;
#endif
};
@@ -138,9 +135,9 @@ static unsigned char read_zsreg(struct zilog_channel __iomem *channel,
{
unsigned char retval;
- sbus_writeb(reg, &channel->control);
+ writeb(reg, &channel->control);
ZSDELAY();
- retval = sbus_readb(&channel->control);
+ retval = readb(&channel->control);
ZSDELAY();
return retval;
@@ -149,9 +146,9 @@ static unsigned char read_zsreg(struct zilog_channel __iomem *channel,
static void write_zsreg(struct zilog_channel __iomem *channel,
unsigned char reg, unsigned char value)
{
- sbus_writeb(reg, &channel->control);
+ writeb(reg, &channel->control);
ZSDELAY();
- sbus_writeb(value, &channel->control);
+ writeb(value, &channel->control);
ZSDELAY();
}
@@ -162,17 +159,17 @@ static void sunzilog_clear_fifo(struct zilog_channel __iomem *channel)
for (i = 0; i < 32; i++) {
unsigned char regval;
- regval = sbus_readb(&channel->control);
+ regval = readb(&channel->control);
ZSDELAY();
if (regval & Rx_CH_AV)
break;
regval = read_zsreg(channel, R1);
- sbus_readb(&channel->data);
+ readb(&channel->data);
ZSDELAY();
if (regval & (PAR_ERR | Rx_OVR | CRC_ERR)) {
- sbus_writeb(ERR_RES, &channel->control);
+ writeb(ERR_RES, &channel->control);
ZSDELAY();
ZS_WSYNC(channel);
}
@@ -194,7 +191,7 @@ static void __load_zsregs(struct zilog_channel __iomem *channel, unsigned char *
udelay(100);
}
- sbus_writeb(ERR_RES, &channel->control);
+ writeb(ERR_RES, &channel->control);
ZSDELAY();
ZS_WSYNC(channel);
@@ -291,7 +288,7 @@ static void sunzilog_kbdms_receive_chars(struct uart_sunzilog_port *up,
/* Stop-A is handled by drivers/char/keyboard.c now. */
#ifdef CONFIG_SERIO
if (up->serio_open)
- serio_interrupt(up->serio, ch, 0, regs);
+ serio_interrupt(&up->serio, ch, 0, regs);
#endif
} else if (ZS_IS_MOUSE(up)) {
int ret = suncore_mouse_baud_detection(ch, is_break);
@@ -306,7 +303,7 @@ static void sunzilog_kbdms_receive_chars(struct uart_sunzilog_port *up,
case 0:
#ifdef CONFIG_SERIO
if (up->serio_open)
- serio_interrupt(up->serio, ch, 0, regs);
+ serio_interrupt(&up->serio, ch, 0, regs);
#endif
break;
};
@@ -330,12 +327,12 @@ sunzilog_receive_chars(struct uart_sunzilog_port *up,
r1 = read_zsreg(channel, R1);
if (r1 & (PAR_ERR | Rx_OVR | CRC_ERR)) {
- sbus_writeb(ERR_RES, &channel->control);
+ writeb(ERR_RES, &channel->control);
ZSDELAY();
ZS_WSYNC(channel);
}
- ch = sbus_readb(&channel->control);
+ ch = readb(&channel->control);
ZSDELAY();
/* This funny hack depends upon BRK_ABRT not interfering
@@ -347,7 +344,7 @@ sunzilog_receive_chars(struct uart_sunzilog_port *up,
if (!(ch & Rx_CH_AV))
break;
- ch = sbus_readb(&channel->data);
+ ch = readb(&channel->data);
ZSDELAY();
ch &= up->parity_mask;
@@ -406,10 +403,10 @@ static void sunzilog_status_handle(struct uart_sunzilog_port *up,
{
unsigned char status;
- status = sbus_readb(&channel->control);
+ status = readb(&channel->control);
ZSDELAY();
- sbus_writeb(RES_EXT_INT, &channel->control);
+ writeb(RES_EXT_INT, &channel->control);
ZSDELAY();
ZS_WSYNC(channel);
@@ -421,7 +418,7 @@ static void sunzilog_status_handle(struct uart_sunzilog_port *up,
* confusing the PROM.
*/
while (1) {
- status = sbus_readb(&channel->control);
+ status = readb(&channel->control);
ZSDELAY();
if (!(status & BRK_ABRT))
break;
@@ -458,7 +455,7 @@ static void sunzilog_transmit_chars(struct uart_sunzilog_port *up,
struct circ_buf *xmit;
if (ZS_IS_CONS(up)) {
- unsigned char status = sbus_readb(&channel->control);
+ unsigned char status = readb(&channel->control);
ZSDELAY();
/* TX still busy? Just wait for the next TX done interrupt.
@@ -487,7 +484,7 @@ static void sunzilog_transmit_chars(struct uart_sunzilog_port *up,
if (up->port.x_char) {
up->flags |= SUNZILOG_FLAG_TX_ACTIVE;
- sbus_writeb(up->port.x_char, &channel->data);
+ writeb(up->port.x_char, &channel->data);
ZSDELAY();
ZS_WSYNC(channel);
@@ -506,7 +503,7 @@ static void sunzilog_transmit_chars(struct uart_sunzilog_port *up,
goto ack_tx_int;
up->flags |= SUNZILOG_FLAG_TX_ACTIVE;
- sbus_writeb(xmit->buf[xmit->tail], &channel->data);
+ writeb(xmit->buf[xmit->tail], &channel->data);
ZSDELAY();
ZS_WSYNC(channel);
@@ -519,7 +516,7 @@ static void sunzilog_transmit_chars(struct uart_sunzilog_port *up,
return;
ack_tx_int:
- sbus_writeb(RES_Tx_P, &channel->control);
+ writeb(RES_Tx_P, &channel->control);
ZSDELAY();
ZS_WSYNC(channel);
}
@@ -540,7 +537,7 @@ static irqreturn_t sunzilog_interrupt(int irq, void *dev_id, struct pt_regs *reg
/* Channel A */
tty = NULL;
if (r3 & (CHAEXT | CHATxIP | CHARxIP)) {
- sbus_writeb(RES_H_IUS, &channel->control);
+ writeb(RES_H_IUS, &channel->control);
ZSDELAY();
ZS_WSYNC(channel);
@@ -563,7 +560,7 @@ static irqreturn_t sunzilog_interrupt(int irq, void *dev_id, struct pt_regs *reg
spin_lock(&up->port.lock);
tty = NULL;
if (r3 & (CHBEXT | CHBTxIP | CHBRxIP)) {
- sbus_writeb(RES_H_IUS, &channel->control);
+ writeb(RES_H_IUS, &channel->control);
ZSDELAY();
ZS_WSYNC(channel);
@@ -594,7 +591,7 @@ static __inline__ unsigned char sunzilog_read_channel_status(struct uart_port *p
unsigned char status;
channel = ZILOG_CHANNEL_FROM_PORT(port);
- status = sbus_readb(&channel->control);
+ status = readb(&channel->control);
ZSDELAY();
return status;
@@ -682,7 +679,7 @@ static void sunzilog_start_tx(struct uart_port *port)
up->flags |= SUNZILOG_FLAG_TX_ACTIVE;
up->flags &= ~SUNZILOG_FLAG_TX_STOPPED;
- status = sbus_readb(&channel->control);
+ status = readb(&channel->control);
ZSDELAY();
/* TX busy? Just wait for the TX done interrupt. */
@@ -693,7 +690,7 @@ static void sunzilog_start_tx(struct uart_port *port)
* IRQ sending engine.
*/
if (port->x_char) {
- sbus_writeb(port->x_char, &channel->data);
+ writeb(port->x_char, &channel->data);
ZSDELAY();
ZS_WSYNC(channel);
@@ -702,7 +699,7 @@ static void sunzilog_start_tx(struct uart_port *port)
} else {
struct circ_buf *xmit = &port->info->xmit;
- sbus_writeb(xmit->buf[xmit->tail], &channel->data);
+ writeb(xmit->buf[xmit->tail], &channel->data);
ZSDELAY();
ZS_WSYNC(channel);
@@ -779,7 +776,7 @@ static void __sunzilog_startup(struct uart_sunzilog_port *up)
struct zilog_channel __iomem *channel;
channel = ZILOG_CHANNEL_FROM_PORT(&up->port);
- up->prev_status = sbus_readb(&channel->control);
+ up->prev_status = readb(&channel->control);
/* Enable receiver and transmitter. */
up->curregs[R3] |= RxENAB;
@@ -963,7 +960,7 @@ sunzilog_set_termios(struct uart_port *port, struct termios *termios,
static const char *sunzilog_type(struct uart_port *port)
{
- return "SunZilog";
+ return "zs";
}
/* We do not request/release mappings of the registers here, this
@@ -1012,7 +1009,6 @@ static struct uart_sunzilog_port *sunzilog_port_table;
static struct zilog_layout __iomem **sunzilog_chip_regs;
static struct uart_sunzilog_port *sunzilog_irq_chain;
-static int zilog_irq = -1;
static struct uart_driver sunzilog_reg = {
.owner = THIS_MODULE,
@@ -1021,232 +1017,47 @@ static struct uart_driver sunzilog_reg = {
.major = TTY_MAJOR,
};
-static void * __init alloc_one_table(unsigned long size)
-{
- void *ret;
-
- ret = kmalloc(size, GFP_KERNEL);
- if (ret != NULL)
- memset(ret, 0, size);
-
- return ret;
-}
-
-static void __init sunzilog_alloc_tables(void)
-{
- sunzilog_port_table =
- alloc_one_table(NUM_CHANNELS * sizeof(struct uart_sunzilog_port));
- sunzilog_chip_regs =
- alloc_one_table(NUM_SUNZILOG * sizeof(struct zilog_layout __iomem *));
-
- if (sunzilog_port_table == NULL || sunzilog_chip_regs == NULL) {
- prom_printf("SunZilog: Cannot allocate tables.\n");
- prom_halt();
- }
-}
-
-#ifdef CONFIG_SPARC64
-
-/* We used to attempt to use the address property of the Zilog device node
- * but that totally is not necessary on sparc64.
- */
-static struct zilog_layout __iomem * __init get_zs_sun4u(int chip, int zsnode)
+static int __init sunzilog_alloc_tables(void)
{
- void __iomem *mapped_addr;
- unsigned int sun4u_ino;
- struct sbus_bus *sbus = NULL;
- struct sbus_dev *sdev = NULL;
- int err;
-
- if (central_bus == NULL) {
- for_each_sbus(sbus) {
- for_each_sbusdev(sdev, sbus) {
- if (sdev->prom_node == zsnode)
- goto found;
- }
- }
- }
- found:
- if (sdev == NULL && central_bus == NULL) {
- prom_printf("SunZilog: sdev&&central == NULL for "
- "Zilog %d in get_zs_sun4u.\n", chip);
- prom_halt();
- }
- if (central_bus == NULL) {
- mapped_addr =
- sbus_ioremap(&sdev->resource[0], 0,
- PAGE_SIZE,
- "Zilog Registers");
- } else {
- struct linux_prom_registers zsregs[1];
-
- err = prom_getproperty(zsnode, "reg",
- (char *) &zsregs[0],
- sizeof(zsregs));
- if (err == -1) {
- prom_printf("SunZilog: Cannot map "
- "Zilog %d regs on "
- "central bus.\n", chip);
- prom_halt();
- }
- apply_fhc_ranges(central_bus->child,
- &zsregs[0], 1);
- apply_central_ranges(central_bus, &zsregs[0], 1);
- mapped_addr = (void __iomem *)
- ((((u64)zsregs[0].which_io)<<32UL) |
- ((u64)zsregs[0].phys_addr));
- }
-
- if (zilog_irq == -1) {
- if (central_bus) {
- unsigned long iclr, imap;
-
- iclr = central_bus->child->fhc_regs.uregs
- + FHC_UREGS_ICLR;
- imap = central_bus->child->fhc_regs.uregs
- + FHC_UREGS_IMAP;
- zilog_irq = build_irq(0, iclr, imap);
- } else {
- err = prom_getproperty(zsnode, "interrupts",
- (char *) &sun4u_ino,
- sizeof(sun4u_ino));
- zilog_irq = sbus_build_irq(sbus_root, sun4u_ino);
- }
- }
-
- return (struct zilog_layout __iomem *) mapped_addr;
-}
-#else /* CONFIG_SPARC64 */
-
-/*
- * XXX The sun4d case is utterly screwed: it tries to re-walk the tree
- * (for the 3rd time) in order to find bootbus and cpu. Streamline it.
- */
-static struct zilog_layout __iomem * __init get_zs_sun4cmd(int chip, int node)
-{
- struct linux_prom_irqs irq_info[2];
- void __iomem *mapped_addr = NULL;
- int zsnode, cpunode, bbnode;
- struct linux_prom_registers zsreg[4];
- struct resource res;
-
- if (sparc_cpu_model == sun4d) {
- int walk;
-
- zsnode = 0;
- bbnode = 0;
- cpunode = 0;
- for (walk = prom_getchild(prom_root_node);
- (walk = prom_searchsiblings(walk, "cpu-unit")) != 0;
- walk = prom_getsibling(walk)) {
- bbnode = prom_getchild(walk);
- if (bbnode &&
- (bbnode = prom_searchsiblings(bbnode, "bootbus"))) {
- if ((zsnode = prom_getchild(bbnode)) == node) {
- cpunode = walk;
- break;
- }
- }
- }
- if (!walk) {
- prom_printf("SunZilog: Cannot find the %d'th bootbus on sun4d.\n",
- (chip / 2));
- prom_halt();
- }
+ struct uart_sunzilog_port *up;
+ unsigned long size;
+ int i;
- if (prom_getproperty(zsnode, "reg",
- (char *) zsreg, sizeof(zsreg)) == -1) {
- prom_printf("SunZilog: Cannot map Zilog %d\n", chip);
- prom_halt();
- }
- /* XXX Looks like an off by one? */
- prom_apply_generic_ranges(bbnode, cpunode, zsreg, 1);
- res.start = zsreg[0].phys_addr;
- res.end = res.start + (8 - 1);
- res.flags = zsreg[0].which_io | IORESOURCE_IO;
- mapped_addr = sbus_ioremap(&res, 0, 8, "Zilog Serial");
+ size = NUM_CHANNELS * sizeof(struct uart_sunzilog_port);
+ sunzilog_port_table = kzalloc(size, GFP_KERNEL);
+ if (!sunzilog_port_table)
+ return -ENOMEM;
- } else {
- zsnode = node;
+ for (i = 0; i < NUM_CHANNELS; i++) {
+ up = &sunzilog_port_table[i];
-#if 0 /* XXX When was this used? */
- if (prom_getintdefault(zsnode, "slave", -1) != chipid) {
- zsnode = prom_getsibling(zsnode);
- continue;
- }
-#endif
+ spin_lock_init(&up->port.lock);
- /*
- * "address" is only present on ports that OBP opened
- * (from Mitch Bradley's "Hitchhiker's Guide to OBP").
- * We do not use it.
- */
+ if (i == 0)
+ sunzilog_irq_chain = up;
- if (prom_getproperty(zsnode, "reg",
- (char *) zsreg, sizeof(zsreg)) == -1) {
- prom_printf("SunZilog: Cannot map Zilog %d\n", chip);
- prom_halt();
- }
- if (sparc_cpu_model == sun4m) /* Crude. Pass parent. XXX */
- prom_apply_obio_ranges(zsreg, 1);
- res.start = zsreg[0].phys_addr;
- res.end = res.start + (8 - 1);
- res.flags = zsreg[0].which_io | IORESOURCE_IO;
- mapped_addr = sbus_ioremap(&res, 0, 8, "Zilog Serial");
+ if (i < NUM_CHANNELS - 1)
+ up->next = up + 1;
+ else
+ up->next = NULL;
}
- if (prom_getproperty(zsnode, "intr",
- (char *) irq_info, sizeof(irq_info))
- % sizeof(struct linux_prom_irqs)) {
- prom_printf("SunZilog: Cannot get IRQ property for Zilog %d.\n",
- chip);
- prom_halt();
- }
- if (zilog_irq == -1) {
- zilog_irq = irq_info[0].pri;
- } else if (zilog_irq != irq_info[0].pri) {
- /* XXX. Dumb. Should handle per-chip IRQ, for add-ons. */
- prom_printf("SunZilog: Inconsistent IRQ layout for Zilog %d.\n",
- chip);
- prom_halt();
+ size = NUM_SUNZILOG * sizeof(struct zilog_layout __iomem *);
+ sunzilog_chip_regs = kzalloc(size, GFP_KERNEL);
+ if (!sunzilog_chip_regs) {
+ kfree(sunzilog_port_table);
+ sunzilog_irq_chain = NULL;
+ return -ENOMEM;
}
- return (struct zilog_layout __iomem *) mapped_addr;
+ return 0;
}
-#endif /* !(CONFIG_SPARC64) */
-/* Get the address of the registers for SunZilog instance CHIP. */
-static struct zilog_layout __iomem * __init get_zs(int chip, int node)
+static void sunzilog_free_tables(void)
{
- if (chip < 0 || chip >= NUM_SUNZILOG) {
- prom_printf("SunZilog: Illegal chip number %d in get_zs.\n", chip);
- prom_halt();
- }
-
-#ifdef CONFIG_SPARC64
- return get_zs_sun4u(chip, node);
-#else
-
- if (sparc_cpu_model == sun4) {
- struct resource res;
-
- /* Not probe-able, hard code it. */
- switch (chip) {
- case 0:
- res.start = 0xf1000000;
- break;
- case 1:
- res.start = 0xf0000000;
- break;
- };
- zilog_irq = 12;
- res.end = (res.start + (8 - 1));
- res.flags = IORESOURCE_IO;
- return sbus_ioremap(&res, 0, 8, "SunZilog");
- }
-
- return get_zs_sun4cmd(chip, node);
-#endif
+ kfree(sunzilog_port_table);
+ sunzilog_irq_chain = NULL;
+ kfree(sunzilog_chip_regs);
}
#define ZS_PUT_CHAR_MAX_DELAY 2000 /* 10 ms */
@@ -1260,7 +1071,7 @@ static void sunzilog_putchar(struct uart_port *port, int ch)
* udelay with ZSDELAY as that is a NOP on some platforms. -DaveM
*/
do {
- unsigned char val = sbus_readb(&channel->control);
+ unsigned char val = readb(&channel->control);
if (val & Tx_BUF_EMP) {
ZSDELAY();
break;
@@ -1268,7 +1079,7 @@ static void sunzilog_putchar(struct uart_port *port, int ch)
udelay(5);
} while (--loops);
- sbus_writeb(ch, &channel->data);
+ writeb(ch, &channel->data);
ZSDELAY();
ZS_WSYNC(channel);
}
@@ -1385,28 +1196,6 @@ static struct console sunzilog_console = {
.data = &sunzilog_reg,
};
-static int __init sunzilog_console_init(void)
-{
- int i;
-
- if (con_is_present())
- return 0;
-
- for (i = 0; i < NUM_CHANNELS; i++) {
- int this_minor = sunzilog_reg.minor + i;
-
- if ((this_minor - 64) == (serial_console - 1))
- break;
- }
- if (i == NUM_CHANNELS)
- return 0;
-
- sunzilog_console.index = i;
- sunzilog_port_table[i].flags |= SUNZILOG_FLAG_IS_CONS;
- register_console(&sunzilog_console);
- return 0;
-}
-
static inline struct console *SUNZILOG_CONSOLE(void)
{
int i;
@@ -1431,101 +1220,8 @@ static inline struct console *SUNZILOG_CONSOLE(void)
#else
#define SUNZILOG_CONSOLE() (NULL)
-#define sunzilog_console_init() do { } while (0)
#endif
-/*
- * We scan the PROM tree recursively. This is the most reliable way
- * to find Zilog nodes on various platforms. However, we face an extreme
- * shortage of kernel stack, so we must be very careful. To that end,
- * we scan only to a certain depth, and we use a common property buffer
- * in the scan structure.
- */
-#define ZS_PROPSIZE 128
-#define ZS_SCAN_DEPTH 5
-
-struct zs_probe_scan {
- int depth;
- void (*scanner)(struct zs_probe_scan *t, int node);
-
- int devices;
- char prop[ZS_PROPSIZE];
-};
-
-static int __inline__ sunzilog_node_ok(int node, const char *name, int len)
-{
- if (strncmp(name, "zs", len) == 0)
- return 1;
- /* Don't fold this procedure just yet. Compare to su_node_ok(). */
- return 0;
-}
-
-static void __init sunzilog_scan(struct zs_probe_scan *t, int node)
-{
- int len;
-
- for (; node != 0; node = prom_getsibling(node)) {
- len = prom_getproperty(node, "name", t->prop, ZS_PROPSIZE);
- if (len <= 1)
- continue; /* Broken PROM node */
- if (sunzilog_node_ok(node, t->prop, len)) {
- (*t->scanner)(t, node);
- } else {
- if (t->depth < ZS_SCAN_DEPTH) {
- t->depth++;
- sunzilog_scan(t, prom_getchild(node));
- --t->depth;
- }
- }
- }
-}
-
-static void __init sunzilog_prepare(void)
-{
- struct uart_sunzilog_port *up;
- struct zilog_layout __iomem *rp;
- int channel, chip;
-
- /*
- * Temporary fix.
- */
- for (channel = 0; channel < NUM_CHANNELS; channel++)
- spin_lock_init(&sunzilog_port_table[channel].port.lock);
-
- sunzilog_irq_chain = up = &sunzilog_port_table[0];
- for (channel = 0; channel < NUM_CHANNELS - 1; channel++)
- up[channel].next = &up[channel + 1];
- up[channel].next = NULL;
-
- for (chip = 0; chip < NUM_SUNZILOG; chip++) {
- rp = sunzilog_chip_regs[chip];
- up[(chip * 2) + 0].port.membase = (void __iomem *)&rp->channelA;
- up[(chip * 2) + 1].port.membase = (void __iomem *)&rp->channelB;
-
- /* Channel A */
- up[(chip * 2) + 0].port.iotype = UPIO_MEM;
- up[(chip * 2) + 0].port.irq = zilog_irq;
- up[(chip * 2) + 0].port.uartclk = ZS_CLOCK;
- up[(chip * 2) + 0].port.fifosize = 1;
- up[(chip * 2) + 0].port.ops = &sunzilog_pops;
- up[(chip * 2) + 0].port.type = PORT_SUNZILOG;
- up[(chip * 2) + 0].port.flags = 0;
- up[(chip * 2) + 0].port.line = (chip * 2) + 0;
- up[(chip * 2) + 0].flags |= SUNZILOG_FLAG_IS_CHANNEL_A;
-
- /* Channel B */
- up[(chip * 2) + 1].port.iotype = UPIO_MEM;
- up[(chip * 2) + 1].port.irq = zilog_irq;
- up[(chip * 2) + 1].port.uartclk = ZS_CLOCK;
- up[(chip * 2) + 1].port.fifosize = 1;
- up[(chip * 2) + 1].port.ops = &sunzilog_pops;
- up[(chip * 2) + 1].port.type = PORT_SUNZILOG;
- up[(chip * 2) + 1].port.flags = 0;
- up[(chip * 2) + 1].port.line = (chip * 2) + 1;
- up[(chip * 2) + 1].flags |= 0;
- }
-}
-
static void __init sunzilog_init_kbdms(struct uart_sunzilog_port *up, int channel)
{
int baud, brg;
@@ -1539,8 +1235,6 @@ static void __init sunzilog_init_kbdms(struct uart_sunzilog_port *up, int channe
up->cflag = B4800 | CS8 | CLOCAL | CREAD;
baud = 4800;
}
- printk(KERN_INFO "zs%d at 0x%p (irq = %d) is a SunZilog\n",
- channel, up->port.membase, zilog_irq);
up->curregs[R15] = BRKIE;
brg = BPS_TO_BRG(baud, ZS_CLOCK / ZS_CLOCK_DIVISOR);
@@ -1552,216 +1246,268 @@ static void __init sunzilog_init_kbdms(struct uart_sunzilog_port *up, int channe
#ifdef CONFIG_SERIO
static void __init sunzilog_register_serio(struct uart_sunzilog_port *up, int channel)
{
- struct serio *serio;
-
- up->serio = serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
- if (serio) {
- memset(serio, 0, sizeof(*serio));
-
- serio->port_data = up;
-
- serio->id.type = SERIO_RS232;
- if (channel == KEYBOARD_LINE) {
- serio->id.proto = SERIO_SUNKBD;
- strlcpy(serio->name, "zskbd", sizeof(serio->name));
- } else {
- serio->id.proto = SERIO_SUN;
- serio->id.extra = 1;
- strlcpy(serio->name, "zsms", sizeof(serio->name));
- }
- strlcpy(serio->phys,
- (channel == KEYBOARD_LINE ? "zs/serio0" : "zs/serio1"),
- sizeof(serio->phys));
+ struct serio *serio = &up->serio;
- serio->write = sunzilog_serio_write;
- serio->open = sunzilog_serio_open;
- serio->close = sunzilog_serio_close;
+ serio->port_data = up;
- serio_register_port(serio);
+ serio->id.type = SERIO_RS232;
+ if (channel == KEYBOARD_LINE) {
+ serio->id.proto = SERIO_SUNKBD;
+ strlcpy(serio->name, "zskbd", sizeof(serio->name));
} else {
- printk(KERN_WARNING "zs%d: not enough memory for serio port\n",
- channel);
+ serio->id.proto = SERIO_SUN;
+ serio->id.extra = 1;
+ strlcpy(serio->name, "zsms", sizeof(serio->name));
}
+ strlcpy(serio->phys,
+ (channel == KEYBOARD_LINE ? "zs/serio0" : "zs/serio1"),
+ sizeof(serio->phys));
+
+ serio->write = sunzilog_serio_write;
+ serio->open = sunzilog_serio_open;
+ serio->close = sunzilog_serio_close;
+ serio->dev.parent = up->port.dev;
+
+ serio_register_port(serio);
}
#endif
-static void __init sunzilog_init_hw(void)
+static void __init sunzilog_init_hw(struct uart_sunzilog_port *up)
{
- int i;
-
- for (i = 0; i < NUM_CHANNELS; i++) {
- struct uart_sunzilog_port *up = &sunzilog_port_table[i];
- struct zilog_channel __iomem *channel = ZILOG_CHANNEL_FROM_PORT(&up->port);
- unsigned long flags;
- int baud, brg;
+ struct zilog_channel __iomem *channel;
+ unsigned long flags;
+ int baud, brg;
- spin_lock_irqsave(&up->port.lock, flags);
+ channel = ZILOG_CHANNEL_FROM_PORT(&up->port);
- if (ZS_IS_CHANNEL_A(up)) {
- write_zsreg(channel, R9, FHWRES);
- ZSDELAY_LONG();
- (void) read_zsreg(channel, R0);
- }
+ spin_lock_irqsave(&up->port.lock, flags);
+ if (ZS_IS_CHANNEL_A(up)) {
+ write_zsreg(channel, R9, FHWRES);
+ ZSDELAY_LONG();
+ (void) read_zsreg(channel, R0);
+ }
- if (i == KEYBOARD_LINE || i == MOUSE_LINE) {
- sunzilog_init_kbdms(up, i);
- up->curregs[R9] |= (NV | MIE);
- write_zsreg(channel, R9, up->curregs[R9]);
- } else {
- /* Normal serial TTY. */
- up->parity_mask = 0xff;
- up->curregs[R1] = EXT_INT_ENAB | INT_ALL_Rx | TxINT_ENAB;
- up->curregs[R4] = PAR_EVEN | X16CLK | SB1;
- up->curregs[R3] = RxENAB | Rx8;
- up->curregs[R5] = TxENAB | Tx8;
- up->curregs[R9] = NV | MIE;
- up->curregs[R10] = NRZ;
- up->curregs[R11] = TCBR | RCBR;
- baud = 9600;
- brg = BPS_TO_BRG(baud, ZS_CLOCK / ZS_CLOCK_DIVISOR);
- up->curregs[R12] = (brg & 0xff);
- up->curregs[R13] = (brg >> 8) & 0xff;
- up->curregs[R14] = BRSRC | BRENAB;
- __load_zsregs(channel, up->curregs);
- write_zsreg(channel, R9, up->curregs[R9]);
- }
+ if (up->port.line == KEYBOARD_LINE ||
+ up->port.line == MOUSE_LINE) {
+ sunzilog_init_kbdms(up, up->port.line);
+ up->curregs[R9] |= (NV | MIE);
+ write_zsreg(channel, R9, up->curregs[R9]);
+ } else {
+ /* Normal serial TTY. */
+ up->parity_mask = 0xff;
+ up->curregs[R1] = EXT_INT_ENAB | INT_ALL_Rx | TxINT_ENAB;
+ up->curregs[R4] = PAR_EVEN | X16CLK | SB1;
+ up->curregs[R3] = RxENAB | Rx8;
+ up->curregs[R5] = TxENAB | Tx8;
+ up->curregs[R9] = NV | MIE;
+ up->curregs[R10] = NRZ;
+ up->curregs[R11] = TCBR | RCBR;
+ baud = 9600;
+ brg = BPS_TO_BRG(baud, ZS_CLOCK / ZS_CLOCK_DIVISOR);
+ up->curregs[R12] = (brg & 0xff);
+ up->curregs[R13] = (brg >> 8) & 0xff;
+ up->curregs[R14] = BRSRC | BRENAB;
+ __load_zsregs(channel, up->curregs);
+ write_zsreg(channel, R9, up->curregs[R9]);
+ }
- spin_unlock_irqrestore(&up->port.lock, flags);
+ spin_unlock_irqrestore(&up->port.lock, flags);
#ifdef CONFIG_SERIO
- if (i == KEYBOARD_LINE || i == MOUSE_LINE)
- sunzilog_register_serio(up, i);
+ if (up->port.line == KEYBOARD_LINE || up->port.line == MOUSE_LINE)
+ sunzilog_register_serio(up, up->port.line);
#endif
- }
-}
-
-static struct zilog_layout __iomem * __init get_zs(int chip, int node);
-
-static void __init sunzilog_scan_probe(struct zs_probe_scan *t, int node)
-{
- sunzilog_chip_regs[t->devices] = get_zs(t->devices, node);
- t->devices++;
}
-static int __init sunzilog_ports_init(void)
+static int __devinit zs_get_instance(struct device_node *dp)
{
- struct zs_probe_scan scan;
int ret;
- int uart_count;
- int i;
-
- printk(KERN_DEBUG "SunZilog: %d chips.\n", NUM_SUNZILOG);
-
- scan.scanner = sunzilog_scan_probe;
- scan.depth = 0;
- scan.devices = 0;
- sunzilog_scan(&scan, prom_getchild(prom_root_node));
-
- sunzilog_prepare();
- if (request_irq(zilog_irq, sunzilog_interrupt, SA_SHIRQ,
- "SunZilog", sunzilog_irq_chain)) {
- prom_printf("SunZilog: Unable to register zs interrupt handler.\n");
- prom_halt();
- }
+ ret = of_getintprop_default(dp, "slave", -1);
+ if (ret != -1)
+ return ret;
- sunzilog_init_hw();
+ if (of_find_property(dp, "keyboard", NULL))
+ ret = 1;
+ else
+ ret = 0;
- /* We can only init this once we have probed the Zilogs
- * in the system. Do not count channels assigned to keyboards
- * or mice when we are deciding how many ports to register.
- */
- uart_count = 0;
- for (i = 0; i < NUM_CHANNELS; i++) {
- struct uart_sunzilog_port *up = &sunzilog_port_table[i];
+ return ret;
+}
- if (ZS_IS_KEYB(up) || ZS_IS_MOUSE(up))
- continue;
+static int zilog_irq = -1;
- uart_count++;
- }
-
- sunzilog_reg.nr = uart_count;
- sunzilog_reg.minor = sunserial_current_minor;
+static int __devinit zs_probe(struct of_device *dev, const struct of_device_id *match)
+{
+ struct of_device *op = to_of_device(&dev->dev);
+ struct uart_sunzilog_port *up;
+ struct zilog_layout __iomem *rp;
+ int inst = zs_get_instance(dev->node);
+ int err;
- ret = uart_register_driver(&sunzilog_reg);
- if (ret == 0) {
- sunzilog_reg.tty_driver->name_base = sunzilog_reg.minor - 64;
- sunzilog_reg.cons = SUNZILOG_CONSOLE();
+ sunzilog_chip_regs[inst] = of_ioremap(&op->resource[0], 0,
+ sizeof(struct zilog_layout),
+ "zs");
+ if (!sunzilog_chip_regs[inst])
+ return -ENOMEM;
- sunserial_current_minor += uart_count;
+ rp = sunzilog_chip_regs[inst];
- for (i = 0; i < NUM_CHANNELS; i++) {
- struct uart_sunzilog_port *up = &sunzilog_port_table[i];
+ if (zilog_irq == -1) {
+ zilog_irq = op->irqs[0];
+ err = request_irq(zilog_irq, sunzilog_interrupt, SA_SHIRQ,
+ "zs", sunzilog_irq_chain);
+ if (err) {
+ of_iounmap(rp, sizeof(struct zilog_layout));
- if (ZS_IS_KEYB(up) || ZS_IS_MOUSE(up))
- continue;
+ return err;
+ }
+ }
- if (uart_add_one_port(&sunzilog_reg, &up->port)) {
- printk(KERN_ERR
- "SunZilog: failed to add port zs%d\n", i);
- }
+ up = &sunzilog_port_table[inst * 2];
+
+ /* Channel A */
+ up[0].port.mapbase = op->resource[0].start + 0x00;
+ up[0].port.membase = (void __iomem *) &rp->channelA;
+ up[0].port.iotype = UPIO_MEM;
+ up[0].port.irq = op->irqs[0];
+ up[0].port.uartclk = ZS_CLOCK;
+ up[0].port.fifosize = 1;
+ up[0].port.ops = &sunzilog_pops;
+ up[0].port.type = PORT_SUNZILOG;
+ up[0].port.flags = 0;
+ up[0].port.line = (inst * 2) + 0;
+ up[0].port.dev = &op->dev;
+ up[0].flags |= SUNZILOG_FLAG_IS_CHANNEL_A;
+ if (inst == 1)
+ up[0].flags |= SUNZILOG_FLAG_CONS_KEYB;
+ sunzilog_init_hw(&up[0]);
+
+ /* Channel B */
+ up[1].port.mapbase = op->resource[0].start + 0x04;
+ up[1].port.membase = (void __iomem *) &rp->channelB;
+ up[1].port.iotype = UPIO_MEM;
+ up[1].port.irq = op->irqs[0];
+ up[1].port.uartclk = ZS_CLOCK;
+ up[1].port.fifosize = 1;
+ up[1].port.ops = &sunzilog_pops;
+ up[1].port.type = PORT_SUNZILOG;
+ up[1].port.flags = 0;
+ up[1].port.line = (inst * 2) + 1;
+ up[1].port.dev = &op->dev;
+ up[1].flags |= 0;
+ if (inst == 1)
+ up[1].flags |= SUNZILOG_FLAG_CONS_MOUSE;
+ sunzilog_init_hw(&up[1]);
+
+ if (inst != 1) {
+ err = uart_add_one_port(&sunzilog_reg, &up[0].port);
+ if (err) {
+ of_iounmap(rp, sizeof(struct zilog_layout));
+ return err;
+ }
+ err = uart_add_one_port(&sunzilog_reg, &up[1].port);
+ if (err) {
+ uart_remove_one_port(&sunzilog_reg, &up[0].port);
+ of_iounmap(rp, sizeof(struct zilog_layout));
+ return err;
}
}
- return ret;
+ dev_set_drvdata(&dev->dev, &up[0]);
+
+ return 0;
}
-static void __init sunzilog_scan_count(struct zs_probe_scan *t, int node)
+static void __devexit zs_remove_one(struct uart_sunzilog_port *up)
{
- t->devices++;
+ if (ZS_IS_KEYB(up) || ZS_IS_MOUSE(up)) {
+#ifdef CONFIG_SERIO
+ serio_unregister_port(&up->serio);
+#endif
+ } else
+ uart_remove_one_port(&sunzilog_reg, &up->port);
}
-static int __init sunzilog_ports_count(void)
+static int __devexit zs_remove(struct of_device *dev)
{
- struct zs_probe_scan scan;
+ struct uart_sunzilog_port *up = dev_get_drvdata(&dev->dev);
+ struct zilog_layout __iomem *regs;
- /* Sun4 Zilog setup is hard coded, no probing to do. */
- if (sparc_cpu_model == sun4)
- return 2;
+ zs_remove_one(&up[0]);
+ zs_remove_one(&up[1]);
- scan.scanner = sunzilog_scan_count;
- scan.depth = 0;
- scan.devices = 0;
+ regs = sunzilog_chip_regs[up[0].port.line / 2];
+ of_iounmap(regs, sizeof(struct zilog_layout));
- sunzilog_scan(&scan, prom_getchild(prom_root_node));
+ dev_set_drvdata(&dev->dev, NULL);
- return scan.devices;
+ return 0;
}
+static struct of_device_id zs_match[] = {
+ {
+ .name = "zs",
+ },
+ {},
+};
+MODULE_DEVICE_TABLE(of, zs_match);
+
+static struct of_platform_driver zs_driver = {
+ .name = "zs",
+ .match_table = zs_match,
+ .probe = zs_probe,
+ .remove = __devexit_p(zs_remove),
+};
+
static int __init sunzilog_init(void)
{
+ struct device_node *dp;
+ int err;
- NUM_SUNZILOG = sunzilog_ports_count();
- if (NUM_SUNZILOG == 0)
- return -ENODEV;
+ NUM_SUNZILOG = 0;
+ for_each_node_by_name(dp, "zs")
+ NUM_SUNZILOG++;
- sunzilog_alloc_tables();
+ if (NUM_SUNZILOG) {
+ int uart_count;
- sunzilog_ports_init();
+ err = sunzilog_alloc_tables();
+ if (err)
+ return err;
- return 0;
+ /* Subtract 1 for keyboard, 1 for mouse. */
+ uart_count = (NUM_SUNZILOG * 2) - 2;
+
+ sunzilog_reg.nr = uart_count;
+ sunzilog_reg.minor = sunserial_current_minor;
+ err = uart_register_driver(&sunzilog_reg);
+ if (err) {
+ sunzilog_free_tables();
+ return err;
+ }
+ sunzilog_reg.tty_driver->name_base = sunzilog_reg.minor - 64;
+ sunzilog_reg.cons = SUNZILOG_CONSOLE();
+
+ sunserial_current_minor += uart_count;
+ }
+
+ return of_register_driver(&zs_driver, &of_bus_type);
}
static void __exit sunzilog_exit(void)
{
- int i;
+ of_unregister_driver(&zs_driver);
- for (i = 0; i < NUM_CHANNELS; i++) {
- struct uart_sunzilog_port *up = &sunzilog_port_table[i];
-
- if (ZS_IS_KEYB(up) || ZS_IS_MOUSE(up)) {
-#ifdef CONFIG_SERIO
- if (up->serio) {
- serio_unregister_port(up->serio);
- up->serio = NULL;
- }
-#endif
- } else
- uart_remove_one_port(&sunzilog_reg, &up->port);
+ if (zilog_irq != -1) {
+ free_irq(zilog_irq, sunzilog_irq_chain);
+ zilog_irq = -1;
}
- uart_unregister_driver(&sunzilog_reg);
+ if (NUM_SUNZILOG) {
+ uart_unregister_driver(&sunzilog_reg);
+ sunzilog_free_tables();
+ }
}
module_init(sunzilog_init);
@@ -1769,4 +1515,5 @@ module_exit(sunzilog_exit);
MODULE_AUTHOR("David S. Miller");
MODULE_DESCRIPTION("Sun Zilog serial port driver");
+MODULE_VERSION("2.0");
MODULE_LICENSE("GPL");
diff --git a/drivers/video/bw2.c b/drivers/video/bw2.c
index 6577fdfdfc16..c66e3d52cbf3 100644
--- a/drivers/video/bw2.c
+++ b/drivers/video/bw2.c
@@ -1,6 +1,6 @@
/* bw2.c: BWTWO frame buffer driver
*
- * Copyright (C) 2003 David S. Miller (davem@redhat.com)
+ * Copyright (C) 2003, 2006 David S. Miller (davem@davemloft.net)
* Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz)
* Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx)
* Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be)
@@ -19,14 +19,11 @@
#include <linux/mm.h>
#include <asm/io.h>
-#include <asm/sbus.h>
#include <asm/oplib.h>
+#include <asm/prom.h>
+#include <asm/of_device.h>
#include <asm/fbio.h>
-#ifdef CONFIG_SPARC32
-#include <asm/sun4paddr.h>
-#endif
-
#include "sbuslib.h"
/*
@@ -59,30 +56,30 @@ static struct fb_ops bw2_ops = {
#define BWTWO_REGISTER_OFFSET 0x400000
struct bt_regs {
- volatile u32 addr;
- volatile u32 color_map;
- volatile u32 control;
- volatile u32 cursor;
+ u32 addr;
+ u32 color_map;
+ u32 control;
+ u32 cursor;
};
struct bw2_regs {
struct bt_regs cmap;
- volatile u8 control;
- volatile u8 status;
- volatile u8 cursor_start;
- volatile u8 cursor_end;
- volatile u8 h_blank_start;
- volatile u8 h_blank_end;
- volatile u8 h_sync_start;
- volatile u8 h_sync_end;
- volatile u8 comp_sync_end;
- volatile u8 v_blank_start_high;
- volatile u8 v_blank_start_low;
- volatile u8 v_blank_end;
- volatile u8 v_sync_start;
- volatile u8 v_sync_end;
- volatile u8 xfer_holdoff_start;
- volatile u8 xfer_holdoff_end;
+ u8 control;
+ u8 status;
+ u8 cursor_start;
+ u8 cursor_end;
+ u8 h_blank_start;
+ u8 h_blank_end;
+ u8 h_sync_start;
+ u8 h_sync_end;
+ u8 comp_sync_end;
+ u8 v_blank_start_high;
+ u8 v_blank_start_low;
+ u8 v_blank_end;
+ u8 v_sync_start;
+ u8 v_sync_end;
+ u8 xfer_holdoff_start;
+ u8 xfer_holdoff_end;
};
/* Status Register Constants */
@@ -117,9 +114,8 @@ struct bw2_par {
#define BW2_FLAG_BLANKED 0x00000001
unsigned long physbase;
+ unsigned long which_io;
unsigned long fbsize;
-
- struct sbus_dev *sdev;
};
/**
@@ -174,9 +170,7 @@ static int bw2_mmap(struct fb_info *info, struct vm_area_struct *vma)
return sbusfb_mmap_helper(bw2_mmap_map,
par->physbase, par->fbsize,
- (par->sdev ?
- par->sdev->reg_addrs[0].which_io :
- 0),
+ par->which_io,
vma);
}
@@ -288,139 +282,124 @@ static void bw2_do_default_mode(struct bw2_par *par, struct fb_info *info,
struct all_info {
struct fb_info info;
struct bw2_par par;
- struct list_head list;
};
-static LIST_HEAD(bw2_list);
-static void bw2_init_one(struct sbus_dev *sdev)
+static int __devinit bw2_init_one(struct of_device *op)
{
+ struct device_node *dp = op->node;
struct all_info *all;
- struct resource *resp;
-#ifdef CONFIG_SUN4
- struct resource res;
-#endif
- int linebytes;
+ int linebytes, err;
- all = kmalloc(sizeof(*all), GFP_KERNEL);
- if (!all) {
- printk(KERN_ERR "bw2: Cannot allocate memory.\n");
- return;
- }
- memset(all, 0, sizeof(*all));
-
- INIT_LIST_HEAD(&all->list);
+ all = kzalloc(sizeof(*all), GFP_KERNEL);
+ if (!all)
+ return -ENOMEM;
spin_lock_init(&all->par.lock);
- all->par.sdev = sdev;
-
-#ifdef CONFIG_SUN4
- if (!sdev) {
- all->par.physbase = sun4_bwtwo_physaddr;
- res.start = sun4_bwtwo_physaddr;
- res.end = res.start + BWTWO_REGISTER_OFFSET + sizeof(struct bw2_regs) - 1;
- res.flags = IORESOURCE_IO;
- resp = &res;
- all->info.var.xres = all->info.var.xres_virtual = 1152;
- all->info.var.yres = all->info.var.yres_virtual = 900;
- all->info.var.bits_per_pixel = 1;
- linebytes = 1152 / 8;
- } else
-#else
- {
- BUG_ON(!sdev);
- all->par.physbase = sdev->reg_addrs[0].phys_addr;
- resp = &sdev->resource[0];
- sbusfb_fill_var(&all->info.var, (sdev ? sdev->prom_node : 0), 1);
- linebytes = prom_getintdefault(sdev->prom_node, "linebytes",
- all->info.var.xres);
- }
-#endif
+
+ all->par.physbase = op->resource[0].start;
+ all->par.which_io = op->resource[0].flags & IORESOURCE_BITS;
+
+ sbusfb_fill_var(&all->info.var, dp->node, 1);
+ linebytes = of_getintprop_default(dp, "linebytes",
+ all->info.var.xres);
+
all->info.var.red.length = all->info.var.green.length =
all->info.var.blue.length = all->info.var.bits_per_pixel;
all->info.var.red.offset = all->info.var.green.offset =
all->info.var.blue.offset = 0;
- all->par.regs = sbus_ioremap(resp, BWTWO_REGISTER_OFFSET,
- sizeof(struct bw2_regs), "bw2 regs");
+ all->par.regs = of_ioremap(&op->resource[0], BWTWO_REGISTER_OFFSET,
+ sizeof(struct bw2_regs), "bw2 regs");
- if (sdev && !prom_getbool(sdev->prom_node, "width"))
+ if (!of_find_property(dp, "width", NULL))
bw2_do_default_mode(&all->par, &all->info, &linebytes);
all->par.fbsize = PAGE_ALIGN(linebytes * all->info.var.yres);
all->info.flags = FBINFO_DEFAULT;
all->info.fbops = &bw2_ops;
-#if defined(CONFIG_SPARC32)
- if (sdev)
- all->info.screen_base = (char __iomem *)
- prom_getintdefault(sdev->prom_node, "address", 0);
-#endif
- if (!all->info.screen_base)
- all->info.screen_base =
- sbus_ioremap(resp, 0, all->par.fbsize, "bw2 ram");
+
+ all->info.screen_base =
+ sbus_ioremap(&op->resource[0], 0, all->par.fbsize, "bw2 ram");
all->info.par = &all->par;
bw2_blank(0, &all->info);
bw2_init_fix(&all->info, linebytes);
- if (register_framebuffer(&all->info) < 0) {
- printk(KERN_ERR "bw2: Could not register framebuffer.\n");
+ err= register_framebuffer(&all->info);
+ if (err < 0) {
+ of_iounmap(all->par.regs, sizeof(struct bw2_regs));
+ of_iounmap(all->info.screen_base, all->par.fbsize);
kfree(all);
- return;
+ return err;
}
- list_add(&all->list, &bw2_list);
+ dev_set_drvdata(&op->dev, all);
+
+ printk("%s: bwtwo at %lx:%lx\n",
+ dp->full_name,
+ all->par.which_io, all->par.physbase);
- printk("bw2: bwtwo at %lx:%lx\n",
- (long) (sdev ? sdev->reg_addrs[0].which_io : 0),
- (long) all->par.physbase);
+ return 0;
}
-int __init bw2_init(void)
+static int __devinit bw2_probe(struct of_device *dev, const struct of_device_id *match)
{
- struct sbus_bus *sbus;
- struct sbus_dev *sdev;
+ struct of_device *op = to_of_device(&dev->dev);
- if (fb_get_options("bw2fb", NULL))
- return -ENODEV;
+ return bw2_init_one(op);
+}
-#ifdef CONFIG_SUN4
- bw2_init_one(NULL);
-#endif
- for_all_sbusdev(sdev, sbus) {
- if (!strcmp(sdev->prom_name, "bwtwo"))
- bw2_init_one(sdev);
- }
+static int __devexit bw2_remove(struct of_device *dev)
+{
+ struct all_info *all = dev_get_drvdata(&dev->dev);
+
+ unregister_framebuffer(&all->info);
+
+ of_iounmap(all->par.regs, sizeof(struct bw2_regs));
+ of_iounmap(all->info.screen_base, all->par.fbsize);
+
+ kfree(all);
+
+ dev_set_drvdata(&dev->dev, NULL);
return 0;
}
-void __exit bw2_exit(void)
-{
- struct list_head *pos, *tmp;
+static struct of_device_id bw2_match[] = {
+ {
+ .name = "bwtwo",
+ },
+ {},
+};
+MODULE_DEVICE_TABLE(of, bw2_match);
- list_for_each_safe(pos, tmp, &bw2_list) {
- struct all_info *all = list_entry(pos, typeof(*all), list);
+static struct of_platform_driver bw2_driver = {
+ .name = "bw2",
+ .match_table = bw2_match,
+ .probe = bw2_probe,
+ .remove = __devexit_p(bw2_remove),
+};
- unregister_framebuffer(&all->info);
- kfree(all);
- }
+static int __init bw2_init(void)
+{
+ if (fb_get_options("bw2fb", NULL))
+ return -ENODEV;
+
+ return of_register_driver(&bw2_driver, &of_bus_type);
}
-int __init
-bw2_setup(char *arg)
+static void __exit bw2_exit(void)
{
- /* No cmdline options yet... */
- return 0;
+ return of_unregister_driver(&bw2_driver);
}
-module_init(bw2_init);
-#ifdef MODULE
+module_init(bw2_init);
module_exit(bw2_exit);
-#endif
MODULE_DESCRIPTION("framebuffer driver for BWTWO chipsets");
-MODULE_AUTHOR("David S. Miller <davem@redhat.com>");
+MODULE_AUTHOR("David S. Miller <davem@davemloft.net>");
+MODULE_VERSION("2.0");
MODULE_LICENSE("GPL");
diff --git a/drivers/video/cg14.c b/drivers/video/cg14.c
index 63b6c79c8a0a..7f926c619b61 100644
--- a/drivers/video/cg14.c
+++ b/drivers/video/cg14.c
@@ -1,6 +1,6 @@
/* cg14.c: CGFOURTEEN frame buffer driver
*
- * Copyright (C) 2003 David S. Miller (davem@redhat.com)
+ * Copyright (C) 2003, 2006 David S. Miller (davem@davemloft.net)
* Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz)
* Copyright (C) 1995 Miguel de Icaza (miguel@nuclecu.unam.mx)
*
@@ -18,8 +18,8 @@
#include <linux/mm.h>
#include <asm/io.h>
-#include <asm/sbus.h>
-#include <asm/oplib.h>
+#include <asm/prom.h>
+#include <asm/of_device.h>
#include <asm/fbio.h>
#include "sbuslib.h"
@@ -99,73 +99,73 @@ static struct fb_ops cg14_ops = {
#define CG14_MCR_PIXMODE_32 3
struct cg14_regs{
- volatile u8 mcr; /* Master Control Reg */
- volatile u8 ppr; /* Packed Pixel Reg */
- volatile u8 tms[2]; /* Test Mode Status Regs */
- volatile u8 msr; /* Master Status Reg */
- volatile u8 fsr; /* Fault Status Reg */
- volatile u8 rev; /* Revision & Impl */
- volatile u8 ccr; /* Clock Control Reg */
- volatile u32 tmr; /* Test Mode Read Back */
- volatile u8 mod; /* Monitor Operation Data Reg */
- volatile u8 acr; /* Aux Control */
+ u8 mcr; /* Master Control Reg */
+ u8 ppr; /* Packed Pixel Reg */
+ u8 tms[2]; /* Test Mode Status Regs */
+ u8 msr; /* Master Status Reg */
+ u8 fsr; /* Fault Status Reg */
+ u8 rev; /* Revision & Impl */
+ u8 ccr; /* Clock Control Reg */
+ u32 tmr; /* Test Mode Read Back */
+ u8 mod; /* Monitor Operation Data Reg */
+ u8 acr; /* Aux Control */
u8 xxx0[6];
- volatile u16 hct; /* Hor Counter */
- volatile u16 vct; /* Vert Counter */
- volatile u16 hbs; /* Hor Blank Start */
- volatile u16 hbc; /* Hor Blank Clear */
- volatile u16 hss; /* Hor Sync Start */
- volatile u16 hsc; /* Hor Sync Clear */
- volatile u16 csc; /* Composite Sync Clear */
- volatile u16 vbs; /* Vert Blank Start */
- volatile u16 vbc; /* Vert Blank Clear */
- volatile u16 vss; /* Vert Sync Start */
- volatile u16 vsc; /* Vert Sync Clear */
- volatile u16 xcs;
- volatile u16 xcc;
- volatile u16 fsa; /* Fault Status Address */
- volatile u16 adr; /* Address Registers */
+ u16 hct; /* Hor Counter */
+ u16 vct; /* Vert Counter */
+ u16 hbs; /* Hor Blank Start */
+ u16 hbc; /* Hor Blank Clear */
+ u16 hss; /* Hor Sync Start */
+ u16 hsc; /* Hor Sync Clear */
+ u16 csc; /* Composite Sync Clear */
+ u16 vbs; /* Vert Blank Start */
+ u16 vbc; /* Vert Blank Clear */
+ u16 vss; /* Vert Sync Start */
+ u16 vsc; /* Vert Sync Clear */
+ u16 xcs;
+ u16 xcc;
+ u16 fsa; /* Fault Status Address */
+ u16 adr; /* Address Registers */
u8 xxx1[0xce];
- volatile u8 pcg[0x100]; /* Pixel Clock Generator */
- volatile u32 vbr; /* Frame Base Row */
- volatile u32 vmcr; /* VBC Master Control */
- volatile u32 vcr; /* VBC refresh */
- volatile u32 vca; /* VBC Config */
+ u8 pcg[0x100]; /* Pixel Clock Generator */
+ u32 vbr; /* Frame Base Row */
+ u32 vmcr; /* VBC Master Control */
+ u32 vcr; /* VBC refresh */
+ u32 vca; /* VBC Config */
};
#define CG14_CCR_ENABLE 0x04
#define CG14_CCR_SELECT 0x02 /* HW/Full screen */
struct cg14_cursor {
- volatile u32 cpl0[32]; /* Enable plane 0 */
- volatile u32 cpl1[32]; /* Color selection plane */
- volatile u8 ccr; /* Cursor Control Reg */
+ u32 cpl0[32]; /* Enable plane 0 */
+ u32 cpl1[32]; /* Color selection plane */
+ u8 ccr; /* Cursor Control Reg */
u8 xxx0[3];
- volatile u16 cursx; /* Cursor x,y position */
- volatile u16 cursy; /* Cursor x,y position */
- volatile u32 color0;
- volatile u32 color1;
+ u16 cursx; /* Cursor x,y position */
+ u16 cursy; /* Cursor x,y position */
+ u32 color0;
+ u32 color1;
u32 xxx1[0x1bc];
- volatile u32 cpl0i[32]; /* Enable plane 0 autoinc */
- volatile u32 cpl1i[32]; /* Color selection autoinc */
+ u32 cpl0i[32]; /* Enable plane 0 autoinc */
+ u32 cpl1i[32]; /* Color selection autoinc */
};
struct cg14_dac {
- volatile u8 addr; /* Address Register */
+ u8 addr; /* Address Register */
u8 xxx0[255];
- volatile u8 glut; /* Gamma table */
+ u8 glut; /* Gamma table */
u8 xxx1[255];
- volatile u8 select; /* Register Select */
+ u8 select; /* Register Select */
u8 xxx2[255];
- volatile u8 mode; /* Mode Register */
+ u8 mode; /* Mode Register */
};
struct cg14_xlut{
- volatile u8 x_xlut [256];
- volatile u8 x_xlutd [256];
+ u8 x_xlut [256];
+ u8 x_xlutd [256];
u8 xxx0[0x600];
- volatile u8 x_xlut_inc [256];
- volatile u8 x_xlutd_inc [256];
+ u8 x_xlut_inc [256];
+ u8 x_xlutd_inc [256];
};
/* Color look up table (clut) */
@@ -204,7 +204,6 @@ struct cg14_par {
int mode;
int ramsize;
- struct sbus_dev *sdev;
};
static void __cg14_reset(struct cg14_par *par)
@@ -355,14 +354,9 @@ static int cg14_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
* Initialisation
*/
-static void cg14_init_fix(struct fb_info *info, int linebytes)
+static void cg14_init_fix(struct fb_info *info, int linebytes, struct device_node *dp)
{
- struct cg14_par *par = (struct cg14_par *)info->par;
- const char *name;
-
- name = "cgfourteen";
- if (par->sdev)
- name = par->sdev->prom_name;
+ const char *name = dp->name;
strlcpy(info->fix.id, name, sizeof(info->fix.id));
@@ -456,98 +450,81 @@ static struct sbus_mmap_map __cg14_mmap_map[CG14_MMAP_ENTRIES] __initdata = {
struct all_info {
struct fb_info info;
struct cg14_par par;
- struct list_head list;
};
-static LIST_HEAD(cg14_list);
-static void cg14_init_one(struct sbus_dev *sdev, int node, int parent_node)
+static void cg14_unmap_regs(struct all_info *all)
{
- struct all_info *all;
- unsigned long phys, rphys;
- u32 bases[6];
- int is_8mb, linebytes, i;
-
- if (!sdev) {
- if (prom_getproperty(node, "address",
- (char *) &bases[0], sizeof(bases)) <= 0
- || !bases[0]) {
- printk(KERN_ERR "cg14: Device is not mapped.\n");
- return;
- }
- if (__get_iospace(bases[0]) != __get_iospace(bases[1])) {
- printk(KERN_ERR "cg14: I/O spaces don't match.\n");
- return;
- }
- }
+ if (all->par.regs)
+ of_iounmap(all->par.regs, sizeof(struct cg14_regs));
+ if (all->par.clut)
+ of_iounmap(all->par.clut, sizeof(struct cg14_clut));
+ if (all->par.cursor)
+ of_iounmap(all->par.cursor, sizeof(struct cg14_cursor));
+ if (all->info.screen_base)
+ of_iounmap(all->info.screen_base, all->par.fbsize);
+}
- all = kmalloc(sizeof(*all), GFP_KERNEL);
- if (!all) {
- printk(KERN_ERR "cg14: Cannot allocate memory.\n");
- return;
- }
- memset(all, 0, sizeof(*all));
+static int __devinit cg14_init_one(struct of_device *op)
+{
+ struct device_node *dp = op->node;
+ struct all_info *all;
+ int is_8mb, linebytes, i, err;
- INIT_LIST_HEAD(&all->list);
+ all = kzalloc(sizeof(*all), GFP_KERNEL);
+ if (!all)
+ return -ENOMEM;
spin_lock_init(&all->par.lock);
- sbusfb_fill_var(&all->info.var, node, 8);
+ sbusfb_fill_var(&all->info.var, dp->node, 8);
all->info.var.red.length = 8;
all->info.var.green.length = 8;
all->info.var.blue.length = 8;
- linebytes = prom_getintdefault(node, "linebytes",
- all->info.var.xres);
+ linebytes = of_getintprop_default(dp, "linebytes",
+ all->info.var.xres);
all->par.fbsize = PAGE_ALIGN(linebytes * all->info.var.yres);
- all->par.sdev = sdev;
- if (sdev) {
- rphys = sdev->reg_addrs[0].phys_addr;
- all->par.physbase = phys = sdev->reg_addrs[1].phys_addr;
- all->par.iospace = sdev->reg_addrs[0].which_io;
-
- all->par.regs = sbus_ioremap(&sdev->resource[0], 0,
- sizeof(struct cg14_regs),
- "cg14 regs");
- all->par.clut = sbus_ioremap(&sdev->resource[0], CG14_CLUT1,
- sizeof(struct cg14_clut),
- "cg14 clut");
- all->par.cursor = sbus_ioremap(&sdev->resource[0], CG14_CURSORREGS,
- sizeof(struct cg14_cursor),
- "cg14 cursor");
- all->info.screen_base = sbus_ioremap(&sdev->resource[1], 0,
- all->par.fbsize, "cg14 ram");
+ if (!strcmp(dp->parent->name, "sbus") ||
+ !strcmp(dp->parent->name, "sbi")) {
+ all->par.physbase = op->resource[0].start;
+ all->par.iospace = op->resource[0].flags & IORESOURCE_BITS;
} else {
- rphys = __get_phys(bases[0]);
- all->par.physbase = phys = __get_phys(bases[1]);
- all->par.iospace = __get_iospace(bases[0]);
- all->par.regs = (struct cg14_regs __iomem *)(unsigned long)bases[0];
- all->par.clut = (struct cg14_clut __iomem *)((unsigned long)bases[0] +
- CG14_CLUT1);
- all->par.cursor =
- (struct cg14_cursor __iomem *)((unsigned long)bases[0] +
- CG14_CURSORREGS);
-
- all->info.screen_base = (char __iomem *)(unsigned long)bases[1];
+ all->par.physbase = op->resource[1].start;
+ all->par.iospace = op->resource[0].flags & IORESOURCE_BITS;
}
- prom_getproperty(node, "reg", (char *) &bases[0], sizeof(bases));
- is_8mb = (bases[5] == 0x800000);
+ all->par.regs = of_ioremap(&op->resource[0], 0,
+ sizeof(struct cg14_regs), "cg14 regs");
+ all->par.clut = of_ioremap(&op->resource[0], CG14_CLUT1,
+ sizeof(struct cg14_clut), "cg14 clut");
+ all->par.cursor = of_ioremap(&op->resource[0], CG14_CURSORREGS,
+ sizeof(struct cg14_cursor), "cg14 cursor");
- if (sizeof(all->par.mmap_map) != sizeof(__cg14_mmap_map)) {
- extern void __cg14_mmap_sized_wrongly(void);
+ all->info.screen_base = of_ioremap(&op->resource[1], 0,
+ all->par.fbsize, "cg14 ram");
- __cg14_mmap_sized_wrongly();
- }
+ if (!all->par.regs || !all->par.clut || !all->par.cursor ||
+ !all->info.screen_base)
+ cg14_unmap_regs(all);
+
+ is_8mb = (((op->resource[1].end - op->resource[1].start) + 1) ==
+ (8 * 1024 * 1024));
+
+ BUILD_BUG_ON(sizeof(all->par.mmap_map) != sizeof(__cg14_mmap_map));
- memcpy(&all->par.mmap_map, &__cg14_mmap_map, sizeof(all->par.mmap_map));
+ memcpy(&all->par.mmap_map, &__cg14_mmap_map,
+ sizeof(all->par.mmap_map));
+
for (i = 0; i < CG14_MMAP_ENTRIES; i++) {
struct sbus_mmap_map *map = &all->par.mmap_map[i];
if (!map->size)
break;
if (map->poff & 0x80000000)
- map->poff = (map->poff & 0x7fffffff) + rphys - phys;
+ map->poff = (map->poff & 0x7fffffff) +
+ (op->resource[0].start -
+ op->resource[1].start);
if (is_8mb &&
map->size >= 0x100000 &&
map->size <= 0x400000)
@@ -564,84 +541,87 @@ static void cg14_init_one(struct sbus_dev *sdev, int node, int parent_node)
__cg14_reset(&all->par);
if (fb_alloc_cmap(&all->info.cmap, 256, 0)) {
- printk(KERN_ERR "cg14: Could not allocate color map.\n");
+ cg14_unmap_regs(all);
kfree(all);
- return;
+ return -ENOMEM;
}
fb_set_cmap(&all->info.cmap, &all->info);
- cg14_init_fix(&all->info, linebytes);
+ cg14_init_fix(&all->info, linebytes, dp);
- if (register_framebuffer(&all->info) < 0) {
- printk(KERN_ERR "cg14: Could not register framebuffer.\n");
+ err = register_framebuffer(&all->info);
+ if (err < 0) {
fb_dealloc_cmap(&all->info.cmap);
+ cg14_unmap_regs(all);
kfree(all);
- return;
+ return err;
}
- list_add(&all->list, &cg14_list);
+ dev_set_drvdata(&op->dev, all);
- printk("cg14: cgfourteen at %lx:%lx, %dMB\n",
- all->par.iospace, all->par.physbase, all->par.ramsize >> 20);
+ printk("%s: cgfourteen at %lx:%lx, %dMB\n",
+ dp->full_name,
+ all->par.iospace, all->par.physbase,
+ all->par.ramsize >> 20);
+ return 0;
}
-int __init cg14_init(void)
+static int __devinit cg14_probe(struct of_device *dev, const struct of_device_id *match)
{
- struct sbus_bus *sbus;
- struct sbus_dev *sdev;
+ struct of_device *op = to_of_device(&dev->dev);
- if (fb_get_options("cg14fb", NULL))
- return -ENODEV;
+ return cg14_init_one(op);
+}
-#ifdef CONFIG_SPARC32
- {
- int root, node;
-
- root = prom_getchild(prom_root_node);
- root = prom_searchsiblings(root, "obio");
- if (root) {
- node = prom_searchsiblings(prom_getchild(root),
- "cgfourteen");
- if (node)
- cg14_init_one(NULL, node, root);
- }
- }
-#endif
- for_all_sbusdev(sdev, sbus) {
- if (!strcmp(sdev->prom_name, "cgfourteen"))
- cg14_init_one(sdev, sdev->prom_node, sbus->prom_node);
- }
+static int __devexit cg14_remove(struct of_device *dev)
+{
+ struct all_info *all = dev_get_drvdata(&dev->dev);
+
+ unregister_framebuffer(&all->info);
+ fb_dealloc_cmap(&all->info.cmap);
+
+ cg14_unmap_regs(all);
+
+ kfree(all);
+
+ dev_set_drvdata(&dev->dev, NULL);
return 0;
}
-void __exit cg14_exit(void)
-{
- struct list_head *pos, *tmp;
+static struct of_device_id cg14_match[] = {
+ {
+ .name = "cgfourteen",
+ },
+ {},
+};
+MODULE_DEVICE_TABLE(of, cg14_match);
- list_for_each_safe(pos, tmp, &cg14_list) {
- struct all_info *all = list_entry(pos, typeof(*all), list);
+static struct of_platform_driver cg14_driver = {
+ .name = "cg14",
+ .match_table = cg14_match,
+ .probe = cg14_probe,
+ .remove = __devexit_p(cg14_remove),
+};
- unregister_framebuffer(&all->info);
- fb_dealloc_cmap(&all->info.cmap);
- kfree(all);
- }
+int __init cg14_init(void)
+{
+ if (fb_get_options("cg14fb", NULL))
+ return -ENODEV;
+
+ return of_register_driver(&cg14_driver, &of_bus_type);
}
-int __init
-cg14_setup(char *arg)
+void __exit cg14_exit(void)
{
- /* No cmdline options yet... */
- return 0;
+ of_unregister_driver(&cg14_driver);
}
module_init(cg14_init);
-
-#ifdef MODULE
module_exit(cg14_exit);
-#endif
MODULE_DESCRIPTION("framebuffer driver for CGfourteen chipsets");
-MODULE_AUTHOR("David S. Miller <davem@redhat.com>");
+MODULE_AUTHOR("David S. Miller <davem@davemloft.net>");
+MODULE_VERSION("2.0");
MODULE_LICENSE("GPL");
diff --git a/drivers/video/cg3.c b/drivers/video/cg3.c
index 3de6e1b5ab2f..9c8c753ef454 100644
--- a/drivers/video/cg3.c
+++ b/drivers/video/cg3.c
@@ -1,6 +1,6 @@
/* cg3.c: CGTHREE frame buffer driver
*
- * Copyright (C) 2003 David S. Miller (davem@redhat.com)
+ * Copyright (C) 2003, 2006 David S. Miller (davem@davemloft.net)
* Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz)
* Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx)
* Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be)
@@ -19,8 +19,9 @@
#include <linux/mm.h>
#include <asm/io.h>
-#include <asm/sbus.h>
#include <asm/oplib.h>
+#include <asm/prom.h>
+#include <asm/of_device.h>
#include <asm/fbio.h>
#include "sbuslib.h"
@@ -80,30 +81,30 @@ enum cg3_type {
};
struct bt_regs {
- volatile u32 addr;
- volatile u32 color_map;
- volatile u32 control;
- volatile u32 cursor;
+ u32 addr;
+ u32 color_map;
+ u32 control;
+ u32 cursor;
};
struct cg3_regs {
struct bt_regs cmap;
- volatile u8 control;
- volatile u8 status;
- volatile u8 cursor_start;
- volatile u8 cursor_end;
- volatile u8 h_blank_start;
- volatile u8 h_blank_end;
- volatile u8 h_sync_start;
- volatile u8 h_sync_end;
- volatile u8 comp_sync_end;
- volatile u8 v_blank_start_high;
- volatile u8 v_blank_start_low;
- volatile u8 v_blank_end;
- volatile u8 v_sync_start;
- volatile u8 v_sync_end;
- volatile u8 xfer_holdoff_start;
- volatile u8 xfer_holdoff_end;
+ u8 control;
+ u8 status;
+ u8 cursor_start;
+ u8 cursor_end;
+ u8 h_blank_start;
+ u8 h_blank_end;
+ u8 h_sync_start;
+ u8 h_sync_end;
+ u8 comp_sync_end;
+ u8 v_blank_start_high;
+ u8 v_blank_start_low;
+ u8 v_blank_end;
+ u8 v_sync_start;
+ u8 v_sync_end;
+ u8 xfer_holdoff_start;
+ u8 xfer_holdoff_end;
};
/* Offset of interesting structures in the OBIO space */
@@ -120,9 +121,8 @@ struct cg3_par {
#define CG3_FLAG_RDI 0x00000002
unsigned long physbase;
+ unsigned long which_io;
unsigned long fbsize;
-
- struct sbus_dev *sdev;
};
/**
@@ -235,7 +235,7 @@ static int cg3_mmap(struct fb_info *info, struct vm_area_struct *vma)
return sbusfb_mmap_helper(cg3_mmap_map,
par->physbase, par->fbsize,
- par->sdev->reg_addrs[0].which_io,
+ par->which_io,
vma);
}
@@ -252,11 +252,9 @@ static int cg3_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
*/
static void
-cg3_init_fix(struct fb_info *info, int linebytes)
+cg3_init_fix(struct fb_info *info, int linebytes, struct device_node *dp)
{
- struct cg3_par *par = (struct cg3_par *)info->par;
-
- strlcpy(info->fix.id, par->sdev->prom_name, sizeof(info->fix.id));
+ strlcpy(info->fix.id, dp->name, sizeof(info->fix.id));
info->fix.type = FB_TYPE_PACKED_PIXELS;
info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
@@ -267,16 +265,15 @@ cg3_init_fix(struct fb_info *info, int linebytes)
}
static void cg3_rdi_maybe_fixup_var(struct fb_var_screeninfo *var,
- struct sbus_dev *sdev)
+ struct device_node *dp)
{
- char buffer[40];
+ char *params;
char *p;
int ww, hh;
- *buffer = 0;
- prom_getstring(sdev->prom_node, "params", buffer, sizeof(buffer));
- if (*buffer) {
- ww = simple_strtoul(buffer, &p, 10);
+ params = of_get_property(dp, "params", NULL);
+ if (params) {
+ ww = simple_strtoul(params, &p, 10);
if (ww && *p == 'x') {
hh = simple_strtoul(p + 1, &p, 10);
if (hh && *p == '-') {
@@ -348,11 +345,11 @@ static void cg3_do_default_mode(struct cg3_par *par)
sbus_writeb(p[1], regp);
}
for (p = cg3_dacvals; *p; p += 2) {
- volatile u8 __iomem *regp;
+ u8 __iomem *regp;
- regp = (volatile u8 __iomem *)&par->regs->cmap.addr;
+ regp = (u8 __iomem *)&par->regs->cmap.addr;
sbus_writeb(p[0], regp);
- regp = (volatile u8 __iomem *)&par->regs->cmap.control;
+ regp = (u8 __iomem *)&par->regs->cmap.control;
sbus_writeb(p[1], regp);
}
}
@@ -360,129 +357,137 @@ static void cg3_do_default_mode(struct cg3_par *par)
struct all_info {
struct fb_info info;
struct cg3_par par;
- struct list_head list;
};
-static LIST_HEAD(cg3_list);
-static void cg3_init_one(struct sbus_dev *sdev)
+static int __devinit cg3_init_one(struct of_device *op)
{
+ struct device_node *dp = op->node;
struct all_info *all;
- int linebytes;
-
- all = kmalloc(sizeof(*all), GFP_KERNEL);
- if (!all) {
- printk(KERN_ERR "cg3: Cannot allocate memory.\n");
- return;
- }
- memset(all, 0, sizeof(*all));
+ int linebytes, err;
- INIT_LIST_HEAD(&all->list);
+ all = kzalloc(sizeof(*all), GFP_KERNEL);
+ if (!all)
+ return -ENOMEM;
spin_lock_init(&all->par.lock);
- all->par.sdev = sdev;
- all->par.physbase = sdev->reg_addrs[0].phys_addr;
+ all->par.physbase = op->resource[0].start;
+ all->par.which_io = op->resource[0].flags & IORESOURCE_BITS;
- sbusfb_fill_var(&all->info.var, sdev->prom_node, 8);
+ sbusfb_fill_var(&all->info.var, dp->node, 8);
all->info.var.red.length = 8;
all->info.var.green.length = 8;
all->info.var.blue.length = 8;
- if (!strcmp(sdev->prom_name, "cgRDI"))
+ if (!strcmp(dp->name, "cgRDI"))
all->par.flags |= CG3_FLAG_RDI;
if (all->par.flags & CG3_FLAG_RDI)
- cg3_rdi_maybe_fixup_var(&all->info.var, sdev);
+ cg3_rdi_maybe_fixup_var(&all->info.var, dp);
- linebytes = prom_getintdefault(sdev->prom_node, "linebytes",
- all->info.var.xres);
+ linebytes = of_getintprop_default(dp, "linebytes",
+ all->info.var.xres);
all->par.fbsize = PAGE_ALIGN(linebytes * all->info.var.yres);
- all->par.regs = sbus_ioremap(&sdev->resource[0], CG3_REGS_OFFSET,
- sizeof(struct cg3_regs), "cg3 regs");
+ all->par.regs = of_ioremap(&op->resource[0], CG3_REGS_OFFSET,
+ sizeof(struct cg3_regs), "cg3 regs");
all->info.flags = FBINFO_DEFAULT;
all->info.fbops = &cg3_ops;
-#ifdef CONFIG_SPARC32
- all->info.screen_base = (char __iomem *)
- prom_getintdefault(sdev->prom_node, "address", 0);
-#endif
- if (!all->info.screen_base)
- all->info.screen_base =
- sbus_ioremap(&sdev->resource[0], CG3_RAM_OFFSET,
- all->par.fbsize, "cg3 ram");
+ all->info.screen_base =
+ of_ioremap(&op->resource[0], CG3_RAM_OFFSET,
+ all->par.fbsize, "cg3 ram");
all->info.par = &all->par;
cg3_blank(0, &all->info);
- if (!prom_getbool(sdev->prom_node, "width"))
+ if (!of_find_property(dp, "width", NULL))
cg3_do_default_mode(&all->par);
if (fb_alloc_cmap(&all->info.cmap, 256, 0)) {
- printk(KERN_ERR "cg3: Could not allocate color map.\n");
+ of_iounmap(all->par.regs, sizeof(struct cg3_regs));
+ of_iounmap(all->info.screen_base, all->par.fbsize);
kfree(all);
- return;
+ return -ENOMEM;
}
fb_set_cmap(&all->info.cmap, &all->info);
- cg3_init_fix(&all->info, linebytes);
+ cg3_init_fix(&all->info, linebytes, dp);
- if (register_framebuffer(&all->info) < 0) {
- printk(KERN_ERR "cg3: Could not register framebuffer.\n");
+ err = register_framebuffer(&all->info);
+ if (err < 0) {
fb_dealloc_cmap(&all->info.cmap);
+ of_iounmap(all->par.regs, sizeof(struct cg3_regs));
+ of_iounmap(all->info.screen_base, all->par.fbsize);
kfree(all);
- return;
+ return err;
}
- list_add(&all->list, &cg3_list);
+ dev_set_drvdata(&op->dev, all);
+
+ printk("%s: cg3 at %lx:%lx\n",
+ dp->full_name, all->par.which_io, all->par.physbase);
- printk("cg3: %s at %lx:%lx\n",
- sdev->prom_name,
- (long) sdev->reg_addrs[0].which_io,
- (long) sdev->reg_addrs[0].phys_addr);
+ return 0;
}
-int __init cg3_init(void)
+static int __devinit cg3_probe(struct of_device *dev, const struct of_device_id *match)
{
- struct sbus_bus *sbus;
- struct sbus_dev *sdev;
+ struct of_device *op = to_of_device(&dev->dev);
- if (fb_get_options("cg3fb", NULL))
- return -ENODEV;
+ return cg3_init_one(op);
+}
- for_all_sbusdev(sdev, sbus) {
- if (!strcmp(sdev->prom_name, "cgthree") ||
- !strcmp(sdev->prom_name, "cgRDI"))
- cg3_init_one(sdev);
- }
+static int __devexit cg3_remove(struct of_device *dev)
+{
+ struct all_info *all = dev_get_drvdata(&dev->dev);
+
+ unregister_framebuffer(&all->info);
+ fb_dealloc_cmap(&all->info.cmap);
+
+ of_iounmap(all->par.regs, sizeof(struct cg3_regs));
+ of_iounmap(all->info.screen_base, all->par.fbsize);
+
+ kfree(all);
+
+ dev_set_drvdata(&dev->dev, NULL);
return 0;
}
-void __exit cg3_exit(void)
-{
- struct list_head *pos, *tmp;
+static struct of_device_id cg3_match[] = {
+ {
+ .name = "cgthree",
+ },
+ {
+ .name = "cgRDI",
+ },
+ {},
+};
+MODULE_DEVICE_TABLE(of, cg3_match);
- list_for_each_safe(pos, tmp, &cg3_list) {
- struct all_info *all = list_entry(pos, typeof(*all), list);
+static struct of_platform_driver cg3_driver = {
+ .name = "cg3",
+ .match_table = cg3_match,
+ .probe = cg3_probe,
+ .remove = __devexit_p(cg3_remove),
+};
- unregister_framebuffer(&all->info);
- fb_dealloc_cmap(&all->info.cmap);
- kfree(all);
- }
+static int __init cg3_init(void)
+{
+ if (fb_get_options("cg3fb", NULL))
+ return -ENODEV;
+
+ return of_register_driver(&cg3_driver, &of_bus_type);
}
-int __init
-cg3_setup(char *arg)
+static void __exit cg3_exit(void)
{
- /* No cmdline options yet... */
- return 0;
+ of_unregister_driver(&cg3_driver);
}
module_init(cg3_init);
-
-#ifdef MODULE
module_exit(cg3_exit);
-#endif
MODULE_DESCRIPTION("framebuffer driver for CGthree chipsets");
-MODULE_AUTHOR("David S. Miller <davem@redhat.com>");
+MODULE_AUTHOR("David S. Miller <davem@davemloft.net>");
+MODULE_VERSION("2.0");
MODULE_LICENSE("GPL");
diff --git a/drivers/video/cg6.c b/drivers/video/cg6.c
index 7aab91ead681..64146be2eeb0 100644
--- a/drivers/video/cg6.c
+++ b/drivers/video/cg6.c
@@ -1,6 +1,6 @@
/* cg6.c: CGSIX (GX, GXplus, TGX) frame buffer driver
*
- * Copyright (C) 2003 David S. Miller (davem@redhat.com)
+ * Copyright (C) 2003, 2006 David S. Miller (davem@davemloft.net)
* Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz)
* Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx)
* Copyright (C) 1996 Eddie C. Dost (ecd@skynet.be)
@@ -19,8 +19,8 @@
#include <linux/mm.h>
#include <asm/io.h>
-#include <asm/sbus.h>
-#include <asm/oplib.h>
+#include <asm/prom.h>
+#include <asm/of_device.h>
#include <asm/fbio.h>
#include "sbuslib.h"
@@ -164,89 +164,89 @@ static struct fb_ops cg6_ops = {
/* The contents are unknown */
struct cg6_tec {
- volatile int tec_matrix;
- volatile int tec_clip;
- volatile int tec_vdc;
+ int tec_matrix;
+ int tec_clip;
+ int tec_vdc;
};
struct cg6_thc {
- uint thc_pad0[512];
- volatile uint thc_hs; /* hsync timing */
- volatile uint thc_hsdvs;
- volatile uint thc_hd;
- volatile uint thc_vs; /* vsync timing */
- volatile uint thc_vd;
- volatile uint thc_refresh;
- volatile uint thc_misc;
- uint thc_pad1[56];
- volatile uint thc_cursxy; /* cursor x,y position (16 bits each) */
- volatile uint thc_cursmask[32]; /* cursor mask bits */
- volatile uint thc_cursbits[32]; /* what to show where mask enabled */
+ u32 thc_pad0[512];
+ u32 thc_hs; /* hsync timing */
+ u32 thc_hsdvs;
+ u32 thc_hd;
+ u32 thc_vs; /* vsync timing */
+ u32 thc_vd;
+ u32 thc_refresh;
+ u32 thc_misc;
+ u32 thc_pad1[56];
+ u32 thc_cursxy; /* cursor x,y position (16 bits each) */
+ u32 thc_cursmask[32]; /* cursor mask bits */
+ u32 thc_cursbits[32]; /* what to show where mask enabled */
};
struct cg6_fbc {
- u32 xxx0[1];
- volatile u32 mode;
- volatile u32 clip;
- u32 xxx1[1];
- volatile u32 s;
- volatile u32 draw;
- volatile u32 blit;
- volatile u32 font;
- u32 xxx2[24];
- volatile u32 x0, y0, z0, color0;
- volatile u32 x1, y1, z1, color1;
- volatile u32 x2, y2, z2, color2;
- volatile u32 x3, y3, z3, color3;
- volatile u32 offx, offy;
- u32 xxx3[2];
- volatile u32 incx, incy;
- u32 xxx4[2];
- volatile u32 clipminx, clipminy;
- u32 xxx5[2];
- volatile u32 clipmaxx, clipmaxy;
- u32 xxx6[2];
- volatile u32 fg;
- volatile u32 bg;
- volatile u32 alu;
- volatile u32 pm;
- volatile u32 pixelm;
- u32 xxx7[2];
- volatile u32 patalign;
- volatile u32 pattern[8];
- u32 xxx8[432];
- volatile u32 apointx, apointy, apointz;
- u32 xxx9[1];
- volatile u32 rpointx, rpointy, rpointz;
- u32 xxx10[5];
- volatile u32 pointr, pointg, pointb, pointa;
- volatile u32 alinex, aliney, alinez;
- u32 xxx11[1];
- volatile u32 rlinex, rliney, rlinez;
- u32 xxx12[5];
- volatile u32 liner, lineg, lineb, linea;
- volatile u32 atrix, atriy, atriz;
- u32 xxx13[1];
- volatile u32 rtrix, rtriy, rtriz;
- u32 xxx14[5];
- volatile u32 trir, trig, trib, tria;
- volatile u32 aquadx, aquady, aquadz;
- u32 xxx15[1];
- volatile u32 rquadx, rquady, rquadz;
- u32 xxx16[5];
- volatile u32 quadr, quadg, quadb, quada;
- volatile u32 arectx, arecty, arectz;
- u32 xxx17[1];
- volatile u32 rrectx, rrecty, rrectz;
- u32 xxx18[5];
- volatile u32 rectr, rectg, rectb, recta;
+ u32 xxx0[1];
+ u32 mode;
+ u32 clip;
+ u32 xxx1[1];
+ u32 s;
+ u32 draw;
+ u32 blit;
+ u32 font;
+ u32 xxx2[24];
+ u32 x0, y0, z0, color0;
+ u32 x1, y1, z1, color1;
+ u32 x2, y2, z2, color2;
+ u32 x3, y3, z3, color3;
+ u32 offx, offy;
+ u32 xxx3[2];
+ u32 incx, incy;
+ u32 xxx4[2];
+ u32 clipminx, clipminy;
+ u32 xxx5[2];
+ u32 clipmaxx, clipmaxy;
+ u32 xxx6[2];
+ u32 fg;
+ u32 bg;
+ u32 alu;
+ u32 pm;
+ u32 pixelm;
+ u32 xxx7[2];
+ u32 patalign;
+ u32 pattern[8];
+ u32 xxx8[432];
+ u32 apointx, apointy, apointz;
+ u32 xxx9[1];
+ u32 rpointx, rpointy, rpointz;
+ u32 xxx10[5];
+ u32 pointr, pointg, pointb, pointa;
+ u32 alinex, aliney, alinez;
+ u32 xxx11[1];
+ u32 rlinex, rliney, rlinez;
+ u32 xxx12[5];
+ u32 liner, lineg, lineb, linea;
+ u32 atrix, atriy, atriz;
+ u32 xxx13[1];
+ u32 rtrix, rtriy, rtriz;
+ u32 xxx14[5];
+ u32 trir, trig, trib, tria;
+ u32 aquadx, aquady, aquadz;
+ u32 xxx15[1];
+ u32 rquadx, rquady, rquadz;
+ u32 xxx16[5];
+ u32 quadr, quadg, quadb, quada;
+ u32 arectx, arecty, arectz;
+ u32 xxx17[1];
+ u32 rrectx, rrecty, rrectz;
+ u32 xxx18[5];
+ u32 rectr, rectg, rectb, recta;
};
struct bt_regs {
- volatile u32 addr;
- volatile u32 color_map;
- volatile u32 control;
- volatile u32 cursor;
+ u32 addr;
+ u32 color_map;
+ u32 control;
+ u32 cursor;
};
struct cg6_par {
@@ -255,15 +255,14 @@ struct cg6_par {
struct cg6_fbc __iomem *fbc;
struct cg6_thc __iomem *thc;
struct cg6_tec __iomem *tec;
- volatile u32 __iomem *fhc;
+ u32 __iomem *fhc;
u32 flags;
#define CG6_FLAG_BLANKED 0x00000001
unsigned long physbase;
+ unsigned long which_io;
unsigned long fbsize;
-
- struct sbus_dev *sdev;
};
static int cg6_sync(struct fb_info *info)
@@ -529,8 +528,7 @@ static int cg6_mmap(struct fb_info *info, struct vm_area_struct *vma)
return sbusfb_mmap_helper(cg6_mmap_map,
par->physbase, par->fbsize,
- par->sdev->reg_addrs[0].which_io,
- vma);
+ par->which_io, vma);
}
static int cg6_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
@@ -658,62 +656,75 @@ static void cg6_chip_init(struct fb_info *info)
struct all_info {
struct fb_info info;
struct cg6_par par;
- struct list_head list;
};
-static LIST_HEAD(cg6_list);
-static void cg6_init_one(struct sbus_dev *sdev)
+static void cg6_unmap_regs(struct all_info *all)
{
- struct all_info *all;
- int linebytes;
+ if (all->par.fbc)
+ of_iounmap(all->par.fbc, 4096);
+ if (all->par.tec)
+ of_iounmap(all->par.tec, sizeof(struct cg6_tec));
+ if (all->par.thc)
+ of_iounmap(all->par.thc, sizeof(struct cg6_thc));
+ if (all->par.bt)
+ of_iounmap(all->par.bt, sizeof(struct bt_regs));
+ if (all->par.fhc)
+ of_iounmap(all->par.fhc, sizeof(u32));
+
+ if (all->info.screen_base)
+ of_iounmap(all->info.screen_base, all->par.fbsize);
+}
- all = kmalloc(sizeof(*all), GFP_KERNEL);
- if (!all) {
- printk(KERN_ERR "cg6: Cannot allocate memory.\n");
- return;
- }
- memset(all, 0, sizeof(*all));
+static int __devinit cg6_init_one(struct of_device *op)
+{
+ struct device_node *dp = op->node;
+ struct all_info *all;
+ int linebytes, err;
- INIT_LIST_HEAD(&all->list);
+ all = kzalloc(sizeof(*all), GFP_KERNEL);
+ if (!all)
+ return -ENOMEM;
spin_lock_init(&all->par.lock);
- all->par.sdev = sdev;
- all->par.physbase = sdev->reg_addrs[0].phys_addr;
+ all->par.physbase = op->resource[0].start;
+ all->par.which_io = op->resource[0].flags & IORESOURCE_BITS;
- sbusfb_fill_var(&all->info.var, sdev->prom_node, 8);
+ sbusfb_fill_var(&all->info.var, dp->node, 8);
all->info.var.red.length = 8;
all->info.var.green.length = 8;
all->info.var.blue.length = 8;
- linebytes = prom_getintdefault(sdev->prom_node, "linebytes",
- all->info.var.xres);
+ linebytes = of_getintprop_default(dp, "linebytes",
+ all->info.var.xres);
all->par.fbsize = PAGE_ALIGN(linebytes * all->info.var.yres);
- if (prom_getbool(sdev->prom_node, "dblbuf"))
+ if (of_find_property(dp, "dblbuf", NULL))
all->par.fbsize *= 4;
- all->par.fbc = sbus_ioremap(&sdev->resource[0], CG6_FBC_OFFSET,
- 4096, "cgsix fbc");
- all->par.tec = sbus_ioremap(&sdev->resource[0], CG6_TEC_OFFSET,
- sizeof(struct cg6_tec), "cgsix tec");
- all->par.thc = sbus_ioremap(&sdev->resource[0], CG6_THC_OFFSET,
- sizeof(struct cg6_thc), "cgsix thc");
- all->par.bt = sbus_ioremap(&sdev->resource[0], CG6_BROOKTREE_OFFSET,
- sizeof(struct bt_regs), "cgsix dac");
- all->par.fhc = sbus_ioremap(&sdev->resource[0], CG6_FHC_OFFSET,
- sizeof(u32), "cgsix fhc");
+ all->par.fbc = of_ioremap(&op->resource[0], CG6_FBC_OFFSET,
+ 4096, "cgsix fbc");
+ all->par.tec = of_ioremap(&op->resource[0], CG6_TEC_OFFSET,
+ sizeof(struct cg6_tec), "cgsix tec");
+ all->par.thc = of_ioremap(&op->resource[0], CG6_THC_OFFSET,
+ sizeof(struct cg6_thc), "cgsix thc");
+ all->par.bt = of_ioremap(&op->resource[0], CG6_BROOKTREE_OFFSET,
+ sizeof(struct bt_regs), "cgsix dac");
+ all->par.fhc = of_ioremap(&op->resource[0], CG6_FHC_OFFSET,
+ sizeof(u32), "cgsix fhc");
all->info.flags = FBINFO_DEFAULT | FBINFO_HWACCEL_IMAGEBLIT |
FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT;
all->info.fbops = &cg6_ops;
-#ifdef CONFIG_SPARC32
- all->info.screen_base = (char __iomem *)
- prom_getintdefault(sdev->prom_node, "address", 0);
-#endif
- if (!all->info.screen_base)
- all->info.screen_base =
- sbus_ioremap(&sdev->resource[0], CG6_RAM_OFFSET,
- all->par.fbsize, "cgsix ram");
+
+ all->info.screen_base = of_ioremap(&op->resource[0], CG6_RAM_OFFSET,
+ all->par.fbsize, "cgsix ram");
+ if (!all->par.fbc || !all->par.tec || !all->par.thc ||
+ !all->par.bt || !all->par.fhc || !all->info.screen_base) {
+ cg6_unmap_regs(all);
+ kfree(all);
+ return -ENOMEM;
+ }
+
all->info.par = &all->par;
all->info.var.accel_flags = FB_ACCELF_TEXT;
@@ -723,72 +734,90 @@ static void cg6_init_one(struct sbus_dev *sdev)
cg6_blank(0, &all->info);
if (fb_alloc_cmap(&all->info.cmap, 256, 0)) {
- printk(KERN_ERR "cg6: Could not allocate color map.\n");
+ cg6_unmap_regs(all);
kfree(all);
- return;
+ return -ENOMEM;
}
fb_set_cmap(&all->info.cmap, &all->info);
cg6_init_fix(&all->info, linebytes);
- if (register_framebuffer(&all->info) < 0) {
- printk(KERN_ERR "cg6: Could not register framebuffer.\n");
+ err = register_framebuffer(&all->info);
+ if (err < 0) {
+ cg6_unmap_regs(all);
fb_dealloc_cmap(&all->info.cmap);
kfree(all);
- return;
+ return err;
}
- list_add(&all->list, &cg6_list);
+ dev_set_drvdata(&op->dev, all);
- printk("cg6: CGsix [%s] at %lx:%lx\n",
+ printk("%s: CGsix [%s] at %lx:%lx\n",
+ dp->full_name,
all->info.fix.id,
- (long) sdev->reg_addrs[0].which_io,
- (long) sdev->reg_addrs[0].phys_addr);
+ all->par.which_io, all->par.physbase);
+
+ return 0;
}
-int __init cg6_init(void)
+static int __devinit cg6_probe(struct of_device *dev, const struct of_device_id *match)
{
- struct sbus_bus *sbus;
- struct sbus_dev *sdev;
+ struct of_device *op = to_of_device(&dev->dev);
- if (fb_get_options("cg6fb", NULL))
- return -ENODEV;
+ return cg6_init_one(op);
+}
- for_all_sbusdev(sdev, sbus) {
- if (!strcmp(sdev->prom_name, "cgsix") ||
- !strcmp(sdev->prom_name, "cgthree+"))
- cg6_init_one(sdev);
- }
+static int __devexit cg6_remove(struct of_device *dev)
+{
+ struct all_info *all = dev_get_drvdata(&dev->dev);
+
+ unregister_framebuffer(&all->info);
+ fb_dealloc_cmap(&all->info.cmap);
+
+ cg6_unmap_regs(all);
+
+ kfree(all);
+
+ dev_set_drvdata(&dev->dev, NULL);
return 0;
}
-void __exit cg6_exit(void)
-{
- struct list_head *pos, *tmp;
+static struct of_device_id cg6_match[] = {
+ {
+ .name = "cgsix",
+ },
+ {
+ .name = "cgthree+",
+ },
+ {},
+};
+MODULE_DEVICE_TABLE(of, cg6_match);
- list_for_each_safe(pos, tmp, &cg6_list) {
- struct all_info *all = list_entry(pos, typeof(*all), list);
+static struct of_platform_driver cg6_driver = {
+ .name = "cg6",
+ .match_table = cg6_match,
+ .probe = cg6_probe,
+ .remove = __devexit_p(cg6_remove),
+};
- unregister_framebuffer(&all->info);
- fb_dealloc_cmap(&all->info.cmap);
- kfree(all);
- }
+static int __init cg6_init(void)
+{
+ if (fb_get_options("cg6fb", NULL))
+ return -ENODEV;
+
+ return of_register_driver(&cg6_driver, &of_bus_type);
}
-int __init
-cg6_setup(char *arg)
+static void __exit cg6_exit(void)
{
- /* No cmdline options yet... */
- return 0;
+ of_unregister_driver(&cg6_driver);
}
module_init(cg6_init);
-
-#ifdef MODULE
module_exit(cg6_exit);
-#endif
MODULE_DESCRIPTION("framebuffer driver for CGsix chipsets");
-MODULE_AUTHOR("David S. Miller <davem@redhat.com>");
+MODULE_AUTHOR("David S. Miller <davem@davemloft.net>");
+MODULE_VERSION("2.0");
MODULE_LICENSE("GPL");
diff --git a/drivers/video/ffb.c b/drivers/video/ffb.c
index 7633e41adda1..2a0e8210d398 100644
--- a/drivers/video/ffb.c
+++ b/drivers/video/ffb.c
@@ -1,6 +1,6 @@
/* ffb.c: Creator/Elite3D frame buffer driver
*
- * Copyright (C) 2003 David S. Miller (davem@redhat.com)
+ * Copyright (C) 2003, 2006 David S. Miller (davem@davemloft.net)
* Copyright (C) 1997,1998,1999 Jakub Jelinek (jj@ultra.linux.cz)
*
* Driver layout based loosely on tgafb.c, see that file for credits.
@@ -19,7 +19,8 @@
#include <asm/io.h>
#include <asm/upa.h>
-#include <asm/oplib.h>
+#include <asm/prom.h>
+#include <asm/of_device.h>
#include <asm/fbio.h>
#include "sbuslib.h"
@@ -184,161 +185,161 @@ static struct fb_ops ffb_ops = {
struct ffb_fbc {
/* Next vertex registers */
- u32 xxx1[3];
- volatile u32 alpha;
- volatile u32 red;
- volatile u32 green;
- volatile u32 blue;
- volatile u32 depth;
- volatile u32 y;
- volatile u32 x;
- u32 xxx2[2];
- volatile u32 ryf;
- volatile u32 rxf;
- u32 xxx3[2];
+ u32 xxx1[3];
+ u32 alpha;
+ u32 red;
+ u32 green;
+ u32 blue;
+ u32 depth;
+ u32 y;
+ u32 x;
+ u32 xxx2[2];
+ u32 ryf;
+ u32 rxf;
+ u32 xxx3[2];
- volatile u32 dmyf;
- volatile u32 dmxf;
- u32 xxx4[2];
- volatile u32 ebyi;
- volatile u32 ebxi;
- u32 xxx5[2];
- volatile u32 by;
- volatile u32 bx;
- u32 dy;
- u32 dx;
- volatile u32 bh;
- volatile u32 bw;
- u32 xxx6[2];
+ u32 dmyf;
+ u32 dmxf;
+ u32 xxx4[2];
+ u32 ebyi;
+ u32 ebxi;
+ u32 xxx5[2];
+ u32 by;
+ u32 bx;
+ u32 dy;
+ u32 dx;
+ u32 bh;
+ u32 bw;
+ u32 xxx6[2];
- u32 xxx7[32];
+ u32 xxx7[32];
/* Setup unit vertex state register */
- volatile u32 suvtx;
- u32 xxx8[63];
+ u32 suvtx;
+ u32 xxx8[63];
/* Control registers */
- volatile u32 ppc;
- volatile u32 wid;
- volatile u32 fg;
- volatile u32 bg;
- volatile u32 consty;
- volatile u32 constz;
- volatile u32 xclip;
- volatile u32 dcss;
- volatile u32 vclipmin;
- volatile u32 vclipmax;
- volatile u32 vclipzmin;
- volatile u32 vclipzmax;
- volatile u32 dcsf;
- volatile u32 dcsb;
- volatile u32 dczf;
- volatile u32 dczb;
+ u32 ppc;
+ u32 wid;
+ u32 fg;
+ u32 bg;
+ u32 consty;
+ u32 constz;
+ u32 xclip;
+ u32 dcss;
+ u32 vclipmin;
+ u32 vclipmax;
+ u32 vclipzmin;
+ u32 vclipzmax;
+ u32 dcsf;
+ u32 dcsb;
+ u32 dczf;
+ u32 dczb;
- u32 xxx9;
- volatile u32 blendc;
- volatile u32 blendc1;
- volatile u32 blendc2;
- volatile u32 fbramitc;
- volatile u32 fbc;
- volatile u32 rop;
- volatile u32 cmp;
- volatile u32 matchab;
- volatile u32 matchc;
- volatile u32 magnab;
- volatile u32 magnc;
- volatile u32 fbcfg0;
- volatile u32 fbcfg1;
- volatile u32 fbcfg2;
- volatile u32 fbcfg3;
+ u32 xxx9;
+ u32 blendc;
+ u32 blendc1;
+ u32 blendc2;
+ u32 fbramitc;
+ u32 fbc;
+ u32 rop;
+ u32 cmp;
+ u32 matchab;
+ u32 matchc;
+ u32 magnab;
+ u32 magnc;
+ u32 fbcfg0;
+ u32 fbcfg1;
+ u32 fbcfg2;
+ u32 fbcfg3;
- u32 ppcfg;
- volatile u32 pick;
- volatile u32 fillmode;
- volatile u32 fbramwac;
- volatile u32 pmask;
- volatile u32 xpmask;
- volatile u32 ypmask;
- volatile u32 zpmask;
- volatile u32 clip0min;
- volatile u32 clip0max;
- volatile u32 clip1min;
- volatile u32 clip1max;
- volatile u32 clip2min;
- volatile u32 clip2max;
- volatile u32 clip3min;
- volatile u32 clip3max;
+ u32 ppcfg;
+ u32 pick;
+ u32 fillmode;
+ u32 fbramwac;
+ u32 pmask;
+ u32 xpmask;
+ u32 ypmask;
+ u32 zpmask;
+ u32 clip0min;
+ u32 clip0max;
+ u32 clip1min;
+ u32 clip1max;
+ u32 clip2min;
+ u32 clip2max;
+ u32 clip3min;
+ u32 clip3max;
/* New 3dRAM III support regs */
- volatile u32 rawblend2;
- volatile u32 rawpreblend;
- volatile u32 rawstencil;
- volatile u32 rawstencilctl;
- volatile u32 threedram1;
- volatile u32 threedram2;
- volatile u32 passin;
- volatile u32 rawclrdepth;
- volatile u32 rawpmask;
- volatile u32 rawcsrc;
- volatile u32 rawmatch;
- volatile u32 rawmagn;
- volatile u32 rawropblend;
- volatile u32 rawcmp;
- volatile u32 rawwac;
- volatile u32 fbramid;
+ u32 rawblend2;
+ u32 rawpreblend;
+ u32 rawstencil;
+ u32 rawstencilctl;
+ u32 threedram1;
+ u32 threedram2;
+ u32 passin;
+ u32 rawclrdepth;
+ u32 rawpmask;
+ u32 rawcsrc;
+ u32 rawmatch;
+ u32 rawmagn;
+ u32 rawropblend;
+ u32 rawcmp;
+ u32 rawwac;
+ u32 fbramid;
- volatile u32 drawop;
- u32 xxx10[2];
- volatile u32 fontlpat;
- u32 xxx11;
- volatile u32 fontxy;
- volatile u32 fontw;
- volatile u32 fontinc;
- volatile u32 font;
- u32 xxx12[3];
- volatile u32 blend2;
- volatile u32 preblend;
- volatile u32 stencil;
- volatile u32 stencilctl;
-
- u32 xxx13[4];
- volatile u32 dcss1;
- volatile u32 dcss2;
- volatile u32 dcss3;
- volatile u32 widpmask;
- volatile u32 dcs2;
- volatile u32 dcs3;
- volatile u32 dcs4;
- u32 xxx14;
- volatile u32 dcd2;
- volatile u32 dcd3;
- volatile u32 dcd4;
- u32 xxx15;
+ u32 drawop;
+ u32 xxx10[2];
+ u32 fontlpat;
+ u32 xxx11;
+ u32 fontxy;
+ u32 fontw;
+ u32 fontinc;
+ u32 font;
+ u32 xxx12[3];
+ u32 blend2;
+ u32 preblend;
+ u32 stencil;
+ u32 stencilctl;
+
+ u32 xxx13[4];
+ u32 dcss1;
+ u32 dcss2;
+ u32 dcss3;
+ u32 widpmask;
+ u32 dcs2;
+ u32 dcs3;
+ u32 dcs4;
+ u32 xxx14;
+ u32 dcd2;
+ u32 dcd3;
+ u32 dcd4;
+ u32 xxx15;
- volatile u32 pattern[32];
+ u32 pattern[32];
- u32 xxx16[256];
+ u32 xxx16[256];
- volatile u32 devid;
- u32 xxx17[63];
+ u32 devid;
+ u32 xxx17[63];
- volatile u32 ucsr;
- u32 xxx18[31];
+ u32 ucsr;
+ u32 xxx18[31];
- volatile u32 mer;
+ u32 mer;
};
struct ffb_dac {
- volatile u32 type;
- volatile u32 value;
- volatile u32 type2;
- volatile u32 value2;
+ u32 type;
+ u32 value;
+ u32 type2;
+ u32 value2;
};
struct ffb_par {
spinlock_t lock;
- struct ffb_fbc *fbc;
- struct ffb_dac *dac;
+ struct ffb_fbc __iomem *fbc;
+ struct ffb_dac __iomem *dac;
u32 flags;
#define FFB_FLAG_AFB 0x00000001
@@ -353,16 +354,13 @@ struct ffb_par {
unsigned long physbase;
unsigned long fbsize;
- char name[64];
- int prom_node;
- int prom_parent_node;
int dac_rev;
int board_type;
};
static void FFBFifo(struct ffb_par *par, int n)
{
- struct ffb_fbc *fbc;
+ struct ffb_fbc __iomem *fbc;
int cache = par->fifo_cache;
if (cache - n < 0) {
@@ -375,7 +373,7 @@ static void FFBFifo(struct ffb_par *par, int n)
static void FFBWait(struct ffb_par *par)
{
- struct ffb_fbc *fbc;
+ struct ffb_fbc __iomem *fbc;
int limit = 10000;
fbc = par->fbc;
@@ -408,8 +406,8 @@ static __inline__ void ffb_rop(struct ffb_par *par, u32 rop)
static void ffb_switch_from_graph(struct ffb_par *par)
{
- struct ffb_fbc *fbc = par->fbc;
- struct ffb_dac *dac = par->dac;
+ struct ffb_fbc __iomem *fbc = par->fbc;
+ struct ffb_dac __iomem *dac = par->dac;
unsigned long flags;
spin_lock_irqsave(&par->lock, flags);
@@ -462,7 +460,7 @@ static int ffb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
static void ffb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
{
struct ffb_par *par = (struct ffb_par *) info->par;
- struct ffb_fbc *fbc = par->fbc;
+ struct ffb_fbc __iomem *fbc = par->fbc;
unsigned long flags;
u32 fg;
@@ -505,7 +503,7 @@ static void
ffb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
{
struct ffb_par *par = (struct ffb_par *) info->par;
- struct ffb_fbc *fbc = par->fbc;
+ struct ffb_fbc __iomem *fbc = par->fbc;
unsigned long flags;
if (area->dx != area->sx ||
@@ -541,7 +539,7 @@ ffb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
static void ffb_imageblit(struct fb_info *info, const struct fb_image *image)
{
struct ffb_par *par = (struct ffb_par *) info->par;
- struct ffb_fbc *fbc = par->fbc;
+ struct ffb_fbc __iomem *fbc = par->fbc;
const u8 *data = image->data;
unsigned long flags;
u32 fg, bg, xy;
@@ -664,7 +662,7 @@ static int
ffb_blank(int blank, struct fb_info *info)
{
struct ffb_par *par = (struct ffb_par *) info->par;
- struct ffb_dac *dac = par->dac;
+ struct ffb_dac __iomem *dac = par->dac;
unsigned long flags;
u32 tmp;
@@ -883,78 +881,42 @@ ffb_init_fix(struct fb_info *info)
info->fix.accel = FB_ACCEL_SUN_CREATOR;
}
-static int ffb_apply_upa_parent_ranges(int parent,
- struct linux_prom64_registers *regs)
-{
- struct linux_prom64_ranges ranges[PROMREG_MAX];
- char name[128];
- int len, i;
-
- prom_getproperty(parent, "name", name, sizeof(name));
- if (strcmp(name, "upa") != 0)
- return 0;
-
- len = prom_getproperty(parent, "ranges", (void *) ranges, sizeof(ranges));
- if (len <= 0)
- return 1;
-
- len /= sizeof(struct linux_prom64_ranges);
- for (i = 0; i < len; i++) {
- struct linux_prom64_ranges *rng = &ranges[i];
- u64 phys_addr = regs->phys_addr;
-
- if (phys_addr >= rng->ot_child_base &&
- phys_addr < (rng->ot_child_base + rng->or_size)) {
- regs->phys_addr -= rng->ot_child_base;
- regs->phys_addr += rng->ot_parent_base;
- return 0;
- }
- }
-
- return 1;
-}
-
struct all_info {
struct fb_info info;
struct ffb_par par;
u32 pseudo_palette[256];
- struct list_head list;
};
-static LIST_HEAD(ffb_list);
-static void ffb_init_one(int node, int parent)
+static int ffb_init_one(struct of_device *op)
{
- struct linux_prom64_registers regs[2*PROMREG_MAX];
- struct ffb_fbc *fbc;
- struct ffb_dac *dac;
+ struct device_node *dp = op->node;
+ struct ffb_fbc __iomem *fbc;
+ struct ffb_dac __iomem *dac;
struct all_info *all;
+ int err;
- if (prom_getproperty(node, "reg", (void *) regs, sizeof(regs)) <= 0) {
- printk("ffb: Cannot get reg device node property.\n");
- return;
- }
+ all = kzalloc(sizeof(*all), GFP_KERNEL);
+ if (!all)
+ return -ENOMEM;
- if (ffb_apply_upa_parent_ranges(parent, &regs[0])) {
- printk("ffb: Cannot apply parent ranges to regs.\n");
- return;
+ spin_lock_init(&all->par.lock);
+ all->par.fbc = of_ioremap(&op->resource[2], 0,
+ sizeof(struct ffb_fbc), "ffb fbc");
+ if (!all->par.fbc) {
+ kfree(all);
+ return -ENOMEM;
}
- all = kmalloc(sizeof(*all), GFP_KERNEL);
- if (!all) {
- printk(KERN_ERR "ffb: Cannot allocate memory.\n");
- return;
+ all->par.dac = of_ioremap(&op->resource[1], 0,
+ sizeof(struct ffb_dac), "ffb dac");
+ if (!all->par.dac) {
+ of_iounmap(all->par.fbc, sizeof(struct ffb_fbc));
+ kfree(all);
+ return -ENOMEM;
}
- memset(all, 0, sizeof(*all));
-
- INIT_LIST_HEAD(&all->list);
- spin_lock_init(&all->par.lock);
- all->par.fbc = (struct ffb_fbc *)(regs[0].phys_addr + FFB_FBC_REGS_POFF);
- all->par.dac = (struct ffb_dac *)(regs[0].phys_addr + FFB_DAC_POFF);
all->par.rop_cache = FFB_ROP_NEW;
- all->par.physbase = regs[0].phys_addr;
- all->par.prom_node = node;
- all->par.prom_parent_node = parent;
+ all->par.physbase = op->resource[0].start;
/* Don't mention copyarea, so SCROLL_REDRAW is always
* used. It is the fastest on this chip.
@@ -968,7 +930,7 @@ static void ffb_init_one(int node, int parent)
all->info.par = &all->par;
all->info.pseudo_palette = all->pseudo_palette;
- sbusfb_fill_var(&all->info.var, all->par.prom_node, 32);
+ sbusfb_fill_var(&all->info.var, dp->node, 32);
all->par.fbsize = PAGE_ALIGN(all->info.var.xres *
all->info.var.yres *
4);
@@ -976,14 +938,13 @@ static void ffb_init_one(int node, int parent)
all->info.var.accel_flags = FB_ACCELF_TEXT;
- prom_getstring(node, "name", all->par.name, sizeof(all->par.name));
- if (!strcmp(all->par.name, "SUNW,afb"))
+ if (!strcmp(dp->name, "SUNW,afb"))
all->par.flags |= FFB_FLAG_AFB;
- all->par.board_type = prom_getintdefault(node, "board_type", 0);
+ all->par.board_type = of_getintprop_default(dp, "board_type", 0);
fbc = all->par.fbc;
- if((upa_readl(&fbc->ucsr) & FFB_UCSR_ALL_ERRORS) != 0)
+ if ((upa_readl(&fbc->ucsr) & FFB_UCSR_ALL_ERRORS) != 0)
upa_writel(FFB_UCSR_ALL_ERRORS, &fbc->ucsr);
ffb_switch_from_graph(&all->par);
@@ -1008,81 +969,88 @@ static void ffb_init_one(int node, int parent)
if (fb_alloc_cmap(&all->info.cmap, 256, 0)) {
printk(KERN_ERR "ffb: Could not allocate color map.\n");
kfree(all);
- return;
+ return -ENOMEM;
}
ffb_init_fix(&all->info);
- if (register_framebuffer(&all->info) < 0) {
+ err = register_framebuffer(&all->info);
+ if (err < 0) {
printk(KERN_ERR "ffb: Could not register framebuffer.\n");
fb_dealloc_cmap(&all->info.cmap);
kfree(all);
- return;
+ return err;
}
- list_add(&all->list, &ffb_list);
+ dev_set_drvdata(&op->dev, all);
- printk("ffb: %s at %016lx type %d DAC %d\n",
+ printk("%s: %s at %016lx, type %d, DAC revision %d\n",
+ dp->full_name,
((all->par.flags & FFB_FLAG_AFB) ? "AFB" : "FFB"),
- regs[0].phys_addr, all->par.board_type, all->par.dac_rev);
+ all->par.physbase, all->par.board_type, all->par.dac_rev);
+
+ return 0;
}
-static void ffb_scan_siblings(int root)
+static int __devinit ffb_probe(struct of_device *dev, const struct of_device_id *match)
{
- int node, child;
-
- child = prom_getchild(root);
- for (node = prom_searchsiblings(child, "SUNW,ffb"); node;
- node = prom_searchsiblings(prom_getsibling(node), "SUNW,ffb"))
- ffb_init_one(node, root);
- for (node = prom_searchsiblings(child, "SUNW,afb"); node;
- node = prom_searchsiblings(prom_getsibling(node), "SUNW,afb"))
- ffb_init_one(node, root);
+ struct of_device *op = to_of_device(&dev->dev);
+
+ return ffb_init_one(op);
}
-int __init ffb_init(void)
+static int __devexit ffb_remove(struct of_device *dev)
{
- int root;
+ struct all_info *all = dev_get_drvdata(&dev->dev);
- if (fb_get_options("ffb", NULL))
- return -ENODEV;
+ unregister_framebuffer(&all->info);
+ fb_dealloc_cmap(&all->info.cmap);
- ffb_scan_siblings(prom_root_node);
+ of_iounmap(all->par.fbc, sizeof(struct ffb_fbc));
+ of_iounmap(all->par.dac, sizeof(struct ffb_dac));
- root = prom_getchild(prom_root_node);
- for (root = prom_searchsiblings(root, "upa"); root;
- root = prom_searchsiblings(prom_getsibling(root), "upa"))
- ffb_scan_siblings(root);
+ kfree(all);
+
+ dev_set_drvdata(&dev->dev, NULL);
return 0;
}
-void __exit ffb_exit(void)
-{
- struct list_head *pos, *tmp;
+static struct of_device_id ffb_match[] = {
+ {
+ .name = "SUNW,ffb",
+ },
+ {
+ .name = "SUNW,afb",
+ },
+ {},
+};
+MODULE_DEVICE_TABLE(of, ffb_match);
+
+static struct of_platform_driver ffb_driver = {
+ .name = "ffb",
+ .match_table = ffb_match,
+ .probe = ffb_probe,
+ .remove = __devexit_p(ffb_remove),
+};
- list_for_each_safe(pos, tmp, &ffb_list) {
- struct all_info *all = list_entry(pos, typeof(*all), list);
+int __init ffb_init(void)
+{
+ if (fb_get_options("ffb", NULL))
+ return -ENODEV;
- unregister_framebuffer(&all->info);
- fb_dealloc_cmap(&all->info.cmap);
- kfree(all);
- }
+ return of_register_driver(&ffb_driver, &of_bus_type);
}
-int __init
-ffb_setup(char *arg)
+void __exit ffb_exit(void)
{
- /* No cmdline options yet... */
- return 0;
+ of_unregister_driver(&ffb_driver);
}
module_init(ffb_init);
-
-#ifdef MODULE
module_exit(ffb_exit);
-#endif
MODULE_DESCRIPTION("framebuffer driver for Creator/Elite3D chipsets");
-MODULE_AUTHOR("David S. Miller <davem@redhat.com>");
+MODULE_AUTHOR("David S. Miller <davem@davemloft.net>");
+MODULE_VERSION("2.0");
MODULE_LICENSE("GPL");
diff --git a/drivers/video/leo.c b/drivers/video/leo.c
index a23cfdb9d826..f3a24338d9ac 100644
--- a/drivers/video/leo.c
+++ b/drivers/video/leo.c
@@ -1,6 +1,6 @@
/* leo.c: LEO frame buffer driver
*
- * Copyright (C) 2003 David S. Miller (davem@redhat.com)
+ * Copyright (C) 2003, 2006 David S. Miller (davem@davemloft.net)
* Copyright (C) 1996-1999 Jakub Jelinek (jj@ultra.linux.cz)
* Copyright (C) 1997 Michal Rehacek (Michal.Rehacek@st.mff.cuni.cz)
*
@@ -18,8 +18,8 @@
#include <linux/mm.h>
#include <asm/io.h>
-#include <asm/sbus.h>
-#include <asm/oplib.h>
+#include <asm/prom.h>
+#include <asm/of_device.h>
#include <asm/fbio.h>
#include "sbuslib.h"
@@ -80,10 +80,10 @@ static struct fb_ops leo_ops = {
struct leo_cursor {
u8 xxx0[16];
- volatile u32 cur_type;
- volatile u32 cur_misc;
- volatile u32 cur_cursxy;
- volatile u32 cur_data;
+ u32 cur_type;
+ u32 cur_misc;
+ u32 cur_cursxy;
+ u32 cur_data;
};
#define LEO_KRN_TYPE_CLUT0 0x00001000
@@ -99,27 +99,27 @@ struct leo_cursor {
#define LEO_KRN_CSR_UNK2 0x00000001
struct leo_lx_krn {
- volatile u32 krn_type;
- volatile u32 krn_csr;
- volatile u32 krn_value;
+ u32 krn_type;
+ u32 krn_csr;
+ u32 krn_value;
};
struct leo_lc_ss0_krn {
- volatile u32 misc;
+ u32 misc;
u8 xxx0[0x800-4];
- volatile u32 rev;
+ u32 rev;
};
struct leo_lc_ss0_usr {
- volatile u32 csr;
- volatile u32 addrspace;
- volatile u32 fontmsk;
- volatile u32 fontt;
- volatile u32 extent;
- volatile u32 src;
+ u32 csr;
+ u32 addrspace;
+ u32 fontmsk;
+ u32 fontt;
+ u32 extent;
+ u32 src;
u32 dst;
- volatile u32 copy;
- volatile u32 fill;
+ u32 copy;
+ u32 fill;
};
struct leo_lc_ss1_krn {
@@ -132,47 +132,47 @@ struct leo_lc_ss1_usr {
struct leo_ld {
u8 xxx0[0xe00];
- volatile u32 csr;
- volatile u32 wid;
- volatile u32 wmask;
- volatile u32 widclip;
- volatile u32 vclipmin;
- volatile u32 vclipmax;
- volatile u32 pickmin; /* SS1 only */
- volatile u32 pickmax; /* SS1 only */
- volatile u32 fg;
- volatile u32 bg;
- volatile u32 src; /* Copy/Scroll (SS0 only) */
- volatile u32 dst; /* Copy/Scroll/Fill (SS0 only) */
- volatile u32 extent; /* Copy/Scroll/Fill size (SS0 only) */
+ u32 csr;
+ u32 wid;
+ u32 wmask;
+ u32 widclip;
+ u32 vclipmin;
+ u32 vclipmax;
+ u32 pickmin; /* SS1 only */
+ u32 pickmax; /* SS1 only */
+ u32 fg;
+ u32 bg;
+ u32 src; /* Copy/Scroll (SS0 only) */
+ u32 dst; /* Copy/Scroll/Fill (SS0 only) */
+ u32 extent; /* Copy/Scroll/Fill size (SS0 only) */
u32 xxx1[3];
- volatile u32 setsem; /* SS1 only */
- volatile u32 clrsem; /* SS1 only */
- volatile u32 clrpick; /* SS1 only */
- volatile u32 clrdat; /* SS1 only */
- volatile u32 alpha; /* SS1 only */
+ u32 setsem; /* SS1 only */
+ u32 clrsem; /* SS1 only */
+ u32 clrpick; /* SS1 only */
+ u32 clrdat; /* SS1 only */
+ u32 alpha; /* SS1 only */
u8 xxx2[0x2c];
- volatile u32 winbg;
- volatile u32 planemask;
- volatile u32 rop;
- volatile u32 z;
- volatile u32 dczf; /* SS1 only */
- volatile u32 dczb; /* SS1 only */
- volatile u32 dcs; /* SS1 only */
- volatile u32 dczs; /* SS1 only */
- volatile u32 pickfb; /* SS1 only */
- volatile u32 pickbb; /* SS1 only */
- volatile u32 dcfc; /* SS1 only */
- volatile u32 forcecol; /* SS1 only */
- volatile u32 door[8]; /* SS1 only */
- volatile u32 pick[5]; /* SS1 only */
+ u32 winbg;
+ u32 planemask;
+ u32 rop;
+ u32 z;
+ u32 dczf; /* SS1 only */
+ u32 dczb; /* SS1 only */
+ u32 dcs; /* SS1 only */
+ u32 dczs; /* SS1 only */
+ u32 pickfb; /* SS1 only */
+ u32 pickbb; /* SS1 only */
+ u32 dcfc; /* SS1 only */
+ u32 forcecol; /* SS1 only */
+ u32 door[8]; /* SS1 only */
+ u32 pick[5]; /* SS1 only */
};
#define LEO_SS1_MISC_ENABLE 0x00000001
#define LEO_SS1_MISC_STEREO 0x00000002
struct leo_ld_ss1 {
- u8 xxx0[0xef4];
- volatile u32 ss1_misc;
+ u8 xxx0[0xef4];
+ u32 ss1_misc;
};
struct leo_ld_gbl {
@@ -193,9 +193,8 @@ struct leo_par {
#define LEO_FLAG_BLANKED 0x00000001
unsigned long physbase;
+ unsigned long which_io;
unsigned long fbsize;
-
- struct sbus_dev *sdev;
};
static void leo_wait(struct leo_lx_krn __iomem *lx_krn)
@@ -368,8 +367,7 @@ static int leo_mmap(struct fb_info *info, struct vm_area_struct *vma)
return sbusfb_mmap_helper(leo_mmap_map,
par->physbase, par->fbsize,
- par->sdev->reg_addrs[0].which_io,
- vma);
+ par->which_io, vma);
}
static int leo_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
@@ -385,11 +383,9 @@ static int leo_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
*/
static void
-leo_init_fix(struct fb_info *info)
+leo_init_fix(struct fb_info *info, struct device_node *dp)
{
- struct leo_par *par = (struct leo_par *)info->par;
-
- strlcpy(info->fix.id, par->sdev->prom_name, sizeof(info->fix.id));
+ strlcpy(info->fix.id, dp->name, sizeof(info->fix.id));
info->fix.type = FB_TYPE_PACKED_PIXELS;
info->fix.visual = FB_VISUAL_TRUECOLOR;
@@ -532,60 +528,74 @@ static void leo_fixup_var_rgb(struct fb_var_screeninfo *var)
struct all_info {
struct fb_info info;
struct leo_par par;
- struct list_head list;
};
-static LIST_HEAD(leo_list);
-static void leo_init_one(struct sbus_dev *sdev)
+static void leo_unmap_regs(struct all_info *all)
{
- struct all_info *all;
- int linebytes;
+ if (all->par.lc_ss0_usr)
+ of_iounmap(all->par.lc_ss0_usr, 0x1000);
+ if (all->par.ld_ss0)
+ of_iounmap(all->par.ld_ss0, 0x1000);
+ if (all->par.ld_ss1)
+ of_iounmap(all->par.ld_ss1, 0x1000);
+ if (all->par.lx_krn)
+ of_iounmap(all->par.lx_krn, 0x1000);
+ if (all->par.cursor)
+ of_iounmap(all->par.cursor, sizeof(struct leo_cursor));
+ if (all->info.screen_base)
+ of_iounmap(all->info.screen_base, 0x800000);
+}
- all = kmalloc(sizeof(*all), GFP_KERNEL);
- if (!all) {
- printk(KERN_ERR "leo: Cannot allocate memory.\n");
- return;
- }
- memset(all, 0, sizeof(*all));
+static int __devinit leo_init_one(struct of_device *op)
+{
+ struct device_node *dp = op->node;
+ struct all_info *all;
+ int linebytes, err;
- INIT_LIST_HEAD(&all->list);
+ all = kzalloc(sizeof(*all), GFP_KERNEL);
+ if (!all)
+ return -ENOMEM;
spin_lock_init(&all->par.lock);
- all->par.sdev = sdev;
- all->par.physbase = sdev->reg_addrs[0].phys_addr;
+ all->par.physbase = op->resource[0].start;
+ all->par.which_io = op->resource[0].flags & IORESOURCE_BITS;
- sbusfb_fill_var(&all->info.var, sdev->prom_node, 32);
+ sbusfb_fill_var(&all->info.var, dp->node, 32);
leo_fixup_var_rgb(&all->info.var);
- linebytes = prom_getintdefault(sdev->prom_node, "linebytes",
- all->info.var.xres);
+ linebytes = of_getintprop_default(dp, "linebytes",
+ all->info.var.xres);
all->par.fbsize = PAGE_ALIGN(linebytes * all->info.var.yres);
-#ifdef CONFIG_SPARC32
- all->info.screen_base = (char __iomem *)
- prom_getintdefault(sdev->prom_node, "address", 0);
-#endif
- if (!all->info.screen_base)
- all->info.screen_base =
- sbus_ioremap(&sdev->resource[0], LEO_OFF_SS0,
- 0x800000, "leo ram");
-
all->par.lc_ss0_usr =
- sbus_ioremap(&sdev->resource[0], LEO_OFF_LC_SS0_USR,
- 0x1000, "leolc ss0usr");
+ of_ioremap(&op->resource[0], LEO_OFF_LC_SS0_USR,
+ 0x1000, "leolc ss0usr");
all->par.ld_ss0 =
- sbus_ioremap(&sdev->resource[0], LEO_OFF_LD_SS0,
- 0x1000, "leold ss0");
+ of_ioremap(&op->resource[0], LEO_OFF_LD_SS0,
+ 0x1000, "leold ss0");
all->par.ld_ss1 =
- sbus_ioremap(&sdev->resource[0], LEO_OFF_LD_SS1,
- 0x1000, "leold ss1");
+ of_ioremap(&op->resource[0], LEO_OFF_LD_SS1,
+ 0x1000, "leold ss1");
all->par.lx_krn =
- sbus_ioremap(&sdev->resource[0], LEO_OFF_LX_KRN,
- 0x1000, "leolx krn");
+ of_ioremap(&op->resource[0], LEO_OFF_LX_KRN,
+ 0x1000, "leolx krn");
all->par.cursor =
- sbus_ioremap(&sdev->resource[0], LEO_OFF_LX_CURSOR,
- sizeof(struct leo_cursor), "leolx cursor");
+ of_ioremap(&op->resource[0], LEO_OFF_LX_CURSOR,
+ sizeof(struct leo_cursor), "leolx cursor");
+ all->info.screen_base =
+ of_ioremap(&op->resource[0], LEO_OFF_SS0,
+ 0x800000, "leo ram");
+ if (!all->par.lc_ss0_usr ||
+ !all->par.ld_ss0 ||
+ !all->par.ld_ss1 ||
+ !all->par.lx_krn ||
+ !all->par.cursor ||
+ !all->info.screen_base) {
+ leo_unmap_regs(all);
+ kfree(all);
+ return -ENOMEM;
+ }
all->info.flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
all->info.fbops = &leo_ops;
@@ -597,69 +607,85 @@ static void leo_init_one(struct sbus_dev *sdev)
leo_blank(0, &all->info);
if (fb_alloc_cmap(&all->info.cmap, 256, 0)) {
- printk(KERN_ERR "leo: Could not allocate color map.\n");
+ leo_unmap_regs(all);
kfree(all);
- return;
+ return -ENOMEM;;
}
- leo_init_fix(&all->info);
+ leo_init_fix(&all->info, dp);
- if (register_framebuffer(&all->info) < 0) {
- printk(KERN_ERR "leo: Could not register framebuffer.\n");
+ err = register_framebuffer(&all->info);
+ if (err < 0) {
fb_dealloc_cmap(&all->info.cmap);
+ leo_unmap_regs(all);
kfree(all);
- return;
+ return err;
}
- list_add(&all->list, &leo_list);
+ dev_set_drvdata(&op->dev, all);
+
+ printk("%s: leo at %lx:%lx\n",
+ dp->full_name,
+ all->par.which_io, all->par.physbase);
- printk("leo: %s at %lx:%lx\n",
- sdev->prom_name,
- (long) sdev->reg_addrs[0].which_io,
- (long) sdev->reg_addrs[0].phys_addr);
+ return 0;
}
-int __init leo_init(void)
+static int __devinit leo_probe(struct of_device *dev, const struct of_device_id *match)
{
- struct sbus_bus *sbus;
- struct sbus_dev *sdev;
+ struct of_device *op = to_of_device(&dev->dev);
- if (fb_get_options("leofb", NULL))
- return -ENODEV;
+ return leo_init_one(op);
+}
- for_all_sbusdev(sdev, sbus) {
- if (!strcmp(sdev->prom_name, "leo"))
- leo_init_one(sdev);
- }
+static int __devexit leo_remove(struct of_device *dev)
+{
+ struct all_info *all = dev_get_drvdata(&dev->dev);
+
+ unregister_framebuffer(&all->info);
+ fb_dealloc_cmap(&all->info.cmap);
+
+ leo_unmap_regs(all);
+
+ kfree(all);
+
+ dev_set_drvdata(&dev->dev, NULL);
return 0;
}
-void __exit leo_exit(void)
-{
- struct list_head *pos, *tmp;
+static struct of_device_id leo_match[] = {
+ {
+ .name = "leo",
+ },
+ {},
+};
+MODULE_DEVICE_TABLE(of, leo_match);
+
+static struct of_platform_driver leo_driver = {
+ .name = "leo",
+ .match_table = leo_match,
+ .probe = leo_probe,
+ .remove = __devexit_p(leo_remove),
+};
- list_for_each_safe(pos, tmp, &leo_list) {
- struct all_info *all = list_entry(pos, typeof(*all), list);
+static int __init leo_init(void)
+{
+ if (fb_get_options("leofb", NULL))
+ return -ENODEV;
- unregister_framebuffer(&all->info);
- fb_dealloc_cmap(&all->info.cmap);
- kfree(all);
- }
+ return of_register_driver(&leo_driver, &of_bus_type);
}
-int __init
-leo_setup(char *arg)
+static void __exit leo_exit(void)
{
- /* No cmdline options yet... */
- return 0;
+ of_unregister_driver(&leo_driver);
}
module_init(leo_init);
-#ifdef MODULE
module_exit(leo_exit);
-#endif
MODULE_DESCRIPTION("framebuffer driver for LEO chipsets");
-MODULE_AUTHOR("David S. Miller <davem@redhat.com>");
+MODULE_AUTHOR("David S. Miller <davem@davemloft.net>");
+MODULE_VERSION("2.0");
MODULE_LICENSE("GPL");
diff --git a/drivers/video/p9100.c b/drivers/video/p9100.c
index 0d1957505359..56ac51d6a7f3 100644
--- a/drivers/video/p9100.c
+++ b/drivers/video/p9100.c
@@ -1,6 +1,6 @@
/* p9100.c: P9100 frame buffer driver
*
- * Copyright (C) 2003 David S. Miller (davem@redhat.com)
+ * Copyright (C) 2003, 2006 David S. Miller (davem@davemloft.net)
* Copyright 1999 Derrick J Brashear (shadow@dementia.org)
*
* Driver layout based loosely on tgafb.c, see that file for credits.
@@ -17,8 +17,8 @@
#include <linux/mm.h>
#include <asm/io.h>
-#include <asm/sbus.h>
-#include <asm/oplib.h>
+#include <asm/prom.h>
+#include <asm/of_device.h>
#include <asm/fbio.h>
#include "sbuslib.h"
@@ -72,60 +72,60 @@ static struct fb_ops p9100_ops = {
struct p9100_regs {
/* Registers for the system control */
- volatile u32 sys_base;
- volatile u32 sys_config;
- volatile u32 sys_intr;
- volatile u32 sys_int_ena;
- volatile u32 sys_alt_rd;
- volatile u32 sys_alt_wr;
- volatile u32 sys_xxx[58];
+ u32 sys_base;
+ u32 sys_config;
+ u32 sys_intr;
+ u32 sys_int_ena;
+ u32 sys_alt_rd;
+ u32 sys_alt_wr;
+ u32 sys_xxx[58];
/* Registers for the video control */
- volatile u32 vid_base;
- volatile u32 vid_hcnt;
- volatile u32 vid_htotal;
- volatile u32 vid_hsync_rise;
- volatile u32 vid_hblank_rise;
- volatile u32 vid_hblank_fall;
- volatile u32 vid_hcnt_preload;
- volatile u32 vid_vcnt;
- volatile u32 vid_vlen;
- volatile u32 vid_vsync_rise;
- volatile u32 vid_vblank_rise;
- volatile u32 vid_vblank_fall;
- volatile u32 vid_vcnt_preload;
- volatile u32 vid_screenpaint_addr;
- volatile u32 vid_screenpaint_timectl1;
- volatile u32 vid_screenpaint_qsfcnt;
- volatile u32 vid_screenpaint_timectl2;
- volatile u32 vid_xxx[15];
+ u32 vid_base;
+ u32 vid_hcnt;
+ u32 vid_htotal;
+ u32 vid_hsync_rise;
+ u32 vid_hblank_rise;
+ u32 vid_hblank_fall;
+ u32 vid_hcnt_preload;
+ u32 vid_vcnt;
+ u32 vid_vlen;
+ u32 vid_vsync_rise;
+ u32 vid_vblank_rise;
+ u32 vid_vblank_fall;
+ u32 vid_vcnt_preload;
+ u32 vid_screenpaint_addr;
+ u32 vid_screenpaint_timectl1;
+ u32 vid_screenpaint_qsfcnt;
+ u32 vid_screenpaint_timectl2;
+ u32 vid_xxx[15];
/* Registers for the video control */
- volatile u32 vram_base;
- volatile u32 vram_memcfg;
- volatile u32 vram_refresh_pd;
- volatile u32 vram_refresh_cnt;
- volatile u32 vram_raslo_max;
- volatile u32 vram_raslo_cur;
- volatile u32 pwrup_cfg;
- volatile u32 vram_xxx[25];
+ u32 vram_base;
+ u32 vram_memcfg;
+ u32 vram_refresh_pd;
+ u32 vram_refresh_cnt;
+ u32 vram_raslo_max;
+ u32 vram_raslo_cur;
+ u32 pwrup_cfg;
+ u32 vram_xxx[25];
/* Registers for IBM RGB528 Palette */
- volatile u32 ramdac_cmap_wridx;
- volatile u32 ramdac_palette_data;
- volatile u32 ramdac_pixel_mask;
- volatile u32 ramdac_palette_rdaddr;
- volatile u32 ramdac_idx_lo;
- volatile u32 ramdac_idx_hi;
- volatile u32 ramdac_idx_data;
- volatile u32 ramdac_idx_ctl;
- volatile u32 ramdac_xxx[1784];
+ u32 ramdac_cmap_wridx;
+ u32 ramdac_palette_data;
+ u32 ramdac_pixel_mask;
+ u32 ramdac_palette_rdaddr;
+ u32 ramdac_idx_lo;
+ u32 ramdac_idx_hi;
+ u32 ramdac_idx_data;
+ u32 ramdac_idx_ctl;
+ u32 ramdac_xxx[1784];
};
struct p9100_cmd_parameng {
- volatile u32 parameng_status;
- volatile u32 parameng_bltcmd;
- volatile u32 parameng_quadcmd;
+ u32 parameng_status;
+ u32 parameng_bltcmd;
+ u32 parameng_quadcmd;
};
struct p9100_par {
@@ -136,9 +136,8 @@ struct p9100_par {
#define P9100_FLAG_BLANKED 0x00000001
unsigned long physbase;
+ unsigned long which_io;
unsigned long fbsize;
-
- struct sbus_dev *sdev;
};
/**
@@ -227,8 +226,7 @@ static int p9100_mmap(struct fb_info *info, struct vm_area_struct *vma)
return sbusfb_mmap_helper(p9100_mmap_map,
par->physbase, par->fbsize,
- par->sdev->reg_addrs[0].which_io,
- vma);
+ par->which_io, vma);
}
static int p9100_ioctl(struct fb_info *info, unsigned int cmd,
@@ -245,12 +243,9 @@ static int p9100_ioctl(struct fb_info *info, unsigned int cmd,
* Initialisation
*/
-static void
-p9100_init_fix(struct fb_info *info, int linebytes)
+static void p9100_init_fix(struct fb_info *info, int linebytes, struct device_node *dp)
{
- struct p9100_par *par = (struct p9100_par *)info->par;
-
- strlcpy(info->fix.id, par->sdev->prom_name, sizeof(info->fix.id));
+ strlcpy(info->fix.id, dp->name, sizeof(info->fix.id));
info->fix.type = FB_TYPE_PACKED_PIXELS;
info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
@@ -263,121 +258,137 @@ p9100_init_fix(struct fb_info *info, int linebytes)
struct all_info {
struct fb_info info;
struct p9100_par par;
- struct list_head list;
};
-static LIST_HEAD(p9100_list);
-static void p9100_init_one(struct sbus_dev *sdev)
+static int __devinit p9100_init_one(struct of_device *op)
{
+ struct device_node *dp = op->node;
struct all_info *all;
- int linebytes;
-
- all = kmalloc(sizeof(*all), GFP_KERNEL);
- if (!all) {
- printk(KERN_ERR "p9100: Cannot allocate memory.\n");
- return;
- }
- memset(all, 0, sizeof(*all));
+ int linebytes, err;
- INIT_LIST_HEAD(&all->list);
+ all = kzalloc(sizeof(*all), GFP_KERNEL);
+ if (!all)
+ return -ENOMEM;
spin_lock_init(&all->par.lock);
- all->par.sdev = sdev;
/* This is the framebuffer and the only resource apps can mmap. */
- all->par.physbase = sdev->reg_addrs[2].phys_addr;
+ all->par.physbase = op->resource[2].start;
+ all->par.which_io = op->resource[2].flags & IORESOURCE_BITS;
- sbusfb_fill_var(&all->info.var, sdev->prom_node, 8);
+ sbusfb_fill_var(&all->info.var, dp->node, 8);
all->info.var.red.length = 8;
all->info.var.green.length = 8;
all->info.var.blue.length = 8;
- linebytes = prom_getintdefault(sdev->prom_node, "linebytes",
- all->info.var.xres);
+ linebytes = of_getintprop_default(dp, "linebytes",
+ all->info.var.xres);
all->par.fbsize = PAGE_ALIGN(linebytes * all->info.var.yres);
- all->par.regs = sbus_ioremap(&sdev->resource[0], 0,
- sizeof(struct p9100_regs), "p9100 regs");
+ all->par.regs = of_ioremap(&op->resource[0], 0,
+ sizeof(struct p9100_regs), "p9100 regs");
+ if (!all->par.regs) {
+ kfree(all);
+ return -ENOMEM;
+ }
all->info.flags = FBINFO_DEFAULT;
all->info.fbops = &p9100_ops;
-#ifdef CONFIG_SPARC32
- all->info.screen_base = (char __iomem *)
- prom_getintdefault(sdev->prom_node, "address", 0);
-#endif
- if (!all->info.screen_base)
- all->info.screen_base = sbus_ioremap(&sdev->resource[2], 0,
- all->par.fbsize, "p9100 ram");
+ all->info.screen_base = of_ioremap(&op->resource[2], 0,
+ all->par.fbsize, "p9100 ram");
+ if (!all->info.screen_base) {
+ of_iounmap(all->par.regs, sizeof(struct p9100_regs));
+ kfree(all);
+ return -ENOMEM;
+ }
all->info.par = &all->par;
p9100_blank(0, &all->info);
if (fb_alloc_cmap(&all->info.cmap, 256, 0)) {
- printk(KERN_ERR "p9100: Could not allocate color map.\n");
+ of_iounmap(all->par.regs, sizeof(struct p9100_regs));
+ of_iounmap(all->info.screen_base, all->par.fbsize);
kfree(all);
- return;
+ return -ENOMEM;
}
- p9100_init_fix(&all->info, linebytes);
+ p9100_init_fix(&all->info, linebytes, dp);
- if (register_framebuffer(&all->info) < 0) {
- printk(KERN_ERR "p9100: Could not register framebuffer.\n");
+ err = register_framebuffer(&all->info);
+ if (err < 0) {
fb_dealloc_cmap(&all->info.cmap);
+ of_iounmap(all->par.regs, sizeof(struct p9100_regs));
+ of_iounmap(all->info.screen_base, all->par.fbsize);
kfree(all);
- return;
+ return err;
}
fb_set_cmap(&all->info.cmap, &all->info);
- list_add(&all->list, &p9100_list);
+ dev_set_drvdata(&op->dev, all);
+
+ printk("%s: p9100 at %lx:%lx\n",
+ dp->full_name,
+ all->par.which_io, all->par.physbase);
- printk("p9100: %s at %lx:%lx\n",
- sdev->prom_name,
- (long) sdev->reg_addrs[0].which_io,
- (long) sdev->reg_addrs[0].phys_addr);
+ return 0;
}
-int __init p9100_init(void)
+static int __devinit p9100_probe(struct of_device *dev, const struct of_device_id *match)
{
- struct sbus_bus *sbus;
- struct sbus_dev *sdev;
+ struct of_device *op = to_of_device(&dev->dev);
- if (fb_get_options("p9100fb", NULL))
- return -ENODEV;
+ return p9100_init_one(op);
+}
- for_all_sbusdev(sdev, sbus) {
- if (!strcmp(sdev->prom_name, "p9100"))
- p9100_init_one(sdev);
- }
+static int __devexit p9100_remove(struct of_device *dev)
+{
+ struct all_info *all = dev_get_drvdata(&dev->dev);
+
+ unregister_framebuffer(&all->info);
+ fb_dealloc_cmap(&all->info.cmap);
+
+ of_iounmap(all->par.regs, sizeof(struct p9100_regs));
+ of_iounmap(all->info.screen_base, all->par.fbsize);
+
+ kfree(all);
+
+ dev_set_drvdata(&dev->dev, NULL);
return 0;
}
-void __exit p9100_exit(void)
-{
- struct list_head *pos, *tmp;
+static struct of_device_id p9100_match[] = {
+ {
+ .name = "p9100",
+ },
+ {},
+};
+MODULE_DEVICE_TABLE(of, p9100_match);
- list_for_each_safe(pos, tmp, &p9100_list) {
- struct all_info *all = list_entry(pos, typeof(*all), list);
+static struct of_platform_driver p9100_driver = {
+ .name = "p9100",
+ .match_table = p9100_match,
+ .probe = p9100_probe,
+ .remove = __devexit_p(p9100_remove),
+};
- unregister_framebuffer(&all->info);
- fb_dealloc_cmap(&all->info.cmap);
- kfree(all);
- }
+static int __init p9100_init(void)
+{
+ if (fb_get_options("p9100fb", NULL))
+ return -ENODEV;
+
+ return of_register_driver(&p9100_driver, &of_bus_type);
}
-int __init
-p9100_setup(char *arg)
+static void __exit p9100_exit(void)
{
- /* No cmdline options yet... */
- return 0;
+ of_unregister_driver(&p9100_driver);
}
module_init(p9100_init);
-
-#ifdef MODULE
module_exit(p9100_exit);
-#endif
MODULE_DESCRIPTION("framebuffer driver for P9100 chipsets");
-MODULE_AUTHOR("David S. Miller <davem@redhat.com>");
+MODULE_AUTHOR("David S. Miller <davem@davemloft.net>");
+MODULE_VERSION("2.0");
MODULE_LICENSE("GPL");
diff --git a/drivers/video/tcx.c b/drivers/video/tcx.c
index 95b918229d9b..6990ab11cd06 100644
--- a/drivers/video/tcx.c
+++ b/drivers/video/tcx.c
@@ -1,6 +1,6 @@
/* tcx.c: TCX frame buffer driver
*
- * Copyright (C) 2003 David S. Miller (davem@redhat.com)
+ * Copyright (C) 2003, 2006 David S. Miller (davem@davemloft.net)
* Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz)
* Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx)
* Copyright (C) 1996 Eddie C. Dost (ecd@skynet.be)
@@ -19,8 +19,8 @@
#include <linux/mm.h>
#include <asm/io.h>
-#include <asm/sbus.h>
-#include <asm/oplib.h>
+#include <asm/prom.h>
+#include <asm/of_device.h>
#include <asm/fbio.h>
#include "sbuslib.h"
@@ -77,32 +77,32 @@ static struct fb_ops tcx_ops = {
/* The contents are unknown */
struct tcx_tec {
- volatile u32 tec_matrix;
- volatile u32 tec_clip;
- volatile u32 tec_vdc;
+ u32 tec_matrix;
+ u32 tec_clip;
+ u32 tec_vdc;
};
struct tcx_thc {
- volatile u32 thc_rev;
+ u32 thc_rev;
u32 thc_pad0[511];
- volatile u32 thc_hs; /* hsync timing */
- volatile u32 thc_hsdvs;
- volatile u32 thc_hd;
- volatile u32 thc_vs; /* vsync timing */
- volatile u32 thc_vd;
- volatile u32 thc_refresh;
- volatile u32 thc_misc;
+ u32 thc_hs; /* hsync timing */
+ u32 thc_hsdvs;
+ u32 thc_hd;
+ u32 thc_vs; /* vsync timing */
+ u32 thc_vd;
+ u32 thc_refresh;
+ u32 thc_misc;
u32 thc_pad1[56];
- volatile u32 thc_cursxy; /* cursor x,y position (16 bits each) */
- volatile u32 thc_cursmask[32]; /* cursor mask bits */
- volatile u32 thc_cursbits[32]; /* what to show where mask enabled */
+ u32 thc_cursxy; /* cursor x,y position (16 bits each) */
+ u32 thc_cursmask[32]; /* cursor mask bits */
+ u32 thc_cursbits[32]; /* what to show where mask enabled */
};
struct bt_regs {
- volatile u32 addr;
- volatile u32 color_map;
- volatile u32 control;
- volatile u32 cursor;
+ u32 addr;
+ u32 color_map;
+ u32 control;
+ u32 cursor;
};
#define TCX_MMAP_ENTRIES 14
@@ -112,24 +112,23 @@ struct tcx_par {
struct bt_regs __iomem *bt;
struct tcx_thc __iomem *thc;
struct tcx_tec __iomem *tec;
- volatile u32 __iomem *cplane;
+ u32 __iomem *cplane;
u32 flags;
#define TCX_FLAG_BLANKED 0x00000001
unsigned long physbase;
+ unsigned long which_io;
unsigned long fbsize;
struct sbus_mmap_map mmap_map[TCX_MMAP_ENTRIES];
int lowdepth;
-
- struct sbus_dev *sdev;
};
/* Reset control plane so that WID is 8-bit plane. */
static void __tcx_set_control_plane (struct tcx_par *par)
{
- volatile u32 __iomem *p, *pend;
+ u32 __iomem *p, *pend;
if (par->lowdepth)
return;
@@ -307,8 +306,7 @@ static int tcx_mmap(struct fb_info *info, struct vm_area_struct *vma)
return sbusfb_mmap_helper(par->mmap_map,
par->physbase, par->fbsize,
- par->sdev->reg_addrs[0].which_io,
- vma);
+ par->which_io, vma);
}
static int tcx_ioctl(struct fb_info *info, unsigned int cmd,
@@ -350,48 +348,71 @@ tcx_init_fix(struct fb_info *info, int linebytes)
struct all_info {
struct fb_info info;
struct tcx_par par;
- struct list_head list;
};
-static LIST_HEAD(tcx_list);
-static void tcx_init_one(struct sbus_dev *sdev)
+static void tcx_unmap_regs(struct all_info *all)
{
- struct all_info *all;
- int linebytes, i;
+ if (all->par.tec)
+ of_iounmap(all->par.tec, sizeof(struct tcx_tec));
+ if (all->par.thc)
+ of_iounmap(all->par.thc, sizeof(struct tcx_thc));
+ if (all->par.bt)
+ of_iounmap(all->par.bt, sizeof(struct bt_regs));
+ if (all->par.cplane)
+ of_iounmap(all->par.cplane, all->par.fbsize * sizeof(u32));
+ if (all->info.screen_base)
+ of_iounmap(all->info.screen_base, all->par.fbsize);
+}
- all = kmalloc(sizeof(*all), GFP_KERNEL);
- if (!all) {
- printk(KERN_ERR "tcx: Cannot allocate memory.\n");
- return;
- }
- memset(all, 0, sizeof(*all));
+static int __devinit tcx_init_one(struct of_device *op)
+{
+ struct device_node *dp = op->node;
+ struct all_info *all;
+ int linebytes, i, err;
- INIT_LIST_HEAD(&all->list);
+ all = kzalloc(sizeof(*all), GFP_KERNEL);
+ if (!all)
+ return -ENOMEM;
spin_lock_init(&all->par.lock);
- all->par.sdev = sdev;
- all->par.lowdepth = prom_getbool(sdev->prom_node, "tcx-8-bit");
+ all->par.lowdepth =
+ (of_find_property(dp, "tcx-8-bit", NULL) != NULL);
- sbusfb_fill_var(&all->info.var, sdev->prom_node, 8);
+ sbusfb_fill_var(&all->info.var, dp->node, 8);
all->info.var.red.length = 8;
all->info.var.green.length = 8;
all->info.var.blue.length = 8;
- linebytes = prom_getintdefault(sdev->prom_node, "linebytes",
- all->info.var.xres);
+ linebytes = of_getintprop_default(dp, "linebytes",
+ all->info.var.xres);
all->par.fbsize = PAGE_ALIGN(linebytes * all->info.var.yres);
- all->par.tec = sbus_ioremap(&sdev->resource[7], 0,
- sizeof(struct tcx_tec), "tcx tec");
- all->par.thc = sbus_ioremap(&sdev->resource[9], 0,
- sizeof(struct tcx_thc), "tcx thc");
- all->par.bt = sbus_ioremap(&sdev->resource[8], 0,
- sizeof(struct bt_regs), "tcx dac");
+ all->par.tec = of_ioremap(&op->resource[7], 0,
+ sizeof(struct tcx_tec), "tcx tec");
+ all->par.thc = of_ioremap(&op->resource[9], 0,
+ sizeof(struct tcx_thc), "tcx thc");
+ all->par.bt = of_ioremap(&op->resource[8], 0,
+ sizeof(struct bt_regs), "tcx dac");
+ all->info.screen_base = of_ioremap(&op->resource[0], 0,
+ all->par.fbsize, "tcx ram");
+ if (!all->par.tec || !all->par.thc ||
+ !all->par.bt || !all->info.screen_base) {
+ tcx_unmap_regs(all);
+ kfree(all);
+ return -ENOMEM;
+ }
+
memcpy(&all->par.mmap_map, &__tcx_mmap_map, sizeof(all->par.mmap_map));
if (!all->par.lowdepth) {
- all->par.cplane = sbus_ioremap(&sdev->resource[4], 0,
- all->par.fbsize * sizeof(u32), "tcx cplane");
+ all->par.cplane = of_ioremap(&op->resource[4], 0,
+ all->par.fbsize * sizeof(u32),
+ "tcx cplane");
+ if (!all->par.cplane) {
+ tcx_unmap_regs(all);
+ kfree(all);
+ return -ENOMEM;
+ }
} else {
all->par.mmap_map[1].size = SBUS_MMAP_EMPTY;
all->par.mmap_map[4].size = SBUS_MMAP_EMPTY;
@@ -400,6 +421,8 @@ static void tcx_init_one(struct sbus_dev *sdev)
}
all->par.physbase = 0;
+ all->par.which_io = op->resource[0].flags & IORESOURCE_BITS;
+
for (i = 0; i < TCX_MMAP_ENTRIES; i++) {
int j;
@@ -416,18 +439,11 @@ static void tcx_init_one(struct sbus_dev *sdev)
j = i;
break;
};
- all->par.mmap_map[i].poff = sdev->reg_addrs[j].phys_addr;
+ all->par.mmap_map[i].poff = op->resource[j].start;
}
all->info.flags = FBINFO_DEFAULT;
all->info.fbops = &tcx_ops;
-#ifdef CONFIG_SPARC32
- all->info.screen_base = (char __iomem *)
- prom_getintdefault(sdev->prom_node, "address", 0);
-#endif
- if (!all->info.screen_base)
- all->info.screen_base = sbus_ioremap(&sdev->resource[0], 0,
- all->par.fbsize, "tcx ram");
all->info.par = &all->par;
/* Initialize brooktree DAC. */
@@ -445,72 +461,88 @@ static void tcx_init_one(struct sbus_dev *sdev)
tcx_blank(FB_BLANK_UNBLANK, &all->info);
if (fb_alloc_cmap(&all->info.cmap, 256, 0)) {
- printk(KERN_ERR "tcx: Could not allocate color map.\n");
+ tcx_unmap_regs(all);
kfree(all);
- return;
+ return -ENOMEM;
}
fb_set_cmap(&all->info.cmap, &all->info);
tcx_init_fix(&all->info, linebytes);
- if (register_framebuffer(&all->info) < 0) {
- printk(KERN_ERR "tcx: Could not register framebuffer.\n");
+ err = register_framebuffer(&all->info);
+ if (err < 0) {
fb_dealloc_cmap(&all->info.cmap);
+ tcx_unmap_regs(all);
kfree(all);
- return;
+ return err;
}
- list_add(&all->list, &tcx_list);
+ dev_set_drvdata(&op->dev, all);
- printk("tcx: %s at %lx:%lx, %s\n",
- sdev->prom_name,
- (long) sdev->reg_addrs[0].which_io,
- (long) sdev->reg_addrs[0].phys_addr,
+ printk("%s: TCX at %lx:%lx, %s\n",
+ dp->full_name,
+ all->par.which_io,
+ op->resource[0].start,
all->par.lowdepth ? "8-bit only" : "24-bit depth");
+
+ return 0;
}
-int __init tcx_init(void)
+static int __devinit tcx_probe(struct of_device *dev, const struct of_device_id *match)
{
- struct sbus_bus *sbus;
- struct sbus_dev *sdev;
+ struct of_device *op = to_of_device(&dev->dev);
- if (fb_get_options("tcxfb", NULL))
- return -ENODEV;
+ return tcx_init_one(op);
+}
- for_all_sbusdev(sdev, sbus) {
- if (!strcmp(sdev->prom_name, "SUNW,tcx"))
- tcx_init_one(sdev);
- }
+static int __devexit tcx_remove(struct of_device *dev)
+{
+ struct all_info *all = dev_get_drvdata(&dev->dev);
+
+ unregister_framebuffer(&all->info);
+ fb_dealloc_cmap(&all->info.cmap);
+
+ tcx_unmap_regs(all);
+
+ kfree(all);
+
+ dev_set_drvdata(&dev->dev, NULL);
return 0;
}
-void __exit tcx_exit(void)
-{
- struct list_head *pos, *tmp;
+static struct of_device_id tcx_match[] = {
+ {
+ .name = "SUNW,tcx",
+ },
+ {},
+};
+MODULE_DEVICE_TABLE(of, tcx_match);
- list_for_each_safe(pos, tmp, &tcx_list) {
- struct all_info *all = list_entry(pos, typeof(*all), list);
+static struct of_platform_driver tcx_driver = {
+ .name = "tcx",
+ .match_table = tcx_match,
+ .probe = tcx_probe,
+ .remove = __devexit_p(tcx_remove),
+};
- unregister_framebuffer(&all->info);
- fb_dealloc_cmap(&all->info.cmap);
- kfree(all);
- }
+int __init tcx_init(void)
+{
+ if (fb_get_options("tcxfb", NULL))
+ return -ENODEV;
+
+ return of_register_driver(&tcx_driver, &of_bus_type);
}
-int __init
-tcx_setup(char *arg)
+void __exit tcx_exit(void)
{
- /* No cmdline options yet... */
- return 0;
+ of_unregister_driver(&tcx_driver);
}
module_init(tcx_init);
-
-#ifdef MODULE
module_exit(tcx_exit);
-#endif
MODULE_DESCRIPTION("framebuffer driver for TCX chipsets");
-MODULE_AUTHOR("David S. Miller <davem@redhat.com>");
+MODULE_AUTHOR("David S. Miller <davem@davemloft.net>");
+MODULE_VERSION("2.0");
MODULE_LICENSE("GPL");
OpenPOWER on IntegriCloud