Ejemplo n.º 1
0
void bcm_timer_stop(bcm_timer_t *t)
{
   bcm_pr_debug("bcm_timer_stop()\n");

   if (bcm_timer_is_active(t)) {
      t->is_active = false;
      del_timer_sync(&(t->kobject));
#ifdef BCMPH_DEBUG
      bcm_pr_debug("stats.count = %lu, stats.too_soon = %lu, stats.drift = %lu, stats.reset_drift = %lu\n",
         (unsigned long)(t->stats.count),
         (unsigned long)(t->stats.too_soon),
         (unsigned long)(t->drift),
         (unsigned long)(t->stats.reset_drift));
#endif // BCMPH_DEBUG
   }
}
Ejemplo n.º 2
0
static int bcm63xx_spi_resume(struct device *dev)
{
   bcm_mpi_dev_data_t *bs =
         platform_get_drvdata(to_platform_device(dev));

   bcm_pr_debug("%s()\n", __func__);

   clk_enable(bs->clk);

   return 0;
}
Ejemplo n.º 3
0
static void bcm_timer_compute_params(bcm_timer_t *t, unsigned long period_in_usecs)
{
   unsigned long real_period;

   bcm_pr_debug("bcm_timer_compute_params(period_in_usecs=%lu)\n", (unsigned long)(period_in_usecs));

   t->period_in_jiffies = usecs_to_jiffies(period_in_usecs);
   real_period = jiffies_to_usecs(t->period_in_jiffies);
   if (real_period < period_in_usecs) {
      t->period_in_jiffies += 1;
      real_period = jiffies_to_usecs(t->period_in_jiffies);
      bcm_assert(real_period >= period_in_usecs);
   }
   t->drift_increment = real_period - period_in_usecs;
   bcm_assert((0 == t->drift_increment) || ((t->drift_increment > 0) && (t->period_in_jiffies >= 1)));

   bcm_pr_debug("one_jiffie_to_usecs = %lu, period_in_jiffies = %lu, real_period = %lu, drift_increment = %lu\n",
      (unsigned long)(one_jiffie_to_usecs), (unsigned long)(t->period_in_jiffies),
      (unsigned long)(real_period), (unsigned long)(t->drift_increment));
}
Ejemplo n.º 4
0
void bcm_timer_start(bcm_timer_t *t, unsigned long period_in_msecs)
{
   bcm_pr_debug("bcm_timer_start()\n");

   bcm_timer_stop(t);
   bcm_timer_compute_params(t, period_in_msecs * 1000);
   t->is_active = true;
#ifdef __KERNEL__
   t->kobject.expires = jiffies + t->period_in_jiffies;
#else // !__KERNEL__
   t->kobject.expires = get_jiffies() + t->period_in_jiffies;
#endif // !__KERNEL__
   t->drift = 0;
   add_timer(&(t->kobject));
}
Ejemplo n.º 5
0
static void bcm_mpi_add_trace(bcm_mpi_t *t, __u8 dir, const __u8 *buf, int len)
{
   if (len > 0) {
      int i;
      if ((t->trace_len + len + 2) > ARRAY_SIZE(t->trace)) {
         bcm_pr_debug("Trace buffer full. Dumping it\n");
         bcm_mpi_dump_and_reset_trace(t);
      }
      t->trace[t->trace_len] = dir;
      t->trace_len += 1;
      t->trace[t->trace_len] = (__u8)(len);
      t->trace_len += 1;
      for (i = 0; (i < len); i += 1) {
         t->trace[t->trace_len] = buf[i];
         t->trace_len += 1;
      }
   }
}
Ejemplo n.º 6
0
static void *le88266_deinit(phone_device_t *d)
{
   size_t line_idx;
   phone_dev_le88266_t *t = container_of(d, phone_dev_le88266_t, ve880.vdz.vd);

   bcm_pr_debug("%s()\n", __func__);

   phone_dev_zarlink_ve880_stop(&(t->ve880.vdz.vd));

   for (line_idx = 0; (line_idx < ARRAY_SIZE(t->lines)); line_idx += 1) {
      phone_dev_zarlink_deinit_line(&(t->ve880.vdz), line_idx);
      phone_line_deinit(&(t->lines[line_idx].vl));
   }

   phone_dev_zarlink_ve880_deinit(&(t->ve880));

   return (t);
}
Ejemplo n.º 7
0
int __init bcm_timer_init(bcm_timer_t *t, void (*callback)(bcm_timer_t *t))
{
   int ret = 0;

   bcm_pr_debug("bcm_timer_init()\n");

   bcm_assert(NULL != callback);

   one_jiffie_to_usecs = jiffies_to_usecs(1);

   t->callback = callback;
   t->period_in_jiffies = msecs_to_jiffies(1000);

   // Init kernel timer
   init_timer(&(t->kobject));
   t->kobject.function = bcm_timer_fn;
   t->kobject.data = (unsigned long)(t);

   return (ret);
}
Ejemplo n.º 8
0
static int bcm63xx_spi_remove(struct platform_device *pdev)
{
   bcm_mpi_dev_data_t *bs = platform_get_drvdata(pdev);

   bcm_pr_debug("%s()\n", __func__);

   bcm_assert(1 == bs->ref_count);

   /* reset spi block */
   bcm_spi_writeb(bs, 0, SPI_INT_MASK);

   /* HW shutdown */
   clk_disable(bs->clk);
   devm_free_irq(&(pdev->dev), bs->irq, bs);
   devm_iounmap(&(pdev->dev), bs->regs);
   devm_release_mem_region(&(pdev->dev), bs->res_start, bs->res_size);
   platform_set_drvdata(pdev, NULL);
   clk_put(bs->clk);
   bs->ref_count = 0;

   return (0);
}
Ejemplo n.º 9
0
int __init phone_dev_le88266_init(phone_dev_le88266_t *t,
   const phone_desc_device_t *dev_desc, __u8 tick_period)
{
   int ret = 0;
   size_t line_idx;

   bcm_pr_debug("%s()\n", __func__);

   bcm_assert(ARRAY_SIZE(t->lines) <= ARRAY_SIZE(t->ve880.vdz.lines));

   bcm_assert((NULL != dev_desc) && (NULL != dev_desc->parameters.zarlink));
   for (line_idx = 0; (line_idx < dev_desc->line_count); line_idx += 1) {
      bcm_assert(NULL != dev_desc->lines[line_idx].parameters.zarlink);
   }

   do { // Empty loop
      if (dev_desc->line_count > ARRAY_SIZE(t->lines)) {
         bcm_pr_err("Le88266 description can only have %lu lines at most\n", (unsigned long)(ARRAY_SIZE(t->lines)));
         ret = -ENODEV;
         break;
      }

      ret = phone_dev_zarlink_ve880_init(&(t->ve880), &(vtbl_le88266), dev_desc, tick_period);
      if (ret) {
         break;
      }

      for (line_idx = 0; (line_idx < ARRAY_SIZE(t->lines)); line_idx += 1) {
         phone_line_init(&(t->lines[line_idx].vl));
         memset(&(t->lines[line_idx].obj), 0, sizeof(t->lines[line_idx].obj));
         memset(&(t->lines[line_idx].ctx), 0, sizeof(t->lines[line_idx].ctx));
         phone_dev_zarlink_init_line(&(t->ve880.vdz), line_idx,
            &(t->lines[line_idx].vl), &(t->lines[line_idx].obj), &(t->lines[line_idx].ctx));
      }
   }
   while (false);

   return (ret);
}
Ejemplo n.º 10
0
void bcm_mpi_deinit(bcm_mpi_t *t)
{
   bcm_pr_debug("%s()\n", __func__);

#ifdef BCMPH_DEBUG_MPI
   bcm_mpi_dump_and_reset_trace(t);
#endif


#ifdef BCMPH_USE_SPI_DRIVER

#ifndef BCMPH_NOHW
   if (t->bus_is_locked) {
      spi_bus_unlock(t->dev->master);
      t->bus_is_locked = false;
   }
   spi_unregister_device(t->dev);
#endif // !BCMPH_NOHW
   t->dev = NULL;

#else // !BCMPH_USE_SPI_DRIVER

#ifndef BCMPH_NOHW
   if (bcm_mpi_dev_data.ref_count > 0) {
      if (1 == bcm_mpi_dev_data.ref_count) {
         platform_driver_unregister(&(bcm63xx_spi_driver));
      }
      else {
         bcm_mpi_dev_data.ref_count -= 1;
      }
   }
   else {
      bcm_pr_err("Illegal call of %s()\n", __func__);
   }
#endif // !BCMPH_NOHW

#endif // !BCMPH_USE_SPI_DRIVER
}
Ejemplo n.º 11
0
int __init bcm_mpi_init(bcm_mpi_t *t, const bcm_mpi_params_t *params)
{
   int ret = -1;

#ifdef BCMPH_USE_SPI_DRIVER
# ifndef BCMPH_NOHW
   struct spi_master *master;
   struct spi_board_info board_info;
# endif // !BCMPH_NOHW
#endif // BCMPH_USE_SPI_DRIVER

   bcm_pr_debug("%s()\n", __func__);
   bcm_assert(NULL != params);

#ifndef BCMPH_NOHW
   t->trx_opts.fill_byte = params->fill_byte;
   t->trx_opts.wait_completion_with_irq = params->wait_completion_with_irq;
   t->trx_opts.drop_cs_after_each_byte = params->drop_cs_after_each_byte;
   t->trx_opts.cs_off_clk_cycles = params->cs_off_clk_cycles;
#endif // !BCMPH_NOHW

#ifdef BCMPH_USE_SPI_DRIVER
   t->mpi_clk = params->clk;
# ifndef BCMPH_NOHW
   master = spi_busnum_to_master(params->bus_num);
   if (NULL == master) {
      bcm_pr_err("No SPI master found for bus num %d. Module bcm63xx-spi not loaded ?\n",
         (int)(params->bus_num));
      ret = -EINVAL;
      goto fail_master;
   }

   memset(&(board_info), 0, sizeof(board_info));
   strcpy(board_info.modalias, driver_name);
   board_info.max_speed_hz = params->clk;
   board_info.bus_num = params->bus_num;
   board_info.chip_select = params->cs;
   board_info.mode = SPI_MODE_3;
   t->dev = spi_new_device(master, &(board_info));
   if (NULL == t->dev) {
      bcm_pr_err("Failed to add SPI device (busnum = %d, chip select = %d, clock = %lu)\n",
         (int)(params->bus_num), (int)(params->cs), (unsigned long)(params->clk));
      ret = -ENOMEM;
      goto fail_new_dev;
   }
   put_device(&(master->dev));
   /* Lock the bus */
   if ((params->has_exclusive_bus_access) && (!bcm_drv_param_mpi_no_exclusive_bus_access)) {
      spi_bus_lock(t->dev->master);
      t->bus_is_locked = true;
   }

   bcm_mpi_enable_extra_CSs(params->cs);
#  ifdef BCMPH_DEBUG_MPI
   t->trace_len = 0;
#  endif // BCMPH_DEBUG_MPI

   return (0);

   spi_unregister_device(t->dev);
fail_new_dev:
   put_device(&(master->dev));
fail_master:
# else // BCMPH_NOHW
   ret = 0;
# endif // BCMPH_NOHW
#else // !BCMPH_USE_SPI_DRIVER
# ifndef BCMPH_NOHW
   t->mpi_cs = params->cs;
   t->clk_cfg = bcm_mpi_get_clk_cfg(params->clk, params->cs_off_clk_cycles);

   bcm_mpi_enable_extra_CSs(params->cs);

   if (bcm_mpi_dev_data.ref_count <= 0) {
      struct device_driver *spi_driver = driver_find(bcm63xx_spi_driver.driver.name, &platform_bus_type);
      if (NULL != spi_driver) {
         bcm_pr_err("Error: Driver '%s' is already registered, aborting...\n",
            bcm63xx_spi_driver.driver.name);
         ret = -EBUSY;
      }
      else {
         ret = platform_driver_register(&(bcm63xx_spi_driver));
      }
      bcm_assert(((ret) && (0 == bcm_mpi_dev_data.ref_count))
         || ((!ret) && (1 == bcm_mpi_dev_data.ref_count)));
   }
   else {
      bcm_mpi_dev_data.ref_count += 1;
      ret = 0;
   }
   if (!ret) {
      bcm_assert(bcm_mpi_dev_data.ref_count > 0);
      if (params->cs > bcm_mpi_dev_data.num_chipselect) {
         dev_err(&(bcm_mpi_dev_data.pdev->dev), "%s, unsupported slave %d\n",
            __func__, params->cs);
         if (1 == bcm_mpi_dev_data.ref_count) {
            platform_driver_unregister(&(bcm63xx_spi_driver));
         }
         bcm_mpi_dev_data.ref_count -= 1;
         ret = -EINVAL;
      }
      else {
         t->dev_data = &(bcm_mpi_dev_data);
      }
   }
# else // BCMPH_NOHW
   ret = 0;
# endif // BCMPH_NOHW

#endif // !BCMPH_USE_SPI_DRIVER

   return (ret);
}
Ejemplo n.º 12
0
static int bcm63xx_spi_probe(struct platform_device *pdev)
{
   struct device *dev = &(pdev->dev);
   int ret;
   struct resource *r;
   int irq;
   bcm_mpi_dev_data_t *bs;

   bcm_pr_debug("%s()\n", __func__);

   if (
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)
       (!pdev->id_entry->driver_data)
#else /* LINUX_VERSION_CODE < KERNEL_VERSION(4, 4, 0) */
       (!BCMCPU_IS_6358())
#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(4, 4, 0) */
      ) {
      return -EINVAL;
   }

   bs = &(bcm_mpi_dev_data);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)
   bcm_mpi_dev_data_init(bs, (const unsigned long *)pdev->id_entry->driver_data);
