blob: a6d7dd2c0c3edd2d8ae159f528933e23d026f706 [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"
Harald Welte0709d2d2017-05-11 00:06:00 +020010#include "trace.h"
Harald Welte31f817c2017-02-03 22:21:32 +010011#include "wwan_perst.h"
Harald Welte9d90d282018-06-29 22:25:42 +020012#include <osmocom/core/timer.h>
Harald Welte987f59a2017-02-04 12:34:35 +010013
Harald Weltecb093ce2017-05-08 22:28:41 +020014struct wwan_perst {
Harald Welte514c6d12017-11-03 20:40:56 +010015 uint8_t idx;
Harald Weltecb093ce2017-05-08 22:28:41 +020016 const Pin pin;
17 struct osmo_timer_list timer;
18};
Harald Welte31f817c2017-02-03 22:21:32 +010019
20#ifdef PIN_PERST1
Harald Weltecb093ce2017-05-08 22:28:41 +020021static struct wwan_perst perst1 = {
Harald Welte514c6d12017-11-03 20:40:56 +010022 .idx = 0,
Harald Weltecb093ce2017-05-08 22:28:41 +020023 .pin = PIN_PERST1,
24};
Harald Welte31f817c2017-02-03 22:21:32 +010025#endif
26
27#ifdef PIN_PERST2
Harald Weltecb093ce2017-05-08 22:28:41 +020028static struct wwan_perst perst2 = {
Harald Welte514c6d12017-11-03 20:40:56 +010029 .idx = 1,
Harald Weltecb093ce2017-05-08 22:28:41 +020030 .pin = PIN_PERST2,
31};
Harald Welte31f817c2017-02-03 22:21:32 +010032#endif
33
Harald Welte114e74d2017-05-09 06:45:27 +020034static int initialized = 0;
35
Harald Welte987f59a2017-02-04 12:34:35 +010036static void perst_tmr_cb(void *data)
37{
Harald Weltecb093ce2017-05-08 22:28:41 +020038 struct wwan_perst *perst = data;
Harald Welte987f59a2017-02-04 12:34:35 +010039 /* release the (low-active) reset */
Harald Welte514c6d12017-11-03 20:40:56 +010040 TRACE_INFO("%u: De-asserting modem reset\r\n", perst->idx);
Harald Weltecb093ce2017-05-08 22:28:41 +020041 PIO_Clear(&perst->pin);
Harald Welte987f59a2017-02-04 12:34:35 +010042}
43
Harald Weltecb093ce2017-05-08 22:28:41 +020044static struct wwan_perst *get_perst_for_modem(int modem_nr)
Harald Welte31f817c2017-02-03 22:21:32 +010045{
Harald Welte114e74d2017-05-09 06:45:27 +020046 if (!initialized) {
47 TRACE_ERROR("Somebody forgot to call wwan_perst_init()\r\n");
48 wwan_perst_init();
49 }
50
Harald Welte31f817c2017-02-03 22:21:32 +010051 switch (modem_nr) {
52#ifdef PIN_PERST1
Harald Welte44622df2017-05-11 00:04:50 +020053 case 0:
Harald Weltecb093ce2017-05-08 22:28:41 +020054 return &perst1;
Harald Welte31f817c2017-02-03 22:21:32 +010055#endif
56#ifdef PIN_PERST2
Harald Welte44622df2017-05-11 00:04:50 +020057 case 1:
Harald Weltecb093ce2017-05-08 22:28:41 +020058 return &perst2;
Harald Welte31f817c2017-02-03 22:21:32 +010059#endif
60 default:
Harald Weltecb093ce2017-05-08 22:28:41 +020061 return NULL;
Harald Welte31f817c2017-02-03 22:21:32 +010062 }
Harald Weltecb093ce2017-05-08 22:28:41 +020063}
64
65int wwan_perst_do_reset_pulse(int modem_nr, unsigned int duration_ms)
66{
67 struct wwan_perst *perst = get_perst_for_modem(modem_nr);
68 if (!perst)
69 return -1;
70
Harald Welte0709d2d2017-05-11 00:06:00 +020071 TRACE_INFO("%u: Asserting modem reset\r\n", modem_nr);
Harald Weltecb093ce2017-05-08 22:28:41 +020072 PIO_Set(&perst->pin);
73 osmo_timer_schedule(&perst->timer, duration_ms/1000, (duration_ms%1000)*1000);
74
75 return 0;
76}
77
78int wwan_perst_set(int modem_nr, int active)
79{
80 struct wwan_perst *perst = get_perst_for_modem(modem_nr);
81 if (!perst)
82 return -1;
83
84 osmo_timer_del(&perst->timer);
Harald Welte0709d2d2017-05-11 00:06:00 +020085 if (active) {
86 TRACE_INFO("%u: Asserting modem reset\r\n", modem_nr);
Harald Weltecb093ce2017-05-08 22:28:41 +020087 PIO_Set(&perst->pin);
Harald Welte0709d2d2017-05-11 00:06:00 +020088 } else {
89 TRACE_INFO("%u: De-asserting modem reset\r\n", modem_nr);
Harald Weltecb093ce2017-05-08 22:28:41 +020090 PIO_Clear(&perst->pin);
Harald Welte0709d2d2017-05-11 00:06:00 +020091 }
Harald Welte987f59a2017-02-04 12:34:35 +010092
Harald Welte31f817c2017-02-03 22:21:32 +010093 return 0;
94}
95
96int wwan_perst_init(void)
97{
98 int num_perst = 0;
99#ifdef PIN_PERST1
Harald Weltecb093ce2017-05-08 22:28:41 +0200100 PIO_Configure(&perst1.pin, 1);
101 perst1.timer.cb = perst_tmr_cb;
102 perst1.timer.data = (void *) &perst1;
Harald Welte31f817c2017-02-03 22:21:32 +0100103 num_perst++;
104#endif
105
106#ifdef PIN_PERST2
Harald Weltecb093ce2017-05-08 22:28:41 +0200107 PIO_Configure(&perst2.pin, 1);
108 perst2.timer.cb = perst_tmr_cb;
109 perst2.timer.data = (void *) &perst2;
Harald Welte31f817c2017-02-03 22:21:32 +0100110 num_perst++;
111#endif
Harald Welteeb50c9f2017-11-03 20:50:47 +0100112 initialized = 1;
Harald Welte31f817c2017-02-03 22:21:32 +0100113 return num_perst;
114}