forked from projectara/gbsim
-
Notifications
You must be signed in to change notification settings - Fork 0
/
pwm.c
142 lines (132 loc) · 3.87 KB
/
pwm.c
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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
/*
* Greybus Simulator
*
* Copyright 2014 Google Inc.
* Copyright 2014 Linaro Ltd.
*
* Provided under the three clause BSD license found in the LICENSE file.
*/
#include <fcntl.h>
#include <libsoc_pwm.h>
#include <linux/fs.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <errno.h>
#include "gbsim.h"
static int pwm_on[2];
static pwm *pwms[2];
int pwm_handler(uint16_t cport_id, uint16_t hd_cport_id, void *rbuf,
size_t rsize, void *tbuf, size_t tsize)
{
struct gb_operation_msg_hdr *oph;
struct op_msg *op_req = rbuf;
struct op_msg *op_rsp;
__u32 duty;
__u32 period;
size_t payload_size;
uint16_t message_size;
uint8_t result = PROTOCOL_STATUS_SUCCESS;
op_rsp = (struct op_msg *)tbuf;
oph = (struct gb_operation_msg_hdr *)&op_req->header;
switch (oph->type) {
case GB_PWM_TYPE_PROTOCOL_VERSION:
payload_size = sizeof(struct gb_protocol_version_response);
op_rsp->pv_rsp.major = GREYBUS_VERSION_MAJOR;
op_rsp->pv_rsp.minor = GREYBUS_VERSION_MINOR;
break;
case GB_PWM_TYPE_PWM_COUNT:
payload_size = sizeof(struct gb_pwm_count_response);
op_rsp->pwm_cnt_rsp.count = 1; /* Something arbitrary, but useful */
break;
case GB_PWM_TYPE_ACTIVATE:
payload_size = 0;
gbsim_debug("PWM %d activate request\n ",
op_req->pwm_act_req.which);
break;
case GB_PWM_TYPE_DEACTIVATE:
payload_size = 0;
gbsim_debug("PWM %d deactivate request\n ",
op_req->pwm_deact_req.which);
break;
case GB_PWM_TYPE_CONFIG:
payload_size = 0;
duty = le32toh(op_req->pwm_cfg_req.duty);
period = le32toh(op_req->pwm_cfg_req.period);
if (bbb_backend) {
libsoc_pwm_set_duty_cycle(pwms[op_req->pwm_cfg_req.which], duty);
libsoc_pwm_set_period(pwms[op_req->pwm_cfg_req.which], period);
}
gbsim_debug("PWM %d config (%dns/%dns) request\n ",
op_req->pwm_cfg_req.which, duty, period);
break;
case GB_PWM_TYPE_POLARITY:
payload_size = 0;
if (pwm_on[op_req->pwm_pol_req.which]) {
result = PROTOCOL_STATUS_BUSY;
} else if (bbb_backend) {
libsoc_pwm_set_polarity(pwms[op_req->pwm_pol_req.which],
op_req->pwm_pol_req.polarity);
}
gbsim_debug("PWM %d polarity (%s) request\n ",
op_req->pwm_cfg_req.which,
op_req->pwm_pol_req.polarity ? "inverse" : "normal");
break;
case GB_PWM_TYPE_ENABLE:
payload_size = 0;
pwm_on[op_req->pwm_enb_req.which] = 1;
if (bbb_backend)
libsoc_pwm_set_enabled(pwms[op_req->pwm_enb_req.which], ENABLED);
gbsim_debug("PWM %d enable request\n ",
op_req->pwm_enb_req.which);
break;
case GB_PWM_TYPE_DISABLE:
payload_size = 0;
pwm_on[op_req->pwm_dis_req.which] = 0;
if (bbb_backend)
libsoc_pwm_set_enabled(pwms[op_req->pwm_dis_req.which], DISABLED);
gbsim_debug("PWM %d disable request\n ",
op_req->pwm_dis_req.which);
break;
default:
gbsim_error("pwm operation type %02x not supported\n", oph->type);
return -EINVAL;
}
message_size = sizeof(struct gb_operation_msg_hdr) + payload_size;
return send_response(op_rsp, hd_cport_id, message_size, oph, result);
}
char *pwm_get_operation(uint8_t type)
{
switch (type) {
case GB_PWM_TYPE_INVALID:
return "GB_PWM_TYPE_INVALID";
case GB_PWM_TYPE_PROTOCOL_VERSION:
return "GB_PWM_TYPE_PROTOCOL_VERSION";
case GB_PWM_TYPE_PWM_COUNT:
return "GB_PWM_TYPE_PWM_COUNT";
case GB_PWM_TYPE_ACTIVATE:
return "GB_PWM_TYPE_ACTIVATE";
case GB_PWM_TYPE_DEACTIVATE:
return "GB_PWM_TYPE_DEACTIVATE";
case GB_PWM_TYPE_CONFIG:
return "GB_PWM_TYPE_CONFIG";
case GB_PWM_TYPE_POLARITY:
return "GB_PWM_TYPE_POLARITY";
case GB_PWM_TYPE_ENABLE:
return "GB_PWM_TYPE_ENABLE";
case GB_PWM_TYPE_DISABLE:
return "GB_PWM_TYPE_DISABLE";
default:
return "(Unknown operation)";
}
}
void pwm_init(void)
{
if (bbb_backend) {
/* Grab PWM0A and PWM0B found on P9-31 and P9-29 */
pwms[0] = libsoc_pwm_request(0, 0, LS_GREEDY);
pwms[1] = libsoc_pwm_request(0, 1, LS_GREEDY);
}
}