~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/sh/drivers/heartbeat.c

Version: ~ [ linux-6.11-rc3 ] ~ [ linux-6.10.4 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.45 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.104 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.164 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.223 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.281 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.319 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0
  2 /*
  3  * Generic heartbeat driver for regular LED banks
  4  *
  5  * Copyright (C) 2007 - 2010  Paul Mundt
  6  *
  7  * Most SH reference boards include a number of individual LEDs that can
  8  * be independently controlled (either via a pre-defined hardware
  9  * function or via the LED class, if desired -- the hardware tends to
 10  * encapsulate some of the same "triggers" that the LED class supports,
 11  * so there's not too much value in it).
 12  *
 13  * Additionally, most of these boards also have a LED bank that we've
 14  * traditionally used for strobing the load average. This use case is
 15  * handled by this driver, rather than giving each LED bit position its
 16  * own struct device.
 17  */
 18 #include <linux/init.h>
 19 #include <linux/platform_device.h>
 20 #include <linux/sched.h>
 21 #include <linux/sched/loadavg.h>
 22 #include <linux/timer.h>
 23 #include <linux/io.h>
 24 #include <linux/slab.h>
 25 #include <asm/heartbeat.h>
 26 
 27 #define DRV_NAME "heartbeat"
 28 #define DRV_VERSION "0.1.2"
 29 
 30 static unsigned char default_bit_pos[] = { 0, 1, 2, 3, 4, 5, 6, 7 };
 31 
 32 static inline void heartbeat_toggle_bit(struct heartbeat_data *hd,
 33                                         unsigned bit, unsigned int inverted)
 34 {
 35         unsigned int new;
 36 
 37         new = (1 << hd->bit_pos[bit]);
 38         if (inverted)
 39                 new = ~new;
 40 
 41         new &= hd->mask;
 42 
 43         switch (hd->regsize) {
 44         case 32:
 45                 new |= ioread32(hd->base) & ~hd->mask;
 46                 iowrite32(new, hd->base);
 47                 break;
 48         case 16:
 49                 new |= ioread16(hd->base) & ~hd->mask;
 50                 iowrite16(new, hd->base);
 51                 break;
 52         default:
 53                 new |= ioread8(hd->base) & ~hd->mask;
 54                 iowrite8(new, hd->base);
 55                 break;
 56         }
 57 }
 58 
 59 static void heartbeat_timer(struct timer_list *t)
 60 {
 61         struct heartbeat_data *hd = from_timer(hd, t, timer);
 62         static unsigned bit = 0, up = 1;
 63 
 64         heartbeat_toggle_bit(hd, bit, hd->flags & HEARTBEAT_INVERTED);
 65 
 66         bit += up;
 67         if ((bit == 0) || (bit == (hd->nr_bits)-1))
 68                 up = -up;
 69 
 70         mod_timer(&hd->timer, jiffies + (110 - ((300 << FSHIFT) /
 71                         ((avenrun[0] / 5) + (3 << FSHIFT)))));
 72 }
 73 
 74 static int heartbeat_drv_probe(struct platform_device *pdev)
 75 {
 76         struct resource *res;
 77         struct heartbeat_data *hd;
 78         int i;
 79 
 80         if (unlikely(pdev->num_resources != 1)) {
 81                 dev_err(&pdev->dev, "invalid number of resources\n");
 82                 return -EINVAL;
 83         }
 84 
 85         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 86         if (unlikely(res == NULL)) {
 87                 dev_err(&pdev->dev, "invalid resource\n");
 88                 return -EINVAL;
 89         }
 90 
 91         if (pdev->dev.platform_data) {
 92                 hd = pdev->dev.platform_data;
 93         } else {
 94                 hd = kzalloc(sizeof(struct heartbeat_data), GFP_KERNEL);
 95                 if (unlikely(!hd))
 96                         return -ENOMEM;
 97         }
 98 
 99         hd->base = ioremap(res->start, resource_size(res));
100         if (unlikely(!hd->base)) {
101                 dev_err(&pdev->dev, "ioremap failed\n");
102 
103                 if (!pdev->dev.platform_data)
104                         kfree(hd);
105 
106                 return -ENXIO;
107         }
108 
109         if (!hd->nr_bits) {
110                 hd->bit_pos = default_bit_pos;
111                 hd->nr_bits = ARRAY_SIZE(default_bit_pos);
112         }
113 
114         hd->mask = 0;
115         for (i = 0; i < hd->nr_bits; i++)
116                 hd->mask |= (1 << hd->bit_pos[i]);
117 
118         if (!hd->regsize) {
119                 switch (res->flags & IORESOURCE_MEM_TYPE_MASK) {
120                 case IORESOURCE_MEM_32BIT:
121                         hd->regsize = 32;
122                         break;
123                 case IORESOURCE_MEM_16BIT:
124                         hd->regsize = 16;
125                         break;
126                 case IORESOURCE_MEM_8BIT:
127                 default:
128                         hd->regsize = 8;
129                         break;
130                 }
131         }
132 
133         timer_setup(&hd->timer, heartbeat_timer, 0);
134         platform_set_drvdata(pdev, hd);
135 
136         return mod_timer(&hd->timer, jiffies + 1);
137 }
138 
139 static struct platform_driver heartbeat_driver = {
140         .probe          = heartbeat_drv_probe,
141         .driver         = {
142                 .name                   = DRV_NAME,
143                 .suppress_bind_attrs    = true,
144         },
145 };
146 
147 static int __init heartbeat_init(void)
148 {
149         printk(KERN_NOTICE DRV_NAME ": version %s loaded\n", DRV_VERSION);
150         return platform_driver_register(&heartbeat_driver);
151 }
152 device_initcall(heartbeat_init);
153 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php