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

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

Version: ~ [ linux-5.9-rc6 ] ~ [ linux-5.8.10 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.66 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.146 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.198 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.236 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.236 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.85 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ 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.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

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

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | 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.

osdn.jp