root/drivers/macintosh/rack-meter.c

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

DEFINITIONS

This source file includes following definitions.
  1. get_cpu_idle_time
  2. rackmeter_setup_i2s
  3. rackmeter_set_default_pattern
  4. rackmeter_do_pause
  5. rackmeter_setup_dbdma
  6. rackmeter_do_timer
  7. rackmeter_init_cpu_sniffer
  8. rackmeter_stop_cpu_sniffer
  9. rackmeter_setup
  10. rackmeter_calc_sample
  11. rackmeter_irq
  12. rackmeter_probe
  13. rackmeter_remove
  14. rackmeter_shutdown
  15. rackmeter_init
  16. rackmeter_exit

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * RackMac vu-meter driver
   4  *
   5  * (c) Copyright 2006 Benjamin Herrenschmidt, IBM Corp.
   6  *                    <benh@kernel.crashing.org>
   7  *
   8  * Support the CPU-meter LEDs of the Xserve G5
   9  *
  10  * TODO: Implement PWM to do variable intensity and provide userland
  11  * interface for fun. Also, the CPU-meter could be made nicer by being
  12  * a bit less "immediate" but giving instead a more average load over
  13  * time. Patches welcome :-)
  14  */
  15 #undef DEBUG
  16 
  17 #include <linux/types.h>
  18 #include <linux/kernel.h>
  19 #include <linux/slab.h>
  20 #include <linux/device.h>
  21 #include <linux/interrupt.h>
  22 #include <linux/module.h>
  23 #include <linux/pci.h>
  24 #include <linux/dma-mapping.h>
  25 #include <linux/kernel_stat.h>
  26 #include <linux/of_address.h>
  27 #include <linux/of_irq.h>
  28 
  29 #include <asm/io.h>
  30 #include <asm/prom.h>
  31 #include <asm/machdep.h>
  32 #include <asm/pmac_feature.h>
  33 #include <asm/dbdma.h>
  34 #include <asm/macio.h>
  35 #include <asm/keylargo.h>
  36 
  37 /* Number of samples in a sample buffer */
  38 #define SAMPLE_COUNT            256
  39 
  40 /* CPU meter sampling rate in ms */
  41 #define CPU_SAMPLING_RATE       250
  42 
  43 struct rackmeter_dma {
  44         struct dbdma_cmd        cmd[4]                  ____cacheline_aligned;
  45         u32                     mark                    ____cacheline_aligned;
  46         u32                     buf1[SAMPLE_COUNT]      ____cacheline_aligned;
  47         u32                     buf2[SAMPLE_COUNT]      ____cacheline_aligned;
  48 } ____cacheline_aligned;
  49 
  50 struct rackmeter_cpu {
  51         struct delayed_work     sniffer;
  52         struct rackmeter        *rm;
  53         u64                     prev_wall;
  54         u64                     prev_idle;
  55         int                     zero;
  56 } ____cacheline_aligned;
  57 
  58 struct rackmeter {
  59         struct macio_dev                *mdev;
  60         unsigned int                    irq;
  61         struct device_node              *i2s;
  62         u8                              *ubuf;
  63         struct dbdma_regs __iomem       *dma_regs;
  64         void __iomem                    *i2s_regs;
  65         dma_addr_t                      dma_buf_p;
  66         struct rackmeter_dma            *dma_buf_v;
  67         int                             stale_irq;
  68         struct rackmeter_cpu            cpu[2];
  69         int                             paused;
  70         struct mutex                    sem;
  71 };
  72 
  73 /* To be set as a tunable */
  74 static int rackmeter_ignore_nice;
  75 
  76 /* This GPIO is whacked by the OS X driver when initializing */
  77 #define RACKMETER_MAGIC_GPIO    0x78
  78 
  79 /* This is copied from cpufreq_ondemand, maybe we should put it in
  80  * a common header somewhere
  81  */
  82 static inline u64 get_cpu_idle_time(unsigned int cpu)
  83 {
  84         u64 retval;
  85 
  86         retval = kcpustat_cpu(cpu).cpustat[CPUTIME_IDLE] +
  87                  kcpustat_cpu(cpu).cpustat[CPUTIME_IOWAIT];
  88 
  89         if (rackmeter_ignore_nice)
  90                 retval += kcpustat_cpu(cpu).cpustat[CPUTIME_NICE];
  91 
  92         return retval;
  93 }
  94 
  95 static void rackmeter_setup_i2s(struct rackmeter *rm)
  96 {
  97         struct macio_chip *macio = rm->mdev->bus->chip;
  98 
  99         /* First whack magic GPIO */
 100         pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, RACKMETER_MAGIC_GPIO, 5);
 101 
 102 
 103         /* Call feature code to enable the sound channel and the proper
 104          * clock sources
 105          */
 106         pmac_call_feature(PMAC_FTR_SOUND_CHIP_ENABLE, rm->i2s, 0, 1);
 107 
 108         /* Power i2s and stop i2s clock. We whack MacIO FCRs directly for now.
 109          * This is a bit racy, thus we should add new platform functions to
 110          * handle that. snd-aoa needs that too
 111          */
 112         MACIO_BIS(KEYLARGO_FCR1, KL1_I2S0_ENABLE);
 113         MACIO_BIC(KEYLARGO_FCR1, KL1_I2S0_CLK_ENABLE_BIT);
 114         (void)MACIO_IN32(KEYLARGO_FCR1);
 115         udelay(10);
 116 
 117         /* Then setup i2s. For now, we use the same magic value that
 118          * the OS X driver seems to use. We might want to play around
 119          * with the clock divisors later
 120          */
 121         out_le32(rm->i2s_regs + 0x10, 0x01fa0000);
 122         (void)in_le32(rm->i2s_regs + 0x10);
 123         udelay(10);
 124 
 125         /* Fully restart i2s*/
 126         MACIO_BIS(KEYLARGO_FCR1, KL1_I2S0_CELL_ENABLE |
 127                   KL1_I2S0_CLK_ENABLE_BIT);
 128         (void)MACIO_IN32(KEYLARGO_FCR1);
 129         udelay(10);
 130 }
 131 
 132 static void rackmeter_set_default_pattern(struct rackmeter *rm)
 133 {
 134         int i;
 135 
 136         for (i = 0; i < 16; i++) {
 137                 if (i < 8)
 138                         rm->ubuf[i] = (i & 1) * 255;
 139                 else
 140                         rm->ubuf[i] = ((~i) & 1) * 255;
 141         }
 142 }
 143 
 144 static void rackmeter_do_pause(struct rackmeter *rm, int pause)
 145 {
 146         struct rackmeter_dma *rdma = rm->dma_buf_v;
 147 
 148         pr_debug("rackmeter: %s\n", pause ? "paused" : "started");
 149 
 150         rm->paused = pause;
 151         if (pause) {
 152                 DBDMA_DO_STOP(rm->dma_regs);
 153                 return;
 154         }
 155         memset(rdma->buf1, 0, sizeof(rdma->buf1));
 156         memset(rdma->buf2, 0, sizeof(rdma->buf2));
 157 
 158         rm->dma_buf_v->mark = 0;
 159 
 160         mb();
 161         out_le32(&rm->dma_regs->cmdptr_hi, 0);
 162         out_le32(&rm->dma_regs->cmdptr, rm->dma_buf_p);
 163         out_le32(&rm->dma_regs->control, (RUN << 16) | RUN);
 164 }
 165 
 166 static void rackmeter_setup_dbdma(struct rackmeter *rm)
 167 {
 168         struct rackmeter_dma *db = rm->dma_buf_v;
 169         struct dbdma_cmd *cmd = db->cmd;
 170 
 171         /* Make sure dbdma is reset */
 172         DBDMA_DO_RESET(rm->dma_regs);
 173 
 174         pr_debug("rackmeter: mark offset=0x%zx\n",
 175                  offsetof(struct rackmeter_dma, mark));
 176         pr_debug("rackmeter: buf1 offset=0x%zx\n",
 177                  offsetof(struct rackmeter_dma, buf1));
 178         pr_debug("rackmeter: buf2 offset=0x%zx\n",
 179                  offsetof(struct rackmeter_dma, buf2));
 180 
 181         /* Prepare 4 dbdma commands for the 2 buffers */
 182         memset(cmd, 0, 4 * sizeof(struct dbdma_cmd));
 183         cmd->req_count = cpu_to_le16(4);
 184         cmd->command = cpu_to_le16(STORE_WORD | INTR_ALWAYS | KEY_SYSTEM);
 185         cmd->phy_addr = cpu_to_le32(rm->dma_buf_p +
 186                 offsetof(struct rackmeter_dma, mark));
 187         cmd->cmd_dep = cpu_to_le32(0x02000000);
 188         cmd++;
 189 
 190         cmd->req_count = cpu_to_le16(SAMPLE_COUNT * 4);
 191         cmd->command = cpu_to_le16(OUTPUT_MORE);
 192         cmd->phy_addr = cpu_to_le32(rm->dma_buf_p +
 193                 offsetof(struct rackmeter_dma, buf1));
 194         cmd++;
 195 
 196         cmd->req_count = cpu_to_le16(4);
 197         cmd->command = cpu_to_le16(STORE_WORD | INTR_ALWAYS | KEY_SYSTEM);
 198         cmd->phy_addr = cpu_to_le32(rm->dma_buf_p +
 199                 offsetof(struct rackmeter_dma, mark));
 200         cmd->cmd_dep = cpu_to_le32(0x01000000);
 201         cmd++;
 202 
 203         cmd->req_count = cpu_to_le16(SAMPLE_COUNT * 4);
 204         cmd->command = cpu_to_le16(OUTPUT_MORE | BR_ALWAYS);
 205         cmd->phy_addr = cpu_to_le32(rm->dma_buf_p +
 206                 offsetof(struct rackmeter_dma, buf2));
 207         cmd->cmd_dep = cpu_to_le32(rm->dma_buf_p);
 208 
 209         rackmeter_do_pause(rm, 0);
 210 }
 211 
 212 static void rackmeter_do_timer(struct work_struct *work)
 213 {
 214         struct rackmeter_cpu *rcpu =
 215                 container_of(work, struct rackmeter_cpu, sniffer.work);
 216         struct rackmeter *rm = rcpu->rm;
 217         unsigned int cpu = smp_processor_id();
 218         u64 cur_nsecs, total_idle_nsecs;
 219         u64 total_nsecs, idle_nsecs;
 220         int i, offset, load, cumm, pause;
 221 
 222         cur_nsecs = jiffies64_to_nsecs(get_jiffies_64());
 223         total_nsecs = cur_nsecs - rcpu->prev_wall;
 224         rcpu->prev_wall = cur_nsecs;
 225 
 226         total_idle_nsecs = get_cpu_idle_time(cpu);
 227         idle_nsecs = total_idle_nsecs - rcpu->prev_idle;
 228         idle_nsecs = min(idle_nsecs, total_nsecs);
 229         rcpu->prev_idle = total_idle_nsecs;
 230 
 231         /* We do a very dumb calculation to update the LEDs for now,
 232          * we'll do better once we have actual PWM implemented
 233          */
 234         load = div64_u64(9 * (total_nsecs - idle_nsecs), total_nsecs);
 235 
 236         offset = cpu << 3;
 237         cumm = 0;
 238         for (i = 0; i < 8; i++) {
 239                 u8 ub = (load > i) ? 0xff : 0;
 240                 rm->ubuf[i + offset] = ub;
 241                 cumm |= ub;
 242         }
 243         rcpu->zero = (cumm == 0);
 244 
 245         /* Now check if LEDs are all 0, we can stop DMA */
 246         pause = (rm->cpu[0].zero && rm->cpu[1].zero);
 247         if (pause != rm->paused) {
 248                 mutex_lock(&rm->sem);
 249                 pause = (rm->cpu[0].zero && rm->cpu[1].zero);
 250                 rackmeter_do_pause(rm, pause);
 251                 mutex_unlock(&rm->sem);
 252         }
 253         schedule_delayed_work_on(cpu, &rcpu->sniffer,
 254                                  msecs_to_jiffies(CPU_SAMPLING_RATE));
 255 }
 256 
 257 static void rackmeter_init_cpu_sniffer(struct rackmeter *rm)
 258 {
 259         unsigned int cpu;
 260 
 261         /* This driver works only with 1 or 2 CPUs numbered 0 and 1,
 262          * but that's really all we have on Apple Xserve. It doesn't
 263          * play very nice with CPU hotplug neither but we don't do that
 264          * on those machines yet
 265          */
 266 
 267         rm->cpu[0].rm = rm;
 268         INIT_DELAYED_WORK(&rm->cpu[0].sniffer, rackmeter_do_timer);
 269         rm->cpu[1].rm = rm;
 270         INIT_DELAYED_WORK(&rm->cpu[1].sniffer, rackmeter_do_timer);
 271 
 272         for_each_online_cpu(cpu) {
 273                 struct rackmeter_cpu *rcpu;
 274 
 275                 if (cpu > 1)
 276                         continue;
 277                 rcpu = &rm->cpu[cpu];
 278                 rcpu->prev_idle = get_cpu_idle_time(cpu);
 279                 rcpu->prev_wall = jiffies64_to_nsecs(get_jiffies_64());
 280                 schedule_delayed_work_on(cpu, &rm->cpu[cpu].sniffer,
 281                                          msecs_to_jiffies(CPU_SAMPLING_RATE));
 282         }
 283 }
 284 
 285 static void rackmeter_stop_cpu_sniffer(struct rackmeter *rm)
 286 {
 287         cancel_delayed_work_sync(&rm->cpu[0].sniffer);
 288         cancel_delayed_work_sync(&rm->cpu[1].sniffer);
 289 }
 290 
 291 static int rackmeter_setup(struct rackmeter *rm)
 292 {
 293         pr_debug("rackmeter: setting up i2s..\n");
 294         rackmeter_setup_i2s(rm);
 295 
 296         pr_debug("rackmeter: setting up default pattern..\n");
 297         rackmeter_set_default_pattern(rm);
 298 
 299         pr_debug("rackmeter: setting up dbdma..\n");
 300         rackmeter_setup_dbdma(rm);
 301 
 302         pr_debug("rackmeter: start CPU measurements..\n");
 303         rackmeter_init_cpu_sniffer(rm);
 304 
 305         printk(KERN_INFO "RackMeter initialized\n");
 306 
 307         return 0;
 308 }
 309 
 310 /*  XXX FIXME: No PWM yet, this is 0/1 */
 311 static u32 rackmeter_calc_sample(struct rackmeter *rm, unsigned int index)
 312 {
 313         int led;
 314         u32 sample = 0;
 315 
 316         for (led = 0; led < 16; led++) {
 317                 sample >>= 1;
 318                 sample |= ((rm->ubuf[led] >= 0x80) << 15);
 319         }
 320         return (sample << 17) | (sample >> 15);
 321 }
 322 
 323 static irqreturn_t rackmeter_irq(int irq, void *arg)
 324 {
 325         struct rackmeter *rm = arg;
 326         struct rackmeter_dma *db = rm->dma_buf_v;
 327         unsigned int mark, i;
 328         u32 *buf;
 329 
 330         /* Flush PCI buffers with an MMIO read. Maybe we could actually
 331          * check the status one day ... in case things go wrong, though
 332          * this never happened to me
 333          */
 334         (void)in_le32(&rm->dma_regs->status);
 335 
 336         /* Make sure the CPU gets us in order */
 337         rmb();
 338 
 339         /* Read mark */
 340         mark = db->mark;
 341         if (mark != 1 && mark != 2) {
 342                 printk(KERN_WARNING "rackmeter: Incorrect DMA mark 0x%08x\n",
 343                        mark);
 344                 /* We allow for 3 errors like that (stale DBDMA irqs) */
 345                 if (++rm->stale_irq > 3) {
 346                         printk(KERN_ERR "rackmeter: Too many errors,"
 347                                " stopping DMA\n");
 348                         DBDMA_DO_RESET(rm->dma_regs);
 349                 }
 350                 return IRQ_HANDLED;
 351         }
 352 
 353         /* Next buffer we need to fill is mark value */
 354         buf = mark == 1 ? db->buf1 : db->buf2;
 355 
 356         /* Fill it now. This routine converts the 8 bits depth sample array
 357          * into the PWM bitmap for each LED.
 358          */
 359         for (i = 0; i < SAMPLE_COUNT; i++)
 360                 buf[i] = rackmeter_calc_sample(rm, i);
 361 
 362 
 363         return IRQ_HANDLED;
 364 }
 365 
 366 static int rackmeter_probe(struct macio_dev* mdev,
 367                            const struct of_device_id *match)
 368 {
 369         struct device_node *i2s = NULL, *np = NULL;
 370         struct rackmeter *rm = NULL;
 371         struct resource ri2s, rdma;
 372         int rc = -ENODEV;
 373 
 374         pr_debug("rackmeter_probe()\n");
 375 
 376         /* Get i2s-a node */
 377         for_each_child_of_node(mdev->ofdev.dev.of_node, i2s)
 378                 if (of_node_name_eq(i2s, "i2s-a"))
 379                         break;
 380 
 381         if (i2s == NULL) {
 382                 pr_debug("  i2s-a child not found\n");
 383                 goto bail;
 384         }
 385         /* Get lightshow or virtual sound */
 386         for_each_child_of_node(i2s, np) {
 387                if (of_node_name_eq(np, "lightshow"))
 388                        break;
 389                if (of_node_name_eq(np, "sound") &&
 390                    of_get_property(np, "virtual", NULL) != NULL)
 391                        break;
 392         }
 393         if (np == NULL) {
 394                 pr_debug("  lightshow or sound+virtual child not found\n");
 395                 goto bail;
 396         }
 397 
 398         /* Create and initialize our instance data */
 399         rm = kzalloc(sizeof(*rm), GFP_KERNEL);
 400         if (rm == NULL) {
 401                 printk(KERN_ERR "rackmeter: failed to allocate memory !\n");
 402                 rc = -ENOMEM;
 403                 goto bail_release;
 404         }
 405         rm->mdev = mdev;
 406         rm->i2s = i2s;
 407         mutex_init(&rm->sem);
 408         dev_set_drvdata(&mdev->ofdev.dev, rm);
 409         /* Check resources availability. We need at least resource 0 and 1 */
 410 #if 0 /* Use that when i2s-a is finally an mdev per-se */
 411         if (macio_resource_count(mdev) < 2 || macio_irq_count(mdev) < 2) {
 412                 printk(KERN_ERR
 413                        "rackmeter: found match but lacks resources: %pOF"
 414                        " (%d resources, %d interrupts)\n",
 415                        mdev->ofdev.dev.of_node);
 416                 rc = -ENXIO;
 417                 goto bail_free;
 418         }
 419         if (macio_request_resources(mdev, "rackmeter")) {
 420                 printk(KERN_ERR
 421                        "rackmeter: failed to request resources: %pOF\n",
 422                        mdev->ofdev.dev.of_node);
 423                 rc = -EBUSY;
 424                 goto bail_free;
 425         }
 426         rm->irq = macio_irq(mdev, 1);
 427 #else
 428         rm->irq = irq_of_parse_and_map(i2s, 1);
 429         if (!rm->irq ||
 430             of_address_to_resource(i2s, 0, &ri2s) ||
 431             of_address_to_resource(i2s, 1, &rdma)) {
 432                 printk(KERN_ERR
 433                        "rackmeter: found match but lacks resources: %pOF",
 434                        mdev->ofdev.dev.of_node);
 435                 rc = -ENXIO;
 436                 goto bail_free;
 437         }
 438 #endif
 439 
 440         pr_debug("  i2s @0x%08x\n", (unsigned int)ri2s.start);
 441         pr_debug("  dma @0x%08x\n", (unsigned int)rdma.start);
 442         pr_debug("  irq %d\n", rm->irq);
 443 
 444         rm->ubuf = (u8 *)__get_free_page(GFP_KERNEL);
 445         if (rm->ubuf == NULL) {
 446                 printk(KERN_ERR
 447                        "rackmeter: failed to allocate samples page !\n");
 448                 rc = -ENOMEM;
 449                 goto bail_release;
 450         }
 451 
 452         rm->dma_buf_v = dma_alloc_coherent(&macio_get_pci_dev(mdev)->dev,
 453                                            sizeof(struct rackmeter_dma),
 454                                            &rm->dma_buf_p, GFP_KERNEL);
 455         if (rm->dma_buf_v == NULL) {
 456                 printk(KERN_ERR
 457                        "rackmeter: failed to allocate dma buffer !\n");
 458                 rc = -ENOMEM;
 459                 goto bail_free_samples;
 460         }
 461 #if 0
 462         rm->i2s_regs = ioremap(macio_resource_start(mdev, 0), 0x1000);
 463 #else
 464         rm->i2s_regs = ioremap(ri2s.start, 0x1000);
 465 #endif
 466         if (rm->i2s_regs == NULL) {
 467                 printk(KERN_ERR
 468                        "rackmeter: failed to map i2s registers !\n");
 469                 rc = -ENXIO;
 470                 goto bail_free_dma;
 471         }
 472 #if 0
 473         rm->dma_regs = ioremap(macio_resource_start(mdev, 1), 0x100);
 474 #else
 475         rm->dma_regs = ioremap(rdma.start, 0x100);
 476 #endif
 477         if (rm->dma_regs == NULL) {
 478                 printk(KERN_ERR
 479                        "rackmeter: failed to map dma registers !\n");
 480                 rc = -ENXIO;
 481                 goto bail_unmap_i2s;
 482         }
 483 
 484         rc = rackmeter_setup(rm);
 485         if (rc) {
 486                 printk(KERN_ERR
 487                        "rackmeter: failed to initialize !\n");
 488                 rc = -ENXIO;
 489                 goto bail_unmap_dma;
 490         }
 491 
 492         rc = request_irq(rm->irq, rackmeter_irq, 0, "rackmeter", rm);
 493         if (rc != 0) {
 494                 printk(KERN_ERR
 495                        "rackmeter: failed to request interrupt !\n");
 496                 goto bail_stop_dma;
 497         }
 498         of_node_put(np);
 499         return 0;
 500 
 501  bail_stop_dma:
 502         DBDMA_DO_RESET(rm->dma_regs);
 503  bail_unmap_dma:
 504         iounmap(rm->dma_regs);
 505  bail_unmap_i2s:
 506         iounmap(rm->i2s_regs);
 507  bail_free_dma:
 508         dma_free_coherent(&macio_get_pci_dev(mdev)->dev,
 509                           sizeof(struct rackmeter_dma),
 510                           rm->dma_buf_v, rm->dma_buf_p);
 511  bail_free_samples:
 512         free_page((unsigned long)rm->ubuf);
 513  bail_release:
 514 #if 0
 515         macio_release_resources(mdev);
 516 #endif
 517  bail_free:
 518         kfree(rm);
 519  bail:
 520         of_node_put(i2s);
 521         of_node_put(np);
 522         dev_set_drvdata(&mdev->ofdev.dev, NULL);
 523         return rc;
 524 }
 525 
 526 static int rackmeter_remove(struct macio_dev* mdev)
 527 {
 528         struct rackmeter *rm = dev_get_drvdata(&mdev->ofdev.dev);
 529 
 530         /* Stop CPU sniffer timer & work queues */
 531         rackmeter_stop_cpu_sniffer(rm);
 532 
 533         /* Clear reference to private data */
 534         dev_set_drvdata(&mdev->ofdev.dev, NULL);
 535 
 536         /* Stop/reset dbdma */
 537         DBDMA_DO_RESET(rm->dma_regs);
 538 
 539         /* Release the IRQ */
 540         free_irq(rm->irq, rm);
 541 
 542         /* Unmap registers */
 543         iounmap(rm->dma_regs);
 544         iounmap(rm->i2s_regs);
 545 
 546         /* Free DMA */
 547         dma_free_coherent(&macio_get_pci_dev(mdev)->dev,
 548                           sizeof(struct rackmeter_dma),
 549                           rm->dma_buf_v, rm->dma_buf_p);
 550 
 551         /* Free samples */
 552         free_page((unsigned long)rm->ubuf);
 553 
 554 #if 0
 555         /* Release resources */
 556         macio_release_resources(mdev);
 557 #endif
 558 
 559         /* Get rid of me */
 560         kfree(rm);
 561 
 562         return 0;
 563 }
 564 
 565 static int rackmeter_shutdown(struct macio_dev* mdev)
 566 {
 567         struct rackmeter *rm = dev_get_drvdata(&mdev->ofdev.dev);
 568 
 569         if (rm == NULL)
 570                 return -ENODEV;
 571 
 572         /* Stop CPU sniffer timer & work queues */
 573         rackmeter_stop_cpu_sniffer(rm);
 574 
 575         /* Stop/reset dbdma */
 576         DBDMA_DO_RESET(rm->dma_regs);
 577 
 578         return 0;
 579 }
 580 
 581 static const struct of_device_id rackmeter_match[] = {
 582         { .name = "i2s" },
 583         { }
 584 };
 585 MODULE_DEVICE_TABLE(of, rackmeter_match);
 586 
 587 static struct macio_driver rackmeter_driver = {
 588         .driver = {
 589                 .name = "rackmeter",
 590                 .owner = THIS_MODULE,
 591                 .of_match_table = rackmeter_match,
 592         },
 593         .probe = rackmeter_probe,
 594         .remove = rackmeter_remove,
 595         .shutdown = rackmeter_shutdown,
 596 };
 597 
 598 
 599 static int __init rackmeter_init(void)
 600 {
 601         pr_debug("rackmeter_init()\n");
 602 
 603         return macio_register_driver(&rackmeter_driver);
 604 }
 605 
 606 static void __exit rackmeter_exit(void)
 607 {
 608         pr_debug("rackmeter_exit()\n");
 609 
 610         macio_unregister_driver(&rackmeter_driver);
 611 }
 612 
 613 module_init(rackmeter_init);
 614 module_exit(rackmeter_exit);
 615 
 616 
 617 MODULE_LICENSE("GPL");
 618 MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>");
 619 MODULE_DESCRIPTION("RackMeter: Support vu-meter on XServe front panel");

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