#include <linux/file.h>
#include <linux/pm_runtime.h>
+#include <linux/dma-iommu.h>
+#include <drm/rockchip_drm.h>
+#include <linux/dma-mapping.h>
+#include <linux/dma-buf.h>
+
extern int rockchip_set_system_status(unsigned long status);
extern int rockchip_clear_system_status(unsigned long status);
struct pinctrl *pinctrl;
struct pinctrl_state *state;
int retval = 0;
- char state_str[20] = {0};
+ char state_str[64] = {0};
camsys_dev_t *camsys_dev = (camsys_dev_t *)ptr;
struct device *dev = &(extdev->pdev->dev);
camsys_soc_priv_t *soc;
int flash_trigger_io;
struct pinctrl *pinctrl;
struct pinctrl_state *state;
- char state_str[20] = {0};
+ char state_str[63] = {0};
int retval = 0;
enum of_gpio_flags flags;
camsys_extdev_t *extdev = NULL;
}
}
}
- } else{
+ } else {
strcpy(state_str, "isp_flash_as_trigger_out");
pinctrl = devm_pinctrl_get(dev);
if (IS_ERR(pinctrl)) {
camsys_dev_t *camsys_dev = (camsys_dev_t *)ptr;
of_property_read_u32(camsys_dev->pdev->dev.of_node,
- "rockchip,isp,iommu_enable", &iommu_enabled);
+ "rockchip,isp,iommu-enable", &iommu_enabled);
if (iommu_enabled != 1) {
camsys_err("isp iommu have not been enabled!\n");
ret = -1;
iommu_dev =
rockchip_get_sysmmu_device_by_compatible
(ISP1_IOMMU_COMPATIBLE_NAME);
- } else{
+ } else {
if (CHIP_TYPE == 3399) {
iommu_dev =
rockchip_get_sysmmu_device_by_compatible
ret = rockchip_iovmm_activate(dev);
ret = ion_map_iommu(dev, client, handle,
&(iommu->linear_addr), &(iommu->len));
- } else{
+ } else {
ion_unmap_iommu(dev, client, handle);
platform_set_sysmmu(iommu_dev, dev);
rockchip_iovmm_deactivate(dev);
iommu_end:
return ret;
}
+
+static int camsys_drm_dma_attach_device(camsys_dev_t *camsys_dev)
+{
+ struct iommu_domain *domain = camsys_dev->domain;
+ struct device *dev = &camsys_dev->pdev->dev;
+ int ret;
+
+ ret = dma_set_coherent_mask(dev, DMA_BIT_MASK(32));
+ if (ret)
+ return ret;
+
+ dma_set_max_seg_size(dev, DMA_BIT_MASK(32));
+ ret = iommu_attach_device(domain, dev);
+ if (ret) {
+ dev_err(dev, "Failed to attach iommu device\n");
+ return ret;
+ }
+
+ if (!common_iommu_setup_dma_ops(dev, 0x10000000, SZ_2G, domain->ops)) {
+ dev_err(dev, "Failed to set dma_ops\n");
+ iommu_detach_device(domain, dev);
+ ret = -ENODEV;
+ }
+
+ return ret;
+}
+
+static void camsys_drm_dma_detach_device(camsys_dev_t *camsys_dev)
+{
+ struct iommu_domain *domain = camsys_dev->domain;
+ struct device *dev = &camsys_dev->pdev->dev;
+
+ iommu_detach_device(domain, dev);
+}
+
+static int camsys_mrv_drm_iommu_cb(void *ptr, camsys_sysctrl_t *devctl)
+{
+ struct device *dev = NULL;
+ camsys_iommu_t *iommu = NULL;
+ struct dma_buf *dma_buf;
+ struct dma_buf_attachment *attach;
+ struct sg_table *sgt;
+ dma_addr_t dma_addr;
+ int index = 0;
+ int ret = 0;
+ camsys_dev_t *camsys_dev = (camsys_dev_t *)ptr;
+
+ dev = &camsys_dev->pdev->dev;
+ iommu = (camsys_iommu_t *)(devctl->rev);
+ if (devctl->on) {
+ /*ummap mapped fd first*/
+ int cur_mapped_cnt = camsys_dev->dma_buf_cnt;
+
+ for (index = 0; index < cur_mapped_cnt; index++) {
+ if (camsys_dev->dma_buf[index].fd == iommu->map_fd)
+ break;
+ }
+ if (index != cur_mapped_cnt) {
+ attach = camsys_dev->dma_buf[index].attach;
+ dma_buf = camsys_dev->dma_buf[index].dma_buf;
+ sgt = camsys_dev->dma_buf[index].sgt;
+ dma_buf_unmap_attachment
+ (attach,
+ sgt,
+ DMA_BIDIRECTIONAL);
+ dma_buf_detach(dma_buf, attach);
+ dma_buf_put(dma_buf);
+ if (camsys_dev->dma_buf_cnt == 1)
+ camsys_drm_dma_detach_device(camsys_dev);
+ camsys_dev->dma_buf_cnt--;
+ camsys_dev->dma_buf[index].fd = -1;
+ }
+ /*get a free slot*/
+ for (index = 0; index < CAMSYS_DMA_BUF_MAX_NUM; index++)
+ if (camsys_dev->dma_buf[index].fd == -1)
+ break;
+
+ if (index == CAMSYS_DMA_BUF_MAX_NUM)
+ return -ENOMEM;
+
+ if (camsys_dev->dma_buf_cnt == 0) {
+ ret = camsys_drm_dma_attach_device(camsys_dev);
+ if (ret)
+ return ret;
+ }
+
+ dma_buf = dma_buf_get(iommu->map_fd);
+ if (IS_ERR(dma_buf))
+ return PTR_ERR(dma_buf);
+ attach = dma_buf_attach(dma_buf, dev);
+ if (IS_ERR(attach)) {
+ dma_buf_put(dma_buf);
+ return PTR_ERR(attach);
+ }
+ sgt = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL);
+ if (IS_ERR(sgt)) {
+ dma_buf_detach(dma_buf, attach);
+ dma_buf_put(dma_buf);
+ return PTR_ERR(sgt);
+ }
+ dma_addr = sg_dma_address(sgt->sgl);
+ camsys_dev->dma_buf[index].dma_addr = dma_addr;
+ camsys_dev->dma_buf[index].attach = attach;
+ camsys_dev->dma_buf[index].dma_buf = dma_buf;
+ camsys_dev->dma_buf[index].sgt = sgt;
+ camsys_dev->dma_buf[index].fd = iommu->map_fd;
+ iommu->linear_addr = dma_addr;
+ iommu->len = sg_dma_len(sgt->sgl);
+ camsys_dev->dma_buf_cnt++;
+ camsys_trace
+ (
+ 1,
+ "%s:iommu map dma_addr 0x%lx,attach %p,"
+ "dma_buf %p,sgt %p,fd %d,buf_cnt %d",
+ __func__,
+ (unsigned long)dma_addr,
+ attach,
+ dma_buf,
+ sgt,
+ iommu->map_fd,
+ camsys_dev->dma_buf_cnt);
+ } else {
+ if (
+ (camsys_dev->dma_buf_cnt == 0) ||
+ (index < 0) ||
+ (index >= CAMSYS_DMA_BUF_MAX_NUM))
+ return -EINVAL;
+
+ for (index = 0; index < camsys_dev->dma_buf_cnt; index++) {
+ if (camsys_dev->dma_buf[index].fd == iommu->map_fd)
+ break;
+ }
+ if (index == camsys_dev->dma_buf_cnt) {
+ camsys_warn("can't find map fd %d", iommu->map_fd);
+ return 0;
+ }
+ attach = camsys_dev->dma_buf[index].attach;
+ dma_buf = camsys_dev->dma_buf[index].dma_buf;
+ sgt = camsys_dev->dma_buf[index].sgt;
+ camsys_trace
+ (
+ 1,
+ "%s:iommu map ,attach %p,"
+ "dma_buf %p,sgt %p,index %d",
+ __func__,
+ attach,
+ dma_buf,
+ sgt,
+ index);
+ dma_buf_unmap_attachment(attach, sgt, DMA_BIDIRECTIONAL);
+ dma_buf_detach(dma_buf, attach);
+ dma_buf_put(dma_buf);
+ if (camsys_dev->dma_buf_cnt == 1)
+ camsys_drm_dma_detach_device(camsys_dev);
+
+ camsys_dev->dma_buf_cnt--;
+ camsys_dev->dma_buf[index].fd = -1;
+ }
+
+ return ret;
+}
+
static int camsys_mrv_reset_cb(void *ptr, unsigned int on)
{
camsys_dev_t *camsys_dev = (camsys_dev_t *)ptr;
if (on == 1)
isp_clk = 210000000;
else
- isp_clk = 210000000;
+ isp_clk = 420000000;
if (strstr(camsys_dev->miscdev.name,
"camsys_marvin1")) {
clk_prepare_enable(clk->pclk_dphytxrx);
clk_prepare_enable(clk->pclkin_isp);
- } else{
+ clk_prepare_enable(clk->cif_clk_out);
+ } else {
clk_set_rate(clk->clk_isp0, isp_clk);
clk_prepare_enable(clk->hclk_isp0_noc);
clk_prepare_enable(clk->hclk_isp0_wrapper);
clk_prepare_enable(clk->pclk_dphy_ref);
}
- clk_set_rate(clk->clk_isp0, isp_clk);
- clk_set_rate(clk->clk_isp1, isp_clk);
-
clk->in_on = true;
camsys_trace(1, "%s clock(f: %ld Hz) in turn on",
clk_disable_unprepare(clk->pclk_dphy_ref);
clk_disable_unprepare(clk->pclkin_isp);
-
- } else{
+ } else {
clk_disable_unprepare(clk->hclk_isp0_noc);
clk_disable_unprepare(clk->hclk_isp0_wrapper);
clk_disable_unprepare(clk->aclk_isp0_noc);
if (CHIP_TYPE == 3368 || CHIP_TYPE == 3366) {
clk_prepare_enable(clk->cif_clk_out);
clk_prepare_enable(clk->pclk_dphyrx);
- if (CHIP_TYPE == 3368)
- clk_prepare_enable(clk->clk_vio0_noc);
- } else{
+ } else {
clk_prepare_enable(clk->clk_mipi_24m);
}
clk->in_on = true;
if (CHIP_TYPE == 3368 || CHIP_TYPE == 3366) {
clk_disable_unprepare(clk->cif_clk_out);
clk_disable_unprepare(clk->pclk_dphyrx);
- if (CHIP_TYPE == 3368)
- clk_disable_unprepare(clk->clk_vio0_noc);
- } else{
+ } else {
clk_disable_unprepare(clk->clk_mipi_24m);
}
/* clk_disable_unprepare(clk->pd_isp); */
mrv_clk = NULL;
}
+ camsys_drm_dma_detach_device(camsys_dev);
+ iommu_group_remove_device(&camsys_dev->pdev->dev);
+ iommu_put_dma_cookie(camsys_dev->domain);
+ iommu_domain_free(camsys_dev->domain);
+
return 0;
}
int camsys_mrv_probe_cb(struct platform_device *pdev, camsys_dev_t *camsys_dev)
{
int err = 0;
camsys_mrv_clk_t *mrv_clk = NULL;
- const char *compatible = NULL;
+ struct resource register_res;
+ struct iommu_domain *domain;
+ struct iommu_group *group;
+ struct device_node *np;
+
+ err = of_address_to_resource(pdev->dev.of_node, 0, ®ister_res);
+ if (err < 0) {
+ camsys_err(
+ "Get register resource from %s platform device failed!",
+ pdev->name);
+ }
err = request_irq(camsys_dev->irq.irq_id, camsys_mrv_irq,
IRQF_SHARED, CAMSYS_MARVIN_IRQNAME,
} else if (CHIP_TYPE == 3399) {
pm_runtime_enable(&pdev->dev);
- mrv_clk->hclk_isp0_noc =
- devm_clk_get(&pdev->dev, "hclk_isp0_noc");
- mrv_clk->hclk_isp0_wrapper =
- devm_clk_get(&pdev->dev, "hclk_isp0_wrapper");
- mrv_clk->aclk_isp0_noc =
- devm_clk_get(&pdev->dev, "aclk_isp0_noc");
- mrv_clk->aclk_isp0_wrapper =
- devm_clk_get(&pdev->dev, "aclk_isp0_wrapper");
- mrv_clk->clk_isp0 =
- devm_clk_get(&pdev->dev, "clk_isp0");
+ if (register_res.start == 0xff920000) {
+ mrv_clk->hclk_isp1_noc =
+ devm_clk_get(&pdev->dev, "hclk_isp1_noc");
+ mrv_clk->hclk_isp1_wrapper =
+ devm_clk_get(&pdev->dev, "hclk_isp1_wrapper");
+ mrv_clk->aclk_isp1_noc =
+ devm_clk_get(&pdev->dev, "aclk_isp1_noc");
+ mrv_clk->aclk_isp1_wrapper =
+ devm_clk_get(&pdev->dev, "aclk_isp1_wrapper");
+ mrv_clk->clk_isp1 =
+ devm_clk_get(&pdev->dev, "clk_isp1");
+ mrv_clk->pclkin_isp =
+ devm_clk_get(&pdev->dev, "pclk_isp1");
+ mrv_clk->pclk_dphytxrx =
+ devm_clk_get(&pdev->dev, "pclk_dphytxrx");
+ } else{
+ mrv_clk->hclk_isp0_noc =
+ devm_clk_get(&pdev->dev, "hclk_isp0_noc");
+ mrv_clk->hclk_isp0_wrapper =
+ devm_clk_get(&pdev->dev, "hclk_isp0_wrapper");
+ mrv_clk->aclk_isp0_noc =
+ devm_clk_get(&pdev->dev, "aclk_isp0_noc");
+ mrv_clk->aclk_isp0_wrapper =
+ devm_clk_get(&pdev->dev, "aclk_isp0_wrapper");
+ mrv_clk->clk_isp0 =
+ devm_clk_get(&pdev->dev, "clk_isp0");
+ mrv_clk->pclk_dphyrx =
+ devm_clk_get(&pdev->dev, "pclk_dphyrx");
+ }
mrv_clk->cif_clk_out =
devm_clk_get(&pdev->dev, "clk_cif_out");
mrv_clk->cif_clk_pll =
devm_clk_get(&pdev->dev, "clk_cif_pll");
- mrv_clk->pclk_dphyrx =
- devm_clk_get(&pdev->dev, "pclk_dphyrx");
mrv_clk->pclk_dphy_ref =
devm_clk_get(&pdev->dev, "pclk_dphy_ref");
-
- mrv_clk->hclk_isp1_noc =
- devm_clk_get(&pdev->dev, "hclk_isp1_noc");
- mrv_clk->hclk_isp1_wrapper =
- devm_clk_get(&pdev->dev, "hclk_isp1_wrapper");
- mrv_clk->aclk_isp1_noc =
- devm_clk_get(&pdev->dev, "aclk_isp1_noc");
- mrv_clk->aclk_isp1_wrapper =
- devm_clk_get(&pdev->dev, "aclk_isp1_wrapper");
- mrv_clk->pclkin_isp =
- devm_clk_get(&pdev->dev, "pclk_isp1");
-
- mrv_clk->clk_isp1 =
- devm_clk_get(&pdev->dev, "clk_isp1");
- mrv_clk->pclk_dphytxrx =
- devm_clk_get(&pdev->dev, "pclk_dphytxrx");
-
- if (IS_ERR_OR_NULL(mrv_clk->hclk_isp0_noc) ||
- IS_ERR_OR_NULL(mrv_clk->hclk_isp0_wrapper) ||
- IS_ERR_OR_NULL(mrv_clk->aclk_isp0_noc) ||
- IS_ERR_OR_NULL(mrv_clk->aclk_isp0_wrapper) ||
- IS_ERR_OR_NULL(mrv_clk->clk_isp0) ||
- IS_ERR_OR_NULL(mrv_clk->cif_clk_out) ||
- IS_ERR_OR_NULL(mrv_clk->cif_clk_pll) ||
- IS_ERR_OR_NULL(mrv_clk->pclk_dphyrx)) {
- camsys_err("Get %s clock resouce failed!\n",
- miscdev_name);
- err = -EINVAL;
- goto clk_failed;
- }
-
- err = of_property_read_string(pdev->dev.of_node,
- "compatible", &compatible);
- if (err < 0) {
- camsys_err("get compatible failed!");
- } else {
- camsys_trace(1, "compatible is %s\n", compatible);
- }
- if (strstr(compatible, "isp1")) {
- clk_set_rate(mrv_clk->clk_isp1, 210000000);
+ if (register_res.start == 0xff920000) {
+ if (IS_ERR_OR_NULL(mrv_clk->hclk_isp1_noc) ||
+ IS_ERR_OR_NULL(mrv_clk->hclk_isp1_wrapper) ||
+ IS_ERR_OR_NULL(mrv_clk->aclk_isp1_noc) ||
+ IS_ERR_OR_NULL(mrv_clk->aclk_isp1_wrapper) ||
+ IS_ERR_OR_NULL(mrv_clk->clk_isp1) ||
+ IS_ERR_OR_NULL(mrv_clk->cif_clk_out) ||
+ IS_ERR_OR_NULL(mrv_clk->cif_clk_pll) ||
+ IS_ERR_OR_NULL(mrv_clk->pclkin_isp) ||
+ IS_ERR_OR_NULL(mrv_clk->pclk_dphytxrx)) {
+ camsys_err("Get %s clock resouce failed!\n",
+ miscdev_name);
+ err = -EINVAL;
+ goto clk_failed;
+ }
} else{
- clk_set_rate(mrv_clk->clk_isp0, 210000000);
+ if (IS_ERR_OR_NULL(mrv_clk->hclk_isp0_noc) ||
+ IS_ERR_OR_NULL(mrv_clk->hclk_isp0_wrapper) ||
+ IS_ERR_OR_NULL(mrv_clk->aclk_isp0_noc) ||
+ IS_ERR_OR_NULL(mrv_clk->aclk_isp0_wrapper) ||
+ IS_ERR_OR_NULL(mrv_clk->clk_isp0) ||
+ IS_ERR_OR_NULL(mrv_clk->cif_clk_out) ||
+ IS_ERR_OR_NULL(mrv_clk->cif_clk_pll) ||
+ IS_ERR_OR_NULL(mrv_clk->pclk_dphyrx)) {
+ camsys_err("Get %s clock resouce failed!\n",
+ miscdev_name);
+ err = -EINVAL;
+ goto clk_failed;
+ }
}
-
} else{
mrv_clk->pd_isp =
devm_clk_get(&pdev->dev, "pd_isp");
mrv_clk->clk_mipi_24m =
devm_clk_get(&pdev->dev, "clk_mipi_24m");
- if (IS_ERR_OR_NULL(mrv_clk->pd_isp) ||
- IS_ERR_OR_NULL(mrv_clk->aclk_isp) ||
- IS_ERR_OR_NULL(mrv_clk->hclk_isp) ||
- IS_ERR_OR_NULL(mrv_clk->isp) ||
- IS_ERR_OR_NULL(mrv_clk->isp_jpe) ||
+ if (IS_ERR_OR_NULL(mrv_clk->pd_isp) ||
+ IS_ERR_OR_NULL(mrv_clk->aclk_isp) ||
+ IS_ERR_OR_NULL(mrv_clk->hclk_isp) ||
+ IS_ERR_OR_NULL(mrv_clk->isp) ||
+ IS_ERR_OR_NULL(mrv_clk->isp_jpe) ||
IS_ERR_OR_NULL(mrv_clk->pclkin_isp) ||
IS_ERR_OR_NULL(mrv_clk->cif_clk_out) ||
IS_ERR_OR_NULL(mrv_clk->clk_mipi_24m)) {
mrv_clk->in_on = false;
mrv_clk->out_on = 0;
+ np = of_find_node_by_name(NULL, "isp0_mmu");
+ if (!np) {
+ int index = 0;
+ /* iommu domain */
+ domain = iommu_domain_alloc(&platform_bus_type);
+ if (!domain)
+ goto clk_failed;
+
+ err = iommu_get_dma_cookie(domain);
+ if (err)
+ goto err_free_domain;
+
+ group = iommu_group_get(&pdev->dev);
+ if (!group) {
+ group = iommu_group_alloc();
+ if (IS_ERR(group)) {
+ dev_err(&pdev->dev, "Failed to allocate IOMMU group\n");
+ goto err_put_cookie;
+ }
+
+ err = iommu_group_add_device(group, &pdev->dev);
+ iommu_group_put(group);
+ if (err) {
+ dev_err(&pdev->dev, "failed to add device to IOMMU group\n");
+ goto err_put_cookie;
+ }
+ }
+ camsys_dev->domain = domain;
+ camsys_dev->dma_buf_cnt = 0;
+ camsys_dev->iommu_cb = camsys_mrv_drm_iommu_cb;
+ for (index = 0; index < CAMSYS_DMA_BUF_MAX_NUM; index++)
+ camsys_dev->dma_buf[index].fd = -1;
+ } else {
+ camsys_dev->iommu_cb = camsys_mrv_iommu_cb;
+ }
+
camsys_dev->clk = (void *)mrv_clk;
camsys_dev->clkin_cb = camsys_mrv_clkin_cb;
camsys_dev->clkout_cb = camsys_mrv_clkout_cb;
camsys_dev->reset_cb = camsys_mrv_reset_cb;
camsys_dev->iomux = camsys_mrv_iomux_cb;
camsys_dev->flash_trigger_cb = camsys_mrv_flash_trigger_cb;
- camsys_dev->iommu_cb = camsys_mrv_iommu_cb;
camsys_dev->miscdev.minor = MISC_DYNAMIC_MINOR;
camsys_dev->miscdev.name = miscdev_name;
camsys_dev->miscdev.fops = &camsys_fops;
if (CHIP_TYPE == 3399) {
- if (strstr(compatible, "isp1")) {
+ if (register_res.start == 0xff920000) {
camsys_dev->miscdev.name = "camsys_marvin1";
camsys_dev->miscdev.nodename = "camsys_marvin1";
}
misc_register_failed:
if (!IS_ERR_OR_NULL(camsys_dev->miscdev.this_device))
misc_deregister(&camsys_dev->miscdev);
-
+err_put_cookie:
+ iommu_put_dma_cookie(domain);
+err_free_domain:
+ iommu_domain_free(domain);
clk_failed:
if (mrv_clk != NULL) {
if (!IS_ERR_OR_NULL(mrv_clk->pd_isp))