/*
|
*************************************************************************
|
* 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 <linux/init.h>
|
#include <linux/delay.h>
|
#include <linux/regmap.h>
|
#include <linux/mfd/syscon.h>
|
#include <linux/clk.h>
|
#include <linux/reset.h>
|
#include <linux/io.h>
|
#include <linux/of.h>
|
#include <linux/kernel.h>
|
#include <linux/platform_device.h>
|
#include <linux/platform_data/rk_isp10_platform.h>
|
|
#define ONE_LANE_ENABLE_BIT 0x1
|
#define TWO_LANE_ENABLE_BIT 0x2
|
#define FOUR_LANE_ENABLE_BIT 0x4
|
|
#define MRV_MIPI_BASE 0x1C00
|
#define MRV_MIPI_CTRL 0x00
|
|
/*
|
* GRF_SOC_CON14
|
* bit 0 dphy_rx0_testclr
|
* bit 1 dphy_rx0_testclk
|
* bit 2 dphy_rx0_testen
|
* bit 3:10 dphy_rx0_testdin
|
*/
|
#define GRF_SOC_CON14_OFFSET (0x027c)
|
#define DPHY_RX0_TESTCLR_MASK (0x1 << 16)
|
#define DPHY_RX0_TESTCLK_MASK (0x1 << 17)
|
#define DPHY_RX0_TESTEN_MASK (0x1 << 18)
|
#define DPHY_RX0_TESTDIN_MASK (0xff << 19)
|
|
#define DPHY_RX0_TESTCLR BIT(0)
|
#define DPHY_RX0_TESTCLK BIT(1)
|
#define DPHY_RX0_TESTEN BIT(2)
|
#define DPHY_RX0_TESTDIN_OFFSET (3)
|
|
#define DPHY_TX1RX1_ENABLECLK_MASK (0x1 << 28)
|
#define DPHY_RX1_SRC_SEL_MASK (0x1 << 29)
|
#define DPHY_TX1RX1_MASTERSLAVEZ_MASK (0x1 << 30)
|
#define DPHY_TX1RX1_BASEDIR_OFFSET (0x1 << 31)
|
|
#define DPHY_TX1RX1_ENABLECLK (0x1 << 12)
|
#define DPHY_TX1RX1_DISABLECLK (0x0 << 12)
|
#define DPHY_RX1_SRC_SEL_ISP (0x1 << 13)
|
#define DPHY_TX1RX1_SLAVEZ (0x0 << 14)
|
#define DPHY_TX1RX1_BASEDIR_REC (0x1 << 15)
|
|
/*
|
* GRF_SOC_CON6
|
* bit 0 grf_con_disable_isp
|
* bit 1 grf_con_isp_dphy_sel 1'b0 mipi phy rx0
|
*/
|
#define GRF_SOC_CON6_OFFSET (0x025c)
|
#define MIPI_PHY_DISABLE_ISP_MASK (0x1 << 16)
|
#define MIPI_PHY_DISABLE_ISP (0x0 << 0)
|
|
#define DSI_CSI_TESTBUS_SEL_MASK (0x1 << 30)
|
#define DSI_CSI_TESTBUS_SEL_OFFSET_BIT (14)
|
|
#define MIPI_PHY_DPHYSEL_OFFSET_MASK (0x1 << 17)
|
#define MIPI_PHY_DPHYSEL_OFFSET_BIT (0x1)
|
|
/*
|
* GRF_SOC_CON10
|
* bit12:15 grf_dphy_rx0_enable
|
* bit 0:3 turn disable
|
*/
|
#define GRF_SOC_CON10_OFFSET (0x026c)
|
#define DPHY_RX0_TURN_DISABLE_MASK (0xf << 16)
|
#define DPHY_RX0_TURN_DISABLE_OFFSET_BITS (0x0)
|
#define DPHY_RX0_ENABLE_MASK (0xf << 28)
|
#define DPHY_RX0_ENABLE_OFFSET_BITS (12)
|
|
/*
|
* GRF_SOC_CON9
|
* bit12:15 grf_dphy_rx0_enable
|
* bit 0:3 turn disable
|
*/
|
#define GRF_SOC_CON9_OFFSET (0x0268)
|
#define DPHY_TX1RX1_TURN_DISABLE_MASK (0xf << 16)
|
#define DPHY_TX1RX1_TURN_DISABLE_OFFSET_BITS (0x0)
|
#define DPHY_TX1RX1_ENABLE_MASK (0xf << 28)
|
#define DPHY_TX1RX1_ENABLE_OFFSET_BITS (12)
|
|
/*
|
* GRF_SOC_CON15
|
* bit 0:3 turn request
|
*/
|
#define GRF_SOC_CON15_OFFSET (0x03a4)
|
#define DPHY_RX0_TURN_REQUEST_MASK (0xf << 16)
|
#define DPHY_RX0_TURN_REQUEST_OFFSET_BITS (0x0)
|
|
#define DPHY_TX1RX1_TURN_REQUEST_MASK (0xf << 20)
|
#define DPHY_TX1RX1_TURN_REQUEST_OFFSET_BITS (0x0)
|
|
/*
|
* GRF_SOC_STATUS21
|
* bit0:7 dphy_rx0_testdout
|
*/
|
#define GRF_SOC_STATUS21_OFFSET (0x2D4)
|
#define DPHY_RX0_TESTDOUT(a) ((a) & 0xff)
|
|
/*
|
* GRF_IO_VSEL
|
*/
|
#define GRF_IO_VSEL_OFFSET (0x0380)
|
#define DVP_V18SEL ((1 << 1) | (1 << 17))
|
#define DVP_V33SEL ((0 << 1) | (1 << 17))
|
|
/*
|
* GRF_IO_VSEL
|
*/
|
#define GRF_GPIO2B_E_OFFSET (0x0380)
|
#define CIF_CLKOUT_STRENGTH(a) ((((a) & 0x03) << 3) | (0x03 << 19))
|
|
/*
|
* CSI HOST
|
*/
|
|
#define CSIHOST_PHY_TEST_CTRL0 (0x30)
|
#define CSIHOST_PHY_TEST_CTRL1 (0x34)
|
#define CSIHOST_PHY_SHUTDOWNZ (0x08)
|
#define CSIHOST_DPHY_RSTZ (0x0c)
|
#define CSIHOST_N_LANES (0x04)
|
#define CSIHOST_CSI2_RESETN (0x10)
|
#define CSIHOST_PHY_STATE (0x14)
|
#define CSIHOST_DATA_IDS1 (0x18)
|
#define CSIHOST_DATA_IDS2 (0x1C)
|
#define CSIHOST_ERR1 (0x20)
|
#define CSIHOST_ERR2 (0x24)
|
|
#define write_cifisp_reg(addr, val) \
|
__raw_writel(val, (addr) + rk3288->isp_base)
|
#define read_cifisp_reg(addr) \
|
__raw_readl((addr) + rk3288->isp_base)
|
|
#define write_grf_reg(addr, val) \
|
regmap_write(rk3288->regmap_grf, addr, val)
|
#define read_grf_reg(addr, val) regmap_read(rk3288->regmap_grf, addr, val)
|
|
#define write_csihost_reg(addr, val) \
|
__raw_writel(val, (addr) + rk3288->csihost_base)
|
#define read_csihost_reg(addr) __raw_readl((addr) + rk3288->csihost_base)
|
|
struct cif_isp10_clk_rst_rk3288 {
|
struct clk *aclk_isp;
|
struct clk *hclk_isp;
|
struct clk *sclk_isp;
|
struct clk *sclk_isp_jpe;
|
struct clk *sclk_mipidsi_24m;
|
struct clk *pclk_mipi_csi;
|
struct clk *pclk_isp_in;
|
struct reset_control *isp_rst;
|
};
|
|
struct cif_isp10_rk3288 {
|
struct regmap *regmap_grf;
|
void __iomem *csihost_base;
|
void __iomem *isp_base;
|
struct cif_isp10_clk_rst_rk3288 clk_rst;
|
struct cif_isp10_device *cif_isp10;
|
};
|
|
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}
|
};
|
|
static struct cif_isp10_rk3288 *rk3288;
|
static int mipi_dphy0_wr_reg(unsigned char addr, unsigned char data)
|
{
|
/*
|
* TESTCLK=1
|
* TESTEN =1,TESTDIN=addr
|
* TESTCLK=0
|
*/
|
write_grf_reg(GRF_SOC_CON14_OFFSET,
|
DPHY_RX0_TESTCLK_MASK | DPHY_RX0_TESTCLK);
|
write_grf_reg(GRF_SOC_CON14_OFFSET,
|
((addr << DPHY_RX0_TESTDIN_OFFSET) | DPHY_RX0_TESTDIN_MASK
|
| DPHY_RX0_TESTEN | DPHY_RX0_TESTEN_MASK));
|
write_grf_reg(GRF_SOC_CON14_OFFSET, DPHY_RX0_TESTCLK_MASK);
|
|
/*
|
* write data:
|
* TESTEN =0,TESTDIN=data
|
* TESTCLK=1
|
*/
|
if (data != 0xff) {
|
write_grf_reg(GRF_SOC_CON14_OFFSET,
|
((data << DPHY_RX0_TESTDIN_OFFSET) |
|
DPHY_RX0_TESTDIN_MASK | DPHY_RX0_TESTEN_MASK));
|
write_grf_reg(GRF_SOC_CON14_OFFSET,
|
DPHY_RX0_TESTCLK_MASK | DPHY_RX0_TESTCLK);
|
}
|
return 0;
|
}
|
|
static int mipi_dphy1_wr_reg(unsigned char addr, unsigned char data)
|
{
|
/*
|
* TESTEN =1,TESTDIN=addr
|
* TESTCLK=0
|
* TESTEN =0,TESTDIN=data
|
* TESTCLK=1
|
*/
|
write_csihost_reg(CSIHOST_PHY_TEST_CTRL1, (0x00010000 | addr));
|
write_csihost_reg(CSIHOST_PHY_TEST_CTRL0, 0x00000000);
|
write_csihost_reg(CSIHOST_PHY_TEST_CTRL1, (0x00000000 | data));
|
write_csihost_reg(CSIHOST_PHY_TEST_CTRL0, 0x00000002);
|
|
return 0;
|
}
|
|
static int mipi_dphy1_rd_reg(unsigned char addr)
|
{
|
return (read_csihost_reg(((CSIHOST_PHY_TEST_CTRL1) & 0xff00)) >> 8);
|
}
|
|
static int mipi_dphy_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) {
|
write_grf_reg(GRF_SOC_CON6_OFFSET,
|
MIPI_PHY_DPHYSEL_OFFSET_MASK |
|
(input_sel << MIPI_PHY_DPHYSEL_OFFSET_BIT));
|
/* set lane num */
|
write_grf_reg(GRF_SOC_CON10_OFFSET,
|
DPHY_RX0_ENABLE_MASK |
|
(datalane_en << DPHY_RX0_ENABLE_OFFSET_BITS));
|
/* set lan turndisab as 1 */
|
write_grf_reg(GRF_SOC_CON10_OFFSET,
|
DPHY_RX0_TURN_DISABLE_MASK |
|
(0xf << DPHY_RX0_TURN_DISABLE_OFFSET_BITS));
|
write_grf_reg(GRF_SOC_CON10_OFFSET,
|
(0x0 << 4) | (0xf << 20));
|
/* set lan turnrequest as 0 */
|
write_grf_reg(GRF_SOC_CON15_OFFSET,
|
DPHY_RX0_TURN_REQUEST_MASK |
|
(0x0 << DPHY_RX0_TURN_REQUEST_OFFSET_BITS));
|
|
/* phy start */
|
/*
|
* TESTCLK=1
|
* TESTCLR=1
|
* delay 100us
|
* TESTCLR=0
|
*/
|
write_grf_reg(GRF_SOC_CON14_OFFSET,
|
DPHY_RX0_TESTCLK_MASK | DPHY_RX0_TESTCLK);
|
write_grf_reg(GRF_SOC_CON14_OFFSET,
|
DPHY_RX0_TESTCLR_MASK | DPHY_RX0_TESTCLR);
|
usleep_range(100, 150);
|
write_grf_reg(GRF_SOC_CON14_OFFSET, DPHY_RX0_TESTCLR_MASK);
|
usleep_range(100, 150);
|
|
/* set clock lane */
|
mipi_dphy0_wr_reg(0x34, 0x15);
|
if (datalane_en == ONE_LANE_ENABLE_BIT) {
|
mipi_dphy0_wr_reg(0x44, hsfreqrange);
|
} else if (datalane_en == TWO_LANE_ENABLE_BIT) {
|
mipi_dphy0_wr_reg(0x44, hsfreqrange);
|
mipi_dphy0_wr_reg(0x54, hsfreqrange);
|
} else if (datalane_en == FOUR_LANE_ENABLE_BIT) {
|
mipi_dphy0_wr_reg(0x44, hsfreqrange);
|
mipi_dphy0_wr_reg(0x54, hsfreqrange);
|
mipi_dphy0_wr_reg(0x84, hsfreqrange);
|
mipi_dphy0_wr_reg(0x94, hsfreqrange);
|
}
|
|
/* Normal operation */
|
/*
|
* TESTCLK=1
|
* TESTEN =0
|
*/
|
mipi_dphy0_wr_reg(0x0, -1);
|
write_grf_reg(GRF_SOC_CON14_OFFSET,
|
DPHY_RX0_TESTCLK_MASK | DPHY_RX0_TESTCLK);
|
write_grf_reg(GRF_SOC_CON14_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_CON6_OFFSET,
|
MIPI_PHY_DPHYSEL_OFFSET_MASK |
|
(input_sel << MIPI_PHY_DPHYSEL_OFFSET_BIT));
|
write_grf_reg(GRF_SOC_CON6_OFFSET,
|
DSI_CSI_TESTBUS_SEL_MASK |
|
(1 << DSI_CSI_TESTBUS_SEL_OFFSET_BIT));
|
|
write_grf_reg(GRF_SOC_CON14_OFFSET,
|
DPHY_RX1_SRC_SEL_ISP | DPHY_RX1_SRC_SEL_MASK);
|
write_grf_reg(GRF_SOC_CON14_OFFSET,
|
DPHY_TX1RX1_SLAVEZ | DPHY_TX1RX1_MASTERSLAVEZ_MASK);
|
write_grf_reg(GRF_SOC_CON14_OFFSET,
|
DPHY_TX1RX1_BASEDIR_REC | DPHY_TX1RX1_BASEDIR_OFFSET);
|
|
/* set lane num */
|
write_grf_reg(GRF_SOC_CON9_OFFSET,
|
DPHY_TX1RX1_ENABLE_MASK |
|
(datalane_en << DPHY_TX1RX1_ENABLE_OFFSET_BITS));
|
/* set lan turndisab as 1 */
|
write_grf_reg(GRF_SOC_CON9_OFFSET,
|
DPHY_TX1RX1_TURN_DISABLE_MASK |
|
(0xf << DPHY_TX1RX1_TURN_DISABLE_OFFSET_BITS));
|
/* set lan turnrequest as 0 */
|
write_grf_reg(GRF_SOC_CON15_OFFSET,
|
DPHY_TX1RX1_TURN_REQUEST_MASK |
|
(0x0 << DPHY_TX1RX1_TURN_REQUEST_OFFSET_BITS));
|
|
/* phy1 start */
|
/*
|
* SHUTDOWNZ=0
|
* RSTZ=0
|
* TESTCLK=1
|
* TESTCLR=1 TESTCLK=1
|
* TESTCLR=0 TESTCLK=1
|
*/
|
write_csihost_reg(CSIHOST_PHY_SHUTDOWNZ, 0x00000000);
|
write_csihost_reg(CSIHOST_DPHY_RSTZ, 0x00000000);
|
write_csihost_reg(CSIHOST_PHY_TEST_CTRL0, 0x00000002);
|
write_csihost_reg(CSIHOST_PHY_TEST_CTRL0, 0x00000003);
|
usleep_range(100, 150);
|
write_csihost_reg(CSIHOST_PHY_TEST_CTRL0, 0x00000002);
|
usleep_range(100, 150);
|
|
/* set clock lane */
|
mipi_dphy1_wr_reg(0x34, 0x15);
|
|
if (datalane_en == ONE_LANE_ENABLE_BIT) {
|
mipi_dphy1_wr_reg(0x44, hsfreqrange);
|
} else if (datalane_en == TWO_LANE_ENABLE_BIT) {
|
mipi_dphy1_wr_reg(0x44, hsfreqrange);
|
mipi_dphy1_wr_reg(0x54, hsfreqrange);
|
} else if (datalane_en == FOUR_LANE_ENABLE_BIT) {
|
mipi_dphy1_wr_reg(0x44, hsfreqrange);
|
mipi_dphy1_wr_reg(0x54, hsfreqrange);
|
mipi_dphy1_wr_reg(0x84, hsfreqrange);
|
mipi_dphy1_wr_reg(0x94, hsfreqrange);
|
}
|
|
mipi_dphy1_rd_reg(0x0);
|
/*
|
* TESTCLK=1
|
* TESTEN =0
|
* SHUTDOWNZ=1
|
* RSTZ=1
|
*/
|
write_csihost_reg(CSIHOST_PHY_TEST_CTRL0, 0x00000002);
|
write_csihost_reg(CSIHOST_PHY_TEST_CTRL1, 0x00000000);
|
write_csihost_reg(CSIHOST_PHY_SHUTDOWNZ, 0x00000001);
|
write_csihost_reg(CSIHOST_DPHY_RSTZ, 0x00000001);
|
} else {
|
goto fail;
|
}
|
|
return 0;
|
fail:
|
return -1;
|
}
|
|
static int soc_clk_enable(void)
|
{
|
struct cif_isp10_clk_rst_rk3288 *clk_rst = &rk3288->clk_rst;
|
|
clk_prepare_enable(clk_rst->hclk_isp);
|
clk_prepare_enable(clk_rst->aclk_isp);
|
clk_prepare_enable(clk_rst->sclk_isp);
|
clk_prepare_enable(clk_rst->sclk_isp_jpe);
|
clk_prepare_enable(clk_rst->sclk_mipidsi_24m);
|
clk_prepare_enable(clk_rst->pclk_isp_in);
|
clk_prepare_enable(clk_rst->pclk_mipi_csi);
|
return 0;
|
}
|
|
static int soc_clk_disable(void)
|
{
|
struct cif_isp10_clk_rst_rk3288 *clk_rst = &rk3288->clk_rst;
|
|
clk_disable_unprepare(clk_rst->hclk_isp);
|
clk_disable_unprepare(clk_rst->aclk_isp);
|
clk_disable_unprepare(clk_rst->sclk_isp);
|
clk_disable_unprepare(clk_rst->sclk_isp_jpe);
|
clk_disable_unprepare(clk_rst->sclk_mipidsi_24m);
|
clk_disable_unprepare(clk_rst->pclk_isp_in);
|
clk_disable_unprepare(clk_rst->pclk_mipi_csi);
|
return 0;
|
}
|
|
static int soc_init(struct pltfrm_soc_init_para *init)
|
{
|
struct cif_isp10_clk_rst_rk3288 *clk_rst;
|
struct platform_device *pdev = init->pdev;
|
struct device_node *np = pdev->dev.of_node, *node;
|
struct resource *res;
|
int err;
|
|
rk3288 = (struct cif_isp10_rk3288 *)devm_kzalloc(
|
&pdev->dev,
|
sizeof(struct cif_isp10_rk3288),
|
GFP_KERNEL);
|
if (!rk3288) {
|
dev_err(&pdev->dev, "Can't allocate cif_isp10_rk3288\n");
|
err = -ENOMEM;
|
goto alloc_failed;
|
}
|
|
node = of_parse_phandle(np, "rockchip,grf", 0);
|
if (node) {
|
rk3288->regmap_grf = syscon_node_to_regmap(node);
|
if (IS_ERR(rk3288->regmap_grf)) {
|
dev_err(&pdev->dev, "Can't allocate cif_isp10_rk3288\n");
|
err = -ENODEV;
|
goto regmap_failed;
|
}
|
}
|
|
res = platform_get_resource_byname(pdev,
|
IORESOURCE_MEM, "csihost-register");
|
if (!res) {
|
dev_err(&pdev->dev,
|
"platform_get_resource_byname csihost-register failed\n");
|
err = -ENODEV;
|
goto regmap_failed;
|
}
|
rk3288->csihost_base = devm_ioremap_resource(&pdev->dev, res);
|
if (IS_ERR_OR_NULL(rk3288->csihost_base)) {
|
dev_err(&pdev->dev, "devm_ioremap_resource failed\n");
|
if (IS_ERR(rk3288->csihost_base))
|
err = PTR_ERR(rk3288->csihost_base);
|
else
|
err = -ENODEV;
|
goto regmap_failed;
|
}
|
|
clk_rst = &rk3288->clk_rst;
|
clk_rst->aclk_isp = devm_clk_get(&pdev->dev, "aclk_isp");
|
clk_rst->hclk_isp = devm_clk_get(&pdev->dev, "hclk_isp");
|
clk_rst->sclk_isp = devm_clk_get(&pdev->dev, "sclk_isp");
|
clk_rst->sclk_isp_jpe = devm_clk_get(&pdev->dev, "sclk_isp_jpe");
|
clk_rst->sclk_mipidsi_24m =
|
devm_clk_get(&pdev->dev, "sclk_mipidsi_24m");
|
clk_rst->pclk_mipi_csi = devm_clk_get(&pdev->dev, "pclk_mipi_csi");
|
clk_rst->isp_rst = devm_reset_control_get(&pdev->dev, "rst_isp");
|
clk_rst->pclk_isp_in = devm_clk_get(&pdev->dev, "pclk_isp_in");
|
|
if (IS_ERR_OR_NULL(clk_rst->aclk_isp) ||
|
IS_ERR_OR_NULL(clk_rst->hclk_isp) ||
|
IS_ERR_OR_NULL(clk_rst->sclk_isp) ||
|
IS_ERR_OR_NULL(clk_rst->sclk_isp_jpe) ||
|
IS_ERR_OR_NULL(clk_rst->pclk_mipi_csi) ||
|
IS_ERR_OR_NULL(clk_rst->isp_rst) ||
|
IS_ERR_OR_NULL(clk_rst->pclk_isp_in) ||
|
IS_ERR_OR_NULL(clk_rst->sclk_mipidsi_24m)) {
|
dev_err(&pdev->dev, "Get rk3288 cif isp10 clock resouce failed !\n");
|
err = -EINVAL;
|
goto clk_failed;
|
}
|
|
clk_set_rate(clk_rst->sclk_isp, 400000000);
|
clk_set_rate(clk_rst->sclk_isp_jpe, 400000000);
|
reset_control_deassert(clk_rst->isp_rst);
|
|
rk3288->isp_base = init->isp_base;
|
return 0;
|
|
clk_failed:
|
if (!IS_ERR_OR_NULL(clk_rst->aclk_isp))
|
devm_clk_put(&pdev->dev, clk_rst->aclk_isp);
|
if (!IS_ERR_OR_NULL(clk_rst->hclk_isp))
|
devm_clk_put(&pdev->dev, clk_rst->hclk_isp);
|
if (!IS_ERR_OR_NULL(clk_rst->sclk_isp))
|
devm_clk_put(&pdev->dev, clk_rst->sclk_isp);
|
if (!IS_ERR_OR_NULL(clk_rst->sclk_isp_jpe))
|
devm_clk_put(&pdev->dev, clk_rst->sclk_isp_jpe);
|
if (!IS_ERR_OR_NULL(clk_rst->pclk_mipi_csi))
|
devm_clk_put(&pdev->dev, clk_rst->pclk_mipi_csi);
|
if (!IS_ERR_OR_NULL(clk_rst->pclk_isp_in))
|
devm_clk_put(&pdev->dev, clk_rst->pclk_isp_in);
|
if (!IS_ERR_OR_NULL(clk_rst->sclk_mipidsi_24m))
|
devm_clk_put(&pdev->dev, clk_rst->sclk_mipidsi_24m);
|
|
if (!IS_ERR_OR_NULL(clk_rst->isp_rst))
|
reset_control_put(clk_rst->isp_rst);
|
|
regmap_failed:
|
|
alloc_failed:
|
|
return err;
|
}
|
|
int pltfrm_rk3288_cfg(struct pltfrm_soc_cfg_para *cfg)
|
{
|
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));
|
break;
|
}
|
case PLTFRM_MIPI_DPHY_CFG:
|
mipi_dphy_cfg((struct pltfrm_cam_mipi_config *)cfg->cfg_para);
|
break;
|
|
case PLTFRM_CLKEN:
|
soc_clk_enable();
|
break;
|
|
case PLTFRM_CLKDIS:
|
soc_clk_disable();
|
break;
|
|
case PLTFRM_CLKRST:
|
reset_control_assert(rk3288->clk_rst.isp_rst);
|
usleep_range(10, 15);
|
reset_control_deassert(rk3288->clk_rst.isp_rst);
|
break;
|
|
case PLTFRM_SOC_INIT:
|
soc_init((struct pltfrm_soc_init_para *)cfg->cfg_para);
|
break;
|
|
default:
|
break;
|
}
|
|
return 0;
|
}
|