#else /* LINUX_VERSION_CODE < KERNEL_VERSION(4, 4, 0) */
   bcm_mpi_dev_data_init(bs, bcm6358_spi_reg_offsets);
#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(4, 4, 0) */
   bs->ref_count = 1;
   bs->pdev = pdev;

   r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
   if (!r) {
      dev_err(dev, "no iomem\n");
      ret = -ENXIO;
      goto fail_get_res;
   }
   bs->res_start = r->start;
   bs->res_size = resource_size(r);

   irq = platform_get_irq(pdev, 0);
   if (irq < 0) {
      dev_err(dev, "no irq\n");
      ret = -ENXIO;
      goto fail_get_irq;
   }
   bs->irq = irq;

   bs->clk = devm_clk_get(dev, "spi");
   if (IS_ERR(bs->clk)) {
      dev_err(dev, "no clock for device\n");
      ret = PTR_ERR(bs->clk);
      goto fail_get_clk;
   }

   platform_set_drvdata(pdev, bs);

   if (!devm_request_mem_region(&(pdev->dev), bs->res_start, bs->res_size, driver_name)) {
      dev_err(dev, "iomem request failed\n");
      ret = -ENXIO;
      goto fail_req_reg;
   }

   bs->regs = devm_ioremap_nocache(&(pdev->dev), bs->res_start, bs->res_size);
   if (!bs->regs) {
      dev_err(dev, "unable to ioremap regs\n");
      ret = -ENOMEM;
      goto fail_io_remap;
   }
   bs->tx_io = (u8 *)(bs->regs + bs->reg_offsets[SPI_MSG_DATA]);
   bs->rx_io = (const u8 *)(bs->regs + bs->reg_offsets[SPI_RX_DATA]);

   ret = devm_request_irq(&(pdev->dev), irq, bcm63xx_spi_interrupt, 0,
                     pdev->name, bs);
   if (ret) {
      dev_err(dev, "unable to request irq\n");
      goto fail_req_irq;
   }

   /* Initialize hardware */
   clk_enable(bs->clk);
   /* Read interupts and clear them immediately */
   bcm_spi_writeb(bs, SPI_INTR_CLEAR_ALL, SPI_INT_STATUS);
   bcm_spi_writeb(bs, 0, SPI_INT_MASK);

   bcm_mpi_set_clk_cfg(bs, SPI_CLK_0_391MHZ);
   bcm_mpi_set_fill_byte(bs, 0);

   dev_info(dev, "at 0x%08x (irq %d, FIFOs size %d)\n",
       bs->res_start, bs->irq, bs->fifo_size);

   return 0;

   clk_disable(bs->clk);
   devm_free_irq(&(pdev->dev), irq, bs);
fail_req_irq:
   devm_iounmap(&(pdev->dev), bs->regs);
fail_io_remap:
   devm_release_mem_region(&(pdev->dev), bs->res_start, bs->res_size);
fail_req_reg:
   platform_set_drvdata(pdev, NULL);
   clk_put(bs->clk);
fail_get_clk:
fail_get_irq:
fail_get_res:
   bs->ref_count = 0;
   return ret;
}
Ejemplo n.º 13
0
void bcm_timer_deinit(bcm_timer_t *t)
{
   bcm_pr_debug("bcm_timer_deinit()\n");

   bcm_timer_stop(t);
}