Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  *  Shared Transport driver
0004  *  HCI-LL module responsible for TI proprietary HCI_LL protocol
0005  *  Copyright (C) 2009-2010 Texas Instruments
0006  *  Author: Pavan Savoy <pavan_savoy@ti.com>
0007  */
0008 
0009 #define pr_fmt(fmt) "(stll) :" fmt
0010 #include <linux/skbuff.h>
0011 #include <linux/module.h>
0012 #include <linux/platform_device.h>
0013 #include <linux/ti_wilink_st.h>
0014 
0015 /**********************************************************************/
0016 /* internal functions */
0017 static void send_ll_cmd(struct st_data_s *st_data,
0018     unsigned char cmd)
0019 {
0020 
0021     pr_debug("%s: writing %x", __func__, cmd);
0022     st_int_write(st_data, &cmd, 1);
0023     return;
0024 }
0025 
0026 static void ll_device_want_to_sleep(struct st_data_s *st_data)
0027 {
0028     struct kim_data_s   *kim_data;
0029     struct ti_st_plat_data  *pdata;
0030 
0031     pr_debug("%s", __func__);
0032     /* sanity check */
0033     if (st_data->ll_state != ST_LL_AWAKE)
0034         pr_err("ERR hcill: ST_LL_GO_TO_SLEEP_IND"
0035               "in state %ld", st_data->ll_state);
0036 
0037     send_ll_cmd(st_data, LL_SLEEP_ACK);
0038     /* update state */
0039     st_data->ll_state = ST_LL_ASLEEP;
0040 
0041     /* communicate to platform about chip asleep */
0042     kim_data = st_data->kim_data;
0043     pdata = kim_data->kim_pdev->dev.platform_data;
0044     if (pdata->chip_asleep)
0045         pdata->chip_asleep(NULL);
0046 }
0047 
0048 static void ll_device_want_to_wakeup(struct st_data_s *st_data)
0049 {
0050     struct kim_data_s   *kim_data;
0051     struct ti_st_plat_data  *pdata;
0052 
0053     /* diff actions in diff states */
0054     switch (st_data->ll_state) {
0055     case ST_LL_ASLEEP:
0056         send_ll_cmd(st_data, LL_WAKE_UP_ACK);   /* send wake_ack */
0057         break;
0058     case ST_LL_ASLEEP_TO_AWAKE:
0059         /* duplicate wake_ind */
0060         pr_err("duplicate wake_ind while waiting for Wake ack");
0061         break;
0062     case ST_LL_AWAKE:
0063         /* duplicate wake_ind */
0064         pr_err("duplicate wake_ind already AWAKE");
0065         break;
0066     case ST_LL_AWAKE_TO_ASLEEP:
0067         /* duplicate wake_ind */
0068         pr_err("duplicate wake_ind");
0069         break;
0070     }
0071     /* update state */
0072     st_data->ll_state = ST_LL_AWAKE;
0073 
0074     /* communicate to platform about chip wakeup */
0075     kim_data = st_data->kim_data;
0076     pdata = kim_data->kim_pdev->dev.platform_data;
0077     if (pdata->chip_awake)
0078         pdata->chip_awake(NULL);
0079 }
0080 
0081 /**********************************************************************/
0082 /* functions invoked by ST Core */
0083 
0084 /* called when ST Core wants to
0085  * enable ST LL */
0086 void st_ll_enable(struct st_data_s *ll)
0087 {
0088     ll->ll_state = ST_LL_AWAKE;
0089 }
0090 
0091 /* called when ST Core /local module wants to
0092  * disable ST LL */
0093 void st_ll_disable(struct st_data_s *ll)
0094 {
0095     ll->ll_state = ST_LL_INVALID;
0096 }
0097 
0098 /* called when ST Core wants to update the state */
0099 void st_ll_wakeup(struct st_data_s *ll)
0100 {
0101     if (likely(ll->ll_state != ST_LL_AWAKE)) {
0102         send_ll_cmd(ll, LL_WAKE_UP_IND);    /* WAKE_IND */
0103         ll->ll_state = ST_LL_ASLEEP_TO_AWAKE;
0104     } else {
0105         /* don't send the duplicate wake_indication */
0106         pr_err(" Chip already AWAKE ");
0107     }
0108 }
0109 
0110 /* called when ST Core wants the state */
0111 unsigned long st_ll_getstate(struct st_data_s *ll)
0112 {
0113     pr_debug(" returning state %ld", ll->ll_state);
0114     return ll->ll_state;
0115 }
0116 
0117 /* called from ST Core, when a PM related packet arrives */
0118 unsigned long st_ll_sleep_state(struct st_data_s *st_data,
0119     unsigned char cmd)
0120 {
0121     switch (cmd) {
0122     case LL_SLEEP_IND:  /* sleep ind */
0123         pr_debug("sleep indication recvd");
0124         ll_device_want_to_sleep(st_data);
0125         break;
0126     case LL_SLEEP_ACK:  /* sleep ack */
0127         pr_err("sleep ack rcvd: host shouldn't");
0128         break;
0129     case LL_WAKE_UP_IND:    /* wake ind */
0130         pr_debug("wake indication recvd");
0131         ll_device_want_to_wakeup(st_data);
0132         break;
0133     case LL_WAKE_UP_ACK:    /* wake ack */
0134         pr_debug("wake ack rcvd");
0135         st_data->ll_state = ST_LL_AWAKE;
0136         break;
0137     default:
0138         pr_err(" unknown input/state ");
0139         return -EINVAL;
0140     }
0141     return 0;
0142 }
0143 
0144 /* Called from ST CORE to initialize ST LL */
0145 long st_ll_init(struct st_data_s *ll)
0146 {
0147     /* set state to invalid */
0148     ll->ll_state = ST_LL_INVALID;
0149     return 0;
0150 }
0151 
0152 /* Called from ST CORE to de-initialize ST LL */
0153 long st_ll_deinit(struct st_data_s *ll)
0154 {
0155     return 0;
0156 }