Re: [PATCH v2] GIO bus support for SGI IP22/28

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 10/20/2011 10:19 PM, Thomas Bogendoerfer wrote:
> SGI IP22/IP28 machines have GIO busses for adding graphics and other
> extension cards. This patch adds support for GIO driver/device
> handling and converts the newport console driver to a GIO driver.
> 
> Signed-off-by: Thomas Bogendoerfer <tsbogend@xxxxxxxxxxxxxxxx>
> ---
> 
> Changes to last version:
> - use EXPORT_SYMBOL_GPL
> - ChallengeS has only 2 slots
> - use subsys_initcall for gio detection
> 
> Florian, the whole patch should go through the MIPS tree, if it's ok for
> you.

No problem. I'm not even sure whether I'm responsible for it as it is not a
framebuffer but a console driver. Anyway I had a look at the console code so you
may add an
	Acked-by: Florian Tobias Schandinat <FlorianSchandinat@xxxxxx>
if you like.


Best regards,

Florian Tobias Schandinat

>  arch/mips/include/asm/gio_device.h  |   56 +++++
>  arch/mips/sgi-ip22/Makefile         |    2 +-
>  arch/mips/sgi-ip22/ip22-gio.c       |  414 +++++++++++++++++++++++++++++++++++
>  arch/mips/sgi-ip22/ip22-mc.c        |   10 +-
>  arch/mips/sgi-ip22/ip22-setup.c     |   21 --
>  drivers/video/console/newport_con.c |   61 ++++--
>  6 files changed, 518 insertions(+), 46 deletions(-)
> 
> diff --git a/arch/mips/include/asm/gio_device.h b/arch/mips/include/asm/gio_device.h
> new file mode 100644
> index 0000000..5437c84
> --- /dev/null
> +++ b/arch/mips/include/asm/gio_device.h
> @@ -0,0 +1,56 @@
> +#include <linux/device.h>
> +#include <linux/mod_devicetable.h>
> +
> +struct gio_device_id {
> +	__u8 id;
> +};
> +
> +struct gio_device {
> +	struct device   dev;
> +	struct resource resource;
> +	unsigned int    irq;
> +	unsigned int    slotno;
> +
> +	const char      *name;
> +	struct gio_device_id id;
> +	unsigned        id32:1;
> +	unsigned        gio64:1;
> +};
> +#define to_gio_device(d) container_of(d, struct gio_device, dev)
> +
> +struct gio_driver {
> +	const char    *name;
> +	struct module *owner;
> +	const struct gio_device_id *id_table;
> +
> +	int  (*probe)(struct gio_device *, const struct gio_device_id *);
> +	void (*remove)(struct gio_device *);
> +	int  (*suspend)(struct gio_device *, pm_message_t);
> +	int  (*resume)(struct gio_device *);
> +	void (*shutdown)(struct gio_device *);
> +
> +	struct device_driver driver;
> +};
> +#define to_gio_driver(drv) container_of(drv, struct gio_driver, driver)
> +
> +extern const struct gio_device_id *gio_match_device(const struct gio_device_id *,
> +						    const struct gio_device *);
> +extern struct gio_device *gio_dev_get(struct gio_device *);
> +extern void gio_dev_put(struct gio_device *);
> +
> +extern int gio_device_register(struct gio_device *);
> +extern void gio_device_unregister(struct gio_device *);
> +extern void gio_release_dev(struct device *);
> +
> +static inline void gio_device_free(struct gio_device *dev)
> +{
> +	gio_release_dev(&dev->dev);
> +}
> +
> +extern int gio_register_driver(struct gio_driver *);
> +extern void gio_unregister_driver(struct gio_driver *);
> +
> +#define gio_get_drvdata(_dev)        drv_get_drvdata(&(_dev)->dev)
> +#define gio_set_drvdata(_dev, data)  drv_set_drvdata(&(_dev)->dev, (data))
> +
> +extern void gio_set_master(struct gio_device *);
> diff --git a/arch/mips/sgi-ip22/Makefile b/arch/mips/sgi-ip22/Makefile
> index cc53849..411cda9 100644
> --- a/arch/mips/sgi-ip22/Makefile
> +++ b/arch/mips/sgi-ip22/Makefile
> @@ -4,7 +4,7 @@
>  #
>  
>  obj-y	+= ip22-mc.o ip22-hpc.o ip22-int.o ip22-time.o ip22-nvram.o \
> -	   ip22-platform.o ip22-reset.o ip22-setup.o
> +	   ip22-platform.o ip22-reset.o ip22-setup.o ip22-gio.o
>  
>  obj-$(CONFIG_SGI_IP22) += ip22-berr.o
>  obj-$(CONFIG_SGI_IP28) += ip28-berr.o
> diff --git a/arch/mips/sgi-ip22/ip22-gio.c b/arch/mips/sgi-ip22/ip22-gio.c
> new file mode 100644
> index 0000000..d841529
> --- /dev/null
> +++ b/arch/mips/sgi-ip22/ip22-gio.c
> @@ -0,0 +1,414 @@
> +#include <linux/kernel.h>
> +#include <linux/init.h>
> +#include <linux/slab.h>
> +
> +#include <asm/addrspace.h>
> +#include <asm/paccess.h>
> +#include <asm/gio_device.h>
> +#include <asm/sgi/gio.h>
> +#include <asm/sgi/hpc3.h>
> +#include <asm/sgi/mc.h>
> +#include <asm/sgi/ip22.h>
> +
> +static struct bus_type gio_bus;
> +
> +static struct {
> +	const char *name;
> +	__u8       id;
> +} gio_name_table[] = {
> +	{ .name = "SGI Impact", .id = 0x10 },
> +	{ .name = "Phobos G160", .id = 0x35 },
> +	/* fake IDs */
> +	{ .name = "SGI Newport", .id = 0x7e },
> +	{ .name = "SGI GR2/GR3", .id = 0x7f },
> +};
> +
> +/**
> + * gio_match_device - Tell if an of_device structure has a matching
> + * gio_match structure
> + * @ids: array of of device match structures to search in
> + * @dev: the of device structure to match against
> + *
> + * Used by a driver to check whether an of_device present in the
> + * system is in its list of supported devices.
> + */
> +const struct gio_device_id *gio_match_device(const struct gio_device_id *match,
> +		     const struct gio_device *dev)
> +{
> +	const struct gio_device_id *ids;
> +
> +	for (ids = match; ids->id != 0xff; ids++)
> +		if (ids->id == dev->id.id)
> +			return ids;
> +
> +	return NULL;
> +}
> +EXPORT_SYMBOL_GPL(gio_match_device);
> +
> +struct gio_device *gio_dev_get(struct gio_device *dev)
> +{
> +	struct device *tmp;
> +
> +	if (!dev)
> +		return NULL;
> +	tmp = get_device(&dev->dev);
> +	if (tmp)
> +		return to_gio_device(tmp);
> +	else
> +		return NULL;
> +}
> +EXPORT_SYMBOL_GPL(gio_dev_get);
> +
> +void gio_dev_put(struct gio_device *dev)
> +{
> +	if (dev)
> +		put_device(&dev->dev);
> +}
> +EXPORT_SYMBOL_GPL(gio_dev_put);
> +
> +static ssize_t dev_show_name(struct device *dev,
> +			     struct device_attribute *attr, char *buf)
> +{
> +	struct gio_device *giodev;
> +
> +	giodev = to_gio_device(dev);
> +	return sprintf(buf, "%s", giodev->name);
> +}
> +
> +static DEVICE_ATTR(name, S_IRUGO, dev_show_name, NULL);
> +
> +static ssize_t dev_show_id(struct device *dev,
> +			   struct device_attribute *attr, char *buf)
> +{
> +	struct gio_device *giodev;
> +
> +	giodev = to_gio_device(dev);
> +	return sprintf(buf, "%x", giodev->id.id);
> +}
> +
> +static DEVICE_ATTR(id, S_IRUGO, dev_show_id, NULL);
> +
> +/**
> + * gio_release_dev - free an gio device structure when all users of it are finished.
> + * @dev: device that's been disconnected
> + *
> + * Will be called only by the device core when all users of this gio device are
> + * done.
> + */
> +void gio_release_dev(struct device *dev)
> +{
> +	struct gio_device *giodev;
> +
> +	giodev = to_gio_device(dev);
> +	kfree(giodev);
> +}
> +EXPORT_SYMBOL_GPL(gio_release_dev);
> +
> +int gio_device_register(struct gio_device *giodev)
> +{
> +	int rc;
> +
> +	giodev->dev.bus = &gio_bus;
> +	rc = device_register(&giodev->dev);
> +	if (rc)
> +		return rc;
> +
> +	rc = device_create_file(&giodev->dev, &dev_attr_name);
> +	if (rc)
> +		goto err;
> +	rc = device_create_file(&giodev->dev, &dev_attr_id);
> +	if (rc)
> +		goto err;
> +
> +	return 0;
> +
> +err:
> +	device_unregister(&giodev->dev);
> +	return rc;
> +}
> +EXPORT_SYMBOL_GPL(gio_device_register);
> +
> +void gio_device_unregister(struct gio_device *giodev)
> +{
> +	device_remove_file(&giodev->dev, &dev_attr_id);
> +	device_remove_file(&giodev->dev, &dev_attr_name);
> +	device_unregister(&giodev->dev);
> +}
> +EXPORT_SYMBOL_GPL(gio_device_unregister);
> +
> +static int gio_bus_match(struct device *dev, struct device_driver *drv)
> +{
> +	struct gio_device *gio_dev = to_gio_device(dev);
> +	struct gio_driver *gio_drv = to_gio_driver(drv);
> +
> +	return gio_match_device(gio_drv->id_table, gio_dev) != NULL;
> +}
> +
> +static int gio_device_probe(struct device *dev)
> +{
> +	int error = -ENODEV;
> +	struct gio_driver *drv;
> +	struct gio_device *gio_dev;
> +	const struct gio_device_id *match;
> +
> +	drv = to_gio_driver(dev->driver);
> +	gio_dev = to_gio_device(dev);
> +
> +	if (!drv->probe)
> +		return error;
> +
> +	gio_dev_get(gio_dev);
> +
> +	match = gio_match_device(drv->id_table, gio_dev);
> +	if (match)
> +		error = drv->probe(gio_dev, match);
> +	if (error)
> +		gio_dev_put(gio_dev);
> +
> +	return error;
> +}
> +
> +static int gio_device_remove(struct device *dev)
> +{
> +	struct gio_device *gio_dev = to_gio_device(dev);
> +	struct gio_driver *drv = to_gio_driver(dev->driver);
> +
> +	if (dev->driver && drv->remove)
> +		drv->remove(gio_dev);
> +	return 0;
> +}
> +
> +static int gio_device_suspend(struct device *dev, pm_message_t state)
> +{
> +	struct gio_device *gio_dev = to_gio_device(dev);
> +	struct gio_driver *drv = to_gio_driver(dev->driver);
> +	int error = 0;
> +
> +	if (dev->driver && drv->suspend)
> +		error = drv->suspend(gio_dev, state);
> +	return error;
> +}
> +
> +static int gio_device_resume(struct device *dev)
> +{
> +	struct gio_device *gio_dev = to_gio_device(dev);
> +	struct gio_driver *drv = to_gio_driver(dev->driver);
> +	int error = 0;
> +
> +	if (dev->driver && drv->resume)
> +		error = drv->resume(gio_dev);
> +	return error;
> +}
> +
> +static void gio_device_shutdown(struct device *dev)
> +{
> +	struct gio_device *gio_dev = to_gio_device(dev);
> +	struct gio_driver *drv = to_gio_driver(dev->driver);
> +
> +	if (dev->driver && drv->shutdown)
> +		drv->shutdown(gio_dev);
> +}
> +
> +int gio_register_driver(struct gio_driver *drv)
> +{
> +	/* initialize common driver fields */
> +	if (!drv->driver.name)
> +		drv->driver.name = drv->name;
> +	if (!drv->driver.owner)
> +		drv->driver.owner = drv->owner;
> +	drv->driver.bus = &gio_bus;
> +
> +	/* register with core */
> +	return driver_register(&drv->driver);
> +}
> +EXPORT_SYMBOL_GPL(gio_register_driver);
> +
> +void gio_unregister_driver(struct gio_driver *drv)
> +{
> +	driver_unregister(&drv->driver);
> +}
> +EXPORT_SYMBOL_GPL(gio_unregister_driver);
> +
> +void gio_set_master(struct gio_device *dev)
> +{
> +	u32 tmp = sgimc->giopar;
> +
> +	switch (dev->slotno) {
> +	case 0:
> +		tmp |= SGIMC_GIOPAR_MASTERGFX;
> +		break;
> +	case 1:
> +		tmp |= SGIMC_GIOPAR_MASTEREXP0;
> +		break;
> +	case 2:
> +		tmp |= SGIMC_GIOPAR_MASTEREXP1;
> +		break;
> +	}
> +	sgimc->giopar = tmp;
> +}
> +EXPORT_SYMBOL_GPL(gio_set_master);
> +
> +void ip22_gio_set_64bit(int slotno)
> +{
> +	u32 tmp = sgimc->giopar;
> +
> +	switch (slotno) {
> +	case 0:
> +		tmp |= SGIMC_GIOPAR_GFX64;
> +		break;
> +	case 1:
> +		tmp |= SGIMC_GIOPAR_EXP064;
> +		break;
> +	case 2:
> +		tmp |= SGIMC_GIOPAR_EXP164;
> +		break;
> +	}
> +	sgimc->giopar = tmp;
> +}
> +
> +static int ip22_gio_id(unsigned long addr, u32 *res)
> +{
> +	u8 tmp8;
> +	u8 tmp16;
> +	u32 tmp32;
> +	u8 *ptr8;
> +	u16 *ptr16;
> +	u32 *ptr32;
> +
> +	ptr32 = (void *)CKSEG1ADDR(addr);
> +	if (!get_dbe(tmp32, ptr32)) {
> +		/*
> +		 * We got no DBE, but this doesn't mean anything.
> +		 * If GIO is pipelined (which can't be disabled
> +		 * for GFX slot) we don't get a DBE, but we see
> +		 * the transfer size as data. So we do an 8bit
> +		 * and a 16bit access and check whether the common
> +		 * data matches
> +		 */
> +		ptr8 = (void *)CKSEG1ADDR(addr + 3);
> +		get_dbe(tmp8, ptr8);
> +		ptr16 = (void *)CKSEG1ADDR(addr + 2);
> +		get_dbe(tmp16, ptr16);
> +		if (tmp8 == (tmp16 & 0xff) &&
> +		    tmp8 == (tmp32 & 0xff) &&
> +		    tmp16 == (tmp32 & 0xffff)) {
> +			*res = tmp32;
> +			return 1;
> +		}
> +	}
> +	return 0; /* nothing here */
> +}
> +
> +#define HQ2_MYSTERY_OFFS       0x6A07C
> +#define NEWPORT_USTATUS_OFFS   0xF133C
> +
> +static int ip22_is_gr2(unsigned long addr)
> +{
> +	u32 tmp;
> +	u32 *ptr;
> +
> +	/* HQ2 only allows 32bit accesses */
> +	ptr = (void *)CKSEG1ADDR(addr + HQ2_MYSTERY_OFFS);
> +	if (!get_dbe(tmp, ptr)) {
> +		if (tmp == 0xdeadbeef)
> +			return 1;
> +	}
> +	return 0;
> +}
> +
> +
> +static void ip22_check_gio(int slotno, unsigned long addr)
> +{
> +	const char *name = "Unknown";
> +	struct gio_device *gio_dev;
> +	u32 tmp;
> +	__u8 id;
> +	int i;
> +
> +	/* first look for GR2/GR3 by checking mystery register */
> +	if (ip22_is_gr2(addr))
> +		tmp = 0x7f;
> +	else {
> +		if (!ip22_gio_id(addr, &tmp)) {
> +			/*
> +			 * no GIO signature at start address of slot, but
> +			 * Newport doesn't have one, so let's check usea
> +			 * status register
> +			 */
> +			if (ip22_gio_id(addr + NEWPORT_USTATUS_OFFS, &tmp))
> +				tmp = 0x7e;
> +			else
> +				tmp = 0;
> +		}
> +	}
> +	if (tmp) {
> +		id = GIO_ID(tmp);
> +		if (tmp & GIO_32BIT_ID) {
> +			if (tmp & GIO_64BIT_IFACE)
> +				ip22_gio_set_64bit(slotno);
> +		}
> +		for (i = 0; i < ARRAY_SIZE(gio_name_table); i++) {
> +			if (id == gio_name_table[i].id) {
> +				name = gio_name_table[i].name;
> +				break;
> +			}
> +		}
> +		printk(KERN_INFO "GIO: slot %d : %s (id %x)\n",
> +		       slotno, name, id);
> +		gio_dev = kzalloc(sizeof *gio_dev, GFP_KERNEL);
> +		gio_dev->name = name;
> +		gio_dev->slotno = slotno;
> +		gio_dev->id.id = id;
> +		gio_dev->resource.start = addr;
> +		gio_dev->resource.end = addr + 0x3fffff;
> +		gio_dev->resource.flags = IORESOURCE_MEM;
> +		dev_set_name(&gio_dev->dev, "gio%d", slotno);
> +		gio_device_register(gio_dev);
> +	} else
> +		printk(KERN_INFO "GIO: slot %d : Empty\n", slotno);
> +}
> +
> +static struct bus_type gio_bus = {
> +	.name     = "gio",
> +	.match    = gio_bus_match,
> +	.probe    = gio_device_probe,
> +	.remove   = gio_device_remove,
> +	.suspend  = gio_device_suspend,
> +	.resume   = gio_device_resume,
> +	.shutdown = gio_device_shutdown,
> +};
> +
> +static struct resource gio_bus_resource = {
> +	.start = GIO_SLOT_GFX_BASE,
> +	.end   = GIO_SLOT_GFX_BASE + 0x9fffff,
> +	.name  = "GIO Bus",
> +	.flags = IORESOURCE_MEM,
> +};
> +
> +int __init ip22_gio_init(void)
> +{
> +	unsigned int pbdma __maybe_unused;
> +	int ret;
> +
> +	ret = bus_register(&gio_bus);
> +	if (!ret) {
> +		request_resource(&iomem_resource, &gio_bus_resource);
> +		printk(KERN_INFO "GIO: Probing bus...\n");
> +
> +		if (ip22_is_fullhouse() ||
> +		    !get_dbe(pbdma, (unsigned int *)&hpc3c1->pbdma[1])) {
> +			/* Indigo2 and ChallengeS */
> +			ip22_check_gio(0, GIO_SLOT_GFX_BASE);
> +			ip22_check_gio(1, GIO_SLOT_EXP0_BASE);
> +		} else {
> +			/* Indy */
> +			ip22_check_gio(0, GIO_SLOT_GFX_BASE);
> +			ip22_check_gio(1, GIO_SLOT_EXP0_BASE);
> +			ip22_check_gio(2, GIO_SLOT_EXP1_BASE);
> +		}
> +	}
> +	return ret;
> +}
> +
> +subsys_initcall(ip22_gio_init);
> +
> diff --git a/arch/mips/sgi-ip22/ip22-mc.c b/arch/mips/sgi-ip22/ip22-mc.c
> index d22262e..75ada8a 100644
> --- a/arch/mips/sgi-ip22/ip22-mc.c
> +++ b/arch/mips/sgi-ip22/ip22-mc.c
> @@ -139,11 +139,11 @@ void __init sgimc_init(void)
>  	 *         zero.
>  	 */
>  	/* don't touch parity settings for IP28 */
> -#ifndef CONFIG_SGI_IP28
>  	tmp = sgimc->cpuctrl0;
> -	tmp |= (SGIMC_CCTRL0_EPERRGIO | SGIMC_CCTRL0_EPERRMEM |
> -		SGIMC_CCTRL0_R4KNOCHKPARR);
> +#ifndef CONFIG_SGI_IP28
> +	tmp |= SGIMC_CCTRL0_EPERRGIO | SGIMC_CCTRL0_EPERRMEM;
>  #endif
> +	tmp |= SGIMC_CCTRL0_R4KNOCHKPARR;
>  	sgimc->cpuctrl0 = tmp;
>  
>  	/* Step 3: Setup the MC write buffer depth, this is controlled
> @@ -178,7 +178,8 @@ void __init sgimc_init(void)
>  	 */
>  
>  	/* First the basic invariants across all GIO64 implementations. */
> -	tmp = SGIMC_GIOPAR_HPC64;	/* All 1st HPC's interface at 64bits */
> +	tmp = sgimc->giopar & SGIMC_GIOPAR_GFX64; /* keep gfx 64bit settings */
> +	tmp |= SGIMC_GIOPAR_HPC64;	/* All 1st HPC's interface at 64bits */
>  	tmp |= SGIMC_GIOPAR_ONEBUS;	/* Only one physical GIO bus exists */
>  
>  	if (ip22_is_fullhouse()) {
> @@ -193,7 +194,6 @@ void __init sgimc_init(void)
>  			tmp |= SGIMC_GIOPAR_PLINEEXP0;	/* exp[01] pipelined */
>  			tmp |= SGIMC_GIOPAR_PLINEEXP1;
>  			tmp |= SGIMC_GIOPAR_MASTEREISA;	/* EISA masters */
> -			tmp |= SGIMC_GIOPAR_GFX64;	/* GFX at 64 bits */
>  		}
>  	} else {
>  		/* Guiness specific settings. */
> diff --git a/arch/mips/sgi-ip22/ip22-setup.c b/arch/mips/sgi-ip22/ip22-setup.c
> index 5e66213..c7bdfe4 100644
> --- a/arch/mips/sgi-ip22/ip22-setup.c
> +++ b/arch/mips/sgi-ip22/ip22-setup.c
> @@ -26,9 +26,6 @@
>  #include <asm/sgi/hpc3.h>
>  #include <asm/sgi/ip22.h>
>  
> -unsigned long sgi_gfxaddr;
> -EXPORT_SYMBOL_GPL(sgi_gfxaddr);
> -
>  extern void ip22_be_init(void) __init;
>  
>  void __init plat_mem_setup(void)
> @@ -78,22 +75,4 @@ void __init plat_mem_setup(void)
>  		prom_flags |= PROM_FLAG_USE_AS_CONSOLE;
>  		add_preferred_console("arc", 0, NULL);
>  	}
> -
> -#if defined(CONFIG_VT) && defined(CONFIG_SGI_NEWPORT_CONSOLE)
> -	{
> -		ULONG *gfxinfo;
> -		ULONG * (*__vec)(void) = (void *) (long)
> -			*((_PULONG *)(long)((PROMBLOCK)->pvector + 0x20));
> -
> -		gfxinfo = __vec();
> -		sgi_gfxaddr = ((gfxinfo[1] >= 0xa0000000
> -			       && gfxinfo[1] <= 0xc0000000)
> -			       ? gfxinfo[1] - 0xa0000000 : 0);
> -
> -		/* newport addresses? */
> -		if (sgi_gfxaddr == 0x1f0f0000 || sgi_gfxaddr == 0x1f4f0000) {
> -			conswitchp = &newport_con;
> -		}
> -	}
> -#endif
>  }
> diff --git a/drivers/video/console/newport_con.c b/drivers/video/console/newport_con.c
> index 93317b5..628b7ec 100644
> --- a/drivers/video/console/newport_con.c
> +++ b/drivers/video/console/newport_con.c
> @@ -25,14 +25,13 @@
>  #include <asm/system.h>
>  #include <asm/page.h>
>  #include <asm/pgtable.h>
> +#include <asm/gio_device.h>
> +
>  #include <video/newport.h>
>  
>  #include <linux/linux_logo.h>
>  #include <linux/font.h>
>  
> -
> -extern unsigned long sgi_gfxaddr;
> -
>  #define FONT_DATA ((unsigned char *)font_vga_8x16.data)
>  
>  /* borrowed from fbcon.c */
> @@ -304,12 +303,6 @@ static const char *newport_startup(void)
>  {
>  	int i;
>  
> -	if (!sgi_gfxaddr)
> -		return NULL;
> -
> -	if (!npregs)
> -		npregs = (struct newport_regs *)/* ioremap cannot fail */
> -			ioremap(sgi_gfxaddr, sizeof(struct newport_regs));
>  	npregs->cset.config = NPORT_CFG_GD0;
>  
>  	if (newport_wait(npregs))
> @@ -743,26 +736,56 @@ const struct consw newport_con = {
>  	.con_save_screen  = DUMMY
>  };
>  
> -#ifdef MODULE
> -static int __init newport_console_init(void)
> +static int newport_probe(struct gio_device *dev,
> +			 const struct gio_device_id *id)
>  {
> -	if (!sgi_gfxaddr)
> -		return 0;
> +	unsigned long newport_addr;
>  
> -	if (!npregs)
> -		npregs = (struct newport_regs *)/* ioremap cannot fail */
> -			ioremap(sgi_gfxaddr, sizeof(struct newport_regs));
> +	if (!dev->resource.start)
> +		return -EINVAL;
> +
> +	if (npregs)
> +		return -EBUSY; /* we only support one Newport as console */
> +
> +	newport_addr = dev->resource.start + 0xF0000;
> +	if (!request_mem_region(newport_addr, 0x10000, "Newport"))
> +		return -ENODEV;
> +
> +	npregs = (struct newport_regs *)/* ioremap cannot fail */
> +		ioremap(newport_addr, sizeof(struct newport_regs));
>  
>  	return take_over_console(&newport_con, 0, MAX_NR_CONSOLES - 1, 1);
>  }
> -module_init(newport_console_init);
>  
> -static void __exit newport_console_exit(void)
> +static void newport_remove(struct gio_device *dev)
>  {
>  	give_up_console(&newport_con);
>  	iounmap((void *)npregs);
>  }
> +
> +static struct gio_device_id newport_ids[] = {
> +	{ .id = 0x7e },
> +	{ .id = 0xff }
> +};
> +
> +static struct gio_driver newport_driver = {
> +	.name = "newport",
> +	.id_table = newport_ids,
> +	.probe = newport_probe,
> +	.remove = newport_remove,
> +};
> +
> +int __init newport_console_init(void)
> +{
> +	return gio_register_driver(&newport_driver);
> +}
> +
> +void __exit newport_console_exit(void)
> +{
> +	gio_unregister_driver(&newport_driver);
> +}
> +
> +module_init(newport_console_init);
>  module_exit(newport_console_exit);
> -#endif
>  
>  MODULE_LICENSE("GPL");
> 




[Index of Archives]     [Linux MIPS Home]     [LKML Archive]     [Linux ARM Kernel]     [Linux ARM]     [Linux]     [Git]     [Yosemite News]     [Linux SCSI]     [Linux Hams]

  Powered by Linux