Merge commit '2688d7f9259151ac782d92bece2458eb998aa829'

* commit '2688d7f9259151ac782d92bece2458eb998aa829':
  media: i2c: add ar2020 sensor driver
  watchdog: dw_wdt: fix array out-of-bounds in theory
  mfd: rkx110_x120: add irq support
  drm/rockchip: vop2: fix overlapping_copy

Change-Id: I50059e725ec7b7efc4e0437e85f9622ba9c97fb9

Conflicts:
	drivers/media/i2c/Kconfig
	drivers/media/i2c/Makefile
This commit is contained in:
Tao Huang
2023-11-22 17:40:00 +08:00
11 changed files with 6467 additions and 2 deletions

View File

@@ -11602,6 +11602,7 @@ static int vop2_win_init(struct vop2 *vop2)
struct vop2_win *win;
struct vop2_layer *layer;
char name[DRM_PROP_NAME_LEN];
char area_name[DRM_PROP_NAME_LEN];
unsigned int num_wins = 0;
uint8_t plane_id = 0;
unsigned int i, j;
@@ -11677,8 +11678,8 @@ static int vop2_win_init(struct vop2 *vop2)
area->phys_id = win->phys_id;
area->area_id = j + 1;
area->plane_id = plane_id++;
snprintf(name, min(sizeof(name), strlen(win->name)), "%s", win->name);
snprintf(name, sizeof(name), "%s%d", name, area->area_id);
snprintf(area_name, min(sizeof(area_name), strlen(win->name)), "%s", win->name);
snprintf(name, sizeof(name), "%s%d", area_name, area->area_id);
area->name = devm_kstrdup(vop2->dev, name, GFP_KERNEL);
num_wins++;
}

View File

@@ -74,6 +74,20 @@ config VIDEO_AR0822
To compile this driver as a module, choose M here: the
module will be called ar0822.
config VIDEO_AR2020
tristate "Onsemi AR2020 sensor support"
depends on I2C && VIDEO_DEV
depends on MEDIA_CAMERA_SUPPORT
select MEDIA_CONTROLLER
select VIDEO_V4L2_SUBDEV_API
select V4L2_FWNODE
help
This is a Video4Linux2 sensor driver for the Onsemi
AR2020 camera.
To compile this driver as a module, choose M here: the
module will be called ar2020.
config VIDEO_BF3925
tristate "BYD BF3925 sensor support"
depends on I2C && VIDEO_DEV

View File

@@ -22,6 +22,7 @@ obj-$(CONFIG_VIDEO_APTINA_PLL) += aptina-pll.o
obj-$(CONFIG_VIDEO_AR0230) += ar0230.o
obj-$(CONFIG_VIDEO_AR0521) += ar0521.o
obj-$(CONFIG_VIDEO_AR0822) += ar0822.o
obj-$(CONFIG_VIDEO_AR2020) += ar2020.o
obj-$(CONFIG_VIDEO_AW36518) += aw36518.o
obj-$(CONFIG_VIDEO_AW8601) += aw8601.o
obj-$(CONFIG_VIDEO_BF3925) += bf3925.o

