blob: f16006f343bbfe6d47dfc799d5b0401ffaed5b4f [file] [log] [blame]
Harald Welte31f817c2017-02-03 22:21:32 +01001/* Code to control the PERST lines of attached modems
2 *
3 * Depending on the board this is running on, it might be possible
4 * for the controller to set the status of the PERST input line of
5 * the cellular modem. If the board supports this, it sets the
6 * PIN_PERST1 and/or PIN_PERST2 defines in its board.h file.
7 */
8
9#include "board.h"
10#include "wwan_perst.h"
Harald Welte987f59a2017-02-04 12:34:35 +010011#include "osmocom/core/timer.h"
12
Harald Weltecb093ce2017-05-08 22:28:41 +020013struct wwan_perst {
14 const Pin pin;
15 struct osmo_timer_list timer;
16};
Harald Welte31f817c2017-02-03 22:21:32 +010017
18#ifdef PIN_PERST1
Harald Weltecb093ce2017-05-08 22:28:41 +020019static struct wwan_perst perst1 = {
20 .pin = PIN_PERST1,
21};
Harald Welte31f817c2017-02-03 22:21:32 +010022#endif
23
24#ifdef PIN_PERST2
Harald Weltecb093ce2017-05-08 22:28:41 +020025static struct wwan_perst perst2 = {
26 .pin = PIN_PERST2,
27};
Harald Welte31f817c2017-02-03 22:21:32 +010028#endif
29
Harald Welte114e74d2017-05-09 06:45:27 +020030static int initialized = 0;
31
Harald Welte987f59a2017-02-04 12:34:35 +010032static void perst_tmr_cb(void *data)
33{
Harald Weltecb093ce2017-05-08 22:28:41 +020034 struct wwan_perst *perst = data;
Harald Welte987f59a2017-02-04 12:34:35 +010035 /* release the (low-active) reset */
Harald Weltecb093ce2017-05-08 22:28:41 +020036 PIO_Clear(&perst->pin);
Harald Welte987f59a2017-02-04 12:34:35 +010037}
38
Harald Weltecb093ce2017-05-08 22:28:41 +020039static struct wwan_perst *get_perst_for_modem(int modem_nr)
Harald Welte31f817c2017-02-03 22:21:32 +010040{
Harald Welte114e74d2017-05-09 06:45:27 +020041 if (!initialized) {
42 TRACE_ERROR("Somebody forgot to call wwan_perst_init()\r\n");
43 wwan_perst_init();
44 }
45
Harald Welte31f817c2017-02-03 22:21:32 +010046 switch (modem_nr) {
47#ifdef PIN_PERST1
48 case 1:
Harald Weltecb093ce2017-05-08 22:28:41 +020049 return &perst1;
Harald Welte31f817c2017-02-03 22:21:32 +010050#endif
51#ifdef PIN_PERST2
52 case 2:
Harald Weltecb093ce2017-05-08 22:28:41 +020053 return &perst2;
Harald Welte31f817c2017-02-03 22:21:32 +010054#endif
55 default:
Harald Weltecb093ce2017-05-08 22:28:41 +020056 return NULL;
Harald Welte31f817c2017-02-03 22:21:32 +010057 }
Harald Weltecb093ce2017-05-08 22:28:41 +020058}
59
60int wwan_perst_do_reset_pulse(int modem_nr, unsigned int duration_ms)
61{
62 struct wwan_perst *perst = get_perst_for_modem(modem_nr);
63 if (!perst)
64 return -1;
65
66 PIO_Set(&perst->pin);
67 osmo_timer_schedule(&perst->timer, duration_ms/1000, (duration_ms%1000)*1000);
68
69 return 0;
70}
71
72int wwan_perst_set(int modem_nr, int active)
73{
74 struct wwan_perst *perst = get_perst_for_modem(modem_nr);
75 if (!perst)
76 return -1;
77
78 osmo_timer_del(&perst->timer);
79 if (active)
80 PIO_Set(&perst->pin);
81 else
82 PIO_Clear(&perst->pin);
Harald Welte987f59a2017-02-04 12:34:35 +010083
Harald Welte31f817c2017-02-03 22:21:32 +010084 return 0;
85}
86
87int wwan_perst_init(void)
88{
89 int num_perst = 0;
90#ifdef PIN_PERST1
Harald Weltecb093ce2017-05-08 22:28:41 +020091 PIO_Configure(&perst1.pin, 1);
92 perst1.timer.cb = perst_tmr_cb;
93 perst1.timer.data = (void *) &perst1;
Harald Welte31f817c2017-02-03 22:21:32 +010094 num_perst++;
95#endif
96
97#ifdef PIN_PERST2
Harald Weltecb093ce2017-05-08 22:28:41 +020098 PIO_Configure(&perst2.pin, 1);
99 perst2.timer.cb = perst_tmr_cb;
100 perst2.timer.data = (void *) &perst2;
Harald Welte31f817c2017-02-03 22:21:32 +0100101 num_perst++;
102#endif
103 return num_perst;
104}