1#include <linux/export.h> 2#include <linux/kernel.h> 3#include <linux/init.h> 4#include <linux/slab.h> 5 6#include <asm/addrspace.h> 7#include <asm/paccess.h> 8#include <asm/gio_device.h> 9#include <asm/sgi/gio.h> 10#include <asm/sgi/hpc3.h> 11#include <asm/sgi/mc.h> 12#include <asm/sgi/ip22.h> 13 14static struct bus_type gio_bus_type; 15 16static struct { 17 const char *name; 18 __u8 id; 19} gio_name_table[] = { 20 { .name = "SGI Impact", .id = 0x10 }, 21 { .name = "Phobos G160", .id = 0x35 }, 22 /* fake IDs */ 23 { .name = "SGI Newport", .id = 0x7e }, 24 { .name = "SGI GR2/GR3", .id = 0x7f }, 25}; 26 27static struct device gio_bus = { 28 .init_name = "gio", 29}; 30 31/** 32 * gio_match_device - Tell if an of_device structure has a matching 33 * gio_match structure 34 * @ids: array of of device match structures to search in 35 * @dev: the of device structure to match against 36 * 37 * Used by a driver to check whether an of_device present in the 38 * system is in its list of supported devices. 39 */ 40const struct gio_device_id *gio_match_device(const struct gio_device_id *match, 41 const struct gio_device *dev) 42{ 43 const struct gio_device_id *ids; 44 45 for (ids = match; ids->id != 0xff; ids++) 46 if (ids->id == dev->id.id) 47 return ids; 48 49 return NULL; 50} 51EXPORT_SYMBOL_GPL(gio_match_device); 52 53struct gio_device *gio_dev_get(struct gio_device *dev) 54{ 55 struct device *tmp; 56 57 if (!dev) 58 return NULL; 59 tmp = get_device(&dev->dev); 60 if (tmp) 61 return to_gio_device(tmp); 62 else 63 return NULL; 64} 65EXPORT_SYMBOL_GPL(gio_dev_get); 66 67void gio_dev_put(struct gio_device *dev) 68{ 69 if (dev) 70 put_device(&dev->dev); 71} 72EXPORT_SYMBOL_GPL(gio_dev_put); 73 74/** 75 * gio_release_dev - free an gio device structure when all users of it are finished. 76 * @dev: device that's been disconnected 77 * 78 * Will be called only by the device core when all users of this gio device are 79 * done. 80 */ 81void gio_release_dev(struct device *dev) 82{ 83 struct gio_device *giodev; 84 85 giodev = to_gio_device(dev); 86 kfree(giodev); 87} 88EXPORT_SYMBOL_GPL(gio_release_dev); 89 90int gio_device_register(struct gio_device *giodev) 91{ 92 giodev->dev.bus = &gio_bus_type; 93 giodev->dev.parent = &gio_bus; 94 return device_register(&giodev->dev); 95} 96EXPORT_SYMBOL_GPL(gio_device_register); 97 98void gio_device_unregister(struct gio_device *giodev) 99{ 100 device_unregister(&giodev->dev); 101} 102EXPORT_SYMBOL_GPL(gio_device_unregister); 103 104static int gio_bus_match(struct device *dev, struct device_driver *drv) 105{ 106 struct gio_device *gio_dev = to_gio_device(dev); 107 struct gio_driver *gio_drv = to_gio_driver(drv); 108 109 return gio_match_device(gio_drv->id_table, gio_dev) != NULL; 110} 111 112static int gio_device_probe(struct device *dev) 113{ 114 int error = -ENODEV; 115 struct gio_driver *drv; 116 struct gio_device *gio_dev; 117 const struct gio_device_id *match; 118 119 drv = to_gio_driver(dev->driver); 120 gio_dev = to_gio_device(dev); 121 122 if (!drv->probe) 123 return error; 124 125 gio_dev_get(gio_dev); 126 127 match = gio_match_device(drv->id_table, gio_dev); 128 if (match) 129 error = drv->probe(gio_dev, match); 130 if (error) 131 gio_dev_put(gio_dev); 132 133 return error; 134} 135 136static int gio_device_remove(struct device *dev) 137{ 138 struct gio_device *gio_dev = to_gio_device(dev); 139 struct gio_driver *drv = to_gio_driver(dev->driver); 140 141 if (dev->driver && drv->remove) 142 drv->remove(gio_dev); 143 return 0; 144} 145 146static int gio_device_suspend(struct device *dev, pm_message_t state) 147{ 148 struct gio_device *gio_dev = to_gio_device(dev); 149 struct gio_driver *drv = to_gio_driver(dev->driver); 150 int error = 0; 151 152 if (dev->driver && drv->suspend) 153 error = drv->suspend(gio_dev, state); 154 return error; 155} 156 157static int gio_device_resume(struct device *dev) 158{ 159 struct gio_device *gio_dev = to_gio_device(dev); 160 struct gio_driver *drv = to_gio_driver(dev->driver); 161 int error = 0; 162 163 if (dev->driver && drv->resume) 164 error = drv->resume(gio_dev); 165 return error; 166} 167 168static void gio_device_shutdown(struct device *dev) 169{ 170 struct gio_device *gio_dev = to_gio_device(dev); 171 struct gio_driver *drv = to_gio_driver(dev->driver); 172 173 if (dev->driver && drv->shutdown) 174 drv->shutdown(gio_dev); 175} 176 177static ssize_t modalias_show(struct device *dev, struct device_attribute *a, 178 char *buf) 179{ 180 struct gio_device *gio_dev = to_gio_device(dev); 181 int len = snprintf(buf, PAGE_SIZE, "gio:%x\n", gio_dev->id.id); 182 183 return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len; 184} 185 186static ssize_t name_show(struct device *dev, 187 struct device_attribute *attr, char *buf) 188{ 189 struct gio_device *giodev; 190 191 giodev = to_gio_device(dev); 192 return sprintf(buf, "%s", giodev->name); 193} 194 195static ssize_t id_show(struct device *dev, 196 struct device_attribute *attr, char *buf) 197{ 198 struct gio_device *giodev; 199 200 giodev = to_gio_device(dev); 201 return sprintf(buf, "%x", giodev->id.id); 202} 203 204static struct device_attribute gio_dev_attrs[] = { 205 __ATTR_RO(modalias), 206 __ATTR_RO(name), 207 __ATTR_RO(id), 208 __ATTR_NULL, 209}; 210 211static int gio_device_uevent(struct device *dev, struct kobj_uevent_env *env) 212{ 213 struct gio_device *gio_dev = to_gio_device(dev); 214 215 add_uevent_var(env, "MODALIAS=gio:%x", gio_dev->id.id); 216 return 0; 217} 218 219int gio_register_driver(struct gio_driver *drv) 220{ 221 /* initialize common driver fields */ 222 if (!drv->driver.name) 223 drv->driver.name = drv->name; 224 if (!drv->driver.owner) 225 drv->driver.owner = drv->owner; 226 drv->driver.bus = &gio_bus_type; 227 228 /* register with core */ 229 return driver_register(&drv->driver); 230} 231EXPORT_SYMBOL_GPL(gio_register_driver); 232 233void gio_unregister_driver(struct gio_driver *drv) 234{ 235 driver_unregister(&drv->driver); 236} 237EXPORT_SYMBOL_GPL(gio_unregister_driver); 238 239void gio_set_master(struct gio_device *dev) 240{ 241 u32 tmp = sgimc->giopar; 242 243 switch (dev->slotno) { 244 case 0: 245 tmp |= SGIMC_GIOPAR_MASTERGFX; 246 break; 247 case 1: 248 tmp |= SGIMC_GIOPAR_MASTEREXP0; 249 break; 250 case 2: 251 tmp |= SGIMC_GIOPAR_MASTEREXP1; 252 break; 253 } 254 sgimc->giopar = tmp; 255} 256EXPORT_SYMBOL_GPL(gio_set_master); 257 258void ip22_gio_set_64bit(int slotno) 259{ 260 u32 tmp = sgimc->giopar; 261 262 switch (slotno) { 263 case 0: 264 tmp |= SGIMC_GIOPAR_GFX64; 265 break; 266 case 1: 267 tmp |= SGIMC_GIOPAR_EXP064; 268 break; 269 case 2: 270 tmp |= SGIMC_GIOPAR_EXP164; 271 break; 272 } 273 sgimc->giopar = tmp; 274} 275 276static int ip22_gio_id(unsigned long addr, u32 *res) 277{ 278 u8 tmp8; 279 u8 tmp16; 280 u32 tmp32; 281 u8 *ptr8; 282 u16 *ptr16; 283 u32 *ptr32; 284 285 ptr32 = (void *)CKSEG1ADDR(addr); 286 if (!get_dbe(tmp32, ptr32)) { 287 /* 288 * We got no DBE, but this doesn't mean anything. 289 * If GIO is pipelined (which can't be disabled 290 * for GFX slot) we don't get a DBE, but we see 291 * the transfer size as data. So we do an 8bit 292 * and a 16bit access and check whether the common 293 * data matches 294 */ 295 ptr8 = (void *)CKSEG1ADDR(addr + 3); 296 get_dbe(tmp8, ptr8); 297 ptr16 = (void *)CKSEG1ADDR(addr + 2); 298 get_dbe(tmp16, ptr16); 299 if (tmp8 == (tmp16 & 0xff) && 300 tmp8 == (tmp32 & 0xff) && 301 tmp16 == (tmp32 & 0xffff)) { 302 *res = tmp32; 303 return 1; 304 } 305 } 306 return 0; /* nothing here */ 307} 308 309#define HQ2_MYSTERY_OFFS 0x6A07C 310#define NEWPORT_USTATUS_OFFS 0xF133C 311 312static int ip22_is_gr2(unsigned long addr) 313{ 314 u32 tmp; 315 u32 *ptr; 316 317 /* HQ2 only allows 32bit accesses */ 318 ptr = (void *)CKSEG1ADDR(addr + HQ2_MYSTERY_OFFS); 319 if (!get_dbe(tmp, ptr)) { 320 if (tmp == 0xdeadbeef) 321 return 1; 322 } 323 return 0; 324} 325 326 327static void ip22_check_gio(int slotno, unsigned long addr) 328{ 329 const char *name = "Unknown"; 330 struct gio_device *gio_dev; 331 u32 tmp; 332 __u8 id; 333 int i; 334 335 /* first look for GR2/GR3 by checking mystery register */ 336 if (ip22_is_gr2(addr)) 337 tmp = 0x7f; 338 else { 339 if (!ip22_gio_id(addr, &tmp)) { 340 /* 341 * no GIO signature at start address of slot, but 342 * Newport doesn't have one, so let's check usea 343 * status register 344 */ 345 if (ip22_gio_id(addr + NEWPORT_USTATUS_OFFS, &tmp)) 346 tmp = 0x7e; 347 else 348 tmp = 0; 349 } 350 } 351 if (tmp) { 352 id = GIO_ID(tmp); 353 if (tmp & GIO_32BIT_ID) { 354 if (tmp & GIO_64BIT_IFACE) 355 ip22_gio_set_64bit(slotno); 356 } 357 for (i = 0; i < ARRAY_SIZE(gio_name_table); i++) { 358 if (id == gio_name_table[i].id) { 359 name = gio_name_table[i].name; 360 break; 361 } 362 } 363 printk(KERN_INFO "GIO: slot %d : %s (id %x)\n", 364 slotno, name, id); 365 gio_dev = kzalloc(sizeof *gio_dev, GFP_KERNEL); 366 gio_dev->name = name; 367 gio_dev->slotno = slotno; 368 gio_dev->id.id = id; 369 gio_dev->resource.start = addr; 370 gio_dev->resource.end = addr + 0x3fffff; 371 gio_dev->resource.flags = IORESOURCE_MEM; 372 dev_set_name(&gio_dev->dev, "%d", slotno); 373 gio_device_register(gio_dev); 374 } else 375 printk(KERN_INFO "GIO: slot %d : Empty\n", slotno); 376} 377 378static struct bus_type gio_bus_type = { 379 .name = "gio", 380 .dev_attrs = gio_dev_attrs, 381 .match = gio_bus_match, 382 .probe = gio_device_probe, 383 .remove = gio_device_remove, 384 .suspend = gio_device_suspend, 385 .resume = gio_device_resume, 386 .shutdown = gio_device_shutdown, 387 .uevent = gio_device_uevent, 388}; 389 390static struct resource gio_bus_resource = { 391 .start = GIO_SLOT_GFX_BASE, 392 .end = GIO_SLOT_GFX_BASE + 0x9fffff, 393 .name = "GIO Bus", 394 .flags = IORESOURCE_MEM, 395}; 396 397int __init ip22_gio_init(void) 398{ 399 unsigned int pbdma __maybe_unused; 400 int ret; 401 402 ret = device_register(&gio_bus); 403 if (ret) 404 return ret; 405 406 ret = bus_register(&gio_bus_type); 407 if (!ret) { 408 request_resource(&iomem_resource, &gio_bus_resource); 409 printk(KERN_INFO "GIO: Probing bus...\n"); 410 411 if (ip22_is_fullhouse() || 412 !get_dbe(pbdma, (unsigned int *)&hpc3c1->pbdma[1])) { 413 /* Indigo2 and ChallengeS */ 414 ip22_check_gio(0, GIO_SLOT_GFX_BASE); 415 ip22_check_gio(1, GIO_SLOT_EXP0_BASE); 416 } else { 417 /* Indy */ 418 ip22_check_gio(0, GIO_SLOT_GFX_BASE); 419 ip22_check_gio(1, GIO_SLOT_EXP0_BASE); 420 ip22_check_gio(2, GIO_SLOT_EXP1_BASE); 421 } 422 } else 423 device_unregister(&gio_bus); 424 425 return ret; 426} 427 428subsys_initcall(ip22_gio_init); 429