/* * SLVS-EC driver for T194 * * Copyright (c) 2017-2019, NVIDIA Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, * version 2, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "slvsec.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "dev.h" #include "bus_client.h" #include "nvhost_acm.h" #include "t194/t194.h" #define SLVSEC_CORE_INTR_STATUS U32_C(0x84) #define SLVSEC_CORE_INTR_STATUS_SW BIT(4) #define SLVSEC_CORE_INTR_STATUS_HOST1X BIT(3) #define SLVSEC_CORE_INTR_STATUS_CIL BIT(2) #define SLVSEC_CORE_INTR_STATUS_STRM_1 BIT(1) #define SLVSEC_CORE_INTR_STATUS_STRM_0 BIT(0) #define SLVSEC_CORE_HOST1X_INTR_STATUS U32_C(0xb0) #define SLVSEC_CORE_HOST1X_INTR_MASK U32_C(0xb4) #define SLVSEC_CORE_DBG_CNT_CTRL U32_C(0x8c) #define SLVSEC_CORE_DBG_CNT_CTRL_EVENT_MASK U32_C(0x3f) #define SLVSEC_CORE_DBG_CNT_CTRL_EVENT_SHIFT U32_C(8) #define SLVSEC_CORE_DBG_CNT_CTRL_STRM_SEL_MASK U32_C(0x1) #define SLVSEC_CORE_DBG_CNT_CTRL_STRM_SEL_SHIFT U32_C(0) #define SLVSEC_CORE_DBG_CNT_VALUE U32_C(0x90) #define SLVSEC_CORE_DBG_CNT_SIZE U32_C(0x08) #define SLVSEC_CORE_NUM_DEBUG_COUNTERS 4U #define SLVSEC_CORE_SW_DEBUG_INTR_STATUS U32_C(0xb8) #define SLVSEC_CORE_SW_DEBUG_INTR_TRIG U32_C(0xbc) #define SLVSEC_CORE_STRM0_INTR_STATUS_CH0 U32_C(0x10048) #define SLVSEC_CORE_STRM0_INTR_STATUS_CH1 U32_C(0x1004c) #define SLVSEC_CORE_STRM0_INTR_STATUS U32_C(0x10050) #define SLVSEC_CORE_STRM1_INTR_STATUS_CH0 U32_C(0x20048) #define SLVSEC_CORE_STRM1_INTR_STATUS_CH1 U32_C(0x2004c) #define SLVSEC_CORE_STRM1_INTR_STATUS U32_C(0x20050) #define SLVSEC_CIL_STRM0_INTR_STATUS U32_C(0x30818) #define SLVSEC_CIL_STRM1_INTR_STATUS U32_C(0x31018) #define SLVSEC_CIL_STRM0_INTR_MASK U32_C(0x3081c) #define SLVSEC_CIL_STRM1_INTR_MASK U32_C(0x3181c) #define SLVSEC_CIL_STRM_INTR_STATUS_CAL_DONE BIT(3) /* HW capabilities */ #define BUS_WIDTH 64 #define LANE_NUM 8 /* split in two to satisfy static code analysis tool */ #define LANE_SPEED_MHZ U64_C(2304) #define ONE_MILLION U64_C(1000000) /* uses 8b10b encoding */ #define ENCODE_NR 8 #define ENCODE_DR 10 struct slvsec { struct platform_device *pdev; struct tegra_mc_slvs *mc_slvs; int irq; int vi_irq; /* Debugfs */ struct slvsec_debug { struct debugfs_regset32 core; struct debugfs_regset32 core_stream0; struct debugfs_regset32 core_stream1; struct debugfs_regset32 cil; struct debugfs_regset32 vi_syncgen0; struct debugfs_regset32 vi_syncgen1; struct debugfs_regset32 vi_syncgen2; struct slvsec_debug_counter { struct dentry *dir; uint8_t number; uint8_t event; uint8_t stream; } counters[SLVSEC_CORE_NUM_DEBUG_COUNTERS]; } debug; }; static int slvsec_init_debugfs(struct slvsec *slvsec); static void slvsec_remove_debugfs(struct slvsec *slvsec); #ifdef SLVSEC_ENABLE_IRQ static irqreturn_t slvsec_isr(int irq, void *arg) { struct platform_device *pdev = arg; struct slvsec *slvsec = nvhost_get_private_data(pdev); u32 status, val; u32 strm0_cil_status = 0; u32 strm1_cil_status = 0; status = host1x_readl(pdev, SLVSEC_CORE_INTR_STATUS); dev_info(&pdev->dev, "INTR: %08x\n", status); if (status & SLVSEC_CORE_INTR_STATUS_SW) { val = host1x_readl(pdev, SLVSEC_CORE_SW_DEBUG_INTR_STATUS); host1x_writel(pdev, SLVSEC_CORE_SW_DEBUG_INTR_STATUS, val); dev_info(&pdev->dev, "SW_DEBUG_INTR: %08x\n", val); } if (status & SLVSEC_CORE_INTR_STATUS_HOST1X) { val = host1x_readl(pdev, SLVSEC_CORE_HOST1X_INTR_STATUS); host1x_writel(pdev, SLVSEC_CORE_HOST1X_INTR_STATUS, val); dev_info(&pdev->dev, "HOST1X_INTR: %08x\n", val); } if (status & SLVSEC_CORE_INTR_STATUS_CIL) { val = host1x_readl(pdev, SLVSEC_CIL_STRM0_INTR_STATUS); host1x_writel(pdev, SLVSEC_CIL_STRM0_INTR_STATUS, val); dev_info(&pdev->dev, "CIL_STRM0_INTR: %08x\n", val); strm0_cil_status = val; val = host1x_readl(pdev, SLVSEC_CIL_STRM1_INTR_STATUS); host1x_writel(pdev, SLVSEC_CIL_STRM1_INTR_STATUS, val); dev_info(&pdev->dev, "CIL_STRM1_INTR: %08x\n", val); strm1_cil_status = val; } if (status & SLVSEC_CORE_INTR_STATUS_STRM_1) { val = host1x_readl(pdev, SLVSEC_CORE_STRM1_INTR_STATUS); host1x_writel(pdev, SLVSEC_CORE_STRM1_INTR_STATUS, val); dev_info(&pdev->dev, "CORE_STRM1_INTR: %08x\n", val); val = host1x_readl(pdev, SLVSEC_CORE_STRM1_INTR_STATUS_CH0); host1x_writel(pdev, SLVSEC_CORE_STRM1_INTR_STATUS_CH0, val); dev_info(&pdev->dev, "CORE_STRM1_CH0_INTR: %08x\n", val); val = host1x_readl(pdev, SLVSEC_CORE_STRM1_INTR_STATUS_CH1); host1x_writel(pdev, SLVSEC_CORE_STRM1_INTR_STATUS_CH1, val); dev_info(&pdev->dev, "CORE_STRM1_CH1_INTR: %08x\n", val); } if (status & SLVSEC_CORE_INTR_STATUS_STRM_0) { val = host1x_readl(pdev, SLVSEC_CORE_STRM0_INTR_STATUS); host1x_writel(pdev, SLVSEC_CORE_STRM0_INTR_STATUS, val); dev_info(&pdev->dev, "CORE_STRM0_INTR: %08x\n", val); val = host1x_readl(pdev, SLVSEC_CORE_STRM0_INTR_STATUS_CH0); host1x_writel(pdev, SLVSEC_CORE_STRM0_INTR_STATUS_CH0, val); dev_info(&pdev->dev, "CORE_STRM0_CH0_INTR: %08x\n", val); val = host1x_readl(pdev, SLVSEC_CORE_STRM0_INTR_STATUS_CH1); host1x_writel(pdev, SLVSEC_CORE_STRM0_INTR_STATUS_CH1, val); dev_info(&pdev->dev, "CORE_STRM0_CH1_INTR: %08x\n", val); } if (strm0_cil_status) tegra_slvs_media_controller_cil_notify(slvsec->mc_slvs, 0, strm0_cil_status); if (strm1_cil_status) tegra_slvs_media_controller_cil_notify(slvsec->mc_slvs, 1, strm1_cil_status); return IRQ_HANDLED; } static irqreturn_t slvsec_vi_isr(int irq, void *arg) { struct platform_device *pdev = arg; dev_info(&pdev->dev, "%s()\n", __func__); return IRQ_HANDLED; } static int slvsec_get_irq(struct platform_device *pdev, char const *name, int *irqslot, irq_handler_t thread_fn) { struct device *dev = &pdev->dev; int ret = of_irq_get_byname(dev->of_node, name); const char *devname; if (ret == 0) ret = -ENXIO; if (ret < 0) { dev_err(dev, "No %s irq available\n", name); *irqslot = -ENXIO; return ret; } *irqslot = ret; devname = devm_kasprintf(dev, GFP_KERNEL, "%s:%s", dev_name(dev), name); ret = devm_request_threaded_irq(dev, *irqslot, NULL, thread_fn, IRQF_ONESHOT, devname, pdev); if (ret < 0) { dev_err(dev, "Cannot setup %s irq\n", name); *irqslot = -ENXIO; } return ret; } #endif int slvsec_finalize_poweron(struct platform_device *pdev) { struct slvsec *slvsec = nvhost_get_private_data(pdev); int i; for (i = 0; i < ARRAY_SIZE(slvsec->debug.counters); i++) { struct slvsec_debug_counter *counter; u32 reg, val; counter = &slvsec->debug.counters[i]; reg = SLVSEC_CORE_DBG_CNT_CTRL + SLVSEC_CORE_DBG_CNT_SIZE * i; val = (counter->event << SLVSEC_CORE_DBG_CNT_CTRL_EVENT_SHIFT) | counter->stream; host1x_writel(pdev, reg, val); reg = SLVSEC_CORE_DBG_CNT_VALUE + SLVSEC_CORE_DBG_CNT_SIZE * i; host1x_writel(pdev, reg, 0); } if (!tegra_platform_is_silicon()) { host1x_writel(pdev, SLVSEC_CORE_HOST1X_INTR_STATUS, 0x1); host1x_writel(pdev, SLVSEC_CORE_STRM0_INTR_STATUS, 0x9); host1x_writel(pdev, SLVSEC_CIL_STRM0_INTR_MASK, 0x1f); host1x_writel(pdev, SLVSEC_CORE_STRM0_INTR_STATUS_CH0, 0xf); } return 0; } EXPORT_SYMBOL(slvsec_finalize_poweron); int slvsec_prepare_poweroff(struct platform_device *pdev) { return 0; } EXPORT_SYMBOL(slvsec_prepare_poweroff); static int slvsec_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct nvhost_device_data *info; struct device_node *vi_np; struct slvsec *slvsec; struct tegra_camera_dev_info slvsec_info; int err = 0; info = (void *)of_device_get_match_data(dev); if (unlikely(info == NULL)) { dev_WARN(dev, "no platform data\n"); return -ENODATA; } slvsec = devm_kzalloc(dev, sizeof(*slvsec), GFP_KERNEL); if (!slvsec) return -ENOMEM; vi_np = of_parse_phandle(dev->of_node, "nvidia,vi-device", 0); if (vi_np == NULL) { dev_WARN(dev, "missing %s handle\n", "nvidia,vi-device"); return -ENODEV; } slvsec->pdev = pdev; info->pdev = pdev; mutex_init(&info->lock); platform_set_drvdata(pdev, info); info->private_data = slvsec; #ifdef SLVSEC_ENABLE_IRQ if (tegra_platform_is_silicon()) { slvsec_get_irq(pdev, "slvs-ec", &slvsec->irq, slvsec_isr); slvsec_get_irq(pdev, "syncgen", &slvsec->vi_irq, slvsec_vi_isr); } #endif err = nvhost_client_device_get_resources(pdev); if (err) goto error; err = nvhost_module_init(pdev); if (err) goto error; err = nvhost_client_device_init(pdev); if (err) goto deinit; memset(&slvsec_info, 0, sizeof(slvsec_info)); slvsec_info.pdev = pdev; slvsec_info.hw_type = HWTYPE_SLVSEC; slvsec_info.use_max = true; slvsec_info.lane_speed = LANE_SPEED_MHZ * ONE_MILLION * ENCODE_NR / ENCODE_DR; slvsec_info.lane_num = LANE_NUM; slvsec_info.bus_width = BUS_WIDTH; err = tegra_camera_device_register(&slvsec_info, slvsec); if (err) goto deinit; slvsec_init_debugfs(slvsec); #ifdef SLVSEC_ENABLE_IRQ dev_info(dev, "clearing pending interrupts\n"); if (tegra_platform_is_silicon()) slvsec_isr(slvsec->irq, pdev); #endif slvsec->mc_slvs = tegra_slvs_media_controller_init(pdev); if (IS_ERR(slvsec->mc_slvs)) { err = (int)PTR_ERR(slvsec->mc_slvs); dev_info(dev, "failed to init SLVS media controller\n"); goto deinit; } dev_info(dev, "probed\n"); return 0; deinit: nvhost_module_deinit(pdev); error: dev_err(dev, "probe failed: %d\n", err); return err; } static int __exit slvsec_remove(struct platform_device *pdev) { struct nvhost_device_data *pdata = platform_get_drvdata(pdev); struct slvsec *slvsec = (struct slvsec *)pdata->private_data; tegra_camera_device_unregister(slvsec); slvsec_remove_debugfs(slvsec); return 0; } static const struct of_device_id tegra_slvsec_of_match[] = { { .compatible = "nvidia,tegra-slvs-ec", .data = &t19_slvsec_info, }, { }, }; static struct platform_driver slvsec_driver = { .probe = slvsec_probe, .remove = __exit_p(slvsec_remove), .driver = { .owner = THIS_MODULE, .name = "tegra-slvs-ec", #ifdef CONFIG_OF .of_match_table = tegra_slvsec_of_match, #endif #ifdef CONFIG_PM .pm = &nvhost_module_pm_ops, #endif }, }; module_platform_driver(slvsec_driver); /* === Debugfs ========================================================== */ static const struct debugfs_reg32 slvsec_core_regs[] = { { .name = "slvsec_id", 0x80 }, { .name = "intr_status", 0x84 }, { .name = "dbg_cnt0_ctrl", 0x8c }, { .name = "dbg_counter0", 0x90 }, { .name = "dbg_cnt1_ctrl", 0x94 }, { .name = "dbg_counter1", 0x98 }, { .name = "dbg_cnt2_ctrl", 0x9C }, { .name = "dbg_counter2", 0xA0 }, { .name = "dbg_cnt3_ctrl", 0xA4 }, { .name = "dbg_counter3", 0xA8 }, }; static const struct debugfs_reg32 slvsec_core_strm_regs[] = { { .name = "ctrl", 0x0 }, { .name = "rst_ctrl", 0x4 }, { .name = "clk_ctrl", 0x8 }, { .name = "ch0_cfg", 0x0c }, { .name = "ch1_cfg", 0x10 }, { .name = "ch0_embd_cfg", 0x14 }, { .name = "ch1_embd_cfg", 0x18 }, { .name = "timeout_ctrl", 0x1C }, { .name = "ph_rx_crc0", 0x20 }, { .name = "ph_rx_crc1", 0x24 }, { .name = "ph_rx_crc2", 0x28 }, { .name = "pd_rx_crc", 0x2c }, { .name = "pd_cal_crc", 0x30 }, { .name = "vi_err_mask_ch0", 0x34 }, { .name = "vi_err_mask_ch1", 0x38 }, { .name = "intr_mask_ch0", 0x3c }, { .name = "intr_mask_ch1", 0x40 }, { .name = "intr_mask", 0x44 }, { .name = "intr_status_ch0", 0x48 }, { .name = "intr_status_ch1", 0x4c }, { .name = "intr_status", 0x50 }, }; static const struct debugfs_reg32 slvsec_cil_regs[] = { { .name = "ctrl", 0x0 }, { .name = "lane_swizzle", 0x4 }, { .name = "uphy_ctrl0", 0x8 }, { .name = "uphy_ctrl1", 0xC }, { .name = "uphy_ctrl2", 0x10 }, { .name = "timeout_ctrl", 0x14 }, { .name = "padctrl_rst_ctrl", 0x18 }, }; static const struct debugfs_reg32 slvsec_vi_syncgen_regs[] = { { .name = "hclk_div", 0x0 }, { .name = "hclk_div_fmt", 0x4 }, { .name = "xhs", 0x8 }, { .name = "xvs", 0xC }, { .name = "xvs_to_xhs_delay", 0x10 }, { .name = "int_status", 0x14 }, { .name = "int_mask", 0x18 }, { .name = "xhs_timer", 0x1c }, { .name = "control", 0x20 }, { .name = "command", 0x24 }, { .name = "status", 0x28 }, { .name = "scan_status", 0x2c }, { .name = "force_xvs", 0x30 }, }; static int slvsec_sw_debug_intr_show(void *data, u64 *val) { struct platform_device *pdev = data; *val = host1x_readl(pdev, SLVSEC_CORE_SW_DEBUG_INTR_STATUS); return 0; } static int slvsec_sw_debug_intr_store(void *data, u64 val) { struct platform_device *pdev = data; if (val > (u32)~U32_C(0)) return -EINVAL; host1x_writel(pdev, SLVSEC_CORE_SW_DEBUG_INTR_TRIG, (u32)val); return 0; } DEFINE_SIMPLE_ATTRIBUTE(slvsec_sw_debug_intr_fops, slvsec_sw_debug_intr_show, slvsec_sw_debug_intr_store, "%llu\n"); static int slvsec_core_debug_cnt_event_show(void *data, u64 *event) { struct slvsec_debug_counter *counter = data; struct slvsec *slvsec = container_of(data, struct slvsec, debug.counters[counter->number]); struct platform_device *pdev = slvsec->pdev; u32 reg = SLVSEC_CORE_DBG_CNT_CTRL + SLVSEC_CORE_DBG_CNT_SIZE * counter->number; u32 val = host1x_readl(pdev, reg); val >>= SLVSEC_CORE_DBG_CNT_CTRL_EVENT_SHIFT; val &= SLVSEC_CORE_DBG_CNT_CTRL_EVENT_MASK; *event = val; return 0; } static int slvsec_core_debug_cnt_event_store(void *data, u64 event) { struct slvsec_debug_counter *counter = data; struct slvsec *slvsec = container_of(data, struct slvsec, debug.counters[counter->number]); struct platform_device *pdev = slvsec->pdev; u32 control_reg = SLVSEC_CORE_DBG_CNT_CTRL + SLVSEC_CORE_DBG_CNT_SIZE * counter->number; u32 counter_reg = SLVSEC_CORE_DBG_CNT_VALUE + SLVSEC_CORE_DBG_CNT_SIZE * counter->number; u32 val = host1x_readl(pdev, control_reg); if (event > SLVSEC_CORE_DBG_CNT_CTRL_EVENT_MASK) return -EINVAL; counter->event = event; val &= ~SLVSEC_CORE_DBG_CNT_CTRL_EVENT_MASK; val |= event << SLVSEC_CORE_DBG_CNT_CTRL_EVENT_SHIFT; host1x_writel(pdev, control_reg, val); /* Clear counter */ host1x_writel(pdev, counter_reg, 0); return 0; } DEFINE_SIMPLE_ATTRIBUTE(slvsec_core_debug_cnt_event_fops, slvsec_core_debug_cnt_event_show, slvsec_core_debug_cnt_event_store, "%llu\n"); static int slvsec_core_debug_cnt_strm_sel_show(void *data, u64 *strm_sel) { struct slvsec_debug_counter *counter = data; struct slvsec *slvsec = container_of(data, struct slvsec, debug.counters[counter->number]); struct platform_device *pdev = slvsec->pdev; u32 reg = SLVSEC_CORE_DBG_CNT_CTRL + SLVSEC_CORE_DBG_CNT_SIZE * counter->number; u32 val = host1x_readl(pdev, reg); val >>= SLVSEC_CORE_DBG_CNT_CTRL_STRM_SEL_SHIFT; val &= SLVSEC_CORE_DBG_CNT_CTRL_STRM_SEL_MASK; *strm_sel = val; return 0; } static int slvsec_core_debug_cnt_strm_sel_store(void *data, u64 strm_sel) { struct slvsec_debug_counter *counter = data; struct slvsec *slvsec = container_of(data, struct slvsec, debug.counters[counter->number]); struct platform_device *pdev = slvsec->pdev; u32 control_reg = SLVSEC_CORE_DBG_CNT_CTRL + SLVSEC_CORE_DBG_CNT_SIZE * counter->number; u32 counter_reg = SLVSEC_CORE_DBG_CNT_VALUE + SLVSEC_CORE_DBG_CNT_SIZE * counter->number; u32 val = host1x_readl(pdev, control_reg); if (strm_sel > SLVSEC_CORE_DBG_CNT_CTRL_STRM_SEL_MASK) return -EINVAL; counter->stream = strm_sel; val &= ~SLVSEC_CORE_DBG_CNT_CTRL_STRM_SEL_MASK; val |= strm_sel << SLVSEC_CORE_DBG_CNT_CTRL_STRM_SEL_SHIFT; host1x_writel(pdev, control_reg, val); /* Clear counter */ host1x_writel(pdev, counter_reg, 0); return 0; } DEFINE_SIMPLE_ATTRIBUTE(slvsec_core_debug_cnt_strm_sel_fops, slvsec_core_debug_cnt_strm_sel_show, slvsec_core_debug_cnt_strm_sel_store, "%llu\n"); static int slvsec_core_debug_cnt_value_show(void *data, u64 *value) { struct slvsec_debug_counter *counter = data; struct slvsec *slvsec = container_of(data, struct slvsec, debug.counters[counter->number]); struct platform_device *pdev = slvsec->pdev; u32 reg = SLVSEC_CORE_DBG_CNT_VALUE + SLVSEC_CORE_DBG_CNT_SIZE * counter->number; *value = host1x_readl(pdev, reg); return 0; } static int slvsec_core_debug_cnt_value_store(void *data, u64 value) { struct slvsec_debug_counter *counter = data; struct slvsec *slvsec = container_of(data, struct slvsec, debug.counters[counter->number]); struct platform_device *pdev = slvsec->pdev; u32 counter_reg = SLVSEC_CORE_DBG_CNT_VALUE + SLVSEC_CORE_DBG_CNT_SIZE * counter->number; if (value > ~U32_C(0)) return -EINVAL; host1x_writel(pdev, counter_reg, (u32)value); return 0; } DEFINE_SIMPLE_ATTRIBUTE(slvsec_core_debug_cnt_value_fops, slvsec_core_debug_cnt_value_show, slvsec_core_debug_cnt_value_store, "%llu\n"); static int slvsec_init_debugfs(struct slvsec *slvsec) { struct nvhost_device_data *pdata = platform_get_drvdata(slvsec->pdev); struct dentry *dir = pdata->debugfs; struct slvsec_debug *debug = &slvsec->debug; int i; /* Trigger or clear SW interrupts */ debugfs_create_file("sw-intr", S_IRUGO | S_IWUSR, dir, slvsec->pdev, &slvsec_sw_debug_intr_fops); for (i = 0; i < ARRAY_SIZE(debug->counters); i++) { struct slvsec_debug_counter *counter = &debug->counters[i]; char name[16]; snprintf(name, sizeof(name), "counter%u", i); counter->number = i; counter->dir = debugfs_create_dir(name, pdata->debugfs); debugfs_create_file("event", S_IRUGO | S_IWUSR, counter->dir, counter, &slvsec_core_debug_cnt_event_fops); debugfs_create_file("stream", S_IRUGO | S_IWUSR, counter->dir, counter, &slvsec_core_debug_cnt_strm_sel_fops); debugfs_create_file("value", S_IRUGO | S_IWUSR, counter->dir, counter, &slvsec_core_debug_cnt_value_fops); } debug->counters[0].event = 0; /* packet num */ debug->counters[1].event = 4; /* sof */ debug->counters[2].event = 5; /* eof */ debug->counters[3].event = 6; /* valid lines */ debug->core.base = pdata->aperture[0]; debug->core.regs = slvsec_core_regs; debug->core.nregs = ARRAY_SIZE(slvsec_core_regs); debugfs_create_regset32("core", S_IRUGO, dir, &debug->core); debug->core_stream0.base = pdata->aperture[0] + 0x10000; debug->core_stream0.regs = slvsec_core_strm_regs; debug->core_stream0.nregs = ARRAY_SIZE(slvsec_core_strm_regs); debugfs_create_regset32("stream0", S_IRUGO, dir, &debug->core_stream0); debug->core_stream1.base = pdata->aperture[0] + 0x20000; debug->core_stream1.regs = slvsec_core_strm_regs; debug->core_stream1.nregs = ARRAY_SIZE(slvsec_core_strm_regs); debugfs_create_regset32("stream1", S_IRUGO, dir, &debug->core_stream1); debug->cil.base = pdata->aperture[0] + 0x30000; debug->cil.regs = slvsec_cil_regs; debug->cil.nregs = ARRAY_SIZE(slvsec_cil_regs); debugfs_create_regset32("cil", S_IRUGO, dir, &debug->cil); debug->vi_syncgen0.base = pdata->aperture[1] + 0x4800; debug->vi_syncgen0.regs = slvsec_vi_syncgen_regs; debug->vi_syncgen0.nregs = ARRAY_SIZE(slvsec_vi_syncgen_regs); debugfs_create_regset32("fw-syncgen0", S_IRUGO, dir, &debug->vi_syncgen0); debug->vi_syncgen1.base = pdata->aperture[1] + 0x4c00; debug->vi_syncgen1.regs = slvsec_vi_syncgen_regs; debug->vi_syncgen1.nregs = ARRAY_SIZE(slvsec_vi_syncgen_regs); debugfs_create_regset32("fw-syncgen1", S_IRUGO, dir, &debug->vi_syncgen1); debug->vi_syncgen2.base = pdata->aperture[1] + 0x5000; debug->vi_syncgen2.regs = slvsec_vi_syncgen_regs; debug->vi_syncgen2.nregs = ARRAY_SIZE(slvsec_vi_syncgen_regs); debugfs_create_regset32("fw-syncgen2", S_IRUGO, dir, &debug->vi_syncgen2); return 0; } static void slvsec_remove_debugfs(struct slvsec *slvsec) { }