5413
drivers/media/i2c/ar2020.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -101,7 +101,33 @@
#define SER_RKLINK_AUDIO_RECOVER LINK_REG(0x0034)
#define SER_RKLINK_AUDIO_FM_STATUS LINK_REG(0x0038)
#define SER_RKLINK_FIFO_STATUS LINK_REG(0x003C)
#define CH1_CMD_FIFO_UNDERRUN BIT(24)
#define CH0_CMD_FIFO_UNDERRUN BIT(23)
#define DATA1_FIFO_UNDERRUN BIT(22)
#define DATA0_FIFO_UNDERRUN BIT(21)
#define AUDIO_FIFO_UNDERRUN BIT(20)
#define LVDS1_FIFO_UNDERRUN BIT(19)
#define LVDS0_FIFO_UNDERRUN BIT(18)
#define DSI_CH1_FIFO_UNDERRUN BIT(17)
#define DSI_CH0_FIFO_UNDERRUN BIT(16)
#define CH1_CMD_FIFO_OVERFLOW BIT(8)
#define CH0_CMD_FIFO_OVERFLOW BIT(7)
#define DATA0_FIFO_OVERFLOW BIT(6)
#define DATA1_FIFO_OVERFLOW BIT(5)
#define AUDIO_FIFO_OVERFLOW BIT(4)
#define LVDS1_FIFO_OVERFLOW BIT(3)
#define LVDS0_FIFO_OVERFLOW BIT(2)
#define DSI_CH1_FIFO_OVERFLOW BIT(1)
#define DSI_CH0_FIFO_OVERFLOW BIT(0)
#define SER_RKLINK_SOURCE_IRQ_EN LINK_REG(0x0040)
#define TRAIN_DONE_IRQ_FLAG BIT(19)
#define FIFO_UNDERRUN_IRQ_FLAG BIT(18)
#define FIFO_OVERFLOW_IRQ_FLAG BIT(17)
#define AUDIO_FM_IRQ_OUTPUT_FLAG BIT(16)
#define TRAIN_DONE_IRQ_OUTPUT_EN BIT(3)
#define FIFO_UNDERRUN_IRQ_OUTPUT_EN BIT(2)
#define FIFO_OVERFLOW_IRQ_OUTPUT_EN BIT(1)
#define AUDIO_FM_IRQ_OUTPUT_EN BIT(0)
#define SER_RKLINK_TRAIN_CTRL LINK_REG(0x0044)
#define SER_RKLINK_I2C_CFG LINK_REG(0x00C0)
@@ -144,7 +170,9 @@
#define PCS_REG24(id) PCS_REG(id, 0x24)
#define PCS_REG28(id) PCS_REG(id, 0x28)
#define PCS_REG30(id) PCS_REG(id, 0x30)
#define PCS_INT_STARTUP(x) HIWORD_UPDATE(x, GENMASK(15, 0), 0)
#define PCS_REG34(id) PCS_REG(id, 0x34)
#define PCS_INT_REMOTE_MODE(x) HIWORD_UPDATE(x, GENMASK(15, 0), 0)
#define PCS_REG40(id) PCS_REG(id, 0x40)
#define PMA_REG(id, x) ((x) + RKX110_SER_PMA0_BASE + (id) * RKX110_SER_PMA_OFFSET)
@@ -195,6 +223,15 @@
#define PMA_CLK_8X_DIV_MASK HIWORD_MASK(7, 1)
#define PMA_CLK_8X_DIV(x) HIWORD_UPDATE(x, GENMASK(7, 1), 1)
#define SER_PMA_IRQ_EN(id) PMA_REG(id, 0xF0)
#define FORCE_INITIAL_IRQ_EN HIWORD_UPDATE(1, BIT(3), 3)
#define RTERM_ONCE_TIMEOUT_IRQ_EN HIWORD_UPDATE(1, BIT(1), 1)
#define PLL_LOCK_TIMEOUT_IRQ_EN HIWORD_UPDATE(1, BIT(0), 0)
#define SER_PMA_IRQ_STATUS(id) PMA_REG(id, 0xF4)
#define FORCE_INITIAL_PULSE_STATUS BIT(3)
#define RTERM_ONCE_TIMEOUT_STATUS BIT(1)
#define PLL_LOCK_TIMEOUT_STATUS BIT(0)
enum {
SER_LINK_CH_ID0 = 0,
SER_LINK_CH_ID1,
@@ -750,3 +787,346 @@ void rkx110_ser_pma_enable(struct rk_serdes *serdes, bool enable, u8 pma_id, u8
serdes->i2c_update_bits(client, SER_GRF_SOC_CON7, mask, val);
}
static void rkx110_linktx_irq_enable(struct rk_serdes *serdes, u8 dev_id)
{
struct i2c_client *client = serdes->chip[dev_id].client;
serdes->i2c_write_reg(client, SER_GRF_IRQ_EN, SER_IRQ_LINK_EN);
serdes->i2c_write_reg(client, SER_RKLINK_SOURCE_IRQ_EN, TRAIN_DONE_IRQ_OUTPUT_EN |
FIFO_UNDERRUN_IRQ_OUTPUT_EN | FIFO_OVERFLOW_IRQ_OUTPUT_EN);
}
static void rkx110_linktx_irq_disable(struct rk_serdes *serdes, u8 dev_id)
{
struct i2c_client *client = serdes->chip[dev_id].client;
u32 val = 0;
serdes->i2c_write_reg(client, SER_GRF_IRQ_EN, SER_IRQ_LINK_DIS);
serdes->i2c_read_reg(client, SER_RKLINK_SOURCE_IRQ_EN, &val);
val &= ~(SER_RKLINK_SOURCE_IRQ_EN | TRAIN_DONE_IRQ_OUTPUT_EN |
FIFO_UNDERRUN_IRQ_OUTPUT_EN | FIFO_OVERFLOW_IRQ_OUTPUT_EN);
serdes->i2c_write_reg(client, SER_RKLINK_SOURCE_IRQ_EN, val);
}
static void rkx110_linktx_fifo_handler(struct rk_serdes *serdes, u8 dev_id)
{
struct i2c_client *client = serdes->chip[dev_id].client;
u32 value;
serdes->i2c_read_reg(client, SER_RKLINK_FIFO_STATUS, &value);
dev_err(serdes->dev, "ser rklink fifo status:0x%x\n", value);
if (value & CH1_CMD_FIFO_UNDERRUN)
dev_err(serdes->dev, "linktx ch1 cmd fifo underrun\n");
if (value & CH0_CMD_FIFO_UNDERRUN)
dev_err(serdes->dev, "linktx ch0 cmd fifo underrun\n");
if (value & DATA1_FIFO_UNDERRUN)
dev_err(serdes->dev, "linktx data1 fifo underrun\n");
if (value & DATA0_FIFO_UNDERRUN)
dev_err(serdes->dev, "linktx data0 fifo underrun\n");
if (value & AUDIO_FIFO_UNDERRUN)
dev_err(serdes->dev, "linktx audio fifo underrun\n");
if (value & LVDS1_FIFO_UNDERRUN)
dev_err(serdes->dev, "linktx lvds1 fifo underrun\n");
if (value & LVDS0_FIFO_UNDERRUN)
dev_err(serdes->dev, "linktx lvds0 fifo underrun\n");
if (value & DSI_CH1_FIFO_UNDERRUN)
dev_err(serdes->dev, "linktx dsi ch1 fifo underrun\n");
if (value & DSI_CH0_FIFO_UNDERRUN)
dev_err(serdes->dev, "linktx dsi ch0 fifo underrun\n");
if (value & CH1_CMD_FIFO_OVERFLOW)
dev_err(serdes->dev, "linktx ch1 cmd fifo overflow\n");
if (value & CH0_CMD_FIFO_OVERFLOW)
dev_err(serdes->dev, "linktx ch0 cmd fifo overflow\n");
if (value & DATA1_FIFO_OVERFLOW)
dev_err(serdes->dev, "linktx data1 fifo overflow\n");
if (value & DATA0_FIFO_OVERFLOW)
dev_err(serdes->dev, "linktx data0 fifo overflow\n");
if (value & AUDIO_FIFO_OVERFLOW)
dev_err(serdes->dev, "linktx audio fifo overflow\n");
if (value & LVDS1_FIFO_OVERFLOW)
dev_err(serdes->dev, "linktx lvds1 fifo overflow\n");
if (value & LVDS0_FIFO_OVERFLOW)
dev_err(serdes->dev, "linktx lvds0 fifo overflow\n");
if (value & DSI_CH1_FIFO_OVERFLOW)
dev_err(serdes->dev, "linktx dsi ch1 fifo overflow\n");
if (value & DSI_CH0_FIFO_OVERFLOW)
dev_err(serdes->dev, "linktx dsi ch0 fifo overflow\n");
/* clear fifo status */
serdes->i2c_write_reg(client, SER_RKLINK_FIFO_STATUS, value);
}
static void rkx110_linktx_irq_handler(struct rk_serdes *serdes, u8 dev_id)
{
struct i2c_client *client = serdes->chip[dev_id].client;
u32 flag, value;
int i = 0;
serdes->i2c_read_reg(client, SER_RKLINK_SOURCE_IRQ_EN, &flag);
flag &= TRAIN_DONE_IRQ_FLAG | FIFO_UNDERRUN_IRQ_FLAG | FIFO_OVERFLOW_IRQ_FLAG |
AUDIO_FM_IRQ_OUTPUT_FLAG;
dev_info(serdes->dev, "linktx irq flag:0x%08x\n", flag);
while (flag) {
switch (flag & BIT(i)) {
case TRAIN_DONE_IRQ_FLAG:
serdes->i2c_read_reg(client, SER_RKLINK_TRAIN_CTRL, &value);
dev_info(serdes->dev, "linktx train done, status:0x%08x\n", value);
/* write any thing to train ctrl will clear the train done irq flag */
serdes->i2c_write_reg(client, SER_RKLINK_TRAIN_CTRL, value);
break;
case FIFO_UNDERRUN_IRQ_FLAG:
case FIFO_OVERFLOW_IRQ_FLAG:
flag &= ~(FIFO_UNDERRUN_IRQ_FLAG | FIFO_OVERFLOW_IRQ_FLAG);
rkx110_linktx_fifo_handler(serdes, dev_id);
break;
case AUDIO_FM_IRQ_OUTPUT_FLAG:
break;
default:
break;
}
flag &= ~BIT(i);
i++;
}
}
static void rkx110_pcs_irq_enable(struct rk_serdes *serdes, u8 pcs_id, u8 dev_id)
{
struct i2c_client *client = serdes->chip[dev_id].client;
u32 val;
val = pcs_id ? SER_IRQ_PCS1_EN : SER_IRQ_PCS0_EN;
serdes->i2c_write_reg(client, SER_GRF_IRQ_EN, val);
serdes->i2c_write_reg(client, PCS_REG30(pcs_id), PCS_INT_STARTUP(0xffff));
serdes->i2c_write_reg(client, PCS_REG34(pcs_id), PCS_INT_REMOTE_MODE(0xffff));
}
static void rkx110_pcs_irq_disable(struct rk_serdes *serdes, u8 pcs_id, u8 dev_id)
{
struct i2c_client *client = serdes->chip[dev_id].client;
u32 val;
val = pcs_id ? SER_IRQ_PCS1_DIS : SER_IRQ_PCS0_DIS;
serdes->i2c_write_reg(client, SER_GRF_IRQ_EN, val);
serdes->i2c_write_reg(client, PCS_REG30(pcs_id), PCS_INT_STARTUP(0));
serdes->i2c_write_reg(client, PCS_REG34(pcs_id), PCS_INT_REMOTE_MODE(0));
}
static void rkx110_pcs_irq_handler(struct rk_serdes *serdes, u8 pcs_id, u8 dev_id)
{
struct i2c_client *client = serdes->chip[dev_id].client;
u32 value;
serdes->i2c_read_reg(client, PCS_REG24(pcs_id), &value);
dev_info(serdes->dev, "ser pcs%d startup fatal status:0x%08x\n", pcs_id, value);
serdes->i2c_read_reg(client, PCS_REG28(pcs_id), &value);
dev_info(serdes->dev, "ser pcs%d remote mode fatal status:0x%08x\n", pcs_id, value);
/* clear startup fatal status */
serdes->i2c_write_reg(client, PCS_REG1C(pcs_id), 0xffffffff);
serdes->i2c_write_reg(client, PCS_REG1C(pcs_id), 0xffff0000);
/* clear remote fatal status */
serdes->i2c_write_reg(client, PCS_REG14(pcs_id), 0xffffffff);
serdes->i2c_write_reg(client, PCS_REG14(pcs_id), 0xffff0000);
}
static void rkx110_pma_irq_enable(struct rk_serdes *serdes, u8 pcs_id, u8 dev_id)
{
struct i2c_client *client = serdes->chip[dev_id].client;
u32 val;
val = pcs_id ? SER_IRQ_PMA_ADAPT1_EN : SER_IRQ_PMA_ADAPT0_EN;
serdes->i2c_write_reg(client, SER_GRF_IRQ_EN, val);
serdes->i2c_write_reg(client, SER_PMA_IRQ_EN(pcs_id), FORCE_INITIAL_IRQ_EN |
RTERM_ONCE_TIMEOUT_IRQ_EN | PLL_LOCK_TIMEOUT_IRQ_EN);
}
static void rkx110_pma_irq_disable(struct rk_serdes *serdes, u8 pcs_id, u8 dev_id)
{
struct i2c_client *client = serdes->chip[dev_id].client;
u32 val;
val = pcs_id ? SER_IRQ_PMA_ADAPT1_DIS : SER_IRQ_PMA_ADAPT0_DIS;
serdes->i2c_write_reg(client, SER_GRF_IRQ_EN, val);
serdes->i2c_write_reg(client, SER_PMA_IRQ_EN(pcs_id), 0);
}
static void rkx110_pma_irq_handler(struct rk_serdes *serdes, u8 pcs_id, u8 dev_id)
{
struct i2c_client *client = serdes->chip[dev_id].client;
u32 value;
serdes->i2c_read_reg(client, SER_PMA_IRQ_STATUS(pcs_id), &value);
dev_info(serdes->dev, "ser pma%d irq status:0x%08x\n", pcs_id, value);
if (value & FORCE_INITIAL_PULSE_STATUS)
dev_info(serdes->dev, "ser pma trig force initial pulse status\n");
else if (value & RTERM_ONCE_TIMEOUT_STATUS)
dev_info(serdes->dev, "ser pma trig rterm once timeout status\n");
else if (value & PLL_LOCK_TIMEOUT_STATUS)
dev_info(serdes->dev, "ser pma trig pll lock timeout status\n");
/* clear pma irq status */
serdes->i2c_write_reg(client, SER_PMA_IRQ_STATUS(pcs_id), value);
}
static void rkx110_remote_irq_enable(struct rk_serdes *serdes, u8 dev_id)
{
struct i2c_client *client = serdes->chip[dev_id].client;
if (serdes->stream_type == STREAM_DISPLAY) {
serdes->i2c_write_reg(client, SER_GRF_IRQ_EN, SER_IRQ_REMOTE_EN);
rkx120_irq_enable(serdes, DEVICE_REMOTE0);
}
}
static void rkx110_remote_irq_disable(struct rk_serdes *serdes, u8 dev_id)
{
struct i2c_client *client = serdes->chip[dev_id].client;
if (serdes->stream_type == STREAM_DISPLAY) {
serdes->i2c_write_reg(client, SER_GRF_IRQ_EN, SER_IRQ_REMOTE_DIS);
rkx120_irq_disable(serdes, DEVICE_REMOTE0);
}
}
static void rkx110_remote_irq_handler(struct rk_serdes *serdes, u8 dev_id)
{
if (serdes->stream_type == STREAM_DISPLAY)
rkx120_irq_handler(serdes, DEVICE_REMOTE0);
}
void rkx110_irq_enable(struct rk_serdes *serdes, u8 dev_id)
{
/* enable pcs irq */
rkx110_pcs_irq_enable(serdes, 0, dev_id);
/* enable dsirx irq */
/* enable gpio irq */
/* enable csihost irq */
/* enable pma_adapt irq */
rkx110_pma_irq_enable(serdes, 0, dev_id);
/* enable efuse irq */
/* enable vicap irq */
/* enable remote irq */
rkx110_remote_irq_enable(serdes, dev_id);
/* enable ext irq */
/* enable link irq */
rkx110_linktx_irq_enable(serdes, dev_id);
}
void rkx110_irq_disable(struct rk_serdes *serdes, u8 dev_id)
{
/* disable pcs irq */
rkx110_pcs_irq_disable(serdes, 0, dev_id);
/* disable dsirx irq */
/* disable gpio irq */
/* disable csihost irq */
/* disable pma_adapt irq */
rkx110_pma_irq_disable(serdes, 0, dev_id);
/* disable efuse irq */
/* disable vicap irq */
/* disable remote irq and other lane irq*/
rkx110_remote_irq_disable(serdes, dev_id);
/* disable ext irq */
/* disable link irq */
rkx110_linktx_irq_disable(serdes, dev_id);
}
int rkx110_irq_handler(struct rk_serdes *serdes, u8 dev_id)
{
struct i2c_client *client = serdes->chip[dev_id].client;
u32 status, mask;
u32 i = 0;
serdes->i2c_read_reg(client, SER_GRF_IRQ_EN, &mask);
serdes->i2c_read_reg(client, SER_GRF_IRQ_STATUS, &status);
dev_info(serdes->dev, "dev%d get the ser irq status:0x%08x\n", dev_id, status);
status &= mask;
while (status) {
switch (status & BIT(i)) {
case SER_IRQ_PCS0:
rkx110_pcs_irq_handler(serdes, 0, dev_id);
break;
case SER_IRQ_PCS1:
rkx110_pcs_irq_handler(serdes, 1, dev_id);
break;
case SER_IRQ_DSIRX0:
/* TBD */
break;
case SER_IRQ_DSIRX1:
/* TBD */
break;
case SER_IRQ_GPIO0:
/* TBD */
break;
case SER_IRQ_GPIO1:
/* TBD */
break;
case SER_IRQ_CSIHOST0:
/* TBD */
break;
case SER_IRQ_CSIHOST1:
/* TBD */
break;
case SER_IRQ_PMA_ADAPT0:
rkx110_pma_irq_handler(serdes, 0, dev_id);
break;
case SER_IRQ_PMA_ADAPT1:
rkx110_pma_irq_handler(serdes, 1, dev_id);
break;
case SER_IRQ_EFUSE:
/* TBD */
break;
case SER_IRQ_VICAP:
/* TBD */
break;
case SER_IRQ_REMOTE:
rkx110_remote_irq_handler(serdes, dev_id);
break;
case SER_IRQ_EXT:
/* TBD */
break;
case SER_IRQ_LINK:
rkx110_linktx_irq_handler(serdes, dev_id);
break;
case SER_IRQ_OTHER_LANE:
/* TBD */
break;
default:
break;
}
status &= ~BIT(i);
i++;
}
return 0;
}

View File

@@ -357,6 +357,8 @@ enum {
#define SER_GRF_SOC_CON5 GRF_REG(0x114)
#define SER_GRF_SOC_CON6 GRF_REG(0x118)
#define SER_GRF_SOC_CON7 GRF_REG(0x11C)
#define SER_GRF_IRQ_EN GRF_REG(0x140)
#define SER_GRF_IRQ_STATUS GRF_REG(0x150)
#define SER_GRF_SOC_STATUS0 GRF_REG(0x160)
enum {
@@ -467,6 +469,71 @@ enum {
PMA0_DISABLE = HIWORD_UPDATE(0, BIT(8), 8),
/* SER_GRF_IRQ_EN */
SER_IRQ_OTHER_LANE_EN = HIWORD_UPDATE(1, BIT(15), 15),
SER_IRQ_OTHER_LANE_DIS = HIWORD_UPDATE(0, BIT(15), 15),
SER_IRQ_LINK_EN = HIWORD_UPDATE(1, BIT(14), 14),
SER_IRQ_LINK_DIS = HIWORD_UPDATE(0, BIT(14), 14),
SER_IRQ_EXT_EN = HIWORD_UPDATE(1, BIT(13), 13),
SER_IRQ_EXT_DIS = HIWORD_UPDATE(0, BIT(13), 13),
SER_IRQ_REMOTE_EN = HIWORD_UPDATE(1, BIT(12), 12),
SER_IRQ_REMOTE_DIS = HIWORD_UPDATE(0, BIT(12), 12),
SER_IRQ_VICAP_EN = HIWORD_UPDATE(1, BIT(11), 11),
SER_IRQ_VICAP_DIS = HIWORD_UPDATE(0, BIT(11), 11),
SER_IRQ_EFUSE_EN = HIWORD_UPDATE(1, BIT(10), 10),
SER_IRQ_EFUSE_DIS = HIWORD_UPDATE(0, BIT(10), 10),
SER_IRQ_PMA_ADAPT1_EN = HIWORD_UPDATE(1, BIT(9), 9),
SER_IRQ_PMA_ADAPT1_DIS = HIWORD_UPDATE(0, BIT(9), 9),
SER_IRQ_PMA_ADAPT0_EN = HIWORD_UPDATE(1, BIT(8), 8),
SER_IRQ_PMA_ADAPT0_DIS = HIWORD_UPDATE(0, BIT(8), 8),
SER_IRQ_CSIHOST1_EN = HIWORD_UPDATE(1, BIT(7), 7),
SER_IRQ_CSIHOST1_DIS = HIWORD_UPDATE(0, BIT(7), 7),
SER_IRQ_CSIHOST0_EN = HIWORD_UPDATE(1, BIT(6), 6),
SER_IRQ_CSIHOST0_DIS = HIWORD_UPDATE(0, BIT(6), 6),
SER_IRQ_GPIO1_EN = HIWORD_UPDATE(1, BIT(5), 5),
SER_IRQ_GPIO1_DIS = HIWORD_UPDATE(0, BIT(5), 5),
SER_IRQ_GPIO0_EN = HIWORD_UPDATE(1, BIT(4), 4),
SER_IRQ_GPIO0_DIS = HIWORD_UPDATE(0, BIT(4), 4),
SER_IRQ_DSIRX1_EN = HIWORD_UPDATE(1, BIT(3), 3),
SER_IRQ_DSIRX1_DIS = HIWORD_UPDATE(0, BIT(3), 3),
SER_IRQ_DSIRX0_EN = HIWORD_UPDATE(1, BIT(2), 2),
SER_IRQ_DSIRX0_DIS = HIWORD_UPDATE(0, BIT(2), 2),
SER_IRQ_PCS1_EN = HIWORD_UPDATE(1, BIT(1), 1),
SER_IRQ_PCS1_DIS = HIWORD_UPDATE(0, BIT(1), 1),
SER_IRQ_PCS0_EN = HIWORD_UPDATE(1, BIT(0), 0),
SER_IRQ_PCS0_DIS = HIWORD_UPDATE(0, BIT(0), 0),
/* SER_GRF_IRQ_STATUS */
SER_IRQ_OTHER_LANE = BIT(15),
SER_IRQ_LINK = BIT(14),
SER_IRQ_EXT = BIT(13),
SER_IRQ_REMOTE = BIT(12),
SER_IRQ_VICAP = BIT(11),
SER_IRQ_EFUSE = BIT(10),
SER_IRQ_PMA_ADAPT1 = BIT(9),
SER_IRQ_PMA_ADAPT0 = BIT(8),
SER_IRQ_CSIHOST1 = BIT(7),
SER_IRQ_CSIHOST0 = BIT(6),
SER_IRQ_GPIO1 = BIT(5),
SER_IRQ_GPIO0 = BIT(4),
SER_IRQ_DSIRX1 = BIT(3),
SER_IRQ_DSIRX0 = BIT(2),
SER_IRQ_PCS1 = BIT(1),
SER_IRQ_PCS0 = BIT(0),
/* SER_GRF_SOC_STATUS0 */
SER_PCS1_READY = BIT(21),

View File

@@ -262,7 +262,9 @@ struct rk_serdes {
struct regulator *supply;
struct gpio_desc *reset;
struct gpio_desc *enable;
struct gpio_desc *irq_gpio;
int irq;
/*
* Control by I2C-Debug
*/
@@ -364,4 +366,10 @@ void rkx110_linktx_passthrough_cfg(struct rk_serdes *serdes, u32 client_id, u32
bool is_rx);
void rkx120_linkrx_passthrough_cfg(struct rk_serdes *serdes, u32 client_id, u32 func_id,
bool is_rx);
void rkx110_irq_enable(struct rk_serdes *serdes, u8 dev_id);
void rkx110_irq_disable(struct rk_serdes *serdes, u8 dev_id);
int rkx110_irq_handler(struct rk_serdes *serdes, u8 dev_id);
void rkx120_irq_enable(struct rk_serdes *serdes, u8 dev_id);
void rkx120_irq_disable(struct rk_serdes *serdes, u8 dev_id);
int rkx120_irq_handler(struct rk_serdes *serdes, u8 dev_id);
#endif

View File

@@ -10,6 +10,7 @@
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/i2c.h>
#include <linux/irq.h>
#include <linux/gpio/consumer.h>
#include <linux/regulator/consumer.h>
#include <linux/mfd/core.h>
@@ -652,6 +653,25 @@ static int rk_serdes_passthrough_init(struct rk_serdes *serdes)
kfree(configs);
}
/* config irq passthrough */
if (serdes->stream_type == STREAM_DISPLAY) {
rkx110_linktx_passthrough_cfg(serdes, DEVICE_LOCAL, RK_SERDES_PASSTHROUGH_IRQ,
false);
rkx120_linkrx_passthrough_cfg(serdes, DEVICE_REMOTE0, RK_SERDES_PASSTHROUGH_IRQ,
true);
if (serdes->remote_nr == 2)
rkx120_linkrx_passthrough_cfg(serdes, DEVICE_REMOTE1,
RK_SERDES_PASSTHROUGH_IRQ, true);
} else {
rkx120_linkrx_passthrough_cfg(serdes, DEVICE_LOCAL, RK_SERDES_PASSTHROUGH_IRQ,
false);
rkx110_linktx_passthrough_cfg(serdes, DEVICE_REMOTE0, RK_SERDES_PASSTHROUGH_IRQ,
true);
if (serdes->remote_nr == 2)
rkx110_linktx_passthrough_cfg(serdes, DEVICE_REMOTE1,
RK_SERDES_PASSTHROUGH_IRQ, true);
}
return 0;
}
@@ -953,9 +973,66 @@ static int rk_serdes_pinctrl_init(struct rk_serdes *serdes)
kfree(configs);
}
/* config irq pinctrl */
if (serdes->stream_type == STREAM_DISPLAY) {
serdes->set_hwpin(serdes, serdes->chip[DEVICE_LOCAL].client, PIN_RKX110,
RK_SERDES_SER_GPIO_BANK0, RK_SERDES_GPIO_PIN_A4,
RK_SERDES_PIN_CONFIG_MUX_FUNC2);
serdes->set_hwpin(serdes, serdes->chip[DEVICE_REMOTE0].client, PIN_RKX120,
RK_SERDES_DES_GPIO_BANK0, RK_SERDES_GPIO_PIN_A4,
RK_SERDES_PIN_CONFIG_MUX_FUNC0);
if (serdes->remote_nr == 2)
serdes->set_hwpin(serdes, serdes->chip[DEVICE_REMOTE1].client, PIN_RKX120,
RK_SERDES_DES_GPIO_BANK0, RK_SERDES_GPIO_PIN_A4,
RK_SERDES_PIN_CONFIG_MUX_FUNC0);
} else {
serdes->set_hwpin(serdes, serdes->chip[DEVICE_REMOTE0].client, PIN_RKX110,
RK_SERDES_SER_GPIO_BANK0, RK_SERDES_GPIO_PIN_A4,
RK_SERDES_PIN_CONFIG_MUX_FUNC0);
serdes->set_hwpin(serdes, serdes->chip[DEVICE_LOCAL].client, PIN_RKX120,
RK_SERDES_DES_GPIO_BANK0, RK_SERDES_GPIO_PIN_A4,
RK_SERDES_PIN_CONFIG_MUX_FUNC2);
if (serdes->remote_nr == 2)
serdes->set_hwpin(serdes, serdes->chip[DEVICE_REMOTE1].client, PIN_RKX110,
RK_SERDES_SER_GPIO_BANK0, RK_SERDES_GPIO_PIN_A4,
RK_SERDES_PIN_CONFIG_MUX_FUNC2);
}
return 0;
}
static int rk_serdes_irq_enable(struct rk_serdes *serdes)
{
if (serdes->stream_type == STREAM_DISPLAY)
rkx110_irq_enable(serdes, DEVICE_LOCAL);
else
rkx120_irq_enable(serdes, DEVICE_LOCAL);
return 0;
}
__maybe_unused static int rk_serdes_irq_disable(struct rk_serdes *serdes)
{
if (serdes->stream_type == STREAM_DISPLAY)
rkx110_irq_disable(serdes, DEVICE_LOCAL);
else
rkx120_irq_disable(serdes, DEVICE_LOCAL);
return 0;
}
static irqreturn_t rk_serdes_irq_handler(int irq, void *arg)
{
struct rk_serdes *serdes = arg;
if (serdes->stream_type == STREAM_DISPLAY)
rkx110_irq_handler(serdes, DEVICE_LOCAL);
else
rkx120_irq_handler(serdes, DEVICE_LOCAL);
return IRQ_HANDLED;
}
static int rk_serdes_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
struct device *dev = &client->dev;
@@ -1014,6 +1091,30 @@ static int rk_serdes_i2c_probe(struct i2c_client *client, const struct i2c_devic
return ret;
}
serdes->irq_gpio = devm_gpiod_get_optional(dev, "irq", GPIOD_IN);
if (IS_ERR(serdes->irq_gpio)) {
ret = PTR_ERR(serdes->irq_gpio);
dev_err(dev, "failed to request irq GPIO: %d\n", ret);
return ret;
}
if (serdes->irq_gpio) {
serdes->irq = gpiod_to_irq(serdes->irq_gpio);
if (serdes->irq < 0)
return dev_err_probe(dev, serdes->irq, "failed to get irq\n");
irq_set_status_flags(serdes->irq, IRQ_NOAUTOEN);
ret = devm_request_threaded_irq(dev, serdes->irq, NULL,
rk_serdes_irq_handler,
IRQF_TRIGGER_LOW |
IRQF_ONESHOT, "serdes-irq", serdes);
if (ret) {
dev_err(dev, "failed to request serdes interrupt\n");
return ret;
}
} else {
dev_warn(dev, "no support serdes irq function\n");
}
disp_np = of_get_child_by_name(dev->of_node, "serdes-panel");
if (disp_np) {
serdes->stream_type = STREAM_DISPLAY;
@@ -1062,6 +1163,9 @@ static int rk_serdes_i2c_probe(struct i2c_client *client, const struct i2c_devic
rk_serdes_set_rate(serdes, RATE_4GBPS_83M);
rk_serdes_pinctrl_init(serdes);
rk_serdes_passthrough_init(serdes);
rk_serdes_irq_enable(serdes);
enable_irq(serdes->irq);
out:
rk_serdes_debugfs_init(serdes);

View File

@@ -36,6 +36,8 @@
#define LANE0_DATA_WIDTH_16BIT UPDATE(1, 13, 12)
#define LANE0_DATA_WIDTH_24BIT UPDATE(2, 13, 12)
#define LANE0_DATA_WIDTH_32BIT UPDATE(3, 13, 12)
#define LANE1_PKT_LOSE_NUM_CLR BIT(9)
#define LANE0_PKT_LOSE_NUM_CLR BIT(8)
#define LANE0_EN BIT(4)
#define LANE1_EN BIT(5)
#define DES_EN BIT(0)
@@ -115,6 +117,42 @@
#define E2_FIRST_FRAME_DEL BIT(6)
#define E1_FIRST_FRAME_DEL BIT(5)
#define E0_FIRST_FRAME_DEL BIT(4)
#define RKLINK_DES_FIFO_STATUS LINK_REG(0x0084)
#define AUDIO_FIFO_UNDERRUN BIT(29)
#define AUDIO_ORDER_UNDERRUN BIT(28)
#define VIDEO_DATA_FIFO_UNDERRUN BIT(27)
#define VIDEO_ORDER_UNDERRUN BIT(26)
#define CMD_FIFO_UNDERRUN BIT(25)
#define E1_ORDER_MIS BIT(15)
#define E0_ORDER_MIS BIT(14)
#define AUDIO_FIFO_OVERFLOW BIT(13)
#define AUDIO_ORDER_OVERFLOW BIT(12)
#define VIDEO_DATA_FIFO_OVERFLOW GENMASK(11, 8)
#define VIDEO_ORDER_OVERFLOW GENMASK(7, 4)
#define CMD_FIFO_OVERFLOW GENMASK(3, 0)
#define RKLINK_DES_SINK_IRQ_EN LINK_REG(0x0088)
#define COMP_NOT_ENOUGH_IRQ_FLAG BIT(26)
#define VIDEO_FM_IRQ_FLAG BIT(25)
#define AUDIO_FM_IRQ_FLAG BIT(24)
#define ORDER_MIS_IRQ_FLAG BIT(23)
#define FIFO_UNDERRUN_IRQ_FLAG BIT(22)
#define FIFO_OVERFLOW_IRQ_FLAG BIT(21)
#define PKT_LOSE_IRQ_FLAG BIT(20)
#define LAST_ERROR_IRQ_FLAG BIT(19)
#define ECC2BIT_ERROR_IRQ_FLAG BIT(18)
#define ECC1BIT_ERROR_IRQ_FLAG BIT(17)
#define CRC_ERROR_IRQ_FLAG BIT(16)
#define COMP_NOT_ENOUGH_IRQ_OUTPUT_EN BIT(10)
#define VIDEO_FM_IRQ_OUTPUT_EN BIT(9)
#define AUDIO_FM_IRQ_OUTPUT_EN BIT(8)
#define ORDER_MIS_IRQ_OUTPUT_EN BIT(7)
#define FIFO_UNDERRUN_IRQ_OUTPUT_EN BIT(6)
#define FIFO_OVERFLOW_IRQ_OUTPUT_EN BIT(5)
#define PKT_LOSE_IRQ_OUTPUT_EN BIT(4)
#define LAST_ERROR_IRQ_OUTPUT_EN BIT(3)
#define ECC2BIT_ERROR_IRQ_OUTPUT_EN BIT(2)
#define ECC1BIT_ERROR_IRQ_OUTPUT_EN BIT(1)
#define CRC_ERROR_IRQ_OUTPUT_EN BIT(0)
#define DES_RKLINK_STOP_CFG LINK_REG(0x009C)
#define STOP_AUDIO BIT(4)
@@ -147,6 +185,7 @@
#define PCS_REG24(id) PCS_REG(id, 0x24)
#define PCS_REG28(id) PCS_REG(id, 0x28)
#define PCS_REG30(id) PCS_REG(id, 0x30)
#define DES_PCS_INI_EN(x) HIWORD_UPDATE(x, GENMASK(15, 0), 0)
#define PCS_REG34(id) PCS_REG(id, 0x34)
#define PCS_REG40(id) PCS_REG(id, 0x40)
@@ -226,6 +265,19 @@
#define DES_PMA_LOAD0E(id) PMA_REG(id, 0x48)
#define DES_PMA_REG100(id) PMA_REG(id, 0x100)
#define DES_PMA_IRQ_EN(id) PMA_REG(id, 0xF0)
#define FORCE_INITIAL_IRQ_EN HIWORD_UPDATE(1, BIT(6), 6)
#define RX_RDY_NEG_IRQ_EN HIWORD_UPDATE(1, BIT(5), 5)
#define RX_LOS_IRQ_EN HIWORD_UPDATE(1, BIT(4), 4)
#define RX_RDY_TIMEOUT_IRQ_EN HIWORD_UPDATE(1, BIT(2), 2)
#define PLL_LOCK_TIMEOUT_IRQ_EN HIWORD_UPDATE(1, BIT(0), 0)
#define DES_PMA_IRQ_STATUS(id) PMA_REG(id, 0xF4)
#define FORCE_INITIAL_IRQ_STATUS BIT(6)
#define RX_RDY_NEG_IRQ_STATUS BIT(5)
#define RX_LOS_IRQ_STATUS BIT(4)
#define RX_RDY_TIMEOUT_IRQ_STATUS BIT(2)
#define PLL_LOCK_TIMEOUT_IRQ_STATUS BIT(0)
static const struct rk_serdes_pt des_pt[] = {
{
/* gpi_gpo_0 */
@@ -813,3 +865,354 @@ void rkx120_des_pma_enable(struct rk_serdes *serdes, bool enable, u8 pma_id, u8
serdes->i2c_update_bits(client, DES_GRF_SOC_CON4, mask, val);
}
static void rkx120_linkrx_irq_enable(struct rk_serdes *serdes, u8 dev_id)
{
struct i2c_client *client = serdes->chip[dev_id].client;
serdes->i2c_write_reg(client, DES_GRF_IRQ_EN, DES_IRQ_LINK_EN);
serdes->i2c_write_reg(client, RKLINK_DES_SINK_IRQ_EN, FIFO_UNDERRUN_IRQ_OUTPUT_EN |
FIFO_OVERFLOW_IRQ_OUTPUT_EN);
}
static void rkx120_linkrx_irq_disable(struct rk_serdes *serdes, u8 dev_id)
{
struct i2c_client *client = serdes->chip[dev_id].client;
u32 val = 0;
serdes->i2c_write_reg(client, DES_GRF_IRQ_EN, DES_IRQ_LINK_DIS);
serdes->i2c_read_reg(client, RKLINK_DES_SINK_IRQ_EN, &val);
val &= ~(FIFO_UNDERRUN_IRQ_OUTPUT_EN | FIFO_OVERFLOW_IRQ_OUTPUT_EN);
serdes->i2c_write_reg(client, RKLINK_DES_SINK_IRQ_EN, val);
}
static void rkx120_linkrx_fifo_handler(struct rk_serdes *serdes, u8 dev_id)
{
struct i2c_client *client = serdes->chip[dev_id].client;
u32 value;
serdes->i2c_read_reg(client, RKLINK_DES_FIFO_STATUS, &value);
dev_err(serdes->dev, "des rklink fifo status:0x%x\n", value);
if (value & AUDIO_FIFO_UNDERRUN)
dev_err(serdes->dev, "linkrx audio fifo underrun\n");
if (value & AUDIO_ORDER_UNDERRUN)
dev_err(serdes->dev, "linkrx audio order underrun\n");
if (value & VIDEO_DATA_FIFO_UNDERRUN)
dev_err(serdes->dev, "linkrx video data fifo underrun\n");
if (value & VIDEO_ORDER_UNDERRUN)
dev_err(serdes->dev, "linkrx video order underrun\n");
if (value & CMD_FIFO_UNDERRUN)
dev_err(serdes->dev, "linkrx cmd fifo underrun\n");
if (value & E1_ORDER_MIS)
dev_err(serdes->dev, "linkrx e1 order miss\n");
if (value & E0_ORDER_MIS)
dev_err(serdes->dev, "linkrx e0 order miss\n");
if (value & AUDIO_FIFO_OVERFLOW)
dev_err(serdes->dev, "linkrx audio fifo overflow\n");
if (value & AUDIO_ORDER_OVERFLOW)
dev_err(serdes->dev, "linkrx audio order overflow\n");
if (value & VIDEO_DATA_FIFO_OVERFLOW)
dev_err(serdes->dev, "linkrx video data fifo overflow\n");
if (value & VIDEO_ORDER_OVERFLOW)
dev_err(serdes->dev, "linkrx video order overflow\n");
if (value & CMD_FIFO_OVERFLOW)
dev_err(serdes->dev, "linkrx cmd fifo overflow\n");
serdes->i2c_write_reg(client, RKLINK_DES_FIFO_STATUS, value);
}
static void rkx120_linkrx_irq_handler(struct rk_serdes *serdes, u8 dev_id)
{
struct i2c_client *client = serdes->chip[dev_id].client;
u32 flag, value;
int i = 0;
serdes->i2c_read_reg(client, RKLINK_DES_SINK_IRQ_EN, &flag);
flag &= COMP_NOT_ENOUGH_IRQ_FLAG | VIDEO_FM_IRQ_FLAG | AUDIO_FM_IRQ_FLAG |
ORDER_MIS_IRQ_FLAG | FIFO_UNDERRUN_IRQ_FLAG | FIFO_OVERFLOW_IRQ_FLAG |
PKT_LOSE_IRQ_FLAG | LAST_ERROR_IRQ_FLAG | ECC2BIT_ERROR_IRQ_FLAG |
ECC1BIT_ERROR_IRQ_FLAG | CRC_ERROR_IRQ_FLAG;
dev_info(serdes->dev, "linkrx irq flag:0x%08x\n", flag);
while (flag) {
switch (flag & BIT(i)) {
case COMP_NOT_ENOUGH_IRQ_FLAG:
break;
case VIDEO_FM_IRQ_FLAG:
break;
case AUDIO_FM_IRQ_FLAG:
break;
case ORDER_MIS_IRQ_FLAG:
case FIFO_UNDERRUN_IRQ_FLAG:
case FIFO_OVERFLOW_IRQ_FLAG:
flag &= ~(ORDER_MIS_IRQ_FLAG | FIFO_UNDERRUN_IRQ_FLAG |
FIFO_OVERFLOW_IRQ_FLAG);
rkx120_linkrx_fifo_handler(serdes, dev_id);
break;
case PKT_LOSE_IRQ_FLAG:
/* clear pkt lost irq flag */
serdes->i2c_read_reg(client, RKLINK_DES_LANE_ENGINE_CFG, &value);
value |= LANE0_PKT_LOSE_NUM_CLR | LANE1_PKT_LOSE_NUM_CLR;
serdes->i2c_write_reg(client, RKLINK_DES_LANE_ENGINE_CFG, value);
break;
case LAST_ERROR_IRQ_FLAG:
case ECC2BIT_ERROR_IRQ_FLAG:
case ECC1BIT_ERROR_IRQ_FLAG:
case CRC_ERROR_IRQ_FLAG:
flag &= ~(LAST_ERROR_IRQ_FLAG | ECC2BIT_ERROR_IRQ_FLAG |
ECC1BIT_ERROR_IRQ_FLAG | CRC_ERROR_IRQ_FLAG);
serdes->i2c_read_reg(client, RKLINK_DES_SINK_IRQ_EN, &value);
dev_info(serdes->dev, "linkrx ecc crc result:0x%08x\n", value);
/* clear ecc crc irq flag */
serdes->i2c_write_reg(client, RKLINK_DES_SINK_IRQ_EN, value);
break;
default:
break;
}
flag &= ~BIT(i);
i++;
}
}
static void rkx120_pcs_irq_enable(struct rk_serdes *serdes, u8 pcs_id, u8 dev_id)
{
struct i2c_client *client = serdes->chip[dev_id].client;
u32 val = 0;
val = pcs_id ? DES_IRQ_PCS1_EN : DES_IRQ_PCS0_EN;
serdes->i2c_write_reg(client, DES_GRF_IRQ_EN, val);
serdes->i2c_write_reg(client, PCS_REG30(pcs_id), DES_PCS_INI_EN(0xffff));
}
static void rkx120_pcs_irq_disable(struct rk_serdes *serdes, u8 pcs_id, u8 dev_id)
{
struct i2c_client *client = serdes->chip[dev_id].client;
u32 val = 0;
val = pcs_id ? DES_IRQ_PCS1_DIS : DES_IRQ_PCS0_DIS;
serdes->i2c_write_reg(client, DES_GRF_IRQ_EN, val);
serdes->i2c_write_reg(client, PCS_REG30(pcs_id), DES_PCS_INI_EN(0));
}
static void rkx120_pcs_irq_handler(struct rk_serdes *serdes, u8 pcs_id, u8 dev_id)
{
struct i2c_client *client = serdes->chip[dev_id].client;
u32 value;
serdes->i2c_read_reg(client, PCS_REG20(pcs_id), &value);
dev_info(serdes->dev, "des pcs%d fatal status:0x%08x\n", pcs_id, value);
/* clear fatal status */
serdes->i2c_write_reg(client, PCS_REG10(pcs_id), 0xffffffff);
serdes->i2c_write_reg(client, PCS_REG10(pcs_id), 0xffff0000);
}
static void rkx120_pma_irq_enable(struct rk_serdes *serdes, u8 pcs_id, u8 dev_id)
{
struct i2c_client *client = serdes->chip[dev_id].client;
u32 val = 0;
val = pcs_id ? DES_IRQ_PMA_ADAPT1_EN : DES_IRQ_PMA_ADAPT0_EN;
serdes->i2c_write_reg(client, DES_GRF_IRQ_EN, val);
serdes->i2c_write_reg(client, DES_PMA_IRQ_EN(pcs_id), FORCE_INITIAL_IRQ_EN |
RX_RDY_NEG_IRQ_EN | RX_LOS_IRQ_EN | RX_RDY_TIMEOUT_IRQ_EN |
PLL_LOCK_TIMEOUT_IRQ_EN);
}
static void rkx120_pma_irq_disable(struct rk_serdes *serdes, u8 pcs_id, u8 dev_id)
{
struct i2c_client *client = serdes->chip[dev_id].client;
u32 val = 0;
val = pcs_id ? DES_IRQ_PMA_ADAPT1_DIS : DES_IRQ_PMA_ADAPT0_DIS;
serdes->i2c_write_reg(client, DES_GRF_IRQ_EN, val);
serdes->i2c_write_reg(client, DES_PMA_IRQ_EN(pcs_id), 0);
}
static void rkx120_pma_irq_handler(struct rk_serdes *serdes, u8 pcs_id, u8 dev_id)
{
struct i2c_client *client = serdes->chip[dev_id].client;
u32 value;
serdes->i2c_read_reg(client, DES_PMA_IRQ_STATUS(pcs_id), &value);
dev_info(serdes->dev, "des pma%d irq status:0x%08x\n", pcs_id, value);
if (value & FORCE_INITIAL_IRQ_STATUS)
dev_info(serdes->dev, "des pma trig force initial pulse status\n");
else if (value & RX_RDY_NEG_IRQ_STATUS)
dev_info(serdes->dev, "des pma trig rx rdy neg status\n");
else if (value & RX_LOS_IRQ_STATUS)
dev_info(serdes->dev, "des pma trig rx los status\n");
else if (value & RX_RDY_TIMEOUT_IRQ_STATUS)
dev_info(serdes->dev, "des pma trig rx rdy timeout status\n");
else if (value & PLL_LOCK_TIMEOUT_IRQ_STATUS)
dev_info(serdes->dev, "des pma trig pll lock timeout status\n");
/* clear pma irq status */
serdes->i2c_write_reg(client, DES_PMA_IRQ_STATUS(pcs_id), value);
}
static void rkx120_remote_irq_enable(struct rk_serdes *serdes, u8 dev_id)
{
struct i2c_client *client = serdes->chip[dev_id].client;
if (serdes->stream_type == STREAM_CAMERA) {
serdes->i2c_write_reg(client, DES_GRF_IRQ_EN, DES_IRQ_REMOTE_EN);
rkx110_irq_enable(serdes, DEVICE_REMOTE0);
}
}
static void rkx120_remote_irq_disable(struct rk_serdes *serdes, u8 dev_id)
{
struct i2c_client *client = serdes->chip[dev_id].client;
if (serdes->stream_type == STREAM_CAMERA) {
serdes->i2c_write_reg(client, DES_GRF_IRQ_EN, DES_IRQ_REMOTE_DIS);
rkx110_irq_disable(serdes, DEVICE_REMOTE0);
}
}
static void rkx120_remote_irq_handler(struct rk_serdes *serdes, u8 dev_id)
{
if (serdes->stream_type == STREAM_CAMERA)
rkx110_irq_handler(serdes, DEVICE_REMOTE0);
}
void rkx120_irq_enable(struct rk_serdes *serdes, u8 dev_id)
{
/* enable pcs irq */
rkx120_pcs_irq_enable(serdes, 0, dev_id);
/* enable efuse irq */
/* enable gpio irq */
/* enable csitx irq */
/* enable mipi dsi host irq */
/* enable pma adapt irq */
rkx120_pma_irq_enable(serdes, 0, dev_id);
/* enable remote irq and other lane irq */
rkx120_remote_irq_enable(serdes, dev_id);
/* enable pwm irq */
/* enable dvp tx irq */
/* enable link irq */
rkx120_linkrx_irq_enable(serdes, dev_id);
/* enable ext irq */
/* enable ext irq */
}
void rkx120_irq_disable(struct rk_serdes *serdes, u8 dev_id)
{
/* disable pcs irq */
rkx120_pcs_irq_disable(serdes, 0, dev_id);
/* disable efuse irq */
/* disable gpio irq */
/* disable csitx irq */
/* disable mipi dsi host irq */
/* disable pma adapt irq */
rkx120_pma_irq_disable(serdes, 0, dev_id);
/* disable remote irq */
rkx120_remote_irq_disable(serdes, dev_id);
/* disable pwm irq */
/* disable dvp tx irq */
/* disable link irq */
rkx120_linkrx_irq_disable(serdes, dev_id);
/* disable ext irq */
}
int rkx120_irq_handler(struct rk_serdes *serdes, u8 dev_id)
{
struct i2c_client *client = serdes->chip[dev_id].client;
u32 status = 0;
u32 mask = 0;
u32 i = 0;
serdes->i2c_read_reg(client, DES_GRF_IRQ_EN, &mask);
serdes->i2c_read_reg(client, DES_GRF_IRQ_STATUS, &status);
dev_info(serdes->dev, "dev%d get the des irq status:0x%08x\n", dev_id, status);
status &= mask;
while (status) {
switch (status & BIT(i)) {
case DES_IRQ_PCS0:
rkx120_pcs_irq_handler(serdes, 0, dev_id);
break;
case DES_IRQ_PCS1:
rkx120_pcs_irq_handler(serdes, 1, dev_id);
break;
case DES_IRQ_EFUSE:
/* TBD */
break;
case DES_IRQ_GPIO0:
/* TBD */
break;
case DES_IRQ_GPIO1:
/* TBD */
break;
case DES_IRQ_CSITX0:
/* TBD */
break;
case DES_IRQ_CSITX1:
/* TBD */
break;
case DES_IRQ_MIPI_DSI_HOST:
/* TBD */
break;
case DES_IRQ_PMA_ADAPT0:
rkx120_pma_irq_handler(serdes, 0, dev_id);
break;
case DES_IRQ_PMA_ADAPT1:
rkx120_pma_irq_handler(serdes, 1, dev_id);
break;
case DES_IRQ_REMOTE:
rkx120_remote_irq_handler(serdes, dev_id);
break;
case DES_IRQ_PWM:
/* TBD */
break;
case DES_IRQ_DVP_TX:
/* TBD */
break;
case DES_IRQ_LINK:
rkx120_linkrx_irq_handler(serdes, dev_id);
break;
case DES_IRQ_EXT:
/* TBD */
break;
case DES_IRQ_OTHER_LANE:
/* TBD */
break;
default:
break;
}
status &= ~BIT(i);
i++;
}
return 0;
}

View File

@@ -328,6 +328,8 @@ enum {
#define DES_GRF_SOC_CON5 GRF_REG(0x114)
#define DES_GRF_SOC_CON6 GRF_REG(0x118)
#define DES_GRF_SOC_CON7 GRF_REG(0x11C)
#define DES_GRF_IRQ_EN GRF_REG(0x140)
#define DES_GRF_IRQ_STATUS GRF_REG(0x150)
enum {
/* SOC_CON0 */
@@ -433,6 +435,71 @@ enum {
/* SOC_CON9 */
/* DES_GRF_IRQ_EN */
DES_IRQ_OTHER_LANE_EN = HIWORD_UPDATE(1, BIT(15), 15),
DES_IRQ_OTHER_LANE_DIS = HIWORD_UPDATE(0, BIT(15), 15),
DES_IRQ_EXT_EN = HIWORD_UPDATE(1, BIT(14), 14),
DES_IRQ_EXT_DIS = HIWORD_UPDATE(0, BIT(14), 14),
DES_IRQ_LINK_EN = HIWORD_UPDATE(1, BIT(13), 13),
DES_IRQ_LINK_DIS = HIWORD_UPDATE(0, BIT(13), 13),
DES_IRQ_DVP_TX_EN = HIWORD_UPDATE(1, BIT(12), 12),
DES_IRQ_DVP_TX_DIS = HIWORD_UPDATE(0, BIT(12), 12),
DES_IRQ_PWM_EN = HIWORD_UPDATE(1, BIT(11), 11),
DES_IRQ_PWM_DIS = HIWORD_UPDATE(0, BIT(11), 11),
DES_IRQ_REMOTE_EN = HIWORD_UPDATE(1, BIT(10), 10),
DES_IRQ_REMOTE_DIS = HIWORD_UPDATE(0, BIT(10), 10),
DES_IRQ_PMA_ADAPT1_EN = HIWORD_UPDATE(1, BIT(9), 9),
DES_IRQ_PMA_ADAPT1_DIS = HIWORD_UPDATE(0, BIT(9), 9),
DES_IRQ_PMA_ADAPT0_EN = HIWORD_UPDATE(1, BIT(8), 8),
DES_IRQ_PMA_ADAPT0_DIS = HIWORD_UPDATE(0, BIT(8), 8),
DES_IRQ_MIPI_DSI_HOST_EN = HIWORD_UPDATE(1, BIT(7), 7),
DES_IRQ_MIPI_DSI_HOST_DIS = HIWORD_UPDATE(0, BIT(7), 7),
DES_IRQ_CSITX1_EN = HIWORD_UPDATE(1, BIT(6), 6),
DES_IRQ_CSITX1_DIS = HIWORD_UPDATE(0, BIT(6), 6),
DES_IRQ_CSITX0_EN = HIWORD_UPDATE(1, BIT(5), 5),
DES_IRQ_CSITX0_DIS = HIWORD_UPDATE(0, BIT(5), 5),
DES_IRQ_GPIO1_EN = HIWORD_UPDATE(1, BIT(4), 4),
DES_IRQ_GPIO1_DIS = HIWORD_UPDATE(0, BIT(4), 4),
DES_IRQ_GPIO0_EN = HIWORD_UPDATE(1, BIT(3), 3),
DES_IRQ_GPIO0_DIS = HIWORD_UPDATE(0, BIT(3), 3),
DES_IRQ_EFUSE_EN = HIWORD_UPDATE(1, BIT(2), 2),
DES_IRQ_EFUSE_DIS = HIWORD_UPDATE(0, BIT(2), 2),
DES_IRQ_PCS1_EN = HIWORD_UPDATE(1, BIT(1), 1),
DES_IRQ_PCS1_DIS = HIWORD_UPDATE(0, BIT(1), 1),
DES_IRQ_PCS0_EN = HIWORD_UPDATE(1, BIT(0), 0),
DES_IRQ_PCS0_DIS = HIWORD_UPDATE(0, BIT(0), 0),
/* DES_GRF_IRQ_STATUS */
DES_IRQ_PCS0 = BIT(0),
DES_IRQ_PCS1 = BIT(1),
DES_IRQ_EFUSE = BIT(2),
DES_IRQ_GPIO0 = BIT(3),
DES_IRQ_GPIO1 = BIT(4),
DES_IRQ_CSITX0 = BIT(5),
DES_IRQ_CSITX1 = BIT(6),
DES_IRQ_MIPI_DSI_HOST = BIT(7),
DES_IRQ_PMA_ADAPT0 = BIT(8),
DES_IRQ_PMA_ADAPT1 = BIT(9),
DES_IRQ_REMOTE = BIT(10),
DES_IRQ_PWM = BIT(11),
DES_IRQ_DVP_TX = BIT(12),
DES_IRQ_LINK = BIT(13),
DES_IRQ_EXT = BIT(14),
DES_IRQ_OTHER_LANE = BIT(15),
/* DES_GRF_SOC_STATUS0 */
DES_PCS1_READY = BIT(1),

View File

@@ -155,6 +155,10 @@ static unsigned int dw_wdt_get_min_timeout(struct dw_wdt *dw_wdt)
break;
}
/* For Coverity check */
if (idx == DW_WDT_NUM_TOPS)
idx = 0;
return dw_wdt->timeouts[idx].sec;
}
@@ -178,6 +182,9 @@ static unsigned int dw_wdt_get_timeout(struct dw_wdt *dw_wdt)
break;
}
if (idx == DW_WDT_NUM_TOPS)
idx = 0;
/*
* In IRQ mode due to the two stages counter, the actual timeout is
* twice greater than the TOP setting.