root/drivers/staging/wusbcore/host/whci/wusb.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. whc_update_di
  2. whc_wusbhc_start
  3. whc_wusbhc_stop
  4. whc_mmcie_add
  5. whc_mmcie_rm
  6. whc_bwa_set
  7. whc_dev_info_set
  8. whc_set_num_dnts
  9. whc_set_key
  10. whc_set_ptk
  11. whc_set_gtk
  12. whc_set_cluster_id

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * Wireless Host Controller (WHC) WUSB operations.
   4  *
   5  * Copyright (C) 2007 Cambridge Silicon Radio Ltd.
   6  */
   7 #include <linux/kernel.h>
   8 
   9 #include "../../../uwb/include/umc.h"
  10 #include "../../wusbhc.h"
  11 
  12 #include "whcd.h"
  13 
  14 static int whc_update_di(struct whc *whc, int idx)
  15 {
  16         int offset = idx / 32;
  17         u32 bit = 1 << (idx % 32);
  18 
  19         le_writel(bit, whc->base + WUSBDIBUPDATED + offset);
  20 
  21         return whci_wait_for(&whc->umc->dev,
  22                              whc->base + WUSBDIBUPDATED + offset, bit, 0,
  23                              100, "DI update");
  24 }
  25 
  26 /*
  27  * WHCI starts MMCs based on there being a valid GTK so these need
  28  * only start/stop the asynchronous and periodic schedules and send a
  29  * channel stop command.
  30  */
  31 
  32 int whc_wusbhc_start(struct wusbhc *wusbhc)
  33 {
  34         struct whc *whc = wusbhc_to_whc(wusbhc);
  35 
  36         asl_start(whc);
  37         pzl_start(whc);
  38 
  39         return 0;
  40 }
  41 
  42 void whc_wusbhc_stop(struct wusbhc *wusbhc, int delay)
  43 {
  44         struct whc *whc = wusbhc_to_whc(wusbhc);
  45         u32 stop_time, now_time;
  46         int ret;
  47 
  48         pzl_stop(whc);
  49         asl_stop(whc);
  50 
  51         now_time = le_readl(whc->base + WUSBTIME) & WUSBTIME_CHANNEL_TIME_MASK;
  52         stop_time = (now_time + ((delay * 8) << 7)) & 0x00ffffff;
  53         ret = whc_do_gencmd(whc, WUSBGENCMDSTS_CHAN_STOP, stop_time, NULL, 0);
  54         if (ret == 0)
  55                 msleep(delay);
  56 }
  57 
  58 int whc_mmcie_add(struct wusbhc *wusbhc, u8 interval, u8 repeat_cnt,
  59                   u8 handle, struct wuie_hdr *wuie)
  60 {
  61         struct whc *whc = wusbhc_to_whc(wusbhc);
  62         u32 params;
  63 
  64         params = (interval << 24)
  65                 | (repeat_cnt << 16)
  66                 | (wuie->bLength << 8)
  67                 | handle;
  68 
  69         return whc_do_gencmd(whc, WUSBGENCMDSTS_MMCIE_ADD, params, wuie, wuie->bLength);
  70 }
  71 
  72 int whc_mmcie_rm(struct wusbhc *wusbhc, u8 handle)
  73 {
  74         struct whc *whc = wusbhc_to_whc(wusbhc);
  75         u32 params;
  76 
  77         params = handle;
  78 
  79         return whc_do_gencmd(whc, WUSBGENCMDSTS_MMCIE_RM, params, NULL, 0);
  80 }
  81 
  82 int whc_bwa_set(struct wusbhc *wusbhc, s8 stream_index, const struct uwb_mas_bm *mas_bm)
  83 {
  84         struct whc *whc = wusbhc_to_whc(wusbhc);
  85 
  86         if (stream_index >= 0)
  87                 whc_write_wusbcmd(whc, WUSBCMD_WUSBSI_MASK, WUSBCMD_WUSBSI(stream_index));
  88 
  89         return whc_do_gencmd(whc, WUSBGENCMDSTS_SET_MAS, 0, (void *)mas_bm, sizeof(*mas_bm));
  90 }
  91 
  92 int whc_dev_info_set(struct wusbhc *wusbhc, struct wusb_dev *wusb_dev)
  93 {
  94         struct whc *whc = wusbhc_to_whc(wusbhc);
  95         int idx = wusb_dev->port_idx;
  96         struct di_buf_entry *di = &whc->di_buf[idx];
  97         int ret;
  98 
  99         mutex_lock(&whc->mutex);
 100 
 101         uwb_mas_bm_copy_le(di->availability_info, &wusb_dev->availability);
 102         di->addr_sec_info &= ~(WHC_DI_DISABLE | WHC_DI_DEV_ADDR_MASK);
 103         di->addr_sec_info |= WHC_DI_DEV_ADDR(wusb_dev->addr);
 104 
 105         ret = whc_update_di(whc, idx);
 106 
 107         mutex_unlock(&whc->mutex);
 108 
 109         return ret;
 110 }
 111 
 112 /*
 113  * Set the number of Device Notification Time Slots (DNTS) and enable
 114  * device notifications.
 115  */
 116 int whc_set_num_dnts(struct wusbhc *wusbhc, u8 interval, u8 slots)
 117 {
 118         struct whc *whc = wusbhc_to_whc(wusbhc);
 119         u32 dntsctrl;
 120 
 121         dntsctrl = WUSBDNTSCTRL_ACTIVE
 122                 | WUSBDNTSCTRL_INTERVAL(interval)
 123                 | WUSBDNTSCTRL_SLOTS(slots);
 124 
 125         le_writel(dntsctrl, whc->base + WUSBDNTSCTRL);
 126 
 127         return 0;
 128 }
 129 
 130 static int whc_set_key(struct whc *whc, u8 key_index, uint32_t tkid,
 131                        const void *key, size_t key_size, bool is_gtk)
 132 {
 133         uint32_t setkeycmd;
 134         uint32_t seckey[4];
 135         int i;
 136         int ret;
 137 
 138         memcpy(seckey, key, key_size);
 139         setkeycmd = WUSBSETSECKEYCMD_SET | WUSBSETSECKEYCMD_IDX(key_index);
 140         if (is_gtk)
 141                 setkeycmd |= WUSBSETSECKEYCMD_GTK;
 142 
 143         le_writel(tkid, whc->base + WUSBTKID);
 144         for (i = 0; i < 4; i++)
 145                 le_writel(seckey[i], whc->base + WUSBSECKEY + 4*i);
 146         le_writel(setkeycmd, whc->base + WUSBSETSECKEYCMD);
 147 
 148         ret = whci_wait_for(&whc->umc->dev, whc->base + WUSBSETSECKEYCMD,
 149                             WUSBSETSECKEYCMD_SET, 0, 100, "set key");
 150 
 151         return ret;
 152 }
 153 
 154 /**
 155  * whc_set_ptk - set the PTK to use for a device.
 156  *
 157  * The index into the key table for this PTK is the same as the
 158  * device's port index.
 159  */
 160 int whc_set_ptk(struct wusbhc *wusbhc, u8 port_idx, u32 tkid,
 161                 const void *ptk, size_t key_size)
 162 {
 163         struct whc *whc = wusbhc_to_whc(wusbhc);
 164         struct di_buf_entry *di = &whc->di_buf[port_idx];
 165         int ret;
 166 
 167         mutex_lock(&whc->mutex);
 168 
 169         if (ptk) {
 170                 ret = whc_set_key(whc, port_idx, tkid, ptk, key_size, false);
 171                 if (ret)
 172                         goto out;
 173 
 174                 di->addr_sec_info &= ~WHC_DI_KEY_IDX_MASK;
 175                 di->addr_sec_info |= WHC_DI_SECURE | WHC_DI_KEY_IDX(port_idx);
 176         } else
 177                 di->addr_sec_info &= ~WHC_DI_SECURE;
 178 
 179         ret = whc_update_di(whc, port_idx);
 180 out:
 181         mutex_unlock(&whc->mutex);
 182         return ret;
 183 }
 184 
 185 /**
 186  * whc_set_gtk - set the GTK for subsequent broadcast packets
 187  *
 188  * The GTK is stored in the last entry in the key table (the previous
 189  * N_DEVICES entries are for the per-device PTKs).
 190  */
 191 int whc_set_gtk(struct wusbhc *wusbhc, u32 tkid,
 192                 const void *gtk, size_t key_size)
 193 {
 194         struct whc *whc = wusbhc_to_whc(wusbhc);
 195         int ret;
 196 
 197         mutex_lock(&whc->mutex);
 198 
 199         ret = whc_set_key(whc, whc->n_devices, tkid, gtk, key_size, true);
 200 
 201         mutex_unlock(&whc->mutex);
 202 
 203         return ret;
 204 }
 205 
 206 int whc_set_cluster_id(struct whc *whc, u8 bcid)
 207 {
 208         whc_write_wusbcmd(whc, WUSBCMD_BCID_MASK, WUSBCMD_BCID(bcid));
 209         return 0;
 210 }

/* [<][>][^][v][top][bottom][index][help] */