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 } }
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; }
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)); }
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)); }
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; } } }
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); }
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); }
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); }
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); }
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 }
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); }
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; }
void bcm_timer_deinit(bcm_timer_t *t) { bcm_pr_debug("bcm_timer_deinit()\n"); bcm_timer_stop(t); }