/** * startup_dim - initialize the dim2 interface * @pdev: platform device * * Get the value of command line parameter "clock_speed" if given or use the * default value, enable the clock and PLL, and initialize the dim2 interface. */ static int startup_dim(struct platform_device *pdev) { struct dim2_hdm *dev = platform_get_drvdata(pdev); struct dim2_platform_data *pdata = pdev->dev.platform_data; u8 hal_ret; dev->clk_speed = -1; if (clock_speed) { if (!strcmp(clock_speed, "256fs")) dev->clk_speed = CLK_256FS; else if (!strcmp(clock_speed, "512fs")) dev->clk_speed = CLK_512FS; else if (!strcmp(clock_speed, "1024fs")) dev->clk_speed = CLK_1024FS; else if (!strcmp(clock_speed, "2048fs")) dev->clk_speed = CLK_2048FS; else if (!strcmp(clock_speed, "3072fs")) dev->clk_speed = CLK_3072FS; else if (!strcmp(clock_speed, "4096fs")) dev->clk_speed = CLK_4096FS; else if (!strcmp(clock_speed, "6144fs")) dev->clk_speed = CLK_6144FS; else if (!strcmp(clock_speed, "8192fs")) dev->clk_speed = CLK_8192FS; } if (dev->clk_speed == -1) { pr_info("Bad or missing clock speed parameter, using default value: 3072fs\n"); dev->clk_speed = CLK_3072FS; } else { pr_info("Selected clock speed: %s\n", clock_speed); } if (pdata && pdata->init) { int ret = pdata->init(pdata, dev->io_base, dev->clk_speed); if (ret) return ret; } pr_info("sync: num of frames per sub-buffer: %u\n", fcnt); hal_ret = dim_startup(dev->io_base, dev->clk_speed, fcnt); if (hal_ret != DIM_NO_ERROR) { pr_err("dim_startup failed: %d\n", hal_ret); if (pdata && pdata->destroy) pdata->destroy(pdata); return -ENODEV; } return 0; }
/* * dim2_probe - dim2 probe handler * @pdev: platform device structure * * Register the dim2 interface with mostcore and initialize it. * Return 0 on success, negative on failure. */ static int dim2_probe(struct platform_device *pdev) { const struct dim2_platform_data *pdata; const struct of_device_id *of_id; const char *clock_speed; struct dim2_hdm *dev; struct resource *res; int ret, i; u8 hal_ret; int irq; enum { MLB_INT_IDX, AHB0_INT_IDX }; dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL); if (!dev) return -ENOMEM; dev->atx_idx = -1; platform_set_drvdata(pdev, dev); ret = of_property_read_string(pdev->dev.of_node, "microchip,clock-speed", &clock_speed); if (ret) { dev_err(&pdev->dev, "missing dt property clock-speed\n"); return ret; } ret = get_dim2_clk_speed(clock_speed, &dev->clk_speed); if (ret) { dev_err(&pdev->dev, "bad dt property clock-speed\n"); return ret; } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); dev->io_base = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(dev->io_base)) return PTR_ERR(dev->io_base); of_id = of_match_node(dim2_of_match, pdev->dev.of_node); pdata = of_id->data; ret = pdata && pdata->enable ? pdata->enable(pdev) : 0; if (ret) return ret; dev->disable_platform = pdata ? pdata->disable : 0; dev_info(&pdev->dev, "sync: num of frames per sub-buffer: %u\n", fcnt); hal_ret = dim_startup(dev->io_base, dev->clk_speed, fcnt); if (hal_ret != DIM_NO_ERROR) { dev_err(&pdev->dev, "dim_startup failed: %d\n", hal_ret); ret = -ENODEV; goto err_disable_platform; } irq = platform_get_irq(pdev, AHB0_INT_IDX); if (irq < 0) { dev_err(&pdev->dev, "failed to get ahb0_int irq: %d\n", irq); ret = irq; goto err_shutdown_dim; } ret = devm_request_irq(&pdev->dev, irq, dim2_ahb_isr, 0, "dim2_ahb0_int", dev); if (ret) { dev_err(&pdev->dev, "failed to request ahb0_int irq %d\n", irq); goto err_shutdown_dim; } irq = platform_get_irq(pdev, MLB_INT_IDX); if (irq < 0) { dev_err(&pdev->dev, "failed to get mlb_int irq: %d\n", irq); ret = irq; goto err_shutdown_dim; } ret = devm_request_irq(&pdev->dev, irq, dim2_mlb_isr, 0, "dim2_mlb_int", dev); if (ret) { dev_err(&pdev->dev, "failed to request mlb_int irq %d\n", irq); goto err_shutdown_dim; } init_waitqueue_head(&dev->netinfo_waitq); dev->deliver_netinfo = 0; dev->netinfo_task = kthread_run(&deliver_netinfo_thread, dev, "dim2_netinfo"); if (IS_ERR(dev->netinfo_task)) { ret = PTR_ERR(dev->netinfo_task); goto err_shutdown_dim; } for (i = 0; i < DMA_CHANNELS; i++) { struct most_channel_capability *cap = dev->capabilities + i; struct hdm_channel *hdm_ch = dev->hch + i; INIT_LIST_HEAD(&hdm_ch->pending_list); INIT_LIST_HEAD(&hdm_ch->started_list); hdm_ch->is_initialized = false; snprintf(hdm_ch->name, sizeof(hdm_ch->name), "ca%d", i * 2 + 2); cap->name_suffix = hdm_ch->name; cap->direction = MOST_CH_RX | MOST_CH_TX; cap->data_type = MOST_CH_CONTROL | MOST_CH_ASYNC | MOST_CH_ISOC | MOST_CH_SYNC; cap->num_buffers_packet = MAX_BUFFERS_PACKET; cap->buffer_size_packet = MAX_BUF_SIZE_PACKET; cap->num_buffers_streaming = MAX_BUFFERS_STREAMING; cap->buffer_size_streaming = MAX_BUF_SIZE_STREAMING; } { const char *fmt; if (sizeof(res->start) == sizeof(long long)) fmt = "dim2-%016llx"; else if (sizeof(res->start) == sizeof(long)) fmt = "dim2-%016lx"; else fmt = "dim2-%016x"; snprintf(dev->name, sizeof(dev->name), fmt, res->start); } dev->most_iface.interface = ITYPE_MEDIALB_DIM2; dev->most_iface.description = dev->name; dev->most_iface.num_channels = DMA_CHANNELS; dev->most_iface.channel_vector = dev->capabilities; dev->most_iface.configure = configure_channel; dev->most_iface.enqueue = enqueue; dev->most_iface.dma_alloc = dma_alloc; dev->most_iface.dma_free = dma_free; dev->most_iface.poison_channel = poison_channel; dev->most_iface.request_netinfo = request_netinfo; dev->most_iface.driver_dev = &pdev->dev; dev->dev.init_name = "dim2_state"; dev->dev.parent = &dev->most_iface.dev; ret = most_register_interface(&dev->most_iface); if (ret) { dev_err(&pdev->dev, "failed to register MOST interface\n"); goto err_stop_thread; } ret = dim2_sysfs_probe(&dev->dev); if (ret) { dev_err(&pdev->dev, "failed to create sysfs attribute\n"); goto err_unreg_iface; } return 0; err_unreg_iface: most_deregister_interface(&dev->most_iface); err_stop_thread: kthread_stop(dev->netinfo_task); err_shutdown_dim: dim_shutdown(); err_disable_platform: if (dev->disable_platform) dev->disable_platform(pdev); return ret; }