0001
0002 #include <linux/export.h>
0003 #include <linux/kernel.h>
0004 #include <linux/init.h>
0005 #include <linux/slab.h>
0006
0007 #include <asm/addrspace.h>
0008 #include <asm/paccess.h>
0009 #include <asm/gio_device.h>
0010 #include <asm/sgi/gio.h>
0011 #include <asm/sgi/hpc3.h>
0012 #include <asm/sgi/mc.h>
0013 #include <asm/sgi/ip22.h>
0014
0015 static struct bus_type gio_bus_type;
0016
0017 static struct {
0018 const char *name;
0019 __u8 id;
0020 } gio_name_table[] = {
0021 { .name = "SGI Impact", .id = 0x10 },
0022 { .name = "Phobos G160", .id = 0x35 },
0023 { .name = "Phobos G130", .id = 0x36 },
0024 { .name = "Phobos G100", .id = 0x37 },
0025 { .name = "Set Engineering GFE", .id = 0x38 },
0026
0027 { .name = "SGI Newport", .id = 0x7e },
0028 { .name = "SGI GR2/GR3", .id = 0x7f },
0029 };
0030
0031 static void gio_bus_release(struct device *dev)
0032 {
0033 kfree(dev);
0034 }
0035
0036 static struct device gio_bus = {
0037 .init_name = "gio",
0038 .release = &gio_bus_release,
0039 };
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050 static const struct gio_device_id *
0051 gio_match_device(const struct gio_device_id *match,
0052 const struct gio_device *dev)
0053 {
0054 const struct gio_device_id *ids;
0055
0056 for (ids = match; ids->id != 0xff; ids++)
0057 if (ids->id == dev->id.id)
0058 return ids;
0059
0060 return NULL;
0061 }
0062
0063 struct gio_device *gio_dev_get(struct gio_device *dev)
0064 {
0065 struct device *tmp;
0066
0067 if (!dev)
0068 return NULL;
0069 tmp = get_device(&dev->dev);
0070 if (tmp)
0071 return to_gio_device(tmp);
0072 else
0073 return NULL;
0074 }
0075 EXPORT_SYMBOL_GPL(gio_dev_get);
0076
0077 void gio_dev_put(struct gio_device *dev)
0078 {
0079 if (dev)
0080 put_device(&dev->dev);
0081 }
0082 EXPORT_SYMBOL_GPL(gio_dev_put);
0083
0084
0085
0086
0087
0088
0089
0090
0091 void gio_release_dev(struct device *dev)
0092 {
0093 struct gio_device *giodev;
0094
0095 giodev = to_gio_device(dev);
0096 kfree(giodev);
0097 }
0098 EXPORT_SYMBOL_GPL(gio_release_dev);
0099
0100 int gio_device_register(struct gio_device *giodev)
0101 {
0102 giodev->dev.bus = &gio_bus_type;
0103 giodev->dev.parent = &gio_bus;
0104 return device_register(&giodev->dev);
0105 }
0106 EXPORT_SYMBOL_GPL(gio_device_register);
0107
0108 void gio_device_unregister(struct gio_device *giodev)
0109 {
0110 device_unregister(&giodev->dev);
0111 }
0112 EXPORT_SYMBOL_GPL(gio_device_unregister);
0113
0114 static int gio_bus_match(struct device *dev, struct device_driver *drv)
0115 {
0116 struct gio_device *gio_dev = to_gio_device(dev);
0117 struct gio_driver *gio_drv = to_gio_driver(drv);
0118
0119 return gio_match_device(gio_drv->id_table, gio_dev) != NULL;
0120 }
0121
0122 static int gio_device_probe(struct device *dev)
0123 {
0124 int error = -ENODEV;
0125 struct gio_driver *drv;
0126 struct gio_device *gio_dev;
0127 const struct gio_device_id *match;
0128
0129 drv = to_gio_driver(dev->driver);
0130 gio_dev = to_gio_device(dev);
0131
0132 if (!drv->probe)
0133 return error;
0134
0135 gio_dev_get(gio_dev);
0136
0137 match = gio_match_device(drv->id_table, gio_dev);
0138 if (match)
0139 error = drv->probe(gio_dev, match);
0140 if (error)
0141 gio_dev_put(gio_dev);
0142
0143 return error;
0144 }
0145
0146 static void gio_device_remove(struct device *dev)
0147 {
0148 struct gio_device *gio_dev = to_gio_device(dev);
0149 struct gio_driver *drv = to_gio_driver(dev->driver);
0150
0151 if (drv->remove)
0152 drv->remove(gio_dev);
0153 }
0154
0155 static void gio_device_shutdown(struct device *dev)
0156 {
0157 struct gio_device *gio_dev = to_gio_device(dev);
0158 struct gio_driver *drv = to_gio_driver(dev->driver);
0159
0160 if (dev->driver && drv->shutdown)
0161 drv->shutdown(gio_dev);
0162 }
0163
0164 static ssize_t modalias_show(struct device *dev, struct device_attribute *a,
0165 char *buf)
0166 {
0167 struct gio_device *gio_dev = to_gio_device(dev);
0168 int len = snprintf(buf, PAGE_SIZE, "gio:%x\n", gio_dev->id.id);
0169
0170 return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len;
0171 }
0172 static DEVICE_ATTR_RO(modalias);
0173
0174 static ssize_t name_show(struct device *dev,
0175 struct device_attribute *attr, char *buf)
0176 {
0177 struct gio_device *giodev;
0178
0179 giodev = to_gio_device(dev);
0180 return sprintf(buf, "%s", giodev->name);
0181 }
0182 static DEVICE_ATTR_RO(name);
0183
0184 static ssize_t id_show(struct device *dev,
0185 struct device_attribute *attr, char *buf)
0186 {
0187 struct gio_device *giodev;
0188
0189 giodev = to_gio_device(dev);
0190 return sprintf(buf, "%x", giodev->id.id);
0191 }
0192 static DEVICE_ATTR_RO(id);
0193
0194 static struct attribute *gio_dev_attrs[] = {
0195 &dev_attr_modalias.attr,
0196 &dev_attr_name.attr,
0197 &dev_attr_id.attr,
0198 NULL,
0199 };
0200 ATTRIBUTE_GROUPS(gio_dev);
0201
0202 static int gio_device_uevent(struct device *dev, struct kobj_uevent_env *env)
0203 {
0204 struct gio_device *gio_dev = to_gio_device(dev);
0205
0206 add_uevent_var(env, "MODALIAS=gio:%x", gio_dev->id.id);
0207 return 0;
0208 }
0209
0210 int gio_register_driver(struct gio_driver *drv)
0211 {
0212
0213 if (!drv->driver.name)
0214 drv->driver.name = drv->name;
0215 if (!drv->driver.owner)
0216 drv->driver.owner = drv->owner;
0217 drv->driver.bus = &gio_bus_type;
0218
0219
0220 return driver_register(&drv->driver);
0221 }
0222 EXPORT_SYMBOL_GPL(gio_register_driver);
0223
0224 void gio_unregister_driver(struct gio_driver *drv)
0225 {
0226 driver_unregister(&drv->driver);
0227 }
0228 EXPORT_SYMBOL_GPL(gio_unregister_driver);
0229
0230 void gio_set_master(struct gio_device *dev)
0231 {
0232 u32 tmp = sgimc->giopar;
0233
0234 switch (dev->slotno) {
0235 case 0:
0236 tmp |= SGIMC_GIOPAR_MASTERGFX;
0237 break;
0238 case 1:
0239 tmp |= SGIMC_GIOPAR_MASTEREXP0;
0240 break;
0241 case 2:
0242 tmp |= SGIMC_GIOPAR_MASTEREXP1;
0243 break;
0244 }
0245 sgimc->giopar = tmp;
0246 }
0247 EXPORT_SYMBOL_GPL(gio_set_master);
0248
0249 void ip22_gio_set_64bit(int slotno)
0250 {
0251 u32 tmp = sgimc->giopar;
0252
0253 switch (slotno) {
0254 case 0:
0255 tmp |= SGIMC_GIOPAR_GFX64;
0256 break;
0257 case 1:
0258 tmp |= SGIMC_GIOPAR_EXP064;
0259 break;
0260 case 2:
0261 tmp |= SGIMC_GIOPAR_EXP164;
0262 break;
0263 }
0264 sgimc->giopar = tmp;
0265 }
0266
0267 static int ip22_gio_id(unsigned long addr, u32 *res)
0268 {
0269 u8 tmp8;
0270 u8 tmp16;
0271 u32 tmp32;
0272 u8 *ptr8;
0273 u16 *ptr16;
0274 u32 *ptr32;
0275
0276 ptr32 = (void *)CKSEG1ADDR(addr);
0277 if (!get_dbe(tmp32, ptr32)) {
0278
0279
0280
0281
0282
0283
0284
0285
0286 ptr8 = (void *)CKSEG1ADDR(addr + 3);
0287 if (get_dbe(tmp8, ptr8)) {
0288
0289
0290
0291
0292
0293
0294 *res = tmp32;
0295 return 1;
0296 }
0297 ptr16 = (void *)CKSEG1ADDR(addr + 2);
0298 get_dbe(tmp16, ptr16);
0299 if (tmp8 == (tmp16 & 0xff) &&
0300 tmp8 == (tmp32 & 0xff) &&
0301 tmp16 == (tmp32 & 0xffff)) {
0302 *res = tmp32;
0303 return 1;
0304 }
0305 }
0306 return 0;
0307 }
0308
0309 #define HQ2_MYSTERY_OFFS 0x6A07C
0310 #define NEWPORT_USTATUS_OFFS 0xF133C
0311
0312 static int ip22_is_gr2(unsigned long addr)
0313 {
0314 u32 tmp;
0315 u32 *ptr;
0316
0317
0318 ptr = (void *)CKSEG1ADDR(addr + HQ2_MYSTERY_OFFS);
0319 if (!get_dbe(tmp, ptr)) {
0320 if (tmp == 0xdeadbeef)
0321 return 1;
0322 }
0323 return 0;
0324 }
0325
0326
0327 static void ip22_check_gio(int slotno, unsigned long addr, int irq)
0328 {
0329 const char *name = "Unknown";
0330 struct gio_device *gio_dev;
0331 u32 tmp;
0332 __u8 id;
0333 int i;
0334
0335
0336 if (ip22_is_gr2(addr))
0337 tmp = 0x7f;
0338 else {
0339 if (!ip22_gio_id(addr, &tmp)) {
0340
0341
0342
0343
0344
0345 if (ip22_gio_id(addr + NEWPORT_USTATUS_OFFS, &tmp))
0346 tmp = 0x7e;
0347 else
0348 tmp = 0;
0349 }
0350 }
0351 if (tmp) {
0352 id = GIO_ID(tmp);
0353 if (tmp & GIO_32BIT_ID) {
0354 if (tmp & GIO_64BIT_IFACE)
0355 ip22_gio_set_64bit(slotno);
0356 }
0357 for (i = 0; i < ARRAY_SIZE(gio_name_table); i++) {
0358 if (id == gio_name_table[i].id) {
0359 name = gio_name_table[i].name;
0360 break;
0361 }
0362 }
0363 printk(KERN_INFO "GIO: slot %d : %s (id %x)\n",
0364 slotno, name, id);
0365 gio_dev = kzalloc(sizeof *gio_dev, GFP_KERNEL);
0366 if (!gio_dev)
0367 return;
0368 gio_dev->name = name;
0369 gio_dev->slotno = slotno;
0370 gio_dev->id.id = id;
0371 gio_dev->resource.start = addr;
0372 gio_dev->resource.end = addr + 0x3fffff;
0373 gio_dev->resource.flags = IORESOURCE_MEM;
0374 gio_dev->irq = irq;
0375 dev_set_name(&gio_dev->dev, "%d", slotno);
0376 gio_device_register(gio_dev);
0377 } else
0378 printk(KERN_INFO "GIO: slot %d : Empty\n", slotno);
0379 }
0380
0381 static struct bus_type gio_bus_type = {
0382 .name = "gio",
0383 .dev_groups = gio_dev_groups,
0384 .match = gio_bus_match,
0385 .probe = gio_device_probe,
0386 .remove = gio_device_remove,
0387 .shutdown = gio_device_shutdown,
0388 .uevent = gio_device_uevent,
0389 };
0390
0391 static struct resource gio_bus_resource = {
0392 .start = GIO_SLOT_GFX_BASE,
0393 .end = GIO_SLOT_GFX_BASE + 0x9fffff,
0394 .name = "GIO Bus",
0395 .flags = IORESOURCE_MEM,
0396 };
0397
0398 int __init ip22_gio_init(void)
0399 {
0400 unsigned int pbdma __maybe_unused;
0401 int ret;
0402
0403 ret = device_register(&gio_bus);
0404 if (ret) {
0405 put_device(&gio_bus);
0406 return ret;
0407 }
0408
0409 ret = bus_register(&gio_bus_type);
0410 if (!ret) {
0411 request_resource(&iomem_resource, &gio_bus_resource);
0412 printk(KERN_INFO "GIO: Probing bus...\n");
0413
0414 if (ip22_is_fullhouse()) {
0415
0416 ip22_check_gio(0, GIO_SLOT_GFX_BASE, SGI_GIO_1_IRQ);
0417 ip22_check_gio(1, GIO_SLOT_EXP0_BASE, SGI_GIO_1_IRQ);
0418 } else {
0419
0420 if (get_dbe(pbdma, (unsigned int *)&hpc3c1->pbdma[1]))
0421 ip22_check_gio(0, GIO_SLOT_GFX_BASE,
0422 SGI_GIO_0_IRQ);
0423 ip22_check_gio(1, GIO_SLOT_EXP0_BASE, SGI_GIOEXP0_IRQ);
0424 ip22_check_gio(2, GIO_SLOT_EXP1_BASE, SGI_GIOEXP1_IRQ);
0425 }
0426 } else
0427 device_unregister(&gio_bus);
0428
0429 return ret;
0430 }
0431
0432 subsys_initcall(ip22_gio_init);