| /* Copyright (c) 2013 The Chromium OS Authors. All rights reserved. |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| /* Wireless power management */ |
| |
| #include "common.h" |
| #include "console.h" |
| #include "gpio.h" |
| #include "host_command.h" |
| #include "util.h" |
| #include "wireless.h" |
| |
| /* Unless told otherwise, disable wireless in suspend */ |
| #ifndef CONFIG_WIRELESS_SUSPEND |
| #define CONFIG_WIRELESS_SUSPEND 0 |
| #endif |
| |
| /* |
| * Flags which will be left on when suspending. Other flags will be disabled |
| * when suspending. |
| */ |
| static int suspend_flags = CONFIG_WIRELESS_SUSPEND; |
| |
| /** |
| * Set wireless switch state. |
| * |
| * @param flags Enable flags from ec_commands.h (EC_WIRELESS_SWITCH_*), |
| * 0 to turn all wireless off, or -1 to turn all wireless |
| * on. |
| * @param mask Which of those flags to set |
| */ |
| static void wireless_enable(int flags) |
| { |
| #ifdef WIRELESS_GPIO_WLAN |
| gpio_set_level(WIRELESS_GPIO_WLAN, |
| flags & EC_WIRELESS_SWITCH_WLAN); |
| #endif |
| |
| #ifdef WIRELESS_GPIO_WWAN |
| gpio_set_level(WIRELESS_GPIO_WWAN, |
| flags & EC_WIRELESS_SWITCH_WWAN); |
| #endif |
| |
| #ifdef WIRELESS_GPIO_BLUETOOTH |
| gpio_set_level(WIRELESS_GPIO_BLUETOOTH, |
| flags & EC_WIRELESS_SWITCH_BLUETOOTH); |
| #endif |
| |
| #ifdef WIRELESS_GPIO_WLAN_POWER |
| #ifndef CONFIG_WLAN_POWER_ACTIVE_LOW |
| gpio_set_level(WIRELESS_GPIO_WLAN_POWER, |
| flags & EC_WIRELESS_SWITCH_WLAN_POWER); |
| #else |
| gpio_set_level(WIRELESS_GPIO_WLAN_POWER, |
| !(flags & EC_WIRELESS_SWITCH_WLAN_POWER)); |
| #endif /* CONFIG_WLAN_POWER_ACTIVE_LOW */ |
| #endif |
| |
| } |
| |
| static int wireless_get(void) |
| { |
| int flags = 0; |
| |
| #ifdef WIRELESS_GPIO_WLAN |
| if (gpio_get_level(WIRELESS_GPIO_WLAN)) |
| flags |= EC_WIRELESS_SWITCH_WLAN; |
| #endif |
| |
| #ifdef WIRELESS_GPIO_WWAN |
| if (gpio_get_level(WIRELESS_GPIO_WWAN)) |
| flags |= EC_WIRELESS_SWITCH_WWAN; |
| #endif |
| |
| #ifdef WIRELESS_GPIO_BLUETOOTH |
| if (gpio_get_level(WIRELESS_GPIO_BLUETOOTH)) |
| flags |= EC_WIRELESS_SWITCH_BLUETOOTH; |
| #endif |
| |
| #ifdef WIRELESS_GPIO_WLAN_POWER |
| #ifndef CONFIG_WLAN_POWER_ACTIVE_LOW |
| if (gpio_get_level(WIRELESS_GPIO_WLAN_POWER)) |
| #else |
| if (!gpio_get_level(WIRELESS_GPIO_WLAN_POWER)) |
| #endif /* CONFIG_WLAN_POWER_ACTIVE_LOW */ |
| flags |= EC_WIRELESS_SWITCH_WLAN_POWER; |
| #endif |
| |
| return flags; |
| } |
| |
| void wireless_set_state(enum wireless_power_state state) |
| { |
| switch (state) { |
| case WIRELESS_OFF: |
| wireless_enable(0); |
| break; |
| case WIRELESS_SUSPEND: |
| /* |
| * When suspending, only turn things off. If the AP has |
| * disabled WiFi power, going into S3 should not re-enable it. |
| */ |
| wireless_enable(wireless_get() & suspend_flags); |
| break; |
| case WIRELESS_ON: |
| wireless_enable(EC_WIRELESS_SWITCH_ALL); |
| break; |
| } |
| } |
| |
| static int wireless_enable_cmd(struct host_cmd_handler_args *args) |
| { |
| const struct ec_params_switch_enable_wireless_v1 *p = args->params; |
| struct ec_response_switch_enable_wireless_v1 *r = args->response; |
| |
| if (args->version == 0) { |
| /* Ver.0 command just set all current flags */ |
| wireless_enable(p->now_flags); |
| return EC_RES_SUCCESS; |
| } |
| |
| /* Ver.1 can set flags based on mask */ |
| wireless_enable((wireless_get() & ~p->now_mask) | |
| (p->now_flags & p->now_mask)); |
| |
| suspend_flags = (suspend_flags & ~p->suspend_mask) | |
| (p->suspend_flags & p->suspend_mask); |
| |
| /* And return the current flags */ |
| r->now_flags = wireless_get(); |
| r->suspend_flags = suspend_flags; |
| args->response_size = sizeof(*r); |
| return EC_RES_SUCCESS; |
| } |
| DECLARE_HOST_COMMAND(EC_CMD_SWITCH_ENABLE_WIRELESS, |
| wireless_enable_cmd, |
| EC_VER_MASK(0) | EC_VER_MASK(1)); |
| |
| static int command_wireless(int argc, char **argv) |
| { |
| char *e; |
| int i; |
| |
| if (argc >= 2) { |
| i = strtoi(argv[1], &e, 0); |
| if (*e) |
| return EC_ERROR_PARAM1; |
| |
| wireless_enable(i); |
| } |
| |
| if (argc >= 3) { |
| i = strtoi(argv[2], &e, 0); |
| if (*e) |
| return EC_ERROR_PARAM2; |
| |
| suspend_flags = i; |
| } |
| |
| ccprintf("Wireless flags: now=0x%x, suspend=0x%x\n", wireless_get(), |
| suspend_flags); |
| |
| return EC_SUCCESS; |
| } |
| DECLARE_CONSOLE_COMMAND(wireless, command_wireless, |
| "[now [suspend]]", |
| "Get/set wireless flags"); |