1 // SPDX-License-Identifier: GPL-2.0
3 * Simple heartbeat STM source driver
4 * Copyright (c) 2016, Intel Corporation.
6 * Heartbeat STM source will send repetitive messages over STM devices to a
10 #include <linux/kernel.h>
11 #include <linux/module.h>
12 #include <linux/hrtimer.h>
13 #include <linux/slab.h>
14 #include <linux/stm.h>
16 #define STM_HEARTBEAT_MAX 32
18 static int nr_devs
= 4;
19 static int interval_ms
= 10;
21 module_param(nr_devs
, int, 0400);
22 module_param(interval_ms
, int, 0600);
24 static struct stm_heartbeat
{
25 struct stm_source_data data
;
26 struct hrtimer hrtimer
;
28 } stm_heartbeat
[STM_HEARTBEAT_MAX
];
30 static const char str
[] = "heartbeat stm source driver is here to serve you";
32 static enum hrtimer_restart
stm_heartbeat_hrtimer_handler(struct hrtimer
*hr
)
34 struct stm_heartbeat
*heartbeat
= container_of(hr
, struct stm_heartbeat
,
37 stm_source_write(&heartbeat
->data
, 0, str
, sizeof str
);
38 if (heartbeat
->active
)
39 hrtimer_forward_now(hr
, ms_to_ktime(interval_ms
));
41 return heartbeat
->active
? HRTIMER_RESTART
: HRTIMER_NORESTART
;
44 static int stm_heartbeat_link(struct stm_source_data
*data
)
46 struct stm_heartbeat
*heartbeat
=
47 container_of(data
, struct stm_heartbeat
, data
);
49 heartbeat
->active
= 1;
50 hrtimer_start(&heartbeat
->hrtimer
, ms_to_ktime(interval_ms
),
56 static void stm_heartbeat_unlink(struct stm_source_data
*data
)
58 struct stm_heartbeat
*heartbeat
=
59 container_of(data
, struct stm_heartbeat
, data
);
61 heartbeat
->active
= 0;
62 hrtimer_cancel(&heartbeat
->hrtimer
);
65 static int stm_heartbeat_init(void)
69 if (nr_devs
< 0 || nr_devs
> STM_HEARTBEAT_MAX
)
72 for (i
= 0; i
< nr_devs
; i
++) {
73 stm_heartbeat
[i
].data
.name
=
74 kasprintf(GFP_KERNEL
, "heartbeat.%d", i
);
75 if (!stm_heartbeat
[i
].data
.name
)
78 stm_heartbeat
[i
].data
.nr_chans
= 1;
79 stm_heartbeat
[i
].data
.link
= stm_heartbeat_link
;
80 stm_heartbeat
[i
].data
.unlink
= stm_heartbeat_unlink
;
81 hrtimer_init(&stm_heartbeat
[i
].hrtimer
, CLOCK_MONOTONIC
,
83 stm_heartbeat
[i
].hrtimer
.function
=
84 stm_heartbeat_hrtimer_handler
;
86 ret
= stm_source_register_device(NULL
, &stm_heartbeat
[i
].data
);
94 for (i
--; i
>= 0; i
--) {
95 stm_source_unregister_device(&stm_heartbeat
[i
].data
);
97 kfree(stm_heartbeat
[i
].data
.name
);
103 static void stm_heartbeat_exit(void)
107 for (i
= 0; i
< nr_devs
; i
++) {
108 stm_source_unregister_device(&stm_heartbeat
[i
].data
);
109 kfree(stm_heartbeat
[i
].data
.name
);
113 module_init(stm_heartbeat_init
);
114 module_exit(stm_heartbeat_exit
);
116 MODULE_LICENSE("GPL v2");
117 MODULE_DESCRIPTION("stm_heartbeat driver");
118 MODULE_AUTHOR("Alexander Shishkin <alexander.shishkin@linux.intel.com>");