diff --git a/arch/arm/boot/dts/rv1126.dtsi b/arch/arm/boot/dts/rv1126.dtsi index 141631c1e57c..9aa0637341c3 100644 --- a/arch/arm/boot/dts/rv1126.dtsi +++ b/arch/arm/boot/dts/rv1126.dtsi @@ -957,6 +957,7 @@ pwm0: pwm@ff430000 { compatible = "rockchip,rv1126-pwm", "rockchip,rk3328-pwm"; reg = <0xff430000 0x10>; + interrupts = ; #pwm-cells = <3>; pinctrl-names = "active"; pinctrl-0 = <&pwm0m0_pins>; @@ -968,6 +969,7 @@ pwm1: pwm@ff430010 { compatible = "rockchip,rv1126-pwm", "rockchip,rk3328-pwm"; reg = <0xff430010 0x10>; + interrupts = ; #pwm-cells = <3>; pinctrl-names = "active"; pinctrl-0 = <&pwm1m0_pins>; @@ -979,6 +981,7 @@ pwm2: pwm@ff430020 { compatible = "rockchip,rv1126-pwm", "rockchip,rk3328-pwm"; reg = <0xff430020 0x10>; + interrupts = ; #pwm-cells = <3>; pinctrl-names = "active"; pinctrl-0 = <&pwm2m0_pins>; @@ -990,6 +993,8 @@ pwm3: pwm@ff430030 { compatible = "rockchip,rv1126-pwm", "rockchip,rk3328-pwm"; reg = <0xff430030 0x10>; + interrupts = , + ; #pwm-cells = <3>; pinctrl-names = "active"; pinctrl-0 = <&pwm3m0_pins>; @@ -1001,6 +1006,7 @@ pwm4: pwm@ff440000 { compatible = "rockchip,rv1126-pwm", "rockchip,rk3328-pwm"; reg = <0xff440000 0x10>; + interrupts = ; #pwm-cells = <3>; pinctrl-names = "active"; pinctrl-0 = <&pwm4m0_pins>; @@ -1012,6 +1018,7 @@ pwm5: pwm@ff440010 { compatible = "rockchip,rv1126-pwm", "rockchip,rk3328-pwm"; reg = <0xff440010 0x10>; + interrupts = ; #pwm-cells = <3>; pinctrl-names = "active"; pinctrl-0 = <&pwm5m0_pins>; @@ -1023,6 +1030,7 @@ pwm6: pwm@ff440020 { compatible = "rockchip,rv1126-pwm", "rockchip,rk3328-pwm"; reg = <0xff440020 0x10>; + interrupts = ; #pwm-cells = <3>; pinctrl-names = "active"; pinctrl-0 = <&pwm6m0_pins>; @@ -1034,6 +1042,8 @@ pwm7: pwm@ff440030 { compatible = "rockchip,rv1126-pwm", "rockchip,rk3328-pwm"; reg = <0xff440030 0x10>; + interrupts = , + ; #pwm-cells = <3>; pinctrl-names = "active"; pinctrl-0 = <&pwm7m0_pins>; @@ -1269,6 +1279,7 @@ pwm8: pwm@ff550000 { compatible = "rockchip,rv1126-pwm", "rockchip,rk3328-pwm"; reg = <0xff550000 0x10>; + interrupts = ; #pwm-cells = <3>; pinctrl-names = "active"; pinctrl-0 = <&pwm8m0_pins>; @@ -1280,6 +1291,7 @@ pwm9: pwm@ff550010 { compatible = "rockchip,rv1126-pwm", "rockchip,rk3328-pwm"; reg = <0xff550010 0x10>; + interrupts = ; #pwm-cells = <3>; pinctrl-names = "active"; pinctrl-0 = <&pwm9m0_pins>; @@ -1291,6 +1303,7 @@ pwm10: pwm@ff550020 { compatible = "rockchip,rv1126-pwm", "rockchip,rk3328-pwm"; reg = <0xff550020 0x10>; + interrupts = ; #pwm-cells = <3>; pinctrl-names = "active"; pinctrl-0 = <&pwm10m0_pins>; @@ -1302,6 +1315,8 @@ pwm11: pwm@ff550030 { compatible = "rockchip,rv1126-pwm", "rockchip,rk3328-pwm"; reg = <0xff550030 0x10>; + interrupts = , + ; #pwm-cells = <3>; pinctrl-names = "active"; pinctrl-0 = <&pwm11m0_pins>; diff --git a/arch/arm64/boot/dts/rockchip/rk1808.dtsi b/arch/arm64/boot/dts/rockchip/rk1808.dtsi index cf9f850b8e74..59e1785de7da 100644 --- a/arch/arm64/boot/dts/rockchip/rk1808.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk1808.dtsi @@ -808,6 +808,7 @@ pwm0: pwm@ff3d0000 { compatible = "rockchip,rk1808-pwm", "rockchip,rk3328-pwm"; reg = <0x0 0xff3d0000 0x0 0x10>; + interrupts = ; #pwm-cells = <3>; pinctrl-names = "active"; pinctrl-0 = <&pwm0_pin>; @@ -819,6 +820,7 @@ pwm1: pwm@ff3d0010 { compatible = "rockchip,rk1808-pwm", "rockchip,rk3328-pwm"; reg = <0x0 0xff3d0010 0x0 0x10>; + interrupts = ; #pwm-cells = <3>; pinctrl-names = "active"; pinctrl-0 = <&pwm1_pin>; @@ -830,6 +832,7 @@ pwm2: pwm@ff3d0020 { compatible = "rockchip,rk1808-pwm", "rockchip,rk3328-pwm"; reg = <0x0 0xff3d0020 0x0 0x10>; + interrupts = ; #pwm-cells = <3>; pinctrl-names = "active"; pinctrl-0 = <&pwm2_pin>; @@ -841,6 +844,8 @@ pwm3: pwm@ff3d0030 { compatible = "rockchip,rk1808-pwm", "rockchip,rk3328-pwm"; reg = <0x0 0xff3d0030 0x0 0x10>; + interrupts = , + ; #pwm-cells = <3>; pinctrl-names = "active"; pinctrl-0 = <&pwm3_pin>; @@ -852,6 +857,7 @@ pwm4: pwm@ff3d8000 { compatible = "rockchip,rk1808-pwm", "rockchip,rk3328-pwm"; reg = <0x0 0xff3d8000 0x0 0x10>; + interrupts = ; #pwm-cells = <3>; pinctrl-names = "active"; pinctrl-0 = <&pwm4_pin>; @@ -863,6 +869,7 @@ pwm5: pwm@ff3d8010 { compatible = "rockchip,rk1808-pwm", "rockchip,rk3328-pwm"; reg = <0x0 0xff3d8010 0x0 0x10>; + interrupts = ; #pwm-cells = <3>; pinctrl-names = "active"; pinctrl-0 = <&pwm5_pin>; @@ -874,6 +881,7 @@ pwm6: pwm@ff3d8020 { compatible = "rockchip,rk1808-pwm", "rockchip,rk3328-pwm"; reg = <0x0 0xff3d8020 0x0 0x10>; + interrupts = ; #pwm-cells = <3>; pinctrl-names = "active"; pinctrl-0 = <&pwm6_pin>; @@ -885,6 +893,8 @@ pwm7: pwm@ff3d8030 { compatible = "rockchip,rk1808-pwm", "rockchip,rk3328-pwm"; reg = <0x0 0xff3d8030 0x0 0x10>; + interrupts = , + ; #pwm-cells = <3>; pinctrl-names = "active"; pinctrl-0 = <&pwm7_pin>; @@ -1213,6 +1223,7 @@ pwm8: pwm@ff5d0000 { compatible = "rockchip,rk1808-pwm", "rockchip,rk3328-pwm"; reg = <0x0 0xff5d0000 0x0 0x10>; + interrupts = ; #pwm-cells = <3>; pinctrl-names = "active"; pinctrl-0 = <&pwm8_pin>; @@ -1224,6 +1235,7 @@ pwm9: pwm@fff5d0010 { compatible = "rockchip,rk1808-pwm", "rockchip,rk3328-pwm"; reg = <0x0 0xff5d0010 0x0 0x10>; + interrupts = ; #pwm-cells = <3>; pinctrl-names = "active"; pinctrl-0 = <&pwm9_pin>; @@ -1235,6 +1247,7 @@ pwm10: pwm@ff5d0020 { compatible = "rockchip,rk1808-pwm", "rockchip,rk3328-pwm"; reg = <0x0 0xff5d0020 0x0 0x10>; + interrupts = ; #pwm-cells = <3>; pinctrl-names = "active"; pinctrl-0 = <&pwm10_pin>; @@ -1246,6 +1259,8 @@ pwm11: pwm@ff5d0030 { compatible = "rockchip,rk1808-pwm", "rockchip,rk3328-pwm"; reg = <0x0 0xff5d0030 0x0 0x10>; + interrupts = , + ; #pwm-cells = <3>; pinctrl-names = "active"; pinctrl-0 = <&pwm11_pin>; diff --git a/arch/arm64/boot/dts/rockchip/rk3328.dtsi b/arch/arm64/boot/dts/rockchip/rk3328.dtsi index b8aa20118e32..556dbc42078a 100644 --- a/arch/arm64/boot/dts/rockchip/rk3328.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3328.dtsi @@ -684,6 +684,7 @@ pwm0: pwm@ff1b0000 { compatible = "rockchip,rk3328-pwm"; reg = <0x0 0xff1b0000 0x0 0x10>; + interrupts = ; clocks = <&cru SCLK_PWM>, <&cru PCLK_PWM>; clock-names = "pwm", "pclk"; pinctrl-names = "active"; @@ -695,6 +696,7 @@ pwm1: pwm@ff1b0010 { compatible = "rockchip,rk3328-pwm"; reg = <0x0 0xff1b0010 0x0 0x10>; + interrupts = ; clocks = <&cru SCLK_PWM>, <&cru PCLK_PWM>; clock-names = "pwm", "pclk"; pinctrl-names = "active"; @@ -706,6 +708,7 @@ pwm2: pwm@ff1b0020 { compatible = "rockchip,rk3328-pwm"; reg = <0x0 0xff1b0020 0x0 0x10>; + interrupts = ; clocks = <&cru SCLK_PWM>, <&cru PCLK_PWM>; clock-names = "pwm", "pclk"; pinctrl-names = "active"; diff --git a/arch/arm64/boot/dts/rockchip/rk3528.dtsi b/arch/arm64/boot/dts/rockchip/rk3528.dtsi index 0160ca6116c3..a4b03b470c43 100644 --- a/arch/arm64/boot/dts/rockchip/rk3528.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3528.dtsi @@ -1803,6 +1803,7 @@ pwm0: pwm@ffa90000 { compatible = "rockchip,rk3528-pwm", "rockchip,rk3328-pwm"; reg = <0x0 0xffa90000 0x0 0x10>; + interrupts = ; #pwm-cells = <3>; pinctrl-names = "active"; pinctrl-0 = <&pwm0m0_pins>; @@ -1814,6 +1815,7 @@ pwm1: pwm@ffa90010 { compatible = "rockchip,rk3528-pwm", "rockchip,rk3328-pwm"; reg = <0x0 0xffa90010 0x0 0x10>; + interrupts = ; #pwm-cells = <3>; pinctrl-names = "active"; pinctrl-0 = <&pwm1m0_pins>; @@ -1825,6 +1827,7 @@ pwm2: pwm@ffa90020 { compatible = "rockchip,rk3528-pwm", "rockchip,rk3328-pwm"; reg = <0x0 0xffa90020 0x0 0x10>; + interrupts = ; #pwm-cells = <3>; pinctrl-names = "active"; pinctrl-0 = <&pwm2m0_pins>; @@ -1849,6 +1852,7 @@ pwm4: pwm@ffa98000 { compatible = "rockchip,rk3528-pwm", "rockchip,rk3328-pwm"; reg = <0x0 0xffa98000 0x0 0x10>; + interrupts = ; #pwm-cells = <3>; pinctrl-names = "active"; pinctrl-0 = <&pwm4m0_pins>; @@ -1860,6 +1864,7 @@ pwm5: pwm@ffa98010 { compatible = "rockchip,rk3528-pwm", "rockchip,rk3328-pwm"; reg = <0x0 0xffa98010 0x0 0x10>; + interrupts = ; #pwm-cells = <3>; pinctrl-names = "active"; pinctrl-0 = <&pwm5m0_pins>; @@ -1871,6 +1876,7 @@ pwm6: pwm@ffa98020 { compatible = "rockchip,rk3528-pwm", "rockchip,rk3328-pwm"; reg = <0x0 0xffa98020 0x0 0x10>; + interrupts = ; #pwm-cells = <3>; pinctrl-names = "active"; pinctrl-0 = <&pwm6m0_pins>; diff --git a/arch/arm64/configs/rockchip_defconfig b/arch/arm64/configs/rockchip_defconfig index 8e96d404a2a6..73cd32aa4b4c 100644 --- a/arch/arm64/configs/rockchip_defconfig +++ b/arch/arm64/configs/rockchip_defconfig @@ -558,6 +558,7 @@ CONFIG_DW_WATCHDOG=y CONFIG_MFD_RK618=y CONFIG_MFD_RK628=y CONFIG_MFD_RK630_I2C=y +CONFIG_MFD_RK806_I2C=y CONFIG_MFD_RK806_SPI=y CONFIG_MFD_RK808=y CONFIG_MFD_RKX110_X120=y diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c index b486f1b57128..19b40e98ad7a 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c @@ -426,14 +426,18 @@ static void repo_hpd_event(struct work_struct *p_work) if (hdmi->bridge.dev) { bool change; + void *data = hdmi->plat_data->phy_data; change = drm_helper_hpd_irq_event(hdmi->bridge.dev); - if (change && hdmi->cec_adap && - hdmi->cec_adap->devnode.registered) - cec_queue_pin_hpd_event(hdmi->cec_adap, - hdmi->hpd_state, - ktime_get()); + if (change) { + if (hdmi->plat_data->set_ddc_io) + hdmi->plat_data->set_ddc_io(data, hdmi->hpd_state); + if (hdmi->cec_adap->devnode.registered) + cec_queue_pin_hpd_event(hdmi->cec_adap, + hdmi->hpd_state, + ktime_get()); + } drm_bridge_hpd_notify(&hdmi->bridge, status); } } @@ -539,10 +543,12 @@ static void dw_hdmi_i2c_init(struct dw_hdmi *hdmi) hdmi_writeb(hdmi, HDMI_IH_I2CM_STAT0_ERROR | HDMI_IH_I2CM_STAT0_DONE, HDMI_IH_MUTE_I2CM_STAT0); - /* set SDA high level holding time */ - hdmi_writeb(hdmi, 0x48, HDMI_I2CM_SDA_HOLD); - - dw_hdmi_i2c_set_divs(hdmi); + /* Only configure when we use the internal I2C controller */ + if (hdmi->i2c) { + /* set SDA high level holding time */ + hdmi_writeb(hdmi, 0x48, HDMI_I2CM_SDA_HOLD); + dw_hdmi_i2c_set_divs(hdmi); + } } static bool dw_hdmi_i2c_unwedge(struct dw_hdmi *hdmi) @@ -647,11 +653,7 @@ static int dw_hdmi_i2c_read(struct dw_hdmi *hdmi, while (retry > 0) { if (!(hdmi_readb(hdmi, HDMI_PHY_STAT0) & HDMI_PHY_HPD)) { - void *data = hdmi->plat_data->phy_data; - dev_dbg(hdmi->dev, "hdmi disconnect, stop ddc read\n"); - if (hdmi->plat_data->set_ddc_io) - hdmi->plat_data->set_ddc_io(data, false); return -EPERM; } @@ -730,11 +732,7 @@ static int dw_hdmi_i2c_write(struct dw_hdmi *hdmi, while (retry > 0) { if (!(hdmi_readb(hdmi, HDMI_PHY_STAT0) & HDMI_PHY_HPD)) { - void *data = hdmi->plat_data->phy_data; - dev_dbg(hdmi->dev, "hdmi disconnect, stop ddc write\n"); - if (hdmi->plat_data->set_ddc_io) - hdmi->plat_data->set_ddc_io(data, false); return -EPERM; } @@ -779,7 +777,6 @@ static int dw_hdmi_i2c_xfer(struct i2c_adapter *adap, struct dw_hdmi *hdmi = i2c_get_adapdata(adap); struct dw_hdmi_i2c *i2c = hdmi->i2c; u8 addr = msgs[0].addr; - void *data = hdmi->plat_data->phy_data; int i, ret = 0; if (addr == DDC_CI_ADDR) @@ -804,9 +801,6 @@ static int dw_hdmi_i2c_xfer(struct i2c_adapter *adap, mutex_lock(&i2c->lock); - if (hdmi->plat_data->set_ddc_io) - hdmi->plat_data->set_ddc_io(data, true); - hdmi_writeb(hdmi, 0, HDMI_I2CM_SOFTRSTZ); udelay(100); @@ -4112,7 +4106,6 @@ static void dw_hdmi_bridge_atomic_disable(struct drm_bridge *bridge, struct drm_bridge_state *old_state) { struct dw_hdmi *hdmi = bridge->driver_private; - void *data = hdmi->plat_data->phy_data; mutex_lock(&hdmi->mutex); hdmi->disabled = true; @@ -4123,11 +4116,6 @@ static void dw_hdmi_bridge_atomic_disable(struct drm_bridge *bridge, if (hdmi->plat_data->dclk_set) hdmi->plat_data->dclk_set(hdmi->plat_data->phy_data, false, 0); mutex_unlock(&hdmi->mutex); - - mutex_lock(&hdmi->i2c->lock); - if (hdmi->plat_data->set_ddc_io) - hdmi->plat_data->set_ddc_io(data, false); - mutex_unlock(&hdmi->i2c->lock); } static void dw_hdmi_bridge_atomic_enable(struct drm_bridge *bridge, @@ -4457,8 +4445,7 @@ static void dw_hdmi_init_hw(struct dw_hdmi *hdmi) * Even if we are using a separate i2c adapter doing this doesn't * hurt. */ - if (hdmi->i2c) - dw_hdmi_i2c_init(hdmi); + dw_hdmi_i2c_init(hdmi); if (hdmi->phy.ops->setup_hpd) hdmi->phy.ops->setup_hpd(hdmi, hdmi->phy.data); @@ -5414,8 +5401,7 @@ void dw_hdmi_resume(struct dw_hdmi *hdmi) pinctrl_pm_select_default_state(hdmi->dev); mutex_lock(&hdmi->mutex); dw_hdmi_reg_initial(hdmi); - if (hdmi->i2c) - dw_hdmi_i2c_init(hdmi); + dw_hdmi_i2c_init(hdmi); if (hdmi->irq) enable_irq(hdmi->irq); /* diff --git a/drivers/media/i2c/sc223a.c b/drivers/media/i2c/sc223a.c index e578ac9f551d..fd82b3e854ab 100644 --- a/drivers/media/i2c/sc223a.c +++ b/drivers/media/i2c/sc223a.c @@ -40,6 +40,8 @@ #define PIXEL_RATE_WITH_405M_10BIT (SC223A_LINK_FREQ_405 * 2 * \ SC223A_LANES / SC223A_BITS_PER_SAMPLE) +/* 79.2Mhz */ +#define SC223A_PIXEL_RATE (79200000) #define SC223A_XVCLK_FREQ 24000000 #define CHIP_ID 0xcb3e @@ -93,10 +95,12 @@ #define SC223A_REG_VALUE_16BIT 2 #define SC223A_REG_VALUE_24BIT 3 +#define RKMODULE_CAMERA_MODULE_MODE "rockchip,camera_mode" #define OF_CAMERA_PINCTRL_STATE_DEFAULT "rockchip,camera_default" #define OF_CAMERA_PINCTRL_STATE_SLEEP "rockchip,camera_sleep" #define SC223A_NAME "sc223a" - +#define CAMERA_MIPI_MODE "mipi_mode" +#define CAMERA_DVP_MODE "dvp_mode" static const char * const sc223a_supply_names[] = { "avdd", /* Analog power */ "dovdd", /* Digital I/O power */ @@ -105,6 +109,17 @@ static const char * const sc223a_supply_names[] = { #define SC223A_NUM_SUPPLIES ARRAY_SIZE(sc223a_supply_names) +enum sc223a_support_mode_id { + SC223A_MIPI_1920X1080 = 0, + SC223A_DVP_1920X1080, + SC223A_MODE_ID_MAX = SC223A_DVP_1920X1080, +}; + +enum sc223a_mode_id { + SC223A_MIPI_MODE = 0, + SC223A_DVP_MODE, +}; + struct regval { u16 addr; u8 val; @@ -121,6 +136,7 @@ struct sc223a_mode { const struct regval *reg_list; u32 hdr_mode; u32 vc[PAD_MAX]; + u8 mode_id; }; struct sc223a { @@ -152,6 +168,7 @@ struct sc223a { const char *module_facing; const char *module_name; const char *len_name; + const char *mode; u32 cur_vts; bool has_init_exp; bool is_thunderboot; @@ -353,8 +370,223 @@ static const struct regval sc223a_linear_10_1920x1080_30fps_regs[] = { {REG_NULL, 0x00}, }; +/* + * Xclk 24Mhz + * Pclk 79.2Mhz + * max_framerate 30fps + * 1920x1080 + * dvp 10bit, 2lane + */ +static const struct regval sc223a_linear_10_1920x1080_dvp_30fps_regs[] = { + {0x0100, 0x00}, + {0x36e9, 0x80}, + {0x37f9, 0x80}, + {0x3001, 0xff}, + {0x3002, 0xf0}, + {0x300a, 0x24}, + {0x3018, 0x0f}, + {0x301a, 0xf8}, + {0x301c, 0x94}, + {0x301f, 0x40}, + {0x303f, 0x81}, + {0x30b8, 0x44}, + {0x3200, 0x00}, + {0x3201, 0x00}, + {0x3202, 0x00}, + {0x3203, 0x00}, + {0x3204, 0x07}, + {0x3205, 0x87}, + {0x3206, 0x04}, + {0x3207, 0x3f}, + {0x3208, 0x07}, + {0x3209, 0x80}, + {0x320a, 0x04}, + {0x320b, 0x38}, + {0x320c, 0x09}, + {0x320d, 0x60}, + {0x320e, 0x04}, + {0x320f, 0x65}, + {0x3210, 0x00}, + {0x3211, 0x04}, + {0x3212, 0x00}, + {0x3213, 0x04}, + {0x3227, 0x03}, + {0x3250, 0x00}, + {0x3253, 0x0c}, + {0x3281, 0x80}, + {0x3301, 0x06}, + {0x3302, 0x12}, + {0x3306, 0x84}, + {0x3309, 0x60}, + {0x330a, 0x00}, + {0x330b, 0xe0}, + {0x330d, 0x20}, + {0x3314, 0x15}, + {0x331e, 0x41}, + {0x331f, 0x51}, + {0x3320, 0x0a}, + {0x3326, 0x0e}, + {0x3333, 0x10}, + {0x3334, 0x40}, + {0x335d, 0x60}, + {0x335e, 0x06}, + {0x335f, 0x08}, + {0x3364, 0x56}, + {0x337a, 0x06}, + {0x337b, 0x0e}, + {0x337c, 0x02}, + {0x337d, 0x0a}, + {0x3390, 0x03}, + {0x3391, 0x0f}, + {0x3392, 0x1f}, + {0x3393, 0x06}, + {0x3394, 0x06}, + {0x3395, 0x06}, + {0x3396, 0x48}, + {0x3397, 0x4b}, + {0x3398, 0x5f}, + {0x3399, 0x06}, + {0x339a, 0x06}, + {0x339b, 0x9c}, + {0x339c, 0x9c}, + {0x33a2, 0x04}, + {0x33a3, 0x0a}, + {0x33ad, 0x1c}, + {0x33af, 0x40}, + {0x33b1, 0x80}, + {0x33b3, 0x20}, + {0x349f, 0x02}, + {0x34a6, 0x48}, + {0x34a7, 0x4b}, + {0x34a8, 0x20}, + {0x34a9, 0x20}, + {0x34f8, 0x5f}, + {0x34f9, 0x10}, + {0x3616, 0xac}, + {0x3630, 0xc0}, + {0x3631, 0x86}, + {0x3632, 0x26}, + {0x3633, 0x32}, + {0x3637, 0x29}, + {0x363a, 0x84}, + {0x363b, 0x04}, + {0x363c, 0x08}, + {0x3641, 0x3a}, + {0x364f, 0x39}, + {0x3670, 0xce}, + {0x3674, 0xc0}, + {0x3675, 0xc0}, + {0x3676, 0xc0}, + {0x3677, 0x86}, + {0x3678, 0x8b}, + {0x3679, 0x8c}, + {0x367c, 0x4b}, + {0x367d, 0x5f}, + {0x367e, 0x4b}, + {0x367f, 0x5f}, + {0x3690, 0x62}, + {0x3691, 0x63}, + {0x3692, 0x63}, + {0x3699, 0x86}, + {0x369a, 0x92}, + {0x369b, 0xa4}, + {0x369c, 0x48}, + {0x369d, 0x4b}, + {0x36a2, 0x4b}, + {0x36a3, 0x4f}, + {0x36ea, 0x09}, + {0x36eb, 0x0c}, + {0x36ec, 0x1c}, + {0x36ed, 0x28}, + {0x370f, 0x01}, + {0x3721, 0x6c}, + {0x3722, 0x09}, + {0x3724, 0x41}, + {0x3725, 0xc4}, + {0x37b0, 0x09}, + {0x37b1, 0x09}, + {0x37b2, 0x09}, + {0x37b3, 0x48}, + {0x37b4, 0x5f}, + {0x37fa, 0x09}, + {0x37fb, 0x32}, + {0x37fc, 0x10}, + {0x37fd, 0x37}, + {0x3900, 0x19}, + {0x3901, 0x02}, + {0x3905, 0xb8}, + {0x391b, 0x82}, + {0x391c, 0x00}, + {0x391f, 0x04}, + {0x3928, 0xc1}, + {0x3933, 0x81}, + {0x3934, 0x4c}, + {0x393f, 0xff}, + {0x3940, 0x73}, + {0x3942, 0x01}, + {0x3943, 0x4d}, + {0x3946, 0x20}, + {0x3957, 0x86}, + {0x3e01, 0x8c}, + {0x3e02, 0x00}, + {0x3e28, 0xc4}, + {0x440e, 0x02}, + {0x4501, 0xc0}, + {0x4509, 0x14}, + {0x450d, 0x11}, + {0x4518, 0x00}, + {0x451b, 0x0a}, + {0x4603, 0x09}, + {0x4819, 0x07}, + {0x481b, 0x04}, + {0x481d, 0x0e}, + {0x3000, 0xff}, + {0x481f, 0x03}, + {0x4821, 0x09}, + {0x4823, 0x04}, + {0x4825, 0x03}, + {0x4827, 0x03}, + {0x4829, 0x06}, + {0x501c, 0x00}, + {0x501d, 0x60}, + {0x501e, 0x00}, + {0x501f, 0x40}, + {0x5799, 0x06}, + {0x5ae0, 0xfe}, + {0x5ae1, 0x40}, + {0x5ae2, 0x38}, + {0x5ae3, 0x30}, + {0x5ae4, 0x28}, + {0x5ae5, 0x38}, + {0x5ae6, 0x30}, + {0x5ae7, 0x28}, + {0x5ae8, 0x3f}, + {0x5ae9, 0x34}, + {0x5aea, 0x2c}, + {0x5aeb, 0x3f}, + {0x5aec, 0x34}, + {0x5aed, 0x2c}, + {0x5aee, 0xfe}, + {0x5aef, 0x40}, + {0x5af4, 0x38}, + {0x5af5, 0x30}, + {0x5af6, 0x28}, + {0x5af7, 0x38}, + {0x5af8, 0x30}, + {0x5af9, 0x28}, + {0x5afa, 0x3f}, + {0x5afb, 0x34}, + {0x5afc, 0x2c}, + {0x5afd, 0x3f}, + {0x5afe, 0x34}, + {0x5aff, 0x2c}, + {0x36e9, 0x53}, + {0x37f9, 0x53}, + {REG_NULL, 0x00}, +}; + static const struct sc223a_mode supported_modes[] = { - { + [SC223A_MIPI_1920X1080] = { .width = 1920, .height = 1080, .max_fps = { @@ -367,11 +599,28 @@ static const struct sc223a_mode supported_modes[] = { .bus_fmt = MEDIA_BUS_FMT_SBGGR10_1X10, .reg_list = sc223a_linear_10_1920x1080_30fps_regs, .hdr_mode = NO_HDR, + .mode_id = SC223A_MIPI_MODE, .vc[PAD0] = V4L2_MBUS_CSI2_CHANNEL_0, - } + }, + [SC223A_DVP_1920X1080] = { + .width = 1920, + .height = 1080, + .max_fps = { + .numerator = 10000, + .denominator = 300000, + }, + .exp_def = 0x0080, + .hts_def = 0x0960, + .vts_def = 0x0465, + .bus_fmt = MEDIA_BUS_FMT_SBGGR8_1X8, + .reg_list = sc223a_linear_10_1920x1080_dvp_30fps_regs, + .hdr_mode = NO_HDR, + .mode_id = SC223A_DVP_MODE, + .vc[PAD0] = 0, + }, }; -static const s64 link_freq_menu_items[] = { +static const __maybe_unused s64 link_freq_menu_items[] = { SC223A_LINK_FREQ_405 }; @@ -694,17 +943,25 @@ static int sc223a_g_mbus_config(struct v4l2_subdev *sd, struct sc223a *sc223a = to_sc223a(sd); const struct sc223a_mode *mode = sc223a->cur_mode; - u32 val = 1 << (SC223A_LANES - 1) | - V4L2_MBUS_CSI2_CHANNEL_0 | - V4L2_MBUS_CSI2_CONTINUOUS_CLOCK; + u32 val; - if (mode->hdr_mode != NO_HDR) - val |= V4L2_MBUS_CSI2_CHANNEL_1; - if (mode->hdr_mode == HDR_X3) - val |= V4L2_MBUS_CSI2_CHANNEL_2; + if (!strcmp(sc223a->mode, CAMERA_MIPI_MODE)) { + val = 1 << (SC223A_LANES - 1) | + V4L2_MBUS_CSI2_CHANNEL_0 | + V4L2_MBUS_CSI2_CONTINUOUS_CLOCK; + if (mode->hdr_mode != NO_HDR) + val |= V4L2_MBUS_CSI2_CHANNEL_1; + if (mode->hdr_mode == HDR_X3) + val |= V4L2_MBUS_CSI2_CHANNEL_2; - config->type = V4L2_MBUS_CSI2_DPHY; - config->flags = val; + config->type = V4L2_MBUS_CSI2_DPHY; + config->flags = val; + } else if (!strcmp(sc223a->mode, CAMERA_DVP_MODE)) { + config->type = V4L2_MBUS_PARALLEL; + config->flags = V4L2_MBUS_HSYNC_ACTIVE_HIGH | + V4L2_MBUS_VSYNC_ACTIVE_LOW | + V4L2_MBUS_PCLK_SAMPLE_RISING; + } return 0; } @@ -724,6 +981,7 @@ static long sc223a_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) struct sc223a *sc223a = to_sc223a(sd); struct rkmodule_hdr_cfg *hdr; u32 i, h, w; + u8 mode; long ret = 0; u32 stream = 0; @@ -740,9 +998,11 @@ static long sc223a_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) hdr = (struct rkmodule_hdr_cfg *)arg; w = sc223a->cur_mode->width; h = sc223a->cur_mode->height; + mode = sc223a->cur_mode->mode_id; for (i = 0; i < ARRAY_SIZE(supported_modes); i++) { if (w == supported_modes[i].width && h == supported_modes[i].height && + mode == supported_modes[i].mode_id && supported_modes[i].hdr_mode == hdr->hdr_mode) { sc223a->cur_mode = &supported_modes[i]; break; @@ -889,6 +1149,7 @@ static int __sc223a_start_stream(struct sc223a *sc223a) } } } + return sc223a_write_reg(sc223a->client, SC223A_REG_CTRL_MODE, SC223A_REG_VALUE_08BIT, SC223A_MODE_STREAMING); } @@ -1293,13 +1554,18 @@ static int sc223a_initialize_controls(struct sc223a *sc223a) return ret; handler->lock = &sc223a->mutex; - ctrl = v4l2_ctrl_new_int_menu(handler, NULL, V4L2_CID_LINK_FREQ, - 0, 0, link_freq_menu_items); - if (ctrl) - ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; + if (!strcmp(sc223a->mode, CAMERA_MIPI_MODE)) { + ctrl = v4l2_ctrl_new_int_menu(handler, NULL, V4L2_CID_LINK_FREQ, + 0, 0, link_freq_menu_items); + if (ctrl) + ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; + v4l2_ctrl_new_std(handler, NULL, V4L2_CID_PIXEL_RATE, + 0, PIXEL_RATE_WITH_405M_10BIT, 1, PIXEL_RATE_WITH_405M_10BIT); + } else if (!strcmp(sc223a->mode, CAMERA_DVP_MODE)) { + v4l2_ctrl_new_std(handler, NULL, V4L2_CID_PIXEL_RATE, + 0, SC223A_PIXEL_RATE, 1, SC223A_PIXEL_RATE); + } - v4l2_ctrl_new_std(handler, NULL, V4L2_CID_PIXEL_RATE, - 0, PIXEL_RATE_WITH_405M_10BIT, 1, PIXEL_RATE_WITH_405M_10BIT); h_blank = mode->hts_def - mode->width; sc223a->hblank = v4l2_ctrl_new_std(handler, NULL, V4L2_CID_HBLANK, @@ -1412,6 +1678,8 @@ static int sc223a_probe(struct i2c_client *client, &sc223a->module_name); ret |= of_property_read_string(node, RKMODULE_CAMERA_LENS_NAME, &sc223a->len_name); + ret |= of_property_read_string(node, RKMODULE_CAMERA_MODULE_MODE, + &sc223a->mode); if (ret) { dev_err(dev, "could not get module information!\n"); return -EINVAL; @@ -1420,14 +1688,18 @@ static int sc223a_probe(struct i2c_client *client, sc223a->is_thunderboot = IS_ENABLED(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP); sc223a->client = client; - for (i = 0; i < ARRAY_SIZE(supported_modes); i++) { - if (hdr_mode == supported_modes[i].hdr_mode) { - sc223a->cur_mode = &supported_modes[i]; - break; + if (!strcmp(sc223a->mode, CAMERA_MIPI_MODE)) { + for (i = 0; i < ARRAY_SIZE(supported_modes); i++) { + if (hdr_mode == supported_modes[i].hdr_mode) { + sc223a->cur_mode = &supported_modes[i]; + break; + } } + if (i == ARRAY_SIZE(supported_modes)) + sc223a->cur_mode = &supported_modes[SC223A_MIPI_1920X1080]; + } else if (!strcmp(sc223a->mode, CAMERA_DVP_MODE)) { + sc223a->cur_mode = &supported_modes[SC223A_DVP_1920X1080]; } - if (i == ARRAY_SIZE(supported_modes)) - sc223a->cur_mode = &supported_modes[0]; sc223a->xvclk = devm_clk_get(dev, "xvclk"); if (IS_ERR(sc223a->xvclk)) { diff --git a/drivers/media/platform/rockchip/isp/dev.c b/drivers/media/platform/rockchip/isp/dev.c index cd80b5dbea40..081e4db5bb45 100644 --- a/drivers/media/platform/rockchip/isp/dev.c +++ b/drivers/media/platform/rockchip/isp/dev.c @@ -280,16 +280,19 @@ static int rkisp_pipeline_open(struct rkisp_pipeline *p, if (prepare) { ret = __isp_pipeline_prepare(p, me); if (ret < 0) - return ret; + goto err; } ret = __isp_pipeline_s_isp_clk(p); if (ret < 0) - return ret; + goto err; if (dev->isp_inp & (INP_CSI | INP_RAWRD0 | INP_RAWRD1 | INP_RAWRD2 | INP_CIF)) rkisp_csi_config_patch(dev); return 0; +err: + atomic_dec(&p->power_cnt); + return ret; } static int rkisp_pipeline_close(struct rkisp_pipeline *p) diff --git a/drivers/media/platform/rockchip/isp/isp_rockit.c b/drivers/media/platform/rockchip/isp/isp_rockit.c index c452752af967..0e4f780972bb 100644 --- a/drivers/media/platform/rockchip/isp/isp_rockit.c +++ b/drivers/media/platform/rockchip/isp/isp_rockit.c @@ -310,8 +310,9 @@ int rkisp_rockit_config_stream(struct rockit_cfg *input_rockit_cfg, int width, int height, int wrap_line) { struct rkisp_stream *stream = NULL; - struct rkisp_buffer *isp_buf; + struct rkisp_buffer *isp_buf, *buf_temp; int offset, i, ret; + unsigned long lock_flags = 0; stream = rkisp_rockit_get_stream(input_rockit_cfg); @@ -331,16 +332,18 @@ int rkisp_rockit_config_stream(struct rockit_cfg *input_rockit_cfg, if (stream->ispdev->cap_dev.wrap_line && stream->id == RKISP_STREAM_MP) rkisp_dvbm_init(stream); + spin_lock_irqsave(&stream->vbq_lock, lock_flags); if (stream->curr_buf) { list_add_tail(&stream->curr_buf->queue, &stream->buf_queue); + if (stream->curr_buf == stream->next_buf) + stream->next_buf = NULL; stream->curr_buf = NULL; } if (stream->next_buf) { list_add_tail(&stream->next_buf->queue, &stream->buf_queue); stream->next_buf = NULL; } - - list_for_each_entry(isp_buf, &stream->buf_queue, queue) { + list_for_each_entry_safe(isp_buf, buf_temp, &stream->buf_queue, queue) { if (stream->out_isp_fmt.mplanes == 1) { for (i = 0; i < stream->out_isp_fmt.cplanes - 1; i++) { height = stream->out_fmt.height; @@ -352,6 +355,7 @@ int rkisp_rockit_config_stream(struct rockit_cfg *input_rockit_cfg, } } } + spin_unlock_irqrestore(&stream->vbq_lock, lock_flags); return 0; } diff --git a/drivers/misc/rockchip/pcie-rkep.c b/drivers/misc/rockchip/pcie-rkep.c index cc45f5bf3c32..ee8cf9359471 100644 --- a/drivers/misc/rockchip/pcie-rkep.c +++ b/drivers/misc/rockchip/pcie-rkep.c @@ -56,6 +56,8 @@ static DEFINE_MUTEX(rkep_mutex); #define PCIE_DMA_WR_SAR_PTR_HI 0x210 #define PCIE_DMA_WR_DAR_PTR_LO 0x214 #define PCIE_DMA_WR_DAR_PTR_HI 0x218 +#define PCIE_DMA_WR_LL_PTR_LO 0x21c +#define PCIE_DMA_WR_LL_PTR_HI 0x220 #define PCIE_DMA_WR_WEILO 0x18 #define PCIE_DMA_WR_WEIHI 0x1c #define PCIE_DMA_WR_DOORBELL 0x10 @@ -63,6 +65,7 @@ static DEFINE_MUTEX(rkep_mutex); #define PCIE_DMA_WR_INT_MASK 0x54 #define PCIE_DMA_WR_INT_CLEAR 0x58 #define PCIE_DMA_WR_ERR_STATUS 0x5c +#define PCIE_DMA_WR_LL_ERR_EN 0x90 #define PCIE_DMA_RD_ENB 0x2c #define PCIE_DMA_RD_CTRL_LO 0x300 @@ -72,6 +75,8 @@ static DEFINE_MUTEX(rkep_mutex); #define PCIE_DMA_RD_SAR_PTR_HI 0x310 #define PCIE_DMA_RD_DAR_PTR_LO 0x314 #define PCIE_DMA_RD_DAR_PTR_HI 0x318 +#define PCIE_DMA_RD_LL_PTR_LO 0x31c +#define PCIE_DMA_RD_LL_PTR_HI 0x320 #define PCIE_DMA_RD_WEILO 0x38 #define PCIE_DMA_RD_WEIHI 0x3c #define PCIE_DMA_RD_DOORBELL 0x30 @@ -80,6 +85,7 @@ static DEFINE_MUTEX(rkep_mutex); #define PCIE_DMA_RD_INT_CLEAR 0xac #define PCIE_DMA_RD_ERR_STATUS_LOW 0xb8 #define PCIE_DMA_RD_ERR_STATUS_HIGH 0xbc +#define PCIE_DMA_RD_LL_ERR_EN 0xc4 #define PCIE_DMA_CHANEL_MAX_NUM 2 @@ -133,9 +139,9 @@ static int rkep_ep_dma_xfer(struct pcie_rkep *pcie_rkep, struct pcie_ep_dma_bloc int ret; if (dma->wr) - ret = pcie_dw_rc_dma_tobus(pcie_rkep->dma_obj, dma->chn, dma->block.bus_paddr, dma->block.local_paddr, dma->block.size); + ret = pcie_dw_wired_dma_tobus_block(pcie_rkep->dma_obj, dma->chn, dma->block.bus_paddr, dma->block.local_paddr, dma->block.size); else - ret = pcie_dw_rc_dma_frombus(pcie_rkep->dma_obj, dma->chn, dma->block.local_paddr, dma->block.bus_paddr, dma->block.size); + ret = pcie_dw_wired_dma_frombus_block(pcie_rkep->dma_obj, dma->chn, dma->block.local_paddr, dma->block.bus_paddr, dma->block.size); return ret; } @@ -660,41 +666,69 @@ static void pcie_rkep_dma_debug(struct dma_trx_obj *obj, struct dma_table *table { struct pci_dev *pdev = container_of(obj->dev, struct pci_dev, dev); struct pcie_rkep *pcie_rkep = pci_get_drvdata(pdev); - unsigned int ctr_off = table->chn * 0x200; + unsigned int ctr_off = PCIE_DMA_OFFSET + table->chn * 0x200; dev_err(&pdev->dev, "chnl=%x\n", table->start.chnl); dev_err(&pdev->dev, "%s\n", table->dir == DMA_FROM_BUS ? "udma read" : "udma write"); - dev_err(&pdev->dev, "src=0x%x %x\n", table->ctx_reg.sarptrhi, table->ctx_reg.sarptrlo); - dev_err(&pdev->dev, "dst=0x%x %x\n", table->ctx_reg.darptrhi, table->ctx_reg.darptrlo); + if (table->dma_mode == RK_PCIE_DMA_BLOCK) { + dev_err(&pdev->dev, "src=0x%x %x\n", table->ctx_reg.sarptrhi, table->ctx_reg.sarptrlo); + dev_err(&pdev->dev, "dst=0x%x %x\n", table->ctx_reg.darptrhi, table->ctx_reg.darptrlo); + } else { + dev_err(&pdev->dev, "phys_descs=0x%llx\n", table->phys_descs); + } dev_err(&pdev->dev, "xfersize=%x\n", table->ctx_reg.xfersize); if (table->dir == DMA_FROM_BUS) { - dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_RD_INT_MASK = %x\n", PCIE_DMA_RD_INT_MASK, pcie_rkep_readl_dbi(pcie_rkep, PCIE_DMA_OFFSET + PCIE_DMA_RD_INT_MASK)); - dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_RD_ENB = %x\n", PCIE_DMA_RD_ENB, pcie_rkep_readl_dbi(pcie_rkep, PCIE_DMA_OFFSET + PCIE_DMA_RD_ENB)); - dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_RD_CTRL_LO = %x\n", ctr_off + PCIE_DMA_RD_CTRL_LO, pcie_rkep_readl_dbi(pcie_rkep, PCIE_DMA_OFFSET + ctr_off + PCIE_DMA_RD_CTRL_LO)); - dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_RD_CTRL_HI = %x\n", ctr_off + PCIE_DMA_RD_CTRL_HI, pcie_rkep_readl_dbi(pcie_rkep, PCIE_DMA_OFFSET + ctr_off + PCIE_DMA_RD_CTRL_HI)); - dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_RD_XFERSIZE = %x\n", ctr_off + PCIE_DMA_RD_XFERSIZE, pcie_rkep_readl_dbi(pcie_rkep, PCIE_DMA_OFFSET + ctr_off + PCIE_DMA_RD_XFERSIZE)); - dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_RD_SAR_PTR_LO = %x\n", ctr_off + PCIE_DMA_RD_SAR_PTR_LO, pcie_rkep_readl_dbi(pcie_rkep, PCIE_DMA_OFFSET + ctr_off + PCIE_DMA_RD_SAR_PTR_LO)); - dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_RD_SAR_PTR_HI = %x\n", ctr_off + PCIE_DMA_RD_SAR_PTR_HI, pcie_rkep_readl_dbi(pcie_rkep, PCIE_DMA_OFFSET + ctr_off + PCIE_DMA_RD_SAR_PTR_HI)); - dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_RD_DAR_PTR_LO = %x\n", ctr_off + PCIE_DMA_RD_DAR_PTR_LO, pcie_rkep_readl_dbi(pcie_rkep, PCIE_DMA_OFFSET + ctr_off + PCIE_DMA_RD_DAR_PTR_LO)); - dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_RD_DAR_PTR_HI = %x\n", ctr_off + PCIE_DMA_RD_DAR_PTR_HI, pcie_rkep_readl_dbi(pcie_rkep, PCIE_DMA_OFFSET + ctr_off + PCIE_DMA_RD_DAR_PTR_HI)); - dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_RD_DOORBELL = %x\n", PCIE_DMA_RD_DOORBELL, pcie_rkep_readl_dbi(pcie_rkep, PCIE_DMA_OFFSET + PCIE_DMA_RD_DOORBELL)); - dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_RD_INT_STATUS = %x\n", PCIE_DMA_RD_INT_STATUS, pcie_rkep_readl_dbi(pcie_rkep, PCIE_DMA_OFFSET + PCIE_DMA_RD_INT_STATUS)); - dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_RD_ERR_STATUS_LOW = %x\n", PCIE_DMA_RD_ERR_STATUS_LOW, pcie_rkep_readl_dbi(pcie_rkep, PCIE_DMA_OFFSET + PCIE_DMA_RD_ERR_STATUS_LOW)); - dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_RD_ERR_STATUS_HIGH = %x\n", PCIE_DMA_RD_ERR_STATUS_HIGH, pcie_rkep_readl_dbi(pcie_rkep, PCIE_DMA_OFFSET + PCIE_DMA_RD_ERR_STATUS_HIGH)); + if (table->dma_mode == RK_PCIE_DMA_BLOCK) { + dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_RD_INT_MASK = %x\n", PCIE_DMA_RD_INT_MASK, pcie_rkep_readl_dbi(pcie_rkep, PCIE_DMA_OFFSET + PCIE_DMA_RD_INT_MASK)); + dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_RD_ENB = %x\n", PCIE_DMA_RD_ENB, pcie_rkep_readl_dbi(pcie_rkep, PCIE_DMA_OFFSET + PCIE_DMA_RD_ENB)); + dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_RD_CTRL_LO = %x\n", ctr_off + PCIE_DMA_RD_CTRL_LO, pcie_rkep_readl_dbi(pcie_rkep, ctr_off + PCIE_DMA_RD_CTRL_LO)); + dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_RD_CTRL_HI = %x\n", ctr_off + PCIE_DMA_RD_CTRL_HI, pcie_rkep_readl_dbi(pcie_rkep, ctr_off + PCIE_DMA_RD_CTRL_HI)); + dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_RD_XFERSIZE = %x\n", ctr_off + PCIE_DMA_RD_XFERSIZE, pcie_rkep_readl_dbi(pcie_rkep, ctr_off + PCIE_DMA_RD_XFERSIZE)); + dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_RD_SAR_PTR_LO = %x\n", ctr_off + PCIE_DMA_RD_SAR_PTR_LO, pcie_rkep_readl_dbi(pcie_rkep, ctr_off + PCIE_DMA_RD_SAR_PTR_LO)); + dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_RD_SAR_PTR_HI = %x\n", ctr_off + PCIE_DMA_RD_SAR_PTR_HI, pcie_rkep_readl_dbi(pcie_rkep, ctr_off + PCIE_DMA_RD_SAR_PTR_HI)); + dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_RD_DAR_PTR_LO = %x\n", ctr_off + PCIE_DMA_RD_DAR_PTR_LO, pcie_rkep_readl_dbi(pcie_rkep, ctr_off + PCIE_DMA_RD_DAR_PTR_LO)); + dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_RD_DAR_PTR_HI = %x\n", ctr_off + PCIE_DMA_RD_DAR_PTR_HI, pcie_rkep_readl_dbi(pcie_rkep, ctr_off + PCIE_DMA_RD_DAR_PTR_HI)); + dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_RD_DOORBELL = %x\n", PCIE_DMA_RD_DOORBELL, pcie_rkep_readl_dbi(pcie_rkep, PCIE_DMA_OFFSET + PCIE_DMA_RD_DOORBELL)); + dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_RD_INT_STATUS = %x\n", PCIE_DMA_RD_INT_STATUS, pcie_rkep_readl_dbi(pcie_rkep, PCIE_DMA_OFFSET + PCIE_DMA_RD_INT_STATUS)); + dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_RD_ERR_STATUS_LOW = %x\n", PCIE_DMA_RD_ERR_STATUS_LOW, pcie_rkep_readl_dbi(pcie_rkep, PCIE_DMA_OFFSET + PCIE_DMA_RD_ERR_STATUS_LOW)); + dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_RD_ERR_STATUS_HIGH = %x\n", PCIE_DMA_RD_ERR_STATUS_HIGH, pcie_rkep_readl_dbi(pcie_rkep, PCIE_DMA_OFFSET + PCIE_DMA_RD_ERR_STATUS_HIGH)); + } else { + dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_RD_INT_MASK = %x\n", PCIE_DMA_RD_INT_MASK, pcie_rkep_readl_dbi(pcie_rkep, PCIE_DMA_OFFSET + PCIE_DMA_RD_INT_MASK)); + dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_RD_ENB = %x\n", PCIE_DMA_RD_ENB, pcie_rkep_readl_dbi(pcie_rkep, PCIE_DMA_OFFSET + PCIE_DMA_RD_ENB)); + dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_RD_CTRL_LO = %x\n", ctr_off + PCIE_DMA_RD_CTRL_LO, pcie_rkep_readl_dbi(pcie_rkep, ctr_off + PCIE_DMA_RD_CTRL_LO)); + dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_RD_CTRL_HI = %x\n", ctr_off + PCIE_DMA_RD_CTRL_HI, pcie_rkep_readl_dbi(pcie_rkep, ctr_off + PCIE_DMA_RD_CTRL_HI)); + dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_RD_LL_PTR_LO = %x\n", ctr_off + PCIE_DMA_RD_LL_PTR_LO, pcie_rkep_readl_dbi(pcie_rkep, ctr_off + PCIE_DMA_RD_LL_PTR_LO)); + dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_RD_LL_PTR_HI = %x\n", ctr_off + PCIE_DMA_RD_LL_PTR_HI, pcie_rkep_readl_dbi(pcie_rkep, ctr_off + PCIE_DMA_RD_LL_PTR_HI)); + dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_RD_DOORBELL = %x\n", PCIE_DMA_RD_DOORBELL, pcie_rkep_readl_dbi(pcie_rkep, PCIE_DMA_OFFSET + PCIE_DMA_RD_DOORBELL)); + dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_RD_ERR_STATUS_LOW = %x\n", PCIE_DMA_RD_ERR_STATUS_LOW, pcie_rkep_readl_dbi(pcie_rkep, PCIE_DMA_OFFSET + PCIE_DMA_RD_ERR_STATUS_LOW)); + dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_RD_ERR_STATUS_HIGH = %x\n", PCIE_DMA_RD_ERR_STATUS_HIGH, pcie_rkep_readl_dbi(pcie_rkep, PCIE_DMA_OFFSET + PCIE_DMA_RD_ERR_STATUS_HIGH)); + } } else { - dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_WR_INT_MASK = %x\n", PCIE_DMA_WR_INT_MASK, pcie_rkep_readl_dbi(pcie_rkep, PCIE_DMA_OFFSET + PCIE_DMA_WR_INT_MASK)); - dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_WR_ENB = %x\n", PCIE_DMA_WR_ENB, pcie_rkep_readl_dbi(pcie_rkep, PCIE_DMA_OFFSET + PCIE_DMA_WR_ENB)); - dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_WR_CTRL_LO = %x\n", ctr_off + PCIE_DMA_WR_CTRL_LO, pcie_rkep_readl_dbi(pcie_rkep, PCIE_DMA_OFFSET + ctr_off + PCIE_DMA_WR_CTRL_LO)); - dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_WR_CTRL_HI = %x\n", ctr_off + PCIE_DMA_WR_CTRL_HI, pcie_rkep_readl_dbi(pcie_rkep, PCIE_DMA_OFFSET + ctr_off + PCIE_DMA_WR_CTRL_HI)); - dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_WR_XFERSIZE = %x\n", ctr_off + PCIE_DMA_WR_XFERSIZE, pcie_rkep_readl_dbi(pcie_rkep, PCIE_DMA_OFFSET + ctr_off + PCIE_DMA_WR_XFERSIZE)); - dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_WR_SAR_PTR_LO = %x\n", ctr_off + PCIE_DMA_WR_SAR_PTR_LO, pcie_rkep_readl_dbi(pcie_rkep, PCIE_DMA_OFFSET + ctr_off + PCIE_DMA_WR_SAR_PTR_LO)); - dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_WR_SAR_PTR_HI = %x\n", ctr_off + PCIE_DMA_WR_SAR_PTR_HI, pcie_rkep_readl_dbi(pcie_rkep, PCIE_DMA_OFFSET + ctr_off + PCIE_DMA_WR_SAR_PTR_HI)); - dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_WR_DAR_PTR_LO = %x\n", ctr_off + PCIE_DMA_WR_DAR_PTR_LO, pcie_rkep_readl_dbi(pcie_rkep, PCIE_DMA_OFFSET + ctr_off + PCIE_DMA_WR_DAR_PTR_LO)); - dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_WR_DAR_PTR_HI = %x\n", ctr_off + PCIE_DMA_WR_DAR_PTR_HI, pcie_rkep_readl_dbi(pcie_rkep, PCIE_DMA_OFFSET + ctr_off + PCIE_DMA_WR_DAR_PTR_HI)); - dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_WR_DOORBELL = %x\n", PCIE_DMA_WR_DOORBELL, pcie_rkep_readl_dbi(pcie_rkep, PCIE_DMA_OFFSET + PCIE_DMA_WR_DOORBELL)); - dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_WR_INT_STATUS = %x\n", PCIE_DMA_WR_INT_STATUS, pcie_rkep_readl_dbi(pcie_rkep, PCIE_DMA_OFFSET + PCIE_DMA_WR_INT_STATUS)); - dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_WR_ERR_STATUS = %x\n", PCIE_DMA_WR_ERR_STATUS, pcie_rkep_readl_dbi(pcie_rkep, PCIE_DMA_OFFSET + PCIE_DMA_WR_ERR_STATUS)); + if (table->dma_mode == RK_PCIE_DMA_BLOCK) { + dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_WR_INT_MASK = %x\n", PCIE_DMA_WR_INT_MASK, pcie_rkep_readl_dbi(pcie_rkep, PCIE_DMA_OFFSET + PCIE_DMA_WR_INT_MASK)); + dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_WR_ENB = %x\n", PCIE_DMA_WR_ENB, pcie_rkep_readl_dbi(pcie_rkep, PCIE_DMA_OFFSET + PCIE_DMA_WR_ENB)); + dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_WR_CTRL_LO = %x\n", ctr_off + PCIE_DMA_WR_CTRL_LO, pcie_rkep_readl_dbi(pcie_rkep, ctr_off + PCIE_DMA_WR_CTRL_LO)); + dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_WR_CTRL_HI = %x\n", ctr_off + PCIE_DMA_WR_CTRL_HI, pcie_rkep_readl_dbi(pcie_rkep, ctr_off + PCIE_DMA_WR_CTRL_HI)); + dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_WR_XFERSIZE = %x\n", ctr_off + PCIE_DMA_WR_XFERSIZE, pcie_rkep_readl_dbi(pcie_rkep, ctr_off + PCIE_DMA_WR_XFERSIZE)); + dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_WR_SAR_PTR_LO = %x\n", ctr_off + PCIE_DMA_WR_SAR_PTR_LO, pcie_rkep_readl_dbi(pcie_rkep, ctr_off + PCIE_DMA_WR_SAR_PTR_LO)); + dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_WR_SAR_PTR_HI = %x\n", ctr_off + PCIE_DMA_WR_SAR_PTR_HI, pcie_rkep_readl_dbi(pcie_rkep, ctr_off + PCIE_DMA_WR_SAR_PTR_HI)); + dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_WR_DAR_PTR_LO = %x\n", ctr_off + PCIE_DMA_WR_DAR_PTR_LO, pcie_rkep_readl_dbi(pcie_rkep, ctr_off + PCIE_DMA_WR_DAR_PTR_LO)); + dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_WR_DAR_PTR_HI = %x\n", ctr_off + PCIE_DMA_WR_DAR_PTR_HI, pcie_rkep_readl_dbi(pcie_rkep, ctr_off + PCIE_DMA_WR_DAR_PTR_HI)); + dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_WR_DOORBELL = %x\n", PCIE_DMA_WR_DOORBELL, pcie_rkep_readl_dbi(pcie_rkep, PCIE_DMA_OFFSET + PCIE_DMA_WR_DOORBELL)); + dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_WR_INT_STATUS = %x\n", PCIE_DMA_WR_INT_STATUS, pcie_rkep_readl_dbi(pcie_rkep, PCIE_DMA_OFFSET + PCIE_DMA_WR_INT_STATUS)); + dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_WR_ERR_STATUS = %x\n", PCIE_DMA_WR_ERR_STATUS, pcie_rkep_readl_dbi(pcie_rkep, PCIE_DMA_OFFSET + PCIE_DMA_WR_ERR_STATUS)); + } else { + dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_WR_INT_MASK = %x\n", PCIE_DMA_WR_INT_MASK, pcie_rkep_readl_dbi(pcie_rkep, PCIE_DMA_OFFSET + PCIE_DMA_WR_INT_MASK)); + dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_WR_ENB = %x\n", PCIE_DMA_WR_ENB, pcie_rkep_readl_dbi(pcie_rkep, PCIE_DMA_OFFSET + PCIE_DMA_WR_ENB)); + dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_WR_CTRL_LO = %x\n", ctr_off + PCIE_DMA_WR_CTRL_LO, pcie_rkep_readl_dbi(pcie_rkep, ctr_off + PCIE_DMA_WR_CTRL_LO)); + dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_WR_CTRL_HI = %x\n", ctr_off + PCIE_DMA_WR_CTRL_HI, pcie_rkep_readl_dbi(pcie_rkep, ctr_off + PCIE_DMA_WR_CTRL_HI)); + dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_WR_LL_PTR_LO = %x\n", ctr_off + PCIE_DMA_WR_LL_PTR_LO, pcie_rkep_readl_dbi(pcie_rkep, ctr_off + PCIE_DMA_WR_LL_PTR_LO)); + dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_WR_LL_PTR_HI = %x\n", ctr_off + PCIE_DMA_WR_LL_PTR_HI, pcie_rkep_readl_dbi(pcie_rkep, ctr_off + PCIE_DMA_WR_LL_PTR_HI)); + dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_WR_DOORBELL = %x\n", PCIE_DMA_WR_DOORBELL, pcie_rkep_readl_dbi(pcie_rkep, PCIE_DMA_OFFSET + PCIE_DMA_WR_DOORBELL)); + dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_WR_INT_STATUS = %x\n", PCIE_DMA_WR_INT_STATUS, pcie_rkep_readl_dbi(pcie_rkep, PCIE_DMA_OFFSET + PCIE_DMA_WR_INT_STATUS)); + dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_WR_ERR_STATUS = %x\n", PCIE_DMA_WR_ERR_STATUS, pcie_rkep_readl_dbi(pcie_rkep, PCIE_DMA_OFFSET + PCIE_DMA_WR_ERR_STATUS)); + } } } @@ -703,24 +737,39 @@ static void pcie_rkep_start_dma_rd(struct dma_trx_obj *obj, struct dma_table *cu struct pci_dev *pdev = container_of(obj->dev, struct pci_dev, dev); struct pcie_rkep *pcie_rkep = pci_get_drvdata(pdev); - pcie_rkep_writel_dbi(pcie_rkep, PCIE_DMA_OFFSET + PCIE_DMA_RD_ENB, - cur->enb.asdword); - pcie_rkep_writel_dbi(pcie_rkep, ctr_off + PCIE_DMA_RD_CTRL_LO, - cur->ctx_reg.ctrllo.asdword); - pcie_rkep_writel_dbi(pcie_rkep, ctr_off + PCIE_DMA_RD_CTRL_HI, - cur->ctx_reg.ctrlhi.asdword); - pcie_rkep_writel_dbi(pcie_rkep, ctr_off + PCIE_DMA_RD_XFERSIZE, - cur->ctx_reg.xfersize); - pcie_rkep_writel_dbi(pcie_rkep, ctr_off + PCIE_DMA_RD_SAR_PTR_LO, - cur->ctx_reg.sarptrlo); - pcie_rkep_writel_dbi(pcie_rkep, ctr_off + PCIE_DMA_RD_SAR_PTR_HI, - cur->ctx_reg.sarptrhi); - pcie_rkep_writel_dbi(pcie_rkep, ctr_off + PCIE_DMA_RD_DAR_PTR_LO, - cur->ctx_reg.darptrlo); - pcie_rkep_writel_dbi(pcie_rkep, ctr_off + PCIE_DMA_RD_DAR_PTR_HI, - cur->ctx_reg.darptrhi); - pcie_rkep_writel_dbi(pcie_rkep, PCIE_DMA_OFFSET + PCIE_DMA_RD_DOORBELL, - cur->start.asdword); + if (cur->dma_mode == RK_PCIE_DMA_BLOCK) { + pcie_rkep_writel_dbi(pcie_rkep, PCIE_DMA_OFFSET + PCIE_DMA_RD_ENB, + cur->enb.asdword); + pcie_rkep_writel_dbi(pcie_rkep, ctr_off + PCIE_DMA_RD_CTRL_LO, + cur->ctx_reg.ctrllo.asdword); + pcie_rkep_writel_dbi(pcie_rkep, ctr_off + PCIE_DMA_RD_CTRL_HI, + cur->ctx_reg.ctrlhi.asdword); + pcie_rkep_writel_dbi(pcie_rkep, ctr_off + PCIE_DMA_RD_XFERSIZE, + cur->ctx_reg.xfersize); + pcie_rkep_writel_dbi(pcie_rkep, ctr_off + PCIE_DMA_RD_SAR_PTR_LO, + cur->ctx_reg.sarptrlo); + pcie_rkep_writel_dbi(pcie_rkep, ctr_off + PCIE_DMA_RD_SAR_PTR_HI, + cur->ctx_reg.sarptrhi); + pcie_rkep_writel_dbi(pcie_rkep, ctr_off + PCIE_DMA_RD_DAR_PTR_LO, + cur->ctx_reg.darptrlo); + pcie_rkep_writel_dbi(pcie_rkep, ctr_off + PCIE_DMA_RD_DAR_PTR_HI, + cur->ctx_reg.darptrhi); + pcie_rkep_writel_dbi(pcie_rkep, PCIE_DMA_OFFSET + PCIE_DMA_RD_DOORBELL, + cur->start.asdword); + } else { + pcie_rkep_writel_dbi(pcie_rkep, PCIE_DMA_OFFSET + PCIE_DMA_RD_ENB, + cur->enb.asdword); + pcie_rkep_writel_dbi(pcie_rkep, ctr_off + PCIE_DMA_RD_CTRL_LO, + cur->ctx_reg.ctrllo.asdword); + pcie_rkep_writel_dbi(pcie_rkep, ctr_off + PCIE_DMA_RD_CTRL_HI, + cur->ctx_reg.ctrlhi.asdword); + pcie_rkep_writel_dbi(pcie_rkep, ctr_off + PCIE_DMA_RD_LL_PTR_LO, + lower_32_bits(cur->phys_descs)); + pcie_rkep_writel_dbi(pcie_rkep, ctr_off + PCIE_DMA_RD_LL_PTR_HI, + upper_32_bits(cur->phys_descs)); + pcie_rkep_writel_dbi(pcie_rkep, PCIE_DMA_OFFSET + PCIE_DMA_RD_DOORBELL, + cur->start.asdword); + } // pcie_rkep_dma_debug(obj, cur); } @@ -729,26 +778,41 @@ static void pcie_rkep_start_dma_wr(struct dma_trx_obj *obj, struct dma_table *cu struct pci_dev *pdev = container_of(obj->dev, struct pci_dev, dev); struct pcie_rkep *pcie_rkep = pci_get_drvdata(pdev); - pcie_rkep_writel_dbi(pcie_rkep, PCIE_DMA_OFFSET + PCIE_DMA_WR_ENB, - cur->enb.asdword); - pcie_rkep_writel_dbi(pcie_rkep, ctr_off + PCIE_DMA_WR_CTRL_LO, - cur->ctx_reg.ctrllo.asdword); - pcie_rkep_writel_dbi(pcie_rkep, ctr_off + PCIE_DMA_WR_CTRL_HI, - cur->ctx_reg.ctrlhi.asdword); - pcie_rkep_writel_dbi(pcie_rkep, ctr_off + PCIE_DMA_WR_XFERSIZE, - cur->ctx_reg.xfersize); - pcie_rkep_writel_dbi(pcie_rkep, ctr_off + PCIE_DMA_WR_SAR_PTR_LO, - cur->ctx_reg.sarptrlo); - pcie_rkep_writel_dbi(pcie_rkep, ctr_off + PCIE_DMA_WR_SAR_PTR_HI, - cur->ctx_reg.sarptrhi); - pcie_rkep_writel_dbi(pcie_rkep, ctr_off + PCIE_DMA_WR_DAR_PTR_LO, - cur->ctx_reg.darptrlo); - pcie_rkep_writel_dbi(pcie_rkep, ctr_off + PCIE_DMA_WR_DAR_PTR_HI, - cur->ctx_reg.darptrhi); - pcie_rkep_writel_dbi(pcie_rkep, ctr_off + PCIE_DMA_WR_WEILO, - cur->weilo.asdword); - pcie_rkep_writel_dbi(pcie_rkep, PCIE_DMA_OFFSET + PCIE_DMA_WR_DOORBELL, - cur->start.asdword); + if (cur->dma_mode == RK_PCIE_DMA_BLOCK) { + pcie_rkep_writel_dbi(pcie_rkep, PCIE_DMA_OFFSET + PCIE_DMA_WR_ENB, + cur->enb.asdword); + pcie_rkep_writel_dbi(pcie_rkep, ctr_off + PCIE_DMA_WR_CTRL_LO, + cur->ctx_reg.ctrllo.asdword); + pcie_rkep_writel_dbi(pcie_rkep, ctr_off + PCIE_DMA_WR_CTRL_HI, + cur->ctx_reg.ctrlhi.asdword); + pcie_rkep_writel_dbi(pcie_rkep, ctr_off + PCIE_DMA_WR_XFERSIZE, + cur->ctx_reg.xfersize); + pcie_rkep_writel_dbi(pcie_rkep, ctr_off + PCIE_DMA_WR_SAR_PTR_LO, + cur->ctx_reg.sarptrlo); + pcie_rkep_writel_dbi(pcie_rkep, ctr_off + PCIE_DMA_WR_SAR_PTR_HI, + cur->ctx_reg.sarptrhi); + pcie_rkep_writel_dbi(pcie_rkep, ctr_off + PCIE_DMA_WR_DAR_PTR_LO, + cur->ctx_reg.darptrlo); + pcie_rkep_writel_dbi(pcie_rkep, ctr_off + PCIE_DMA_WR_DAR_PTR_HI, + cur->ctx_reg.darptrhi); + pcie_rkep_writel_dbi(pcie_rkep, ctr_off + PCIE_DMA_WR_WEILO, + cur->weilo.asdword); + pcie_rkep_writel_dbi(pcie_rkep, PCIE_DMA_OFFSET + PCIE_DMA_WR_DOORBELL, + cur->start.asdword); + } else { + pcie_rkep_writel_dbi(pcie_rkep, PCIE_DMA_OFFSET + PCIE_DMA_WR_ENB, + cur->enb.asdword); + pcie_rkep_writel_dbi(pcie_rkep, ctr_off + PCIE_DMA_WR_CTRL_LO, + cur->ctx_reg.ctrllo.asdword); + pcie_rkep_writel_dbi(pcie_rkep, ctr_off + PCIE_DMA_WR_CTRL_HI, + cur->ctx_reg.ctrlhi.asdword); + pcie_rkep_writel_dbi(pcie_rkep, ctr_off + PCIE_DMA_WR_LL_PTR_LO, + lower_32_bits(cur->phys_descs)); + pcie_rkep_writel_dbi(pcie_rkep, ctr_off + PCIE_DMA_WR_LL_PTR_HI, + upper_32_bits(cur->phys_descs)); + pcie_rkep_writel_dbi(pcie_rkep, PCIE_DMA_OFFSET + PCIE_DMA_WR_DOORBELL, + cur->start.asdword); + } // pcie_rkep_dma_debug(obj, cur); } @@ -767,26 +831,36 @@ static void pcie_rkep_start_dma_dwc(struct dma_trx_obj *obj, struct dma_table *t static void pcie_rkep_config_dma_dwc(struct dma_table *table) { - table->enb.enb = 0x1; - table->ctx_reg.ctrllo.lie = 0x1; - table->ctx_reg.ctrllo.rie = 0x0; - table->ctx_reg.ctrllo.td = 0x1; - table->ctx_reg.ctrlhi.asdword = 0x0; - table->ctx_reg.xfersize = table->buf_size; - if (table->dir == DMA_FROM_BUS) { - table->ctx_reg.sarptrlo = (u32)(table->bus & 0xffffffff); - table->ctx_reg.sarptrhi = (u32)(table->bus >> 32); - table->ctx_reg.darptrlo = (u32)(table->local & 0xffffffff); - table->ctx_reg.darptrhi = (u32)(table->local >> 32); - } else if (table->dir == DMA_TO_BUS) { - table->ctx_reg.sarptrlo = (u32)(table->local & 0xffffffff); - table->ctx_reg.sarptrhi = (u32)(table->local >> 32); - table->ctx_reg.darptrlo = (u32)(table->bus & 0xffffffff); - table->ctx_reg.darptrhi = (u32)(table->bus >> 32); + if (table->dma_mode == RK_PCIE_DMA_BLOCK) { + table->enb.enb = 0x1; + table->ctx_reg.ctrllo.lie = 0x1; + table->ctx_reg.ctrllo.rie = 0x0; + table->ctx_reg.ctrllo.td = 0x1; + table->ctx_reg.ctrlhi.asdword = 0x0; + table->ctx_reg.xfersize = table->buf_size; + if (table->dir == DMA_FROM_BUS) { + table->ctx_reg.sarptrlo = (u32)(table->bus & 0xffffffff); + table->ctx_reg.sarptrhi = (u32)(table->bus >> 32); + table->ctx_reg.darptrlo = (u32)(table->local & 0xffffffff); + table->ctx_reg.darptrhi = (u32)(table->local >> 32); + } else if (table->dir == DMA_TO_BUS) { + table->ctx_reg.sarptrlo = (u32)(table->local & 0xffffffff); + table->ctx_reg.sarptrhi = (u32)(table->local >> 32); + table->ctx_reg.darptrlo = (u32)(table->bus & 0xffffffff); + table->ctx_reg.darptrhi = (u32)(table->bus >> 32); + } + table->weilo.weight0 = 0x0; + table->start.stop = 0x0; + table->start.chnl = table->chn; + } else { + table->enb.enb = 0x1; + table->ctx_reg.ctrllo.lie = 0x1; + table->ctx_reg.ctrllo.rie = 0x0; + table->ctx_reg.ctrllo.ccs = 1; + table->ctx_reg.ctrllo.llen = 1; + table->ctx_reg.ctrlhi.asdword = 0x0; + table->start.chnl = table->chn; } - table->weilo.weight0 = 0x0; - table->start.stop = 0x0; - table->start.chnl = table->chn; } static int pcie_rkep_get_dma_status(struct dma_trx_obj *obj, u8 chn, enum dma_dir dir) @@ -812,7 +886,7 @@ static int pcie_rkep_get_dma_status(struct dma_trx_obj *obj, u8 chn, enum dma_di } if (status.abortsta & BIT(chn)) { - dev_err(&pdev->dev, "%s, write abort\n", __func__); + dev_err(&pdev->dev, "%s, write abort %x\n", __func__, status.asdword); clears.abortclr = BIT(chn); pcie_rkep_writel_dbi(pcie_rkep, PCIE_DMA_OFFSET + PCIE_DMA_WR_INT_CLEAR, clears.asdword); @@ -1130,6 +1204,7 @@ static int pcie_rkep_probe(struct pci_dev *pdev, const struct pci_device_id *id) } if (pcie_rkep->dma_obj) { + dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); pcie_rkep->dma_obj->start_dma_func = pcie_rkep_start_dma_dwc; pcie_rkep->dma_obj->config_dma_func = pcie_rkep_config_dma_dwc; pcie_rkep->dma_obj->get_dma_status = pcie_rkep_get_dma_status; @@ -1137,6 +1212,10 @@ static int pcie_rkep_probe(struct pci_dev *pdev, const struct pci_device_id *id) if (!dmatest_irq) { pcie_rkep_writel_dbi(pcie_rkep, PCIE_DMA_OFFSET + PCIE_DMA_WR_INT_MASK, 0xffffffff); pcie_rkep_writel_dbi(pcie_rkep, PCIE_DMA_OFFSET + PCIE_DMA_RD_INT_MASK, 0xffffffff); + + /* Enable linked list err en */ + pcie_rkep_writel_dbi(pcie_rkep, PCIE_DMA_OFFSET + PCIE_DMA_WR_LL_ERR_EN, 0xffffffff); + pcie_rkep_writel_dbi(pcie_rkep, PCIE_DMA_OFFSET + PCIE_DMA_RD_LL_ERR_EN, 0xffffffff); } } diff --git a/drivers/pci/controller/dwc/pcie-dw-dmatest.c b/drivers/pci/controller/dwc/pcie-dw-dmatest.c index f9c445a39e58..049256e61433 100644 --- a/drivers/pci/controller/dwc/pcie-dw-dmatest.c +++ b/drivers/pci/controller/dwc/pcie-dw-dmatest.c @@ -46,13 +46,14 @@ static unsigned int test_dev; module_param(test_dev, uint, 0644); MODULE_PARM_DESC(test_dev, "Choose dma_obj device,(default 0)"); -static bool is_rc = true; -module_param_named(is_rc, is_rc, bool, 0644); -MODULE_PARM_DESC(is_rc, "Test port is rc(default true)"); +static bool is_wired; +module_param_named(is_wired, is_wired, bool, 0644); +MODULE_PARM_DESC(is_wired, "Transfer is triggered by wired DMA(default false)"); #define PCIE_DW_MISC_DMATEST_DEV_MAX 8 #define PCIE_DMA_CHANEL_MAX_NUM 2 +#define PCIE_DMA_LL_MAX_NUM 1024 /* Unrestricted, tentative value */ struct pcie_dw_dmatest_dev { struct dma_trx_obj *obj; @@ -113,11 +114,11 @@ static int rk_pcie_dma_wait_for_finished(struct dma_trx_obj *obj, struct dma_tab return ret; } -static int rk_pcie_ep_dma_frombus(struct pcie_dw_dmatest_dev *dmatest_dev, u32 chn, - u64 local_paddr, u64 bus_paddr, u32 size) +static int rk_pcie_local_dma_frombus_block(struct dma_trx_obj *obj, u32 chn, + u64 local_paddr, u64 bus_paddr, u32 size) { + struct pcie_dw_dmatest_dev *dmatest_dev = (struct pcie_dw_dmatest_dev *)obj->priv; struct dma_table *table; - struct dma_trx_obj *obj = dmatest_dev->obj; int ret; if (chn >= PCIE_DMA_CHANEL_MAX_NUM) @@ -154,11 +155,11 @@ static int rk_pcie_ep_dma_frombus(struct pcie_dw_dmatest_dev *dmatest_dev, u32 c return ret; } -static int rk_pcie_ep_dma_tobus(struct pcie_dw_dmatest_dev *dmatest_dev, u32 chn, - u64 bus_paddr, u64 local_paddr, u32 size) +int rk_pcie_local_dma_tobus_block(struct dma_trx_obj *obj, u32 chn, + u64 bus_paddr, u64 local_paddr, u32 size) { + struct pcie_dw_dmatest_dev *dmatest_dev = (struct pcie_dw_dmatest_dev *)obj->priv; struct dma_table *table; - struct dma_trx_obj *obj = dmatest_dev->obj; int ret; if (chn >= PCIE_DMA_CHANEL_MAX_NUM) @@ -195,18 +196,6 @@ static int rk_pcie_ep_dma_tobus(struct pcie_dw_dmatest_dev *dmatest_dev, u32 chn return ret; } -static int rk_pcie_rc_dma_frombus(struct pcie_dw_dmatest_dev *dmatest_dev, u32 chn, - u64 local_paddr, u64 bus_paddr, u32 size) -{ - return rk_pcie_ep_dma_tobus(dmatest_dev, chn, local_paddr, bus_paddr, size); -} - -static int rk_pcie_rc_dma_tobus(struct pcie_dw_dmatest_dev *dmatest_dev, u32 chn, - u64 bus_paddr, u64 local_paddr, u32 size) -{ - return rk_pcie_ep_dma_frombus(dmatest_dev, chn, bus_paddr, local_paddr, size); -} - static int rk_pcie_dma_interrupt_handler_call_back(struct dma_trx_obj *obj, u32 chn, enum dma_dir dir) { struct pcie_dw_dmatest_dev *dmatest_dev = (struct pcie_dw_dmatest_dev *)obj->priv; @@ -257,20 +246,16 @@ void pcie_dw_dmatest_unregister(struct dma_trx_obj *obj) cur_dmatest_dev = 0; } -int pcie_dw_rc_dma_frombus(struct dma_trx_obj *obj, u32 chn, +int pcie_dw_wired_dma_frombus_block(struct dma_trx_obj *obj, u32 chn, u64 local_paddr, u64 bus_paddr, u32 size) { - struct pcie_dw_dmatest_dev *dmatest_dev = obj->priv; - - return rk_pcie_ep_dma_tobus(dmatest_dev, chn, local_paddr, bus_paddr, size); + return rk_pcie_local_dma_tobus_block(obj, chn, local_paddr, bus_paddr, size); } -int pcie_dw_rc_dma_tobus(struct dma_trx_obj *obj, u32 chn, +int pcie_dw_wired_dma_tobus_block(struct dma_trx_obj *obj, u32 chn, u64 bus_paddr, u64 local_paddr, u32 size) { - struct pcie_dw_dmatest_dev *dmatest_dev = obj->priv; - - return rk_pcie_ep_dma_frombus(dmatest_dev, chn, bus_paddr, local_paddr, size); + return rk_pcie_local_dma_frombus_block(obj, chn, bus_paddr, local_paddr, size); } static int dma_test(struct pcie_dw_dmatest_dev *dmatest_dev, u32 chn, @@ -295,19 +280,19 @@ static int dma_test(struct pcie_dw_dmatest_dev *dmatest_dev, u32 chn, start_time = ktime_get(); for (i = 0; i < loop; i++) { if (rd_en) { - if (is_rc) - rk_pcie_rc_dma_frombus(dmatest_dev, chn, local_paddr, bus_paddr, size); + if (is_wired) + pcie_dw_wired_dma_frombus_block(dmatest_dev->obj, chn, local_paddr, bus_paddr, size); else - rk_pcie_ep_dma_frombus(dmatest_dev, chn, local_paddr, bus_paddr, size); + rk_pcie_local_dma_frombus_block(dmatest_dev->obj, chn, local_paddr, bus_paddr, size); dma_sync_single_for_cpu(obj->dev, local_paddr, size, DMA_FROM_DEVICE); } if (wr_en) { dma_sync_single_for_device(obj->dev, local_paddr, size, DMA_TO_DEVICE); - if (is_rc) - rk_pcie_rc_dma_tobus(dmatest_dev, chn, bus_paddr, local_paddr, size); + if (is_wired) + pcie_dw_wired_dma_tobus_block(dmatest_dev->obj, chn, bus_paddr, local_paddr, size); else - rk_pcie_ep_dma_tobus(dmatest_dev, chn, bus_paddr, local_paddr, size); + rk_pcie_local_dma_tobus_block(dmatest_dev->obj, chn, bus_paddr, local_paddr, size); } } end_time = ktime_get(); @@ -363,19 +348,17 @@ static int pcie_dw_dmatest(const char *val, const struct kernel_param *kp) if (!s_dmatest_dev[0].obj) { pr_err("dmatest dev not exits\n"); - kfree(tmp); return -1; } strncpy(tmp, val, 8); - if (!strncmp(tmp, "run", 3)) { + if (!strncmp(tmp, "run", 3)) dma_run(); - } else if (!strncmp(tmp, "show", 4)) { + else if (!strncmp(tmp, "show", 4)) pcie_dw_dmatest_show(); - } else { + else pr_info("input error\n"); - } return 0; } diff --git a/drivers/pci/controller/dwc/pcie-dw-dmatest.h b/drivers/pci/controller/dwc/pcie-dw-dmatest.h index 68fa1b1efc60..07aa27c389ab 100644 --- a/drivers/pci/controller/dwc/pcie-dw-dmatest.h +++ b/drivers/pci/controller/dwc/pcie-dw-dmatest.h @@ -11,8 +11,8 @@ struct device; #if IS_ENABLED(CONFIG_PCIE_DW_DMATEST) struct dma_trx_obj *pcie_dw_dmatest_register(struct device *dev, bool irq_en); void pcie_dw_dmatest_unregister(struct dma_trx_obj *obj); -int pcie_dw_rc_dma_frombus(struct dma_trx_obj *obj, u32 chn, u64 local_paddr, u64 bus_paddr, u32 size); -int pcie_dw_rc_dma_tobus(struct dma_trx_obj *obj, u32 chn, u64 bus_paddr, u64 local_paddr, u32 size); +int pcie_dw_wired_dma_frombus_block(struct dma_trx_obj *obj, u32 chn, u64 local_paddr, u64 bus_paddr, u32 size); +int pcie_dw_wired_dma_tobus_block(struct dma_trx_obj *obj, u32 chn, u64 bus_paddr, u64 local_paddr, u32 size); #else static inline struct dma_trx_obj *pcie_dw_dmatest_register(struct device *dev, bool irq_en) { @@ -21,12 +21,12 @@ static inline struct dma_trx_obj *pcie_dw_dmatest_register(struct device *dev, b static inline void pcie_dw_dmatest_unregister(struct dma_trx_obj *obj) { } -static inline int pcie_dw_rc_dma_frombus(struct dma_trx_obj *obj, u32 chn, u64 local_paddr, u64 bus_paddr, u32 size) +static inline int pcie_dw_wired_dma_frombus_block(struct dma_trx_obj *obj, u32 chn, u64 local_paddr, u64 bus_paddr, u32 size) { return -1; } -static inline int pcie_dw_rc_dma_tobus(struct dma_trx_obj *obj, u32 chn, u64 bus_paddr, u64 local_paddr, u32 size) +static inline int pcie_dw_wired_dma_tobus_block(struct dma_trx_obj *obj, u32 chn, u64 bus_paddr, u64 local_paddr, u32 size) { return -1; } diff --git a/drivers/pci/controller/rockchip-pcie-dma.h b/drivers/pci/controller/rockchip-pcie-dma.h index 4a184fcaf122..f06222e314a8 100644 --- a/drivers/pci/controller/rockchip-pcie-dma.h +++ b/drivers/pci/controller/rockchip-pcie-dma.h @@ -20,11 +20,31 @@ #define PCIE_DMA_DATA_FREE_ACK_TABLE_OFFSET 0x10 #define PCIE_DMA_DATA_READ_REMOTE_TABLE_OFFSET 0x18 +/* DMA linked list register filed */ +#define PCIE_DWC_DMA_CB BIT(0) +#define PCIE_DWC_DMA_TCB BIT(1) +#define PCIE_DWC_DMA_LLP BIT(2) +#define PCIE_DWC_DMA_LIE BIT(3) +#define PCIE_DWC_DMA_RIE BIT(4) +#define PCIE_DWC_DMA_CCS BIT(8) +#define PCIE_DWC_DMA_LLE BIT(9) + +#define SET_LL_32(ll, value) \ + writel(value, ll) + +#define SET_LL_64(ll, value) \ + writeq(value, ll) + enum dma_dir { DMA_FROM_BUS, DMA_TO_BUS, }; +enum dma_mode { + RK_PCIE_DMA_BLOCK, + RK_PCIE_DMA_LL, +}; + /** * The Channel Control Register for read and write. */ @@ -155,8 +175,40 @@ struct dma_table { phys_addr_t local; phys_addr_t bus; size_t buf_size; + u32 dma_mode; }; +struct rk_edma_lli { + u32 control; + u32 transfer_size; + union { + u64 reg; + struct { + u32 lsb; + u32 msb; + }; + } sar; + union { + u64 reg; + struct { + u32 lsb; + u32 msb; + }; + } dar; +} __packed; + +struct rk_edma_llp { + u32 control; + u32 reserved; + union { + u64 reg; + struct { + u32 lsb; + u32 msb; + }; + } llp; +} __packed; + struct dma_trx_obj { struct device *dev; int loop_count; diff --git a/drivers/pwm/pwm-rockchip.h b/drivers/pwm/pwm-rockchip-irq-callbacks.h similarity index 86% rename from drivers/pwm/pwm-rockchip.h rename to drivers/pwm/pwm-rockchip-irq-callbacks.h index 1995b9d2420e..c157fef5d6ed 100644 --- a/drivers/pwm/pwm-rockchip.h +++ b/drivers/pwm/pwm-rockchip-irq-callbacks.h @@ -3,8 +3,8 @@ * Copyright (c) 2023 Rockchip Electronics Co., Ltd. */ -#ifndef _PWM_ROCKCHIP_H_ -#define _PWM_ROCKCHIP_H_ +#ifndef _PWM_ROCKCHIP_IRQ_CALLBACKS_H_ +#define _PWM_ROCKCHIP_IRQ_CALLBACKS_H_ #include diff --git a/drivers/pwm/pwm-rockchip.c b/drivers/pwm/pwm-rockchip.c index 1a405b5aabc4..0071ce43b38f 100644 --- a/drivers/pwm/pwm-rockchip.c +++ b/drivers/pwm/pwm-rockchip.c @@ -19,7 +19,7 @@ #include #include #include -#include "pwm-rockchip.h" +#include "pwm-rockchip-irq-callbacks.h" #define PWM_MAX_CHANNEL_NUM 4 diff --git a/drivers/video/rockchip/mpp/mpp_common.h b/drivers/video/rockchip/mpp/mpp_common.h index 9393396d669d..8b75a845ee2b 100644 --- a/drivers/video/rockchip/mpp/mpp_common.h +++ b/drivers/video/rockchip/mpp/mpp_common.h @@ -490,7 +490,6 @@ struct mpp_taskqueue { u32 core_id_max; u32 core_count; unsigned long dev_active_flags; - u32 iommu_fault; }; struct mpp_reset_group { diff --git a/drivers/video/rockchip/mpp/mpp_rkvdec2.c b/drivers/video/rockchip/mpp/mpp_rkvdec2.c index f45680d62f89..305996c676fe 100644 --- a/drivers/video/rockchip/mpp/mpp_rkvdec2.c +++ b/drivers/video/rockchip/mpp/mpp_rkvdec2.c @@ -1531,6 +1531,7 @@ static int rkvdec2_core_probe(struct platform_device *pdev) if (dec->ccu->ccu_mode == RKVDEC2_CCU_TASK_SOFT) { mpp->dev_ops->task_worker = rkvdec2_soft_ccu_worker; irq_proc = rkvdec2_soft_ccu_irq; + mpp->fault_handler = rkvdec2_soft_ccu_iommu_fault_handle; } else if (dec->ccu->ccu_mode == RKVDEC2_CCU_TASK_HARD) { if (mpp->core_id == 0 && mpp->task_capacity > 1) { dec->link_dec->task_capacity = mpp->task_capacity; @@ -1540,8 +1541,8 @@ static int rkvdec2_core_probe(struct platform_device *pdev) } mpp->dev_ops->task_worker = rkvdec2_hard_ccu_worker; irq_proc = rkvdec2_hard_ccu_irq; + mpp->fault_handler = rkvdec2_hard_ccu_iommu_fault_handle; } - mpp->fault_handler = rkvdec2_ccu_iommu_fault_handle; kthread_init_work(&mpp->work, mpp->dev_ops->task_worker); /* get irq request */ diff --git a/drivers/video/rockchip/mpp/mpp_rkvdec2.h b/drivers/video/rockchip/mpp/mpp_rkvdec2.h index aa56015873b7..3a1ac035abb0 100644 --- a/drivers/video/rockchip/mpp/mpp_rkvdec2.h +++ b/drivers/video/rockchip/mpp/mpp_rkvdec2.h @@ -219,12 +219,7 @@ struct rkvdec2_dev { u32 task_index; /* mmu info */ void __iomem *mmu_base; - u32 fault_iova; u32 mmu_fault; - u32 mmu0_st; - u32 mmu1_st; - u32 mmu0_pta; - u32 mmu1_pta; }; int mpp_set_rcbbuf(struct mpp_dev *mpp, struct mpp_session *session, diff --git a/drivers/video/rockchip/mpp/mpp_rkvdec2_link.c b/drivers/video/rockchip/mpp/mpp_rkvdec2_link.c index 0d87eb476f40..7c5a58df1865 100644 --- a/drivers/video/rockchip/mpp/mpp_rkvdec2_link.c +++ b/drivers/video/rockchip/mpp/mpp_rkvdec2_link.c @@ -1555,7 +1555,7 @@ static int rkvdec2_soft_ccu_reset(struct mpp_taskqueue *queue, if (mpp->disable) continue; - dev_info(mpp->dev, "resetting...\n"); + dev_info(mpp->dev, "resetting for err %#x\n", mpp->irq_status); disable_hardirq(mpp->irq); /* foce idle, disconnect core and ccu */ @@ -1618,61 +1618,104 @@ void *rkvdec2_ccu_alloc_task(struct mpp_session *session, return &task->mpp_task; } -static void rkvdec2_ccu_check_pagefault_info(struct mpp_dev *mpp) +static struct mpp_dev *rkvdec2_ccu_dev_match_by_iommu(struct mpp_taskqueue *queue, + struct device *iommu_dev) { - u32 i = 0; + struct mpp_dev *mpp = NULL; + struct rkvdec2_dev *dec = NULL; + u32 mmu[2] = {0, 0x40}; + u32 i; - for (i = 0; i < mpp->queue->core_count; i++) { - struct mpp_dev *core = mpp->queue->cores[i]; - struct rkvdec2_dev *dec = to_rkvdec2_dev(core); - void __iomem *mmu_base = dec->mmu_base; - u32 mmu0_st; - u32 mmu1_st; - u32 mmu0_pta; - u32 mmu1_pta; + for (i = 0; i < queue->core_count; i++) { + struct mpp_dev *core = queue->cores[i]; - if (!mmu_base) - return; - - #define FAULT_STATUS 0x7e2 - rkvdec2_ccu_power_on(mpp->queue, dec->ccu); - - mmu0_st = readl(mmu_base + 0x4); - mmu1_st = readl(mmu_base + 0x44); - mmu0_pta = readl(mmu_base + 0xc); - mmu1_pta = readl(mmu_base + 0x4c); - - dec->mmu0_st = mmu0_st; - dec->mmu1_st = mmu1_st; - dec->mmu0_pta = mmu0_pta; - dec->mmu1_pta = mmu1_pta; - - pr_err("core %d mmu0 %08x %08x mm1 %08x %08x\n", - core->core_id, mmu0_st, mmu0_pta, mmu1_st, mmu1_pta); - if ((mmu0_st & FAULT_STATUS) || (mmu1_st & FAULT_STATUS) || - mmu0_pta || mmu1_pta) { - dec->fault_iova = readl(dec->link_dec->reg_base + 0x4); - dec->mmu_fault = 1; - pr_err("core %d fault iova %08x\n", core->core_id, dec->fault_iova); - rockchip_iommu_mask_irq(core->dev); - } else { - dec->mmu_fault = 0; - dec->fault_iova = 0; + if (&core->iommu_info->pdev->dev == iommu_dev) { + mpp = core; + dec = to_rkvdec2_dev(mpp); } } + + if (!dec || !dec->mmu_base) + goto out; + + /* there are two iommus */ + for (i = 0; i < 2; i++) { + u32 status = readl(dec->mmu_base + mmu[i] + 0x4); + u32 iova = readl(dec->mmu_base + mmu[i] + 0xc); + u32 is_write = (status & BIT(5)) ? 1 : 0; + + if (status && iova) + dev_err(iommu_dev, "core %d pagfault at iova %#08x type %s status %#x\n", + mpp->core_id, iova, is_write ? "write" : "read", status); + } +out: + return mpp; } -int rkvdec2_ccu_iommu_fault_handle(struct iommu_domain *iommu, - struct device *iommu_dev, - unsigned long iova, int status, void *arg) +int rkvdec2_soft_ccu_iommu_fault_handle(struct iommu_domain *iommu, + struct device *iommu_dev, + unsigned long iova, int status, void *arg) { struct mpp_dev *mpp = (struct mpp_dev *)arg; + struct mpp_taskqueue *queue = mpp->queue; + struct mpp_task *mpp_task; mpp_debug_enter(); - rkvdec2_ccu_check_pagefault_info(mpp); + mpp = rkvdec2_ccu_dev_match_by_iommu(queue, iommu_dev); + if (!mpp) { + dev_err(iommu_dev, "iommu fault, but no dev match\n"); + return 0; + } + mpp_task = mpp->cur_task; + if (mpp_task) + mpp_task_dump_mem_region(mpp, mpp_task); - mpp->queue->iommu_fault = 1; + /* + * Mask iommu irq, in order for iommu not repeatedly trigger pagefault. + * Until the pagefault task finish by hw timeout. + */ + rockchip_iommu_mask_irq(mpp->dev); + atomic_inc(&mpp->queue->reset_request); + kthread_queue_work(&mpp->queue->worker, &mpp->work); + + mpp_debug_leave(); + + return 0; +} + +int rkvdec2_hard_ccu_iommu_fault_handle(struct iommu_domain *iommu, + struct device *iommu_dev, + unsigned long iova, int status, void *arg) +{ + struct mpp_dev *mpp = (struct mpp_dev *)arg; + struct mpp_taskqueue *queue = mpp->queue; + struct mpp_task *mpp_task = NULL, *n; + struct rkvdec2_dev *dec; + u32 err_task_iova; + + mpp_debug_enter(); + + mpp = rkvdec2_ccu_dev_match_by_iommu(queue, iommu_dev); + if (!mpp) { + dev_err(iommu_dev, "iommu fault, but no dev match\n"); + return 0; + } + + dec = to_rkvdec2_dev(mpp); + err_task_iova = readl(dec->link_dec->reg_base + 0x4); + dev_err(mpp->dev, "core %d err task iova %#08x\n", mpp->core_id, err_task_iova); + rockchip_iommu_mask_irq(mpp->dev); + + list_for_each_entry_safe(mpp_task, n, &queue->running_list, queue_link) { + struct rkvdec2_task *task = to_rkvdec2_task(mpp_task); + + if ((u32)task->table->iova == err_task_iova) { + mpp_task_dump_mem_region(mpp, mpp_task); + set_bit(TASK_STATE_ABORT, &mpp_task->state); + break; + } + } atomic_inc(&mpp->queue->reset_request); kthread_queue_work(&mpp->queue->worker, &mpp->work); @@ -2041,7 +2084,7 @@ static int rkvdec2_hard_ccu_dequeue(struct mpp_taskqueue *queue, ccu_decoded_num = readl(ccu->reg_base + RKVDEC_CCU_DEC_NUM_BASE); ccu_total_dec_num = readl(ccu->reg_base + RKVDEC_CCU_TOTAL_NUM_BASE); mpp_debug(DEBUG_IRQ_CHECK, - "session %d task %d w:h[%d %d] err %d irq_status %08x timeout=%u abort=%u iova %08x next %08x ccu[%d %d]\n", + "session %d task %d w:h[%d %d] err %d irq_status %#x timeout=%u abort=%u iova %08x next %08x ccu[%d %d]\n", mpp_task->session->index, mpp_task->task_index, task->width, task->height, !!(irq_status & RKVDEC_INT_ERROR_MASK), irq_status, timeout_flag, abort_flag, (u32)task->table->iova, @@ -2055,7 +2098,7 @@ static int rkvdec2_hard_ccu_dequeue(struct mpp_taskqueue *queue, cancel_delayed_work(&mpp_task->timeout_work); mpp_task->hw_cycles = tb_reg[hw->tb_reg_cycle]; mpp_time_diff_with_hw_time(mpp_task, dec->cycle_clk->real_rate_hz); - task->irq_status = irq_status; + task->irq_status = irq_status ? irq_status : RKVDEC_ERROR_STA; if (irq_status) rkvdec2_hard_ccu_finish(hw, task); @@ -2081,7 +2124,7 @@ static int rkvdec2_hard_ccu_dequeue(struct mpp_taskqueue *queue, /* Wake up the GET thread */ wake_up(&mpp_task->wait); if ((irq_status & RKVDEC_INT_ERROR_MASK) || timeout_flag) { - pr_err("session %d task %d irq_status %08x timeout=%u abort=%u\n", + pr_err("session %d task %d irq_status %#x timeout=%u abort=%u\n", mpp_task->session->index, mpp_task->task_index, irq_status, timeout_flag, abort_flag); atomic_inc(&queue->reset_request); @@ -2339,51 +2382,6 @@ done: return 0; } -static void rkvdec2_hard_ccu_handle_pagefault_task(struct rkvdec2_dev *dec, - struct mpp_task *mpp_task) -{ - struct rkvdec2_task *task = to_rkvdec2_task(mpp_task); - - mpp_dbg_ccu("session %d task %d w:h[%d %d] pagefault mmu0[%08x %08x] mmu1[%08x %08x] fault_iova %08x\n", - mpp_task->session->index, mpp_task->task_index, - task->width, task->height, dec->mmu0_st, dec->mmu0_pta, - dec->mmu1_st, dec->mmu1_pta, dec->fault_iova); - - set_bit(TASK_STATE_HANDLE, &mpp_task->state); - task->irq_status |= BIT(4); - cancel_delayed_work(&mpp_task->timeout_work); - rkvdec2_hard_ccu_finish(dec->link_dec->info, task); - set_bit(TASK_STATE_FINISH, &mpp_task->state); - set_bit(TASK_STATE_DONE, &mpp_task->state); - list_move_tail(&task->table->link, &dec->ccu->unused_list); - list_del_init(&mpp_task->queue_link); - /* Wake up the GET thread */ - wake_up(&mpp_task->wait); - kref_put(&mpp_task->ref, mpp_free_task); - dec->mmu_fault = 0; - dec->fault_iova = 0; -} - -static void rkvdec2_hard_ccu_pagefault_proc(struct mpp_taskqueue *queue) -{ - struct mpp_task *loop = NULL, *n; - - list_for_each_entry_safe(loop, n, &queue->running_list, queue_link) { - struct rkvdec2_task *task = to_rkvdec2_task(loop); - u32 iova = (u32)task->table->iova; - u32 i; - - for (i = 0; i < queue->core_count; i++) { - struct mpp_dev *core = queue->cores[i]; - struct rkvdec2_dev *dec = to_rkvdec2_dev(core); - - if (!dec->mmu_fault || dec->fault_iova != iova) - continue; - rkvdec2_hard_ccu_handle_pagefault_task(dec, loop); - } - } -} - static void rkvdec2_hard_ccu_resend_tasks(struct mpp_dev *mpp, struct mpp_taskqueue *queue) { struct rkvdec2_task *task_pre = NULL; @@ -2463,11 +2461,6 @@ void rkvdec2_hard_ccu_worker(struct kthread_work *work_s) /* reset process */ rkvdec2_hard_ccu_reset(queue, dec->ccu); atomic_set(&queue->reset_request, 0); - /* if iommu pagefault, find the fault task and drop it */ - if (queue->iommu_fault) { - rkvdec2_hard_ccu_pagefault_proc(queue); - queue->iommu_fault = 0; - } /* relink running task iova in list, and resend them to hw */ if (!list_empty(&queue->running_list)) diff --git a/drivers/video/rockchip/mpp/mpp_rkvdec2_link.h b/drivers/video/rockchip/mpp/mpp_rkvdec2_link.h index 7a0c0a0a75e3..518927e9481e 100644 --- a/drivers/video/rockchip/mpp/mpp_rkvdec2_link.h +++ b/drivers/video/rockchip/mpp/mpp_rkvdec2_link.h @@ -221,9 +221,9 @@ void rkvdec2_link_session_deinit(struct mpp_session *session); int rkvdec2_attach_ccu(struct device *dev, struct rkvdec2_dev *dec); int rkvdec2_ccu_link_init(struct platform_device *pdev, struct rkvdec2_dev *dec); void *rkvdec2_ccu_alloc_task(struct mpp_session *session, struct mpp_task_msgs *msgs); -int rkvdec2_ccu_iommu_fault_handle(struct iommu_domain *iommu, - struct device *iommu_dev, - unsigned long iova, int status, void *arg); +int rkvdec2_soft_ccu_iommu_fault_handle(struct iommu_domain *iommu, + struct device *iommu_dev, + unsigned long iova, int status, void *arg); irqreturn_t rkvdec2_soft_ccu_irq(int irq, void *param); void rkvdec2_soft_ccu_worker(struct kthread_work *work_s); @@ -231,5 +231,8 @@ int rkvdec2_ccu_alloc_table(struct rkvdec2_dev *dec, struct rkvdec_link_dev *link_dec); irqreturn_t rkvdec2_hard_ccu_irq(int irq, void *param); void rkvdec2_hard_ccu_worker(struct kthread_work *work_s); +int rkvdec2_hard_ccu_iommu_fault_handle(struct iommu_domain *iommu, + struct device *iommu_dev, + unsigned long iova, int status, void *arg); #endif diff --git a/drivers/video/rockchip/mpp/mpp_rkvenc2.c b/drivers/video/rockchip/mpp/mpp_rkvenc2.c index 83017ee38ef0..23ace2538f67 100644 --- a/drivers/video/rockchip/mpp/mpp_rkvenc2.c +++ b/drivers/video/rockchip/mpp/mpp_rkvenc2.c @@ -130,6 +130,11 @@ struct rkvenc_hw_info { #define INT_STA_RBUS_ERR_STA BIT(7) #define INT_STA_WDG_STA BIT(8) +#define INT_STA_ERROR (INT_STA_BRSP_OTSD_STA | \ + INT_STA_WBUS_ERR_STA | \ + INT_STA_RBUS_ERR_STA | \ + INT_STA_WDG_STA) + #define DCHS_REG_OFFSET (0x304) #define DCHS_CLASS_OFFSET (33) #define DCHS_TXE (0x10) @@ -1266,9 +1271,9 @@ static int rkvenc_run(struct mpp_dev *mpp, struct mpp_task *mpp_task) return 0; } -static void rkvenc2_read_slice_len(struct mpp_dev *mpp, struct rkvenc_task *task) +static void rkvenc2_read_slice_len(struct mpp_dev *mpp, struct rkvenc_task *task, + u32 last) { - u32 last = mpp_read_relaxed(mpp, 0x002c) & INT_STA_ENC_DONE_STA; u32 sli_num = mpp_read_relaxed(mpp, RKVENC2_REG_SLICE_NUM_BASE); union rkvenc2_slice_len_info slice_info; u32 task_id = task->mpp_task.task_id; @@ -1308,46 +1313,41 @@ static int rkvenc_irq(struct mpp_dev *mpp) struct rkvenc_hw_info *hw = enc->hw_info; struct mpp_task *mpp_task = NULL; struct rkvenc_task *task = NULL; - u32 int_clear = 1; - u32 irq_mask = 0; + u32 irq_status; int ret = IRQ_NONE; mpp_debug_enter(); - mpp->irq_status = mpp_read(mpp, hw->int_sta_base); - if (!mpp->irq_status) + irq_status = mpp_read(mpp, hw->int_sta_base); + + mpp_debug(DEBUG_IRQ_STATUS, "%s irq_status: %08x\n", + dev_name(mpp->dev), irq_status); + + if (!irq_status) return ret; + /* clear int first */ + mpp_write(mpp, hw->int_clr_base, irq_status); + if (mpp->cur_task) { mpp_task = mpp->cur_task; task = to_rkvenc_task(mpp_task); } - if (mpp->irq_status & INT_STA_ENC_DONE_STA) { - if (task) { - if (task->task_split) - rkvenc2_read_slice_len(mpp, task); + /* 1. read slice number and slice length */ + if (task && task->task_split && + (irq_status & (INT_STA_SLC_DONE_STA | INT_STA_ENC_DONE_STA))) { + mpp_time_part_diff(mpp_task); + rkvenc2_read_slice_len(mpp, task, irq_status & INT_STA_ENC_DONE_STA); + wake_up(&mpp_task->wait); + } - wake_up(&mpp_task->wait); - } + /* 2. process slice irq */ + if (irq_status & INT_STA_SLC_DONE_STA) + ret = IRQ_HANDLED; - irq_mask = INT_STA_ENC_DONE_STA; - ret = IRQ_WAKE_THREAD; - if (enc->bs_overflow) { - mpp->irq_status |= INT_STA_BSF_OFLW_STA; - enc->bs_overflow = 0; - } - } else if (mpp->irq_status & INT_STA_SLC_DONE_STA) { - if (task && task->task_split) { - mpp_time_part_diff(mpp_task); - - rkvenc2_read_slice_len(mpp, task); - wake_up(&mpp_task->wait); - } - - irq_mask = INT_STA_ENC_DONE_STA; - int_clear = 0; - } else if (mpp->irq_status & INT_STA_BSF_OFLW_STA) { + /* 3. process bitstream overflow */ + if (irq_status & INT_STA_BSF_OFLW_STA) { u32 bs_rd = mpp_read(mpp, RKVENC2_REG_ADR_BSBR); u32 bs_wr = mpp_read(mpp, RKVENC2_REG_ST_BSB); u32 bs_top = mpp_read(mpp, RKVENC2_REG_ADR_BSBT); @@ -1359,28 +1359,33 @@ static int rkvenc_irq(struct mpp_dev *mpp) bs_wr += 128; if (bs_wr >= bs_top) bs_wr = bs_bot; - /* clear int first */ - mpp_write(mpp, hw->int_clr_base, mpp->irq_status); + /* update write addr for enc continue */ mpp_write(mpp, RKVENC2_REG_ADR_BSBS, bs_wr); enc->bs_overflow = 1; - irq_mask = 0; - int_clear = 0; - ret = IRQ_HANDLED; - } else { - dev_err(mpp->dev, "found error status %08x\n", mpp->irq_status); - irq_mask = mpp->irq_status; + ret = IRQ_HANDLED; + } + + /* 4. process frame irq */ + if (irq_status & INT_STA_ENC_DONE_STA) { + mpp->irq_status = irq_status; + + if (enc->bs_overflow) { + mpp->irq_status |= INT_STA_BSF_OFLW_STA; + enc->bs_overflow = 0; + } + ret = IRQ_WAKE_THREAD; } - if (irq_mask) - mpp_write(mpp, hw->int_mask_base, irq_mask); + /* 5. process error irq */ + if (irq_status & INT_STA_ERROR) { + mpp->irq_status = irq_status; - if (int_clear) { - mpp_write(mpp, hw->int_clr_base, mpp->irq_status); - udelay(5); - mpp_write(mpp, hw->int_sta_base, 0); + dev_err(mpp->dev, "found error status %08x\n", irq_status); + + ret = IRQ_WAKE_THREAD; } mpp_debug_leave(); @@ -1388,6 +1393,11 @@ static int rkvenc_irq(struct mpp_dev *mpp) return ret; } +static int vepu540c_irq(struct mpp_dev *mpp) +{ + return rkvenc_irq(mpp); +} + static int rkvenc_isr(struct mpp_dev *mpp) { struct rkvenc_task *task; @@ -1416,9 +1426,6 @@ static int rkvenc_isr(struct mpp_dev *mpp) rkvenc2_update_dchs(enc, task); - mpp_debug(DEBUG_IRQ_STATUS, "%s irq_status: %08x\n", - dev_name(mpp->dev), task->irq_status); - if (task->irq_status & enc->hw_info->err_mask) { atomic_inc(&mpp->reset_request); @@ -2162,6 +2169,20 @@ static struct mpp_dev_ops rkvenc_ccu_dev_ops = { .dump_session = rkvenc_dump_session, }; +static struct mpp_dev_ops vepu540c_dev_ops_v2 = { + .wait_result = rkvenc2_wait_result, + .alloc_task = rkvenc_alloc_task, + .run = rkvenc_run, + .irq = vepu540c_irq, + .isr = rkvenc_isr, + .finish = rkvenc_finish, + .result = rkvenc_result, + .free_task = rkvenc_free_task, + .ioctl = rkvenc_control, + .init_session = rkvenc_init_session, + .free_session = rkvenc_free_session, + .dump_session = rkvenc_dump_session, +}; static const struct mpp_dev_var rkvenc_v2_data = { .device_type = MPP_DEVICE_RKVENC, @@ -2176,7 +2197,7 @@ static const struct mpp_dev_var rkvenc_540c_data = { .hw_info = &rkvenc_540c_hw_info.hw, .trans_info = trans_rkvenc_540c, .hw_ops = &rkvenc_hw_ops, - .dev_ops = &rkvenc_dev_ops_v2, + .dev_ops = &vepu540c_dev_ops_v2, }; static const struct mpp_dev_var rkvenc_ccu_data = { diff --git a/drivers/video/rockchip/rga3/include/rga_mm.h b/drivers/video/rockchip/rga3/include/rga_mm.h index 0bb8e926559a..d68fd75dcb45 100644 --- a/drivers/video/rockchip/rga3/include/rga_mm.h +++ b/drivers/video/rockchip/rga3/include/rga_mm.h @@ -56,8 +56,8 @@ void rga_mm_dump_info(struct rga_mm *session); int rga_mm_map_job_info(struct rga_job *job); void rga_mm_unmap_job_info(struct rga_job *job); -uint32_t rga_mm_import_buffer(struct rga_external_buffer *external_buffer, - struct rga_session *session); +int rga_mm_import_buffer(struct rga_external_buffer *external_buffer, + struct rga_session *session); int rga_mm_release_buffer(uint32_t handle); int rga_mm_session_release_buffer(struct rga_session *session); diff --git a/drivers/video/rockchip/rga3/rga_drv.c b/drivers/video/rockchip/rga3/rga_drv.c index 0ea84e48f0ef..2d80c8089440 100644 --- a/drivers/video/rockchip/rga3/rga_drv.c +++ b/drivers/video/rockchip/rga3/rga_drv.c @@ -650,7 +650,7 @@ static long rga_ioctl_import_buffer(unsigned long arg, struct rga_session *sessi } ret = rga_mm_import_buffer(&external_buffer[i], session); - if (ret == 0) { + if (ret <= 0) { pr_err("buffer[%d] mm import buffer failed! memory = 0x%lx, type = %s(0x%x)\n", i, (unsigned long)external_buffer[i].memory, rga_get_memory_type_str(external_buffer[i].type), diff --git a/drivers/video/rockchip/rga3/rga_mm.c b/drivers/video/rockchip/rga3/rga_mm.c index 78b262013460..de7e9a6fd7fa 100644 --- a/drivers/video/rockchip/rga3/rga_mm.c +++ b/drivers/video/rockchip/rga3/rga_mm.c @@ -455,6 +455,7 @@ static int rga_mm_map_dma_buffer(struct rga_external_buffer *external_buffer, phys_addr = sg_phys(buffer->sgt->sgl); if (phys_addr == 0) { pr_err("%s get physical address error!", __func__); + ret = -EFAULT; goto unmap_buffer; } @@ -571,6 +572,7 @@ static int rga_mm_map_virt_addr(struct rga_external_buffer *external_buffer, phys_addr = sg_phys(sgt->sgl); if (phys_addr == 0) { pr_err("%s get physical address error!", __func__); + ret = -EFAULT; goto free_sgt; } @@ -621,8 +623,9 @@ static int rga_mm_map_virt_addr(struct rga_external_buffer *external_buffer, if (mm_flag & RGA_MEM_PHYSICAL_CONTIGUOUS) break; - pr_err("Current %s[%d] cannot support virtual address!\n", + pr_err("Current %s[%d] cannot support physically discontinuous virtual address!\n", rga_get_mmu_type_str(scheduler->data->mmu), scheduler->data->mmu); + ret = -EOPNOTSUPP; goto free_dma_buffer; } @@ -2044,8 +2047,18 @@ void rga_mm_unmap_job_info(struct rga_job *job) } } -uint32_t rga_mm_import_buffer(struct rga_external_buffer *external_buffer, - struct rga_session *session) +/* + * rga_mm_import_buffer - Importing external buffer into the RGA driver + * + * @external_buffer: [in] Parameters of external buffer + * @session: [in] Session of the current process + * + * returns: + * if return value > 0, the buffer import is successful and is the generated + * buffer-handle, negative error code on failure. + */ +int rga_mm_import_buffer(struct rga_external_buffer *external_buffer, + struct rga_session *session) { int ret = 0, new_id; struct rga_mm *mm; @@ -2054,7 +2067,7 @@ uint32_t rga_mm_import_buffer(struct rga_external_buffer *external_buffer, mm = rga_drvdata->mm; if (mm == NULL) { pr_err("rga mm is null!\n"); - return 0; + return -EFAULT; } mutex_lock(&mm->lock); @@ -2080,7 +2093,7 @@ uint32_t rga_mm_import_buffer(struct rga_external_buffer *external_buffer, pr_err("%s alloc internal_buffer error!\n", __func__); mutex_unlock(&mm->lock); - return 0; + return -ENOMEM; } ret = rga_mm_map_buffer(external_buffer, internal_buffer, NULL, true); @@ -2099,6 +2112,7 @@ uint32_t rga_mm_import_buffer(struct rga_external_buffer *external_buffer, idr_preload_end(); if (new_id < 0) { pr_err("internal_buffer alloc id failed!\n"); + ret = new_id; goto FREE_INTERNAL_BUFFER; } @@ -2117,7 +2131,7 @@ FREE_INTERNAL_BUFFER: mutex_unlock(&mm->lock); kfree(internal_buffer); - return 0; + return ret; } int rga_mm_release_buffer(uint32_t handle)