1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
|
//
// Copyright (C) 2010 Andy Pugh
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
//
// Onboard LED driver for the Mesa FPGA cards
#include <linux/slab.h>
#include "rtapi.h"
#include "rtapi_string.h"
#include "rtapi_math.h"
#include "hal.h"
#include "hal/drivers/mesa-hostmot2/hostmot2.h"
int hm2_led_parse_md(hostmot2_t *hm2, int md_index) {
hm2_module_descriptor_t *md = &hm2->md[md_index];
int r;
//
// some standard sanity checks
//
if (!hm2_md_is_consistent_or_complain(hm2, md_index, 0, 1, 4, 0x0000)) {
HM2_ERR("inconsistent Module Descriptor!\n");
return -EINVAL;
}
// LEDs were enumerated during llio setup
if (hm2->llio->num_leds == 0 || hm2->config.num_leds == 0) return 0;
if (hm2->config.num_leds > hm2->llio->num_leds) {
hm2->config.num_leds = hm2->llio->num_leds;
HM2_ERR( "There are only %d LEDs on this board type, defaulting to %d\n",
hm2->llio->num_leds, hm2->config.num_leds );
}
else if (hm2->config.num_leds == -1) {
hm2->config.num_leds = hm2->llio->num_leds;
}
//
// looks good, start initializing
//
// allocate the module-global HAL shared memory
hm2->led.instance = (hm2_led_instance_t *)hal_malloc(hm2->config.num_leds * sizeof(hm2_led_instance_t));
if (hm2->led.instance == NULL) {
HM2_ERR("out of memory!\n");
r = -ENOMEM;
goto fail0;
}
hm2->led.led_reg = (u32 *)kmalloc( sizeof(u32), GFP_KERNEL);
if (hm2->led.led_reg == NULL) {
HM2_ERR("out of memory!\n");
r = -ENOMEM;
goto fail0;
}
hm2->led.led_addr = md->base_address;
// export to HAL
{
int i;
char name[HAL_NAME_LEN+1];
for (i = 0 ; i < hm2->config.num_leds ; i++) {
rtapi_snprintf(name, sizeof(name), "%s.led.CR%02d", hm2->llio->name, i + 1 );
r = hal_pin_bit_new(name, HAL_IN, &(hm2->led.instance[i].led), hm2->llio->comp_id);
if (r < 0) {
HM2_ERR("error adding pin '%s', aborting\n", name);
goto fail1;
}
}
return 1;
fail1:
kfree(hm2->led.led_reg);
fail0:
return r;
}
}
void hm2_led_write(hostmot2_t *hm2) {
u32 regval = 0;
int i;
for (i = 0 ; i < hm2->config.num_leds; i++ ) {
if (*hm2->led.instance[i].led) {
regval |= 1 << (31 - i);
}
}
if (regval != hm2->led.written_buff) {
*hm2->led.led_reg = regval;
hm2->led.written_buff = regval;
hm2->llio->write(hm2->llio, hm2->led.led_addr, hm2->led.led_reg, sizeof(u32));
}
}
void hm2_led_cleanup(hostmot2_t *hm2) {
if (hm2->led.led_reg != NULL) {
kfree(hm2->led.led_reg);
hm2->led.led_reg = NULL;
}
}
|