diff --git a/arch/arm64/boot/dts/rockchip/rk3576s-evb.dtsi b/arch/arm64/boot/dts/rockchip/rk3576s-evb.dtsi index 4df3eacfaa49..d743c12c4b82 100644 --- a/arch/arm64/boot/dts/rockchip/rk3576s-evb.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3576s-evb.dtsi @@ -805,10 +805,6 @@ status = "okay"; }; -&u2phy1 { - status = "okay"; -}; - &u2phy0_otg { status = "okay"; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3576s.dtsi b/arch/arm64/boot/dts/rockchip/rk3576s.dtsi index 4a19f63614b9..7389b5451347 100644 --- a/arch/arm64/boot/dts/rockchip/rk3576s.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3576s.dtsi @@ -63,4 +63,5 @@ /delete-node/ &sata1; /delete-node/ &usb_drd1_dwc3; /delete-node/ &u2phy1_otg; +/delete-node/ &u2phy1; /delete-node/ &vopl; diff --git a/drivers/clk/rockchip/clk-pvtpll.c b/drivers/clk/rockchip/clk-pvtpll.c index 0900b6716a61..860993008ed9 100644 --- a/drivers/clk/rockchip/clk-pvtpll.c +++ b/drivers/clk/rockchip/clk-pvtpll.c @@ -30,6 +30,8 @@ #define RV1103B_GCK_RING_LEN_SEL_MASK 0x1ff #define RV1103B_GCK_RING_SEL_OFFSET 10 #define RV1103B_GCK_RING_SEL_MASK 0x07 +#define RV1103B_PVTPLL_MAX_LENGTH 0x1ff +#define RV1103B_PVTPLL_GCK_CNT_AVG 0x54 #define RK3506_GRF_CORE_PVTPLL_CON0_L 0x00 #define RK3506_GRF_CORE_PVTPLL_CON0_H 0x04 @@ -56,8 +58,12 @@ struct rockchip_clock_pvtpll_info { struct pvtpll_table *table; unsigned int jm_table_size; struct pvtpll_table *jm_table; + unsigned int pvtpll_adjust_factor; + unsigned int calibrate_length_step; + unsigned int calibrate_freq_per_step; int (*config)(struct rockchip_clock_pvtpll *pvtpll, struct pvtpll_table *table); + int (*pvtpll_calibrate)(struct rockchip_clock_pvtpll *pvtpll); int (*pvtpll_volt_sel_adjust)(struct rockchip_clock_pvtpll *pvtpll, u32 clock_id, u32 volt_sel); @@ -74,6 +80,7 @@ struct rockchip_clock_pvtpll { struct clk *pvtpll_clk; struct clk *pvtpll_out; struct notifier_block pvtpll_nb; + struct delayed_work pvtpll_calibrate_work; unsigned long cur_rate; u32 pvtpll_clk_id; }; @@ -105,21 +112,31 @@ struct otp_opp_info { static struct pvtpll_table rv1103b_core_pvtpll_table[] = { /* rate_hz, ring_sel, length */ - ROCKCHIP_PVTPLL(1608000000, 1, 6), - ROCKCHIP_PVTPLL(1512000000, 1, 6), - ROCKCHIP_PVTPLL(1416000000, 1, 6), - ROCKCHIP_PVTPLL(1296000000, 1, 6), - ROCKCHIP_PVTPLL(1200000000, 1, 14), - ROCKCHIP_PVTPLL(1008000000, 1, 32), - ROCKCHIP_PVTPLL(816000000, 1, 60), + ROCKCHIP_PVTPLL_VOLT_SEL(1608000000, 1, 6, 7), + ROCKCHIP_PVTPLL_VOLT_SEL(1512000000, 1, 6, 6), + ROCKCHIP_PVTPLL_VOLT_SEL(1416000000, 1, 6, 6), + ROCKCHIP_PVTPLL_VOLT_SEL(1296000000, 1, 6, 5), + ROCKCHIP_PVTPLL_VOLT_SEL(1200000000, 1, 6, 3), + ROCKCHIP_PVTPLL_VOLT_SEL(1008000000, 1, 26, 3), + ROCKCHIP_PVTPLL_VOLT_SEL(816000000, 1, 50, 3), +}; + +static struct pvtpll_table rv1103b_enc_pvtpll_table[] = { + /* rate_hz, ring_se, length */ + ROCKCHIP_PVTPLL(500000000, 1, 80), +}; + +static struct pvtpll_table rv1103b_isp_pvtpll_table[] = { + /* rate_hz, ring_se, length */ + ROCKCHIP_PVTPLL(400000000, 1, 160), }; static struct pvtpll_table rv1103b_npu_pvtpll_table[] = { /* rate_hz, ring_se, length */ - ROCKCHIP_PVTPLL(1000000000, 1, 12), - ROCKCHIP_PVTPLL(900000000, 1, 12), - ROCKCHIP_PVTPLL(800000000, 1, 16), - ROCKCHIP_PVTPLL(700000000, 1, 36), + ROCKCHIP_PVTPLL_VOLT_SEL(1000000000, 1, 12, 7), + ROCKCHIP_PVTPLL_VOLT_SEL(900000000, 1, 12, 6), + ROCKCHIP_PVTPLL_VOLT_SEL(800000000, 1, 12, 4), + ROCKCHIP_PVTPLL_VOLT_SEL(700000000, 1, 32, 4), }; static struct pvtpll_table rk3506_core_pvtpll_table[] = { @@ -230,6 +247,15 @@ static int rockchip_clock_pvtpll_set_rate(struct clk_hw *hw, if (!pvtpll) return 0; + /* + * The calibration is only for the init frequency of pvtpll on the platform + * which regulator is fixed, if the frequency will be change, we assume that + * dvfs is working, so just cancel the calibration work and use the pvtpll + * configuration from pvtpll_table, it will match the opp-table. + */ + if (pvtpll->info->pvtpll_calibrate) + cancel_delayed_work_sync(&pvtpll->pvtpll_calibrate_work); + table = rockchip_get_pvtpll_settings(pvtpll, rate); if (!table) return 0; @@ -302,12 +328,13 @@ static int clock_pvtpll_regitstor(struct device *dev, pvtpll->pvtpll_out); } -static int rk3506_pvtpll_volt_sel_adjust(struct rockchip_clock_pvtpll *pvtpll, +static int pvtpll_volt_sel_adjust_linear(struct rockchip_clock_pvtpll *pvtpll, u32 clock_id, u32 volt_sel) { struct pvtpll_table *table = pvtpll->info->table; unsigned int size = pvtpll->info->table_size; + unsigned int factor = pvtpll->info->pvtpll_adjust_factor; uint32_t delta_len = 0; int i; @@ -315,10 +342,14 @@ static int rk3506_pvtpll_volt_sel_adjust(struct rockchip_clock_pvtpll *pvtpll, if (!table[i].volt_sel_thr) continue; if (volt_sel >= table[i].volt_sel_thr) { - delta_len = volt_sel - table[i].volt_sel_thr + 1; + delta_len = (volt_sel - table[i].volt_sel_thr + 1) * factor; table[i].length += delta_len; if (table[i].length > RK3506_PVTPLL_MAX_LENGTH) table[i].length = RK3506_PVTPLL_MAX_LENGTH; + + /* update new pvtpll config for current rate */ + if (table[i].rate == pvtpll->cur_rate) + pvtpll->info->config(pvtpll, table + i); } } @@ -422,16 +453,116 @@ static void rockchip_adjust_pvtpll_by_otp(struct device *dev, } } +static int rv1103b_pvtpll_calibrate(struct rockchip_clock_pvtpll *pvtpll) +{ + unsigned int rate, delta, length, length_ori, val, i = 0; + unsigned int length_step = pvtpll->info->calibrate_length_step; + unsigned int freq_per_step = pvtpll->info->calibrate_freq_per_step; + unsigned long target_rate = pvtpll->cur_rate / MHz; + int ret; + + ret = regmap_read(pvtpll->regmap, RV1103B_PVTPLL_GCK_CNT_AVG, &rate); + if (ret) + return ret; + + if (rate < target_rate) + return 0; + + /* delta < (6.25% * target_rate) */ + if ((rate - target_rate) < (target_rate >> 4)) + return 0; + + ret = regmap_read(pvtpll->regmap, RV1103B_PVTPLL_GCK_LEN, &val); + if (ret) + return ret; + length_ori = (val >> RV1103B_GCK_RING_LEN_SEL_OFFSET) & RV1103B_GCK_RING_LEN_SEL_MASK; + length = length_ori; + delta = rate - target_rate; + length += (delta / freq_per_step) * length_step; + val = HIWORD_UPDATE(length, RV1103B_GCK_RING_LEN_SEL_MASK, + RV1103B_GCK_RING_LEN_SEL_OFFSET); + ret = regmap_write(pvtpll->regmap, RV1103B_PVTPLL_GCK_LEN, val); + if (ret) + return ret; + usleep_range(2000, 2100); + ret = regmap_read(pvtpll->regmap, RV1103B_PVTPLL_GCK_CNT_AVG, &rate); + if (ret) + return ret; + + while ((rate < target_rate) || ((rate - target_rate) > (target_rate >> 4))) { + if (i++ > 20) + break; + + if (rate > target_rate) + length += length_step; + else + length -= length_step; + if (length < length_ori) + break; + + val = HIWORD_UPDATE(length, RV1103B_GCK_RING_LEN_SEL_MASK, + RV1103B_GCK_RING_LEN_SEL_OFFSET); + ret = regmap_write(pvtpll->regmap, RV1103B_PVTPLL_GCK_LEN, val); + if (ret) + return ret; + usleep_range(2000, 2100); + ret = regmap_read(pvtpll->regmap, RV1103B_PVTPLL_GCK_CNT_AVG, &rate); + if (ret) + return ret; + } + + return 0; +} + +static void rockchip_pvtpll_calibrate(struct work_struct *work) +{ + struct rockchip_clock_pvtpll *pvtpll; + int ret; + + pvtpll = container_of(work, struct rockchip_clock_pvtpll, pvtpll_calibrate_work.work); + + if (pvtpll->info->pvtpll_calibrate) { + ret = pvtpll->info->pvtpll_calibrate(pvtpll); + if (ret) + dev_warn(pvtpll->dev, "%s: calibrate error, ret %d\n", __func__, ret); + } +} + static const struct rockchip_clock_pvtpll_info rv1103b_core_pvtpll_data = { .config = rv1103b_pvtpll_configs, .table_size = ARRAY_SIZE(rv1103b_core_pvtpll_table), .table = rv1103b_core_pvtpll_table, + .pvtpll_adjust_factor = 4, + .pvtpll_volt_sel_adjust = pvtpll_volt_sel_adjust_linear, + .calibrate_length_step = 2, + .calibrate_freq_per_step = 30, + .pvtpll_calibrate = rv1103b_pvtpll_calibrate, +}; + +static const struct rockchip_clock_pvtpll_info rv1103b_enc_pvtpll_data = { + .config = rv1103b_pvtpll_configs, + .table_size = ARRAY_SIZE(rv1103b_enc_pvtpll_table), + .table = rv1103b_enc_pvtpll_table, + .calibrate_length_step = 8, + .calibrate_freq_per_step = 25, + .pvtpll_calibrate = rv1103b_pvtpll_calibrate, +}; + +static const struct rockchip_clock_pvtpll_info rv1103b_isp_pvtpll_data = { + .config = rv1103b_pvtpll_configs, + .table_size = ARRAY_SIZE(rv1103b_isp_pvtpll_table), + .table = rv1103b_isp_pvtpll_table, }; static const struct rockchip_clock_pvtpll_info rv1103b_npu_pvtpll_data = { .config = rv1103b_pvtpll_configs, .table_size = ARRAY_SIZE(rv1103b_npu_pvtpll_table), .table = rv1103b_npu_pvtpll_table, + .pvtpll_adjust_factor = 6, + .pvtpll_volt_sel_adjust = pvtpll_volt_sel_adjust_linear, + .calibrate_length_step = 4, + .calibrate_freq_per_step = 25, + .pvtpll_calibrate = rv1103b_pvtpll_calibrate, }; static const struct rockchip_clock_pvtpll_info rk3506_core_pvtpll_data = { @@ -440,7 +571,8 @@ static const struct rockchip_clock_pvtpll_info rk3506_core_pvtpll_data = { .table = rk3506_core_pvtpll_table, .jm_table_size = ARRAY_SIZE(rk3506j_core_pvtpll_table), .jm_table = rk3506j_core_pvtpll_table, - .pvtpll_volt_sel_adjust = rk3506_pvtpll_volt_sel_adjust, + .pvtpll_adjust_factor = 1, + .pvtpll_volt_sel_adjust = pvtpll_volt_sel_adjust_linear, }; static const struct of_device_id rockchip_clock_pvtpll_match[] = { @@ -448,6 +580,14 @@ static const struct of_device_id rockchip_clock_pvtpll_match[] = { .compatible = "rockchip,rv1103b-core-pvtpll", .data = (void *)&rv1103b_core_pvtpll_data, }, + { + .compatible = "rockchip,rv1103b-enc-pvtpll", + .data = (void *)&rv1103b_enc_pvtpll_data, + }, + { + .compatible = "rockchip,rv1103b-isp-pvtpll", + .data = (void *)&rv1103b_isp_pvtpll_data, + }, { .compatible = "rockchip,rv1103b-npu-pvtpll", .data = (void *)&rv1103b_npu_pvtpll_data, @@ -480,7 +620,9 @@ static int rockchip_clock_pvtpll_probe(struct platform_device *pdev) if (IS_ERR(pvtpll->regmap)) return PTR_ERR(pvtpll->regmap); + pvtpll->dev = dev; pvtpll->pvtpll_clk_id = UINT_MAX; + INIT_DELAYED_WORK(&pvtpll->pvtpll_calibrate_work, rockchip_pvtpll_calibrate); error = of_parse_phandle_with_args(np, "clocks", "#clock-cells", 0, &clkspec); @@ -501,6 +643,11 @@ static int rockchip_clock_pvtpll_probe(struct platform_device *pdev) return error; } + if (pvtpll->info->pvtpll_calibrate) + queue_delayed_work(system_freezable_wq, + &pvtpll->pvtpll_calibrate_work, + 0); + mutex_lock(&pvtpll_list_mutex); list_add(&pvtpll->list_head, &rockchip_clock_pvtpll_list); mutex_unlock(&pvtpll_list_mutex); diff --git a/drivers/mtd/nand/spi/unim.c b/drivers/mtd/nand/spi/unim.c index 094983974468..f43513d8083d 100644 --- a/drivers/mtd/nand/spi/unim.c +++ b/drivers/mtd/nand/spi/unim.c @@ -183,6 +183,31 @@ static int um19a9xisw_ecc_get_status(struct spinand_device *spinand, } } +/* + * ecc bits: 0xC0[4,6] + * [0b000], No bit errors were detected; + * [0b001], Bit errors were detected and corrected; + * [0b010], Bit errors greater than ECC capability(8 bits) and not corrected; + * [0b011], Bit error count equals the bit flip detection threshold + * [0b100], Reserved; + * [0b101], Bit error count equals the bit flip detection threshold + * [0b110], Reserved; + * [0b111], Invalid; + */ +static int um19a0xisw_ecc_ecc_get_status(struct spinand_device *spinand, + u8 status) +{ + struct nand_device *nand = spinand_to_nand(spinand); + u8 eccsr = (status & GENMASK(6, 4)) >> 4; + + if (eccsr <= 1) + return eccsr; + else if (eccsr == 3 || eccsr == 5) + return nanddev_get_ecc_requirements(nand)->strength; + else + return -EBADMSG; +} + static const struct spinand_info unim_zl_spinand_table[] = { SPINAND_INFO("TX25G01", SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xF1), @@ -250,6 +275,24 @@ static const struct spinand_info unim_spinand_table[] = { &update_cache_variants), SPINAND_HAS_QE_BIT, SPINAND_ECCINFO(&um19a1xisw_ooblayout, um19a9xisw_ecc_get_status)), + SPINAND_INFO("UM19A0HISW", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x14), + NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1), + NAND_ECCREQ(8, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, + &write_cache_variants, + &update_cache_variants), + SPINAND_HAS_QE_BIT, + SPINAND_ECCINFO(&um19a0xisw_ooblayout, um19a0xisw_ecc_ecc_get_status)), + SPINAND_INFO("UM19A0LISW", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x15), + NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1), + NAND_ECCREQ(8, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, + &write_cache_variants, + &update_cache_variants), + SPINAND_HAS_QE_BIT, + SPINAND_ECCINFO(&um19a0xisw_ooblayout, um19a0xisw_ecc_ecc_get_status)), }; static const struct spinand_manufacturer_ops unim_spinand_manuf_ops = { diff --git a/drivers/mtd/nand/spi/xtx.c b/drivers/mtd/nand/spi/xtx.c index ee705de096c9..7c60987cf569 100644 --- a/drivers/mtd/nand/spi/xtx.c +++ b/drivers/mtd/nand/spi/xtx.c @@ -404,6 +404,42 @@ static const struct spinand_info xtx_spinand_table[] = { &update_cache_variants), SPINAND_HAS_QE_BIT, SPINAND_ECCINFO(&xt26g01c_ooblayout, xt26g11c_ecc_get_status)), + SPINAND_INFO("XT26G12DWSIGA", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x35), + NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1), + NAND_ECCREQ(8, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, + &write_cache_variants, + &update_cache_variants), + SPINAND_HAS_QE_BIT, + SPINAND_ECCINFO(&xt26g01c_ooblayout, xt26g11c_ecc_get_status)), + SPINAND_INFO("XT26Q12DWSIGA", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x55), + NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1), + NAND_ECCREQ(8, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, + &write_cache_variants, + &update_cache_variants), + SPINAND_HAS_QE_BIT, + SPINAND_ECCINFO(&xt26g01c_ooblayout, xt26g11c_ecc_get_status)), + SPINAND_INFO("XT26G11DWSIGA", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x34), + NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1), + NAND_ECCREQ(8, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, + &write_cache_variants, + &update_cache_variants), + SPINAND_HAS_QE_BIT, + SPINAND_ECCINFO(&xt26g01c_ooblayout, xt26g11c_ecc_get_status)), + SPINAND_INFO("XT26Q14DWSIGA", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x56), + NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 1), + NAND_ECCREQ(8, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, + &write_cache_variants, + &update_cache_variants), + SPINAND_HAS_QE_BIT, + SPINAND_ECCINFO(&xt26g01c_ooblayout, xt26g11c_ecc_get_status)), }; static const struct spinand_manufacturer_ops xtx_spinand_manuf_ops = { diff --git a/drivers/mtd/spi-nor/xmc.c b/drivers/mtd/spi-nor/xmc.c index 747c0577aecf..c2a5ccbfee01 100644 --- a/drivers/mtd/spi-nor/xmc.c +++ b/drivers/mtd/spi-nor/xmc.c @@ -37,6 +37,9 @@ static const struct flash_info xmc_nor_parts[] = { { "XM25QU128C", INFO(0x204118, 0, 64 * 1024, 256) NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, + { "XM25QU256C", INFO(0x204119, 0, 64 * 1024, 512) + NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ | + SPI_NOR_QUAD_READ) }, }; const struct spi_nor_manufacturer spi_nor_xmc = { diff --git a/drivers/pwm/pwm-rockchip.c b/drivers/pwm/pwm-rockchip.c index 3acae9805b21..820d26e42cb1 100644 --- a/drivers/pwm/pwm-rockchip.c +++ b/drivers/pwm/pwm-rockchip.c @@ -73,7 +73,7 @@ /* * regs for pwm v4 */ -#define HIWORD_UPDATE(v, l, h) (((v) << (l)) | (GENMASK(h, l) << 16)) +#define HIWORD_UPDATE(v, l, h) ((((v) << (l)) & GENMASK((h), (l))) | (GENMASK(h, l) << 16)) /* VERSION_ID */ #define VERSION_ID 0x0 @@ -1621,8 +1621,6 @@ static int rockchip_pwm_set_wave_v4(struct pwm_chip *chip, struct pwm_device *pw writel_relaxed(middle, pc->base + WAVE_MIDDLE); writel_relaxed(rpt, pc->base + RPT); - writel_relaxed(WAVE_MAX_INT_EN(config->enable) | WAVE_MIDDLE_INT_EN(config->enable), - pc->base + INT_EN); pc->wave_en = config->enable; @@ -1652,7 +1650,7 @@ int rockchip_pwm_set_wave(struct pwm_device *pwm, struct rockchip_pwm_wave_confi return -EINVAL; } - pc->scaler = DIV_ROUND_CLOSEST_ULL(pc->clk_rate, config->clk_rate * 2); + pc->scaler = DIV_ROUND_CLOSEST_ULL(pc->clk_rate, config->clk_rate) / 2; if (pc->scaler > 256) { dev_err(chip->dev, "Unsupported scale factor %d(max: 512) for PWM%d\n", pc->scaler * 2, pc->channel_id); diff --git a/drivers/video/rockchip/mpp/mpp_common.c b/drivers/video/rockchip/mpp/mpp_common.c index db93061f34b9..ab02cea09f17 100644 --- a/drivers/video/rockchip/mpp/mpp_common.c +++ b/drivers/video/rockchip/mpp/mpp_common.c @@ -550,7 +550,9 @@ static void mpp_task_timeout_work(struct work_struct *work_s) } disable_irq(mpp->irq); if (test_and_set_bit(TASK_STATE_HANDLE, &task->state)) { - mpp_err("task has been handled\n"); + mpp_err("session %d:%d task %d has been handled\n", + session->device_type, session->index, task->task_index); + enable_irq(mpp->irq); return; } mpp_err("session %d:%d task %d processing time out!\n",