root/arch/mips/sgi-ip22/ip22-gio.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. gio_bus_release
  2. gio_match_device
  3. gio_dev_get
  4. gio_dev_put
  5. gio_release_dev
  6. gio_device_register
  7. gio_device_unregister
  8. gio_bus_match
  9. gio_device_probe
  10. gio_device_remove
  11. gio_device_shutdown
  12. modalias_show
  13. name_show
  14. id_show
  15. gio_device_uevent
  16. gio_register_driver
  17. gio_unregister_driver
  18. gio_set_master
  19. ip22_gio_set_64bit
  20. ip22_gio_id
  21. ip22_is_gr2
  22. ip22_check_gio
  23. ip22_gio_init

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

/* [<][>][^][v][top][bottom][index][help] */