/* ************************************************************************* * Rockchip driver for CIF ISP 1.0 * (Based on Intel driver for sofiaxxx) * * Copyright (C) 2015 Intel Mobile Communications GmbH * Copyright (C) 2016 Fuzhou Rockchip Electronics Co., Ltd. * * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. ************************************************************************* */ #include #include #include #include #include #include #include #include #include #include #include #define VI_IRCL 0x0014 #define MRV_MIPI_BASE 0x1C00 #define MRV_MIPI_CTRL 0x00 /* * GRF_IO_VSEL */ #define GRF_IO_VSEL_OFFSET (0x0900) #define DVP_V18SEL ((1 << 1) | (1 << 17)) #define DVP_V33SEL ((0 << 1) | (1 << 17)) /* * GRF_IO_VSEL */ #define GRF_GPIO2B_E_OFFSET (0x0204) #define CIF_CLKOUT_STRENGTH(a) \ ((((a) & 0x03) << 3) | (0x03 << 19)) #define GRF_SOC_STATUS1 (0x0e2a4) #define GRF_SOC_CON9_OFFSET (0x6224) #define DPHY_RX0_TURNREQUEST_MASK (0xF << 16) #define DPHY_RX0_TURNREQUEST_BIT (0) #define GRF_SOC_CON21_OFFSET (0x6254) #define DPHY_RX0_FORCERXMODE_MASK (0xF << 20) #define DPHY_RX0_FORCERXMODE_BIT (4) #define DPHY_RX0_FORCETXSTOPMODE_MASK (0xF << 24) #define DPHY_RX0_FORCETXSTOPMODE_BIT (8) #define DPHY_RX0_TURNDISABLE_MASK (0xF << 28) #define DPHY_RX0_TURNDISABLE_BIT (12) #define DPHY_RX0_ENABLE_MASK (0xF << 16) #define DPHY_RX0_ENABLE_BIT (0) #define GRF_SOC_CON23_OFFSET (0x625c) #define DPHY_TX1RX1_TURNDISABLE_MASK (0xF << 28) #define DPHY_TX1RX1_TURNDISABLE_BIT (12) #define DPHY_TX1RX1_FORCERXMODE_MASK (0xF << 20) #define DPHY_TX1RX1_FORCERXMODE_BIT (4) #define DPHY_TX1RX1_FORCETXSTOPMODE_MASK (0xF << 24) #define DPHY_TX1RX1_FORCETXSTOPMODE_BIT (8) #define DPHY_TX1RX1_ENABLE_MASK (0xF << 16) #define DPHY_TX1RX1_ENABLE_BIT (0) #define GRF_SOC_CON24_OFFSET (0x6260) #define DPHY_TX1RX1_MASTERSLAVEZ_MASK (0x1 << 23) #define DPHY_TX1RX1_MASTERSLAVEZ_BIT (7) #define DPHY_TX1RX1_BASEDIR_MASK (0x1 << 21) #define DPHY_TX1RX1_BASEDIR_BIT (5) #define DPHY_RX1_MASK (0x1 << 20) #define DPHY_RX1_SEL_BIT (4) #define GRF_SOC_CON25_OFFSET (0x6264) #define DPHY_RX0_TESTCLK_MASK (0x1 << 25) #define DPHY_RX0_TESTCLK_BIT (9) #define DPHY_RX0_TESTCLR_MASK (0x1 << 26) #define DPHY_RX0_TESTCLR_BIT (10) #define DPHY_RX0_TESTDIN_MASK (0xFF << 16) #define DPHY_RX0_TESTDIN_BIT (0) #define DPHY_RX0_TESTEN_MASK (0x1 << 24) #define DPHY_RX0_TESTEN_BIT (8) #define DPHY_TX1RX1_TURNREQUEST_MASK (0xF << 16) #define DPHY_TX1RX1_TURNREQUEST_BIT (0) #define DSIHOST_PHY_SHUTDOWNZ (0x00a0) #define DSIHOST_DPHY_RSTZ (0x00a0) #define DSIHOST_PHY_TEST_CTRL0 (0x00b4) #define DSIHOST_PHY_TEST_CTRL1 (0x00b8) #define write_cifisp_reg(addr, val) \ __raw_writel(val, (addr) + isp_cfg->isp_base) #define read_cifisp_reg(addr) \ __raw_readl((addr) + isp_cfg->isp_base) #define write_grf_reg(addr, val) \ regmap_write(isp_cfg->regmap_grf, addr, val) #define read_grf_reg(addr, val) \ regmap_read(isp_cfg->regmap_grf, addr, val) #define write_dsihost_reg(addr, val) \ __raw_writel(val, (addr) + isp_cfg->dsihost_base) #define read_dsihost_reg(addr) \ __raw_readl((addr) + isp_cfg->dsihost_base) enum cif_isp10_isp_idx { CIF_ISP10_ISP0 = 0, CIF_ISP10_ISP1 = 1 }; struct cif_isp10_clk_rst_rk3399 { struct clk *hclk_isp0_noc; struct clk *hclk_isp0_wrapper; struct clk *hclk_isp1_noc; struct clk *hclk_isp1_wrapper; struct clk *aclk_isp0_noc; struct clk *aclk_isp0_wrapper; struct clk *aclk_isp1_noc; struct clk *aclk_isp1_wrapper; struct clk *clk_isp0; struct clk *clk_isp1; struct clk *pclkin_isp1; struct clk *pclk_dphy_ref; struct clk *pclk_dphytxrx; struct clk *pclk_dphyrx; struct clk *cif_clk_out; struct clk *cif_clk_pll; struct clk *cif_clk_mipi_dsi; struct clk *cif_clk_mipi_dphy_cfg; }; struct cif_isp10_rk3399 { struct regmap *regmap_grf; void __iomem *dsihost_base; void __iomem *isp_base; struct cif_isp10_clk_rst_rk3399 clk_rst; struct cif_isp10_device *cif_isp10; enum cif_isp10_isp_idx isp_idx; }; struct mipi_dphy_hsfreqrange { unsigned int range_l; unsigned int range_h; unsigned char cfg_bit; }; static struct mipi_dphy_hsfreqrange mipi_dphy_hsfreq_range[] = { {80, 90, 0x00}, {90, 100, 0x10}, {100, 110, 0x20}, {110, 130, 0x01}, {130, 140, 0x11}, {140, 150, 0x21}, {150, 170, 0x02}, {170, 180, 0x12}, {180, 200, 0x22}, {200, 220, 0x03}, {220, 240, 0x13}, {240, 250, 0x23}, {250, 270, 0x4}, {270, 300, 0x14}, {300, 330, 0x5}, {330, 360, 0x15}, {360, 400, 0x25}, {400, 450, 0x06}, {450, 500, 0x16}, {500, 550, 0x07}, {550, 600, 0x17}, {600, 650, 0x08}, {650, 700, 0x18}, {700, 750, 0x09}, {750, 800, 0x19}, {800, 850, 0x29}, {850, 900, 0x39}, {900, 950, 0x0a}, {950, 1000, 0x1a}, {1000, 1050, 0x2a}, {1100, 1150, 0x3a}, {1150, 1200, 0x0b}, {1200, 1250, 0x1b}, {1250, 1300, 0x2b}, {1300, 1350, 0x0c}, {1350, 1400, 0x1c}, {1400, 1450, 0x2c}, {1450, 1500, 0x3c} }; static int mipi_dphy0_wr_reg(struct cif_isp10_rk3399 *isp_cfg, unsigned char addr, unsigned char data) { /* * TESTCLK=1 * TESTEN =1,TESTDIN=addr * TESTCLK=0 */ write_grf_reg(GRF_SOC_CON25_OFFSET, DPHY_RX0_TESTCLK_MASK | (1 << DPHY_RX0_TESTCLK_BIT)); write_grf_reg(GRF_SOC_CON25_OFFSET, ((addr << DPHY_RX0_TESTDIN_BIT) | DPHY_RX0_TESTDIN_MASK | (1 << DPHY_RX0_TESTEN_BIT) | DPHY_RX0_TESTEN_MASK)); write_grf_reg(GRF_SOC_CON25_OFFSET, DPHY_RX0_TESTCLK_MASK); /* * write data: * TESTEN =0,TESTDIN=data * TESTCLK=1 */ if (data != 0xff) { write_grf_reg(GRF_SOC_CON25_OFFSET, ((data << DPHY_RX0_TESTDIN_BIT) | DPHY_RX0_TESTDIN_MASK | DPHY_RX0_TESTEN_MASK)); write_grf_reg(GRF_SOC_CON25_OFFSET, DPHY_RX0_TESTCLK_MASK | (1 << DPHY_RX0_TESTCLK_BIT)); } return 0; } static int mipi_dphy0_rd_reg(struct cif_isp10_rk3399 *isp_cfg, unsigned char addr) { int val = 0; /*TESTCLK=1*/ write_grf_reg(GRF_SOC_CON25_OFFSET, DPHY_RX0_TESTCLK_MASK | (1 << DPHY_RX0_TESTCLK_BIT)); /*TESTEN =1,TESTDIN=addr*/ write_grf_reg(GRF_SOC_CON25_OFFSET, ((addr << DPHY_RX0_TESTDIN_BIT) | DPHY_RX0_TESTDIN_MASK | (1 << DPHY_RX0_TESTEN_BIT) | DPHY_RX0_TESTEN_MASK)); /*TESTCLK=0*/ write_grf_reg(GRF_SOC_CON25_OFFSET, DPHY_RX0_TESTCLK_MASK); read_grf_reg(GRF_SOC_STATUS1, &val); return val & 0xff; } static int mipi_dphy1_wr_reg(struct cif_isp10_rk3399 *isp_cfg, unsigned char addr, unsigned char data) { /* * TESTEN =1,TESTDIN=addr * TESTCLK=0 * TESTEN =0,TESTDIN=data * TESTCLK=1 */ write_dsihost_reg(DSIHOST_PHY_TEST_CTRL1, (0x00010000 | addr)); write_dsihost_reg(DSIHOST_PHY_TEST_CTRL0, 0x00000000); write_dsihost_reg(DSIHOST_PHY_TEST_CTRL1, (0x00000000 | data)); write_dsihost_reg(DSIHOST_PHY_TEST_CTRL0, 0x00000002); return 0; } static int mipi_dphy1_rd_reg(struct cif_isp10_rk3399 *isp_cfg, unsigned char addr) { /* TESTEN =1,TESTDIN=addr */ write_dsihost_reg(DSIHOST_PHY_TEST_CTRL1, (0x00010000 | addr)); /* TESTCLK=0 */ write_dsihost_reg(DSIHOST_PHY_TEST_CTRL0, 0x00000000); return ((read_dsihost_reg(DSIHOST_PHY_TEST_CTRL1) & 0xff00) >> 8); } static int mipi_dphy_cfg(struct cif_isp10_rk3399 *isp_cfg, struct pltfrm_cam_mipi_config *para) { unsigned char hsfreqrange = 0xff, i; struct mipi_dphy_hsfreqrange *hsfreqrange_p; unsigned char datalane_en, input_sel; hsfreqrange_p = mipi_dphy_hsfreq_range; for (i = 0; i < (sizeof(mipi_dphy_hsfreq_range) / sizeof(struct mipi_dphy_hsfreqrange)); i++) { if ((para->bit_rate > hsfreqrange_p->range_l) && (para->bit_rate <= hsfreqrange_p->range_h)) { hsfreqrange = hsfreqrange_p->cfg_bit; break; } hsfreqrange_p++; } if (hsfreqrange == 0xff) hsfreqrange = 0x00; hsfreqrange <<= 1; input_sel = para->dphy_index; datalane_en = 0; for (i = 0; i < para->nb_lanes; i++) datalane_en |= (1 << i); if (input_sel == 0) { /* * According to the sequence of RK3399_TXRX_DPHY, the setting of isp0 mipi * will affect txrx dphy in default state of grf_soc_con24. */ write_grf_reg(GRF_SOC_CON24_OFFSET, DPHY_TX1RX1_MASTERSLAVEZ_MASK | (0x0 << DPHY_TX1RX1_MASTERSLAVEZ_BIT) | DPHY_TX1RX1_BASEDIR_MASK | (0x1 << DPHY_TX1RX1_BASEDIR_BIT) | DPHY_RX1_MASK | 0x0 << DPHY_RX1_SEL_BIT); write_grf_reg(GRF_SOC_CON21_OFFSET, DPHY_RX0_FORCERXMODE_MASK | (0x0 << DPHY_RX0_FORCERXMODE_BIT) | DPHY_RX0_FORCETXSTOPMODE_MASK | (0x0 << DPHY_RX0_FORCETXSTOPMODE_BIT)); /* set lane num */ write_grf_reg(GRF_SOC_CON21_OFFSET, DPHY_RX0_ENABLE_MASK | (datalane_en << DPHY_RX0_ENABLE_BIT)); /* set lan turndisab as 1 */ write_grf_reg(GRF_SOC_CON21_OFFSET, DPHY_RX0_TURNDISABLE_MASK | (0xf << DPHY_RX0_TURNDISABLE_BIT)); write_grf_reg(GRF_SOC_CON21_OFFSET, (0x0 << 4) | (0xf << 20)); /* set lan turnrequest as 0 */ write_grf_reg(GRF_SOC_CON9_OFFSET, DPHY_RX0_TURNREQUEST_MASK | (0x0 << DPHY_RX0_TURNREQUEST_BIT)); /* phy start */ /* * TESTCLK=1 * TESTCLR=1 * delay 100us * TESTCLR=0 */ write_grf_reg(GRF_SOC_CON25_OFFSET, DPHY_RX0_TESTCLK_MASK | (0x1 << DPHY_RX0_TESTCLK_BIT)); /* TESTCLK=1 */ write_grf_reg(GRF_SOC_CON25_OFFSET, DPHY_RX0_TESTCLR_MASK | (0x1 << DPHY_RX0_TESTCLR_BIT)); /* TESTCLR=1 */ usleep_range(100, 150); /* TESTCLR=0 zyc */ write_grf_reg(GRF_SOC_CON25_OFFSET, DPHY_RX0_TESTCLR_MASK); usleep_range(100, 150); /* set clock lane */ mipi_dphy0_wr_reg (isp_cfg, 0x34, 0); /* HS hsfreqrange & lane 0 settle bypass */ mipi_dphy0_wr_reg(isp_cfg, 0x44, hsfreqrange); mipi_dphy0_wr_reg(isp_cfg, 0x54, 0); mipi_dphy0_wr_reg(isp_cfg, 0x84, 0); mipi_dphy0_wr_reg(isp_cfg, 0x94, 0); mipi_dphy0_wr_reg(isp_cfg, 0x75, 0x04); mipi_dphy0_rd_reg(isp_cfg, 0x75); /* Normal operation */ /* * TESTCLK=1 * TESTEN =0 */ mipi_dphy0_wr_reg(isp_cfg, 0x0, -1); write_grf_reg(GRF_SOC_CON25_OFFSET, DPHY_RX0_TESTCLK_MASK | (1 << DPHY_RX0_TESTCLK_BIT)); write_grf_reg(GRF_SOC_CON25_OFFSET, (DPHY_RX0_TESTEN_MASK)); write_cifisp_reg((MRV_MIPI_BASE + MRV_MIPI_CTRL), read_cifisp_reg(MRV_MIPI_BASE + MRV_MIPI_CTRL) | (0x0f << 8)); } else if (input_sel == 1) { write_grf_reg(GRF_SOC_CON23_OFFSET, DPHY_RX0_FORCERXMODE_MASK | (0x0 << DPHY_RX0_FORCERXMODE_BIT) | DPHY_RX0_FORCETXSTOPMODE_MASK | (0x0 << DPHY_RX0_FORCETXSTOPMODE_BIT)); write_grf_reg(GRF_SOC_CON24_OFFSET, DPHY_TX1RX1_MASTERSLAVEZ_MASK | (0x0 << DPHY_TX1RX1_MASTERSLAVEZ_BIT) | DPHY_TX1RX1_BASEDIR_MASK | (0x1 << DPHY_TX1RX1_BASEDIR_BIT) | DPHY_RX1_MASK | 0x0 << DPHY_RX1_SEL_BIT); /* set lane num */ write_grf_reg(GRF_SOC_CON23_OFFSET, DPHY_TX1RX1_ENABLE_MASK | (datalane_en << DPHY_TX1RX1_ENABLE_BIT)); /* set lan turndisab as 1 */ write_grf_reg(GRF_SOC_CON23_OFFSET, DPHY_TX1RX1_TURNDISABLE_MASK | (0xf << DPHY_TX1RX1_TURNDISABLE_BIT)); write_grf_reg(GRF_SOC_CON23_OFFSET, (0x0 << 4) | (0xf << 20)); /* set lan turnrequest as 0 */ write_grf_reg(GRF_SOC_CON24_OFFSET, DPHY_TX1RX1_TURNREQUEST_MASK | (0x0 << DPHY_TX1RX1_TURNREQUEST_BIT)); /* phy1 start */ /* * SHUTDOWNZ=0 * RSTZ=0 * TESTCLK=1 * TESTCLR=1 TESTCLK=1 * TESTCLR=0 TESTCLK=1 */ write_dsihost_reg(DSIHOST_PHY_SHUTDOWNZ, 0x00000000); write_dsihost_reg(DSIHOST_DPHY_RSTZ, 0x00000000); write_dsihost_reg(DSIHOST_PHY_TEST_CTRL0, 0x00000002); write_dsihost_reg(DSIHOST_PHY_TEST_CTRL1, 0x00000003); usleep_range(100, 150); write_dsihost_reg(DSIHOST_PHY_TEST_CTRL0, 0x00000002); usleep_range(100, 150); /* set clock lane */ mipi_dphy1_wr_reg(isp_cfg, 0x34, 0x00); mipi_dphy1_wr_reg(isp_cfg, 0x44, hsfreqrange); mipi_dphy1_wr_reg(isp_cfg, 0x54, 0); mipi_dphy1_wr_reg(isp_cfg, 0x84, 0); mipi_dphy1_wr_reg(isp_cfg, 0x94, 0); mipi_dphy1_wr_reg(isp_cfg, 0x75, 0x04); mipi_dphy1_rd_reg(isp_cfg, 0x0); /* * TESTCLK=1 * TESTEN =0 * SHUTDOWNZ=1 * RSTZ=1 */ write_dsihost_reg(DSIHOST_PHY_TEST_CTRL0, 0x00000002); write_dsihost_reg(DSIHOST_PHY_TEST_CTRL1, 0x00000000); /*SHUTDOWNZ=1, RSTZ=1*/ write_dsihost_reg(DSIHOST_DPHY_RSTZ, 0x00000003); write_cifisp_reg((MRV_MIPI_BASE + MRV_MIPI_CTRL), read_cifisp_reg(MRV_MIPI_BASE + MRV_MIPI_CTRL) | (0x0f << 8)); } else { goto fail; } return 0; fail: return -1; } static int soc_clk_enable(struct cif_isp10_rk3399 *isp_cfg) { struct cif_isp10_clk_rst_rk3399 *clk_rst = &isp_cfg->clk_rst; if (isp_cfg->isp_idx == CIF_ISP10_ISP0) { clk_prepare_enable(clk_rst->hclk_isp0_noc); clk_prepare_enable(clk_rst->hclk_isp0_wrapper); clk_prepare_enable(clk_rst->aclk_isp0_noc); clk_prepare_enable(clk_rst->aclk_isp0_wrapper); clk_prepare_enable(clk_rst->clk_isp0); clk_prepare_enable(clk_rst->pclk_dphyrx); clk_prepare_enable(clk_rst->cif_clk_out); clk_prepare_enable(clk_rst->pclk_dphy_ref); } else { clk_prepare_enable(clk_rst->hclk_isp1_noc); clk_prepare_enable(clk_rst->hclk_isp1_wrapper); clk_prepare_enable(clk_rst->aclk_isp1_noc); clk_prepare_enable(clk_rst->aclk_isp1_wrapper); clk_prepare_enable(clk_rst->clk_isp1); clk_prepare_enable(clk_rst->pclkin_isp1); clk_prepare_enable(clk_rst->pclk_dphytxrx); clk_prepare_enable(clk_rst->cif_clk_mipi_dsi); clk_prepare_enable(clk_rst->cif_clk_mipi_dphy_cfg); clk_prepare_enable(clk_rst->cif_clk_out); clk_prepare_enable(clk_rst->pclk_dphy_ref); } return 0; } static int soc_clk_disable(struct cif_isp10_rk3399 *isp_cfg) { struct cif_isp10_clk_rst_rk3399 *clk_rst = &isp_cfg->clk_rst; if (isp_cfg->isp_idx == CIF_ISP10_ISP0) { clk_disable_unprepare(clk_rst->hclk_isp0_noc); clk_disable_unprepare(clk_rst->hclk_isp0_wrapper); clk_disable_unprepare(clk_rst->aclk_isp0_noc); clk_disable_unprepare(clk_rst->aclk_isp0_wrapper); clk_disable_unprepare(clk_rst->clk_isp0); clk_disable_unprepare(clk_rst->pclk_dphyrx); if (!IS_ERR_OR_NULL(clk_rst->cif_clk_pll)) clk_set_parent(clk_rst->cif_clk_out, clk_rst->cif_clk_pll); clk_disable_unprepare(clk_rst->cif_clk_out); clk_disable_unprepare(clk_rst->pclk_dphy_ref); } else { clk_disable_unprepare(clk_rst->hclk_isp1_noc); clk_disable_unprepare(clk_rst->hclk_isp1_wrapper); clk_disable_unprepare(clk_rst->aclk_isp1_noc); clk_disable_unprepare(clk_rst->aclk_isp1_wrapper); clk_disable_unprepare(clk_rst->clk_isp1); clk_disable_unprepare(clk_rst->pclkin_isp1); clk_disable_unprepare(clk_rst->pclk_dphytxrx); clk_disable_unprepare(clk_rst->cif_clk_mipi_dsi); clk_disable_unprepare(clk_rst->cif_clk_mipi_dphy_cfg); if (!IS_ERR_OR_NULL(clk_rst->cif_clk_pll)) clk_set_parent(clk_rst->cif_clk_out, clk_rst->cif_clk_pll); clk_disable_unprepare(clk_rst->cif_clk_out); clk_disable_unprepare(clk_rst->pclk_dphy_ref); } return 0; } static int soc_init(struct cif_isp10_rk3399 **isp_cfg, struct pltfrm_soc_init_para *init) { struct cif_isp10_clk_rst_rk3399 *clk_rst; struct platform_device *pdev = init->pdev; struct device_node *np = pdev->dev.of_node, *node; struct resource *res; struct cif_isp10_rk3399 *isp_cfg_tmp; int err; *isp_cfg = NULL; isp_cfg_tmp = (struct cif_isp10_rk3399 *)devm_kzalloc( &pdev->dev, sizeof(struct cif_isp10_rk3399), GFP_KERNEL); if (!isp_cfg_tmp) { dev_err(&pdev->dev, "Can't allocate cif_isp10_rk3399\n"); err = -ENOMEM; goto alloc_failed; } node = of_parse_phandle(np, "rockchip,grf", 0); if (node) { isp_cfg_tmp->regmap_grf = syscon_node_to_regmap(node); if (IS_ERR(isp_cfg_tmp->regmap_grf)) { dev_err(&pdev->dev, "Can't allocate cif_isp10_rk3399\n"); err = -ENODEV; goto regmap_failed; } } clk_rst = &isp_cfg_tmp->clk_rst; if (strcmp(pdev->name, "ff910000.cif_isp") == 0) { clk_rst->hclk_isp0_noc = devm_clk_get(&pdev->dev, "hclk_isp0_noc"); clk_rst->hclk_isp0_wrapper = devm_clk_get(&pdev->dev, "hclk_isp0_wrapper"); clk_rst->aclk_isp0_noc = devm_clk_get(&pdev->dev, "aclk_isp0_noc"); clk_rst->aclk_isp0_wrapper = devm_clk_get(&pdev->dev, "aclk_isp0_wrapper"); clk_rst->clk_isp0 = devm_clk_get(&pdev->dev, "clk_isp0"); clk_rst->pclk_dphyrx = devm_clk_get(&pdev->dev, "pclk_dphyrx"); clk_rst->cif_clk_out = devm_clk_get(&pdev->dev, "clk_cif_out"); clk_rst->cif_clk_pll = devm_clk_get(&pdev->dev, "clk_cif_pll"); clk_rst->pclk_dphy_ref = devm_clk_get(&pdev->dev, "pclk_dphy_ref"); if (IS_ERR_OR_NULL(clk_rst->hclk_isp0_noc) || IS_ERR_OR_NULL(clk_rst->hclk_isp0_wrapper) || IS_ERR_OR_NULL(clk_rst->aclk_isp0_noc) || IS_ERR_OR_NULL(clk_rst->aclk_isp0_wrapper) || IS_ERR_OR_NULL(clk_rst->clk_isp0) || IS_ERR_OR_NULL(clk_rst->pclk_dphyrx) || IS_ERR_OR_NULL(clk_rst->cif_clk_out) || IS_ERR_OR_NULL(clk_rst->pclk_dphy_ref)) { dev_err(&pdev->dev, "Get rk3399 cif isp10 clock resouce failed !\n"); err = -EINVAL; goto clk_failed; } clk_set_rate(clk_rst->clk_isp0, 420000000); isp_cfg_tmp->isp_idx = CIF_ISP10_ISP0; } else { res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dsihost-register"); if (!res) { dev_err(&pdev->dev, "platform_get_resource_byname dsihost-register failed\n"); err = -ENODEV; goto regmap_failed; } isp_cfg_tmp->dsihost_base = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR_OR_NULL(isp_cfg_tmp->dsihost_base)) { dev_err(&pdev->dev, "devm_ioremap_resource failed\n"); if (IS_ERR(isp_cfg_tmp->dsihost_base)) err = PTR_ERR(isp_cfg_tmp->dsihost_base); else err = -ENODEV; goto regmap_failed; } clk_rst->hclk_isp1_noc = devm_clk_get(&pdev->dev, "hclk_isp1_noc"); clk_rst->hclk_isp1_wrapper = devm_clk_get(&pdev->dev, "hclk_isp1_wrapper"); clk_rst->aclk_isp1_noc = devm_clk_get(&pdev->dev, "aclk_isp1_noc"); clk_rst->aclk_isp1_wrapper = devm_clk_get(&pdev->dev, "aclk_isp1_wrapper"); clk_rst->clk_isp1 = devm_clk_get(&pdev->dev, "clk_isp1"); clk_rst->pclkin_isp1 = devm_clk_get(&pdev->dev, "pclkin_isp1"); clk_rst->pclk_dphytxrx = devm_clk_get(&pdev->dev, "pclk_dphytxrx"); clk_rst->cif_clk_mipi_dsi = devm_clk_get(&pdev->dev, "pclk_mipi_dsi"); clk_rst->cif_clk_mipi_dphy_cfg = devm_clk_get(&pdev->dev, "mipi_dphy_cfg"); clk_rst->cif_clk_out = devm_clk_get(&pdev->dev, "clk_cif_out"); clk_rst->cif_clk_pll = devm_clk_get(&pdev->dev, "clk_cif_pll"); clk_rst->pclk_dphy_ref = devm_clk_get(&pdev->dev, "pclk_dphy_ref"); if (IS_ERR_OR_NULL(clk_rst->hclk_isp1_noc) || IS_ERR_OR_NULL(clk_rst->hclk_isp1_wrapper) || IS_ERR_OR_NULL(clk_rst->aclk_isp1_noc) || IS_ERR_OR_NULL(clk_rst->aclk_isp1_wrapper) || IS_ERR_OR_NULL(clk_rst->clk_isp1) || IS_ERR_OR_NULL(clk_rst->pclkin_isp1) || IS_ERR_OR_NULL(clk_rst->pclk_dphytxrx) || IS_ERR_OR_NULL(clk_rst->cif_clk_mipi_dsi) || IS_ERR_OR_NULL(clk_rst->cif_clk_mipi_dphy_cfg) || IS_ERR_OR_NULL(clk_rst->cif_clk_out) || IS_ERR_OR_NULL(clk_rst->pclk_dphy_ref)) { dev_err(&pdev->dev, "Get rk3399 cif isp10 clock resouce failed !\n"); err = -EINVAL; goto clk_failed; } clk_set_rate(clk_rst->clk_isp1, 420000000); isp_cfg_tmp->isp_idx = CIF_ISP10_ISP1; } isp_cfg_tmp->isp_base = init->isp_base; *isp_cfg = isp_cfg_tmp; return 0; clk_failed: if (!IS_ERR_OR_NULL(clk_rst->hclk_isp0_noc)) devm_clk_put(&pdev->dev, clk_rst->hclk_isp0_noc); if (!IS_ERR_OR_NULL(clk_rst->hclk_isp0_wrapper)) devm_clk_put(&pdev->dev, clk_rst->hclk_isp0_wrapper); if (!IS_ERR_OR_NULL(clk_rst->aclk_isp0_noc)) devm_clk_put(&pdev->dev, clk_rst->aclk_isp0_noc); if (!IS_ERR_OR_NULL(clk_rst->aclk_isp0_wrapper)) devm_clk_put(&pdev->dev, clk_rst->aclk_isp0_wrapper); if (!IS_ERR_OR_NULL(clk_rst->clk_isp0)) devm_clk_put(&pdev->dev, clk_rst->clk_isp0); if (!IS_ERR_OR_NULL(clk_rst->pclk_dphyrx)) devm_clk_put(&pdev->dev, clk_rst->pclk_dphyrx); if (!IS_ERR_OR_NULL(clk_rst->hclk_isp1_noc)) devm_clk_put(&pdev->dev, clk_rst->hclk_isp1_noc); if (!IS_ERR_OR_NULL(clk_rst->hclk_isp1_wrapper)) devm_clk_put(&pdev->dev, clk_rst->hclk_isp1_wrapper); if (!IS_ERR_OR_NULL(clk_rst->aclk_isp1_noc)) devm_clk_put(&pdev->dev, clk_rst->aclk_isp1_noc); if (!IS_ERR_OR_NULL(clk_rst->aclk_isp1_wrapper)) devm_clk_put(&pdev->dev, clk_rst->aclk_isp1_wrapper); if (!IS_ERR_OR_NULL(clk_rst->clk_isp1)) devm_clk_put(&pdev->dev, clk_rst->clk_isp1); if (!IS_ERR_OR_NULL(clk_rst->pclkin_isp1)) devm_clk_put(&pdev->dev, clk_rst->pclkin_isp1); if (!IS_ERR_OR_NULL(clk_rst->pclk_dphytxrx)) devm_clk_put(&pdev->dev, clk_rst->pclk_dphytxrx); if (!IS_ERR_OR_NULL(clk_rst->cif_clk_mipi_dsi)) devm_clk_put(&pdev->dev, clk_rst->cif_clk_mipi_dsi); if (!IS_ERR_OR_NULL(clk_rst->cif_clk_mipi_dphy_cfg)) devm_clk_put(&pdev->dev, clk_rst->cif_clk_mipi_dphy_cfg); if (!IS_ERR_OR_NULL(clk_rst->cif_clk_out)) devm_clk_put(&pdev->dev, clk_rst->cif_clk_out); if (!IS_ERR_OR_NULL(clk_rst->pclk_dphy_ref)) devm_clk_put(&pdev->dev, clk_rst->pclk_dphy_ref); regmap_failed: alloc_failed: return err; } int pltfrm_rk3399_cfg(struct pltfrm_soc_cfg_para *cfg) { int ret = -1; struct cif_isp10_rk3399 *isp_cfg = NULL; if (cfg->isp_config == NULL) { return -1; } else { isp_cfg = (struct cif_isp10_rk3399 *)(*cfg->isp_config); if (isp_cfg == NULL && cfg->cmd != PLTFRM_SOC_INIT) return -1; } switch (cfg->cmd) { case PLTFRM_MCLK_CFG: { struct pltfrm_soc_mclk_para *mclk_para; mclk_para = (struct pltfrm_soc_mclk_para *)cfg->cfg_para; if (mclk_para->io_voltage == PLTFRM_IO_1V8) write_grf_reg(GRF_IO_VSEL_OFFSET, DVP_V18SEL); else write_grf_reg(GRF_IO_VSEL_OFFSET, DVP_V33SEL); write_grf_reg(GRF_GPIO2B_E_OFFSET, CIF_CLKOUT_STRENGTH(mclk_para->drv_strength)); ret = 0; break; } case PLTFRM_MIPI_DPHY_CFG: ret = mipi_dphy_cfg(isp_cfg, (struct pltfrm_cam_mipi_config *)cfg->cfg_para); break; case PLTFRM_CLKEN: ret = soc_clk_enable(isp_cfg); break; case PLTFRM_CLKDIS: ret = soc_clk_disable(isp_cfg); break; case PLTFRM_CLKRST: write_cifisp_reg(VI_IRCL, 0xf7f); usleep_range(10, 15); write_cifisp_reg(VI_IRCL, 0x00); ret = 0; break; case PLTFRM_SOC_INIT: ret = soc_init((struct cif_isp10_rk3399 **)cfg->isp_config, (struct pltfrm_soc_init_para *)cfg->cfg_para); break; default: break; } return ret; }