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

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

DEFINITIONS

This source file includes following definitions.
  1. whc_hw_reset
  2. whc_hw_init_di_buf
  3. whc_hw_init_dn_buf
  4. whc_init
  5. whc_clean_up

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * Wireless Host Controller (WHC) initialization.
   4  *
   5  * Copyright (C) 2007 Cambridge Silicon Radio Ltd.
   6  */
   7 #include <linux/kernel.h>
   8 #include <linux/gfp.h>
   9 #include <linux/dma-mapping.h>
  10 
  11 #include "../../../uwb/include/umc.h"
  12 #include "../../wusbhc.h"
  13 
  14 #include "whcd.h"
  15 
  16 /*
  17  * Reset the host controller.
  18  */
  19 static void whc_hw_reset(struct whc *whc)
  20 {
  21         le_writel(WUSBCMD_WHCRESET, whc->base + WUSBCMD);
  22         whci_wait_for(&whc->umc->dev, whc->base + WUSBCMD, WUSBCMD_WHCRESET, 0,
  23                       100, "reset");
  24 }
  25 
  26 static void whc_hw_init_di_buf(struct whc *whc)
  27 {
  28         int d;
  29 
  30         /* Disable all entries in the Device Information buffer. */
  31         for (d = 0; d < whc->n_devices; d++)
  32                 whc->di_buf[d].addr_sec_info = WHC_DI_DISABLE;
  33 
  34         le_writeq(whc->di_buf_dma, whc->base + WUSBDEVICEINFOADDR);
  35 }
  36 
  37 static void whc_hw_init_dn_buf(struct whc *whc)
  38 {
  39         /* Clear the Device Notification buffer to ensure the V (valid)
  40          * bits are clear.  */
  41         memset(whc->dn_buf, 0, 4096);
  42 
  43         le_writeq(whc->dn_buf_dma, whc->base + WUSBDNTSBUFADDR);
  44 }
  45 
  46 int whc_init(struct whc *whc)
  47 {
  48         u32 whcsparams;
  49         int ret, i;
  50         resource_size_t start, len;
  51 
  52         spin_lock_init(&whc->lock);
  53         mutex_init(&whc->mutex);
  54         init_waitqueue_head(&whc->cmd_wq);
  55         init_waitqueue_head(&whc->async_list_wq);
  56         init_waitqueue_head(&whc->periodic_list_wq);
  57         whc->workqueue = alloc_ordered_workqueue(dev_name(&whc->umc->dev), 0);
  58         if (whc->workqueue == NULL) {
  59                 ret = -ENOMEM;
  60                 goto error;
  61         }
  62         INIT_WORK(&whc->dn_work, whc_dn_work);
  63 
  64         INIT_WORK(&whc->async_work, scan_async_work);
  65         INIT_LIST_HEAD(&whc->async_list);
  66         INIT_LIST_HEAD(&whc->async_removed_list);
  67 
  68         INIT_WORK(&whc->periodic_work, scan_periodic_work);
  69         for (i = 0; i < 5; i++)
  70                 INIT_LIST_HEAD(&whc->periodic_list[i]);
  71         INIT_LIST_HEAD(&whc->periodic_removed_list);
  72 
  73         /* Map HC registers. */
  74         start = whc->umc->resource.start;
  75         len   = whc->umc->resource.end - start + 1;
  76         if (!request_mem_region(start, len, "whci-hc")) {
  77                 dev_err(&whc->umc->dev, "can't request HC region\n");
  78                 ret = -EBUSY;
  79                 goto error;
  80         }
  81         whc->base_phys = start;
  82         whc->base = ioremap(start, len);
  83         if (!whc->base) {
  84                 dev_err(&whc->umc->dev, "ioremap\n");
  85                 ret = -ENOMEM;
  86                 goto error;
  87         }
  88 
  89         whc_hw_reset(whc);
  90 
  91         /* Read maximum number of devices, keys and MMC IEs. */
  92         whcsparams = le_readl(whc->base + WHCSPARAMS);
  93         whc->n_devices = WHCSPARAMS_TO_N_DEVICES(whcsparams);
  94         whc->n_keys    = WHCSPARAMS_TO_N_KEYS(whcsparams);
  95         whc->n_mmc_ies = WHCSPARAMS_TO_N_MMC_IES(whcsparams);
  96 
  97         dev_dbg(&whc->umc->dev, "N_DEVICES = %d, N_KEYS = %d, N_MMC_IES = %d\n",
  98                 whc->n_devices, whc->n_keys, whc->n_mmc_ies);
  99 
 100         whc->qset_pool = dma_pool_create("qset", &whc->umc->dev,
 101                                          sizeof(struct whc_qset), 64, 0);
 102         if (whc->qset_pool == NULL) {
 103                 ret = -ENOMEM;
 104                 goto error;
 105         }
 106 
 107         ret = asl_init(whc);
 108         if (ret < 0)
 109                 goto error;
 110         ret = pzl_init(whc);
 111         if (ret < 0)
 112                 goto error;
 113 
 114         /* Allocate and initialize a buffer for generic commands, the
 115            Device Information buffer, and the Device Notification
 116            buffer. */
 117 
 118         whc->gen_cmd_buf = dma_alloc_coherent(&whc->umc->dev, WHC_GEN_CMD_DATA_LEN,
 119                                               &whc->gen_cmd_buf_dma, GFP_KERNEL);
 120         if (whc->gen_cmd_buf == NULL) {
 121                 ret = -ENOMEM;
 122                 goto error;
 123         }
 124 
 125         whc->dn_buf = dma_alloc_coherent(&whc->umc->dev,
 126                                          sizeof(struct dn_buf_entry) * WHC_N_DN_ENTRIES,
 127                                          &whc->dn_buf_dma, GFP_KERNEL);
 128         if (!whc->dn_buf) {
 129                 ret = -ENOMEM;
 130                 goto error;
 131         }
 132         whc_hw_init_dn_buf(whc);
 133 
 134         whc->di_buf = dma_alloc_coherent(&whc->umc->dev,
 135                                          sizeof(struct di_buf_entry) * whc->n_devices,
 136                                          &whc->di_buf_dma, GFP_KERNEL);
 137         if (!whc->di_buf) {
 138                 ret = -ENOMEM;
 139                 goto error;
 140         }
 141         whc_hw_init_di_buf(whc);
 142 
 143         return 0;
 144 
 145 error:
 146         whc_clean_up(whc);
 147         return ret;
 148 }
 149 
 150 void whc_clean_up(struct whc *whc)
 151 {
 152         resource_size_t len;
 153 
 154         if (whc->di_buf)
 155                 dma_free_coherent(&whc->umc->dev, sizeof(struct di_buf_entry) * whc->n_devices,
 156                                   whc->di_buf, whc->di_buf_dma);
 157         if (whc->dn_buf)
 158                 dma_free_coherent(&whc->umc->dev, sizeof(struct dn_buf_entry) * WHC_N_DN_ENTRIES,
 159                                   whc->dn_buf, whc->dn_buf_dma);
 160         if (whc->gen_cmd_buf)
 161                 dma_free_coherent(&whc->umc->dev, WHC_GEN_CMD_DATA_LEN,
 162                                   whc->gen_cmd_buf, whc->gen_cmd_buf_dma);
 163 
 164         pzl_clean_up(whc);
 165         asl_clean_up(whc);
 166 
 167         dma_pool_destroy(whc->qset_pool);
 168 
 169         len   = resource_size(&whc->umc->resource);
 170         if (whc->base)
 171                 iounmap(whc->base);
 172         if (whc->base_phys)
 173                 release_mem_region(whc->base_phys, len);
 174 
 175         if (whc->workqueue)
 176                 destroy_workqueue(whc->workqueue);
 177 }

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