Re: [PATCH v6 05/12] pinctrl: Ingenic: Add DMIC pins support for Ingenic SoCs.

2021-04-19 Thread Paul Cercueil

Hi Zhou,

Le dim. 18 avril 2021 à 22:44, 周琰杰 (Zhou Yanjie) 
 a écrit :

1.Add DMIC pins support for the JZ4780 SoC.
2.Add DMIC pins support for the X1000 SoC.
3.Add DMIC pins support for the X1500 SoC.
4.Add DMIC pins support for the X1830 SoC.

Signed-off-by: 周琰杰 (Zhou Yanjie) 


Reviewed-by: Paul Cercueil 

Cheers,
-Paul


---

Notes:
v6:
New patch.

 drivers/pinctrl/pinctrl-ingenic.c | 22 ++
 1 file changed, 22 insertions(+)

diff --git a/drivers/pinctrl/pinctrl-ingenic.c 
b/drivers/pinctrl/pinctrl-ingenic.c

index 8ed62a4..b57433d 100644
--- a/drivers/pinctrl/pinctrl-ingenic.c
+++ b/drivers/pinctrl/pinctrl-ingenic.c
@@ -941,6 +941,7 @@ static int jz4780_i2s_data_rx_pins[] = { 0x86, };
 static int jz4780_i2s_clk_txrx_pins[] = { 0x6c, 0x6d, };
 static int jz4780_i2s_clk_rx_pins[] = { 0x88, 0x89, };
 static int jz4780_i2s_sysclk_pins[] = { 0x85, };
+static int jz4780_dmic_pins[] = { 0x32, 0x33, };
 static int jz4780_hdmi_ddc_pins[] = { 0xb9, 0xb8, };

 static u8 jz4780_i2s_clk_txrx_funcs[] = { 1, 0, };
@@ -1039,6 +1040,7 @@ static const struct group_desc jz4780_groups[] 
= {

jz4780_i2s_clk_txrx_funcs),
INGENIC_PIN_GROUP("i2s-clk-rx", jz4780_i2s_clk_rx, 1),
INGENIC_PIN_GROUP("i2s-sysclk", jz4780_i2s_sysclk, 2),
+   INGENIC_PIN_GROUP("dmic", jz4780_dmic, 1),
INGENIC_PIN_GROUP("hdmi-ddc", jz4780_hdmi_ddc, 0),
INGENIC_PIN_GROUP("cim-data", jz4770_cim_8bit, 0),
INGENIC_PIN_GROUP("cim-data-12bit", jz4770_cim_12bit, 0),
@@ -1095,6 +1097,7 @@ static const char *jz4780_i2c4_groups[] = { 
"i2c4-data-e", "i2c4-data-f", };

 static const char *jz4780_i2s_groups[] = {
 	"i2s-data-tx", "i2s-data-rx", "i2s-clk-txrx", "i2s-clk-rx", 
"i2s-sysclk",

 };
+static const char *jz4780_dmic_groups[] = { "dmic", };
 static const char *jz4780_cim_groups[] = { "cim-data", };
 static const char *jz4780_hdmi_ddc_groups[] = { "hdmi-ddc", };

@@ -1122,6 +1125,7 @@ static const struct function_desc 
jz4780_functions[] = {

{ "i2c3", jz4780_i2c3_groups, ARRAY_SIZE(jz4780_i2c3_groups), },
{ "i2c4", jz4780_i2c4_groups, ARRAY_SIZE(jz4780_i2c4_groups), },
{ "i2s", jz4780_i2s_groups, ARRAY_SIZE(jz4780_i2s_groups), },
+   { "dmic", jz4780_dmic_groups, ARRAY_SIZE(jz4780_dmic_groups), },
{ "cim", jz4780_cim_groups, ARRAY_SIZE(jz4780_cim_groups), },
{ "lcd", jz4770_lcd_groups, ARRAY_SIZE(jz4770_lcd_groups), },
{ "pwm0", jz4770_pwm0_groups, ARRAY_SIZE(jz4770_pwm0_groups), },
@@ -1207,6 +1211,8 @@ static int x1000_i2s_data_tx_pins[] = { 0x24, };
 static int x1000_i2s_data_rx_pins[] = { 0x23, };
 static int x1000_i2s_clk_txrx_pins[] = { 0x21, 0x22, };
 static int x1000_i2s_sysclk_pins[] = { 0x20, };
+static int x1000_dmic0_pins[] = { 0x35, 0x36, };
+static int x1000_dmic1_pins[] = { 0x25, };
 static int x1000_cim_pins[] = {
0x08, 0x09, 0x0a, 0x0b,
0x13, 0x12, 0x11, 0x10, 0x0f, 0x0e, 0x0d, 0x0c,
@@ -1272,6 +1278,8 @@ static const struct group_desc x1000_groups[] = 
{

INGENIC_PIN_GROUP("i2s-data-rx", x1000_i2s_data_rx, 1),
INGENIC_PIN_GROUP("i2s-clk-txrx", x1000_i2s_clk_txrx, 1),
INGENIC_PIN_GROUP("i2s-sysclk", x1000_i2s_sysclk, 1),
+   INGENIC_PIN_GROUP("dmic0", x1000_dmic0, 0),
+   INGENIC_PIN_GROUP("dmic1", x1000_dmic1, 1),
INGENIC_PIN_GROUP("cim-data", x1000_cim, 2),
INGENIC_PIN_GROUP("lcd-8bit", x1000_lcd_8bit, 1),
INGENIC_PIN_GROUP("lcd-16bit", x1000_lcd_16bit, 1),
@@ -1315,6 +1323,7 @@ static const char *x1000_i2c2_groups[] = { 
"i2c2-data", };

 static const char *x1000_i2s_groups[] = {
"i2s-data-tx", "i2s-data-rx", "i2s-clk-txrx", "i2s-sysclk",
 };
+static const char *x1000_dmic_groups[] = { "dmic0", "dmic1", };
 static const char *x1000_cim_groups[] = { "cim-data", };
 static const char *x1000_lcd_groups[] = { "lcd-8bit", "lcd-16bit", };
 static const char *x1000_pwm0_groups[] = { "pwm0", };
@@ -1339,6 +1348,7 @@ static const struct function_desc 
x1000_functions[] = {

{ "i2c1", x1000_i2c1_groups, ARRAY_SIZE(x1000_i2c1_groups), },
{ "i2c2", x1000_i2c2_groups, ARRAY_SIZE(x1000_i2c2_groups), },
{ "i2s", x1000_i2s_groups, ARRAY_SIZE(x1000_i2s_groups), },
+   { "dmic", x1000_dmic_groups, ARRAY_SIZE(x1000_dmic_groups), },
{ "cim", x1000_cim_groups, ARRAY_SIZE(x1000_cim_groups), },
{ "lcd", x1000_lcd_groups, ARRAY_SIZE(x1000_lcd_groups), },
{ "pwm0", x1000_pwm0_groups, ARRA

Re: [PATCH v5 11/11] pinctrl: Ingenic: Add pinctrl driver for X2000.

2021-04-17 Thread Paul Cercueil
t;version >= ID_X2000) {
+   ingenic_gpio_shadow_set_bit(jzgc, reg2, offset, val1);
+   ingenic_gpio_shadow_set_bit(jzgc, reg1, offset, val2);
+   ingenic_gpio_shadow_set_bit_load(jzgc);
+   ingenic_gpio_set_bit(jzgc, X2000_GPIO_EDG, offset, val3);
+   } else if (jzgc->jzpc->info->version >= ID_X1000) {
ingenic_gpio_shadow_set_bit(jzgc, reg2, offset, val1);
ingenic_gpio_shadow_set_bit(jzgc, reg1, offset, val2);
ingenic_gpio_shadow_set_bit_load(jzgc);
@@ -2501,7 +2963,8 @@ static void ingenic_gpio_irq_ack(struct 
irq_data *irqd)

int irq = irqd->hwirq;
bool high;

-   if (irqd_get_trigger_type(irqd) == IRQ_TYPE_EDGE_BOTH) {
+   if ((irqd_get_trigger_type(irqd) == IRQ_TYPE_EDGE_BOTH) &&
+   (jzgc->jzpc->info->version < ID_X2000)) {
/*
 * Switch to an interrupt for the opposite edge to the one that
 * triggered the interrupt being ACKed.
@@ -2540,7 +3003,7 @@ static int ingenic_gpio_irq_set_type(struct 
irq_data *irqd, unsigned int type)

irq_set_handler_locked(irqd, handle_bad_irq);
}

-   if (type == IRQ_TYPE_EDGE_BOTH) {
+	if ((type == IRQ_TYPE_EDGE_BOTH) && (jzgc->jzpc->info->version < 
ID_X2000)) {

/*
 * The hardware does not support interrupts on both edges. The
 * best we can do is to set up a single-edge interrupt and then
@@ -2613,7 +3076,7 @@ static int ingenic_gpio_direction_output(struct 
gpio_chip *gc,

 }

 static inline void ingenic_config_pin(struct ingenic_pinctrl *jzpc,
-   unsigned int pin, u8 reg, bool set)
+   unsigned int pin, unsigned int reg, bool set)
 {
unsigned int idx = pin % PINS_PER_GPIO_CHIP;
unsigned int offt = pin / PINS_PER_GPIO_CHIP;
@@ -2668,7 +3131,7 @@ static inline void 
jz4730_config_pin_function(struct ingenic_pinctrl *jzpc,

 }

 static inline bool ingenic_get_pin_config(struct ingenic_pinctrl 
*jzpc,

-   unsigned int pin, u8 reg)
+   unsigned int pin, unsigned int reg)
 {
unsigned int idx = pin % PINS_PER_GPIO_CHIP;
unsigned int offt = pin / PINS_PER_GPIO_CHIP;
@@ -2847,10 +3310,19 @@ static int ingenic_pinconf_get(struct 
pinctrl_dev *pctldev,

enum pin_config_param param = pinconf_to_config_param(*config);
unsigned int idx = pin % PINS_PER_GPIO_CHIP;
unsigned int offt = pin / PINS_PER_GPIO_CHIP;
+   unsigned int reg, arg;
unsigned int bias;
bool pull, pullup, pulldown;

-   if (jzpc->info->version >= ID_X1830) {
+   if (jzpc->info->version >= ID_X2000) {
+   pullup = ingenic_get_pin_config(jzpc, pin, X2000_GPIO_PEPU) &&
+   !ingenic_get_pin_config(jzpc, pin, X2000_GPIO_PEPD) 
&&
+   (jzpc->info->pull_ups[offt] & BIT(idx));
+   pulldown = ingenic_get_pin_config(jzpc, pin, X2000_GPIO_PEPD) &&
+   !ingenic_get_pin_config(jzpc, pin, X2000_GPIO_PEPU) 
&&
+   (jzpc->info->pull_downs[offt] & BIT(idx));
+
+   } else if (jzpc->info->version >= ID_X1830) {
unsigned int half = PINS_PER_GPIO_CHIP / 2;
unsigned int idxh = (pin % half) * 2;

@@ -2882,30 +3354,84 @@ static int ingenic_pinconf_get(struct 
pinctrl_dev *pctldev,

case PIN_CONFIG_BIAS_DISABLE:
if (pullup || pulldown)
return -EINVAL;
+
+   arg = 1;


Maybe initialize arg = 1? Then you wouldn't have to set it in every 
single case.



break;

case PIN_CONFIG_BIAS_PULL_UP:
if (!pullup)
return -EINVAL;
+
+   arg = 1;
break;

case PIN_CONFIG_BIAS_PULL_DOWN:
if (!pulldown)
return -EINVAL;
+
+   arg = 1;
+   break;
+
+   case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
+   if (jzpc->info->version >= ID_X2000)
+   reg = X2000_GPIO_SMT;
+   else if (jzpc->info->version >= ID_X1830)
+   reg = X1830_GPIO_SMT;
+   else
+   return -EINVAL;
+
+   if (ingenic_get_pin_config(jzpc, pin, reg))
+   arg = 1;
+   else
+   arg = 0;


arg = !!ingenic_get_pin_config(jzpc, pin, reg)


+
+   break;
+
+   case PIN_CONFIG_SLEW_RATE:
+   if (jzpc->info->version >= ID_X2000)
+   reg = X2000_GPIO_SR;
+   else if (jzpc->info->version >= ID_X1830)
+   reg = X1830_GPIO_SR;
+   else
+  

Re: [PATCH v5 10/11] pinctrl: Ingenic: Add pinctrl driver for JZ4775.

2021-04-17 Thread Paul Cercueil

Hi Zhou,

Le sam. 17 avril 2021 à 0:14, 周琰杰 (Zhou Yanjie) 
 a écrit :

Add support for probing the pinctrl-ingenic driver on the
JZ4775 SoC from Ingenic.

Signed-off-by: 周琰杰 (Zhou Yanjie) 
Reviewed-by: Andy Shevchenko 


Reviewed-by: Paul Cercueil 

Cheers,
-Paul


---

Notes:
v3:
New patch.

v3->v4:
1.Split lcd pins into several groups.
2.Drop "lcd-no-pins" which is pointless.

v4->v5:
No change.

 drivers/pinctrl/pinctrl-ingenic.c | 275 
++

 1 file changed, 275 insertions(+)

diff --git a/drivers/pinctrl/pinctrl-ingenic.c 
b/drivers/pinctrl/pinctrl-ingenic.c

index 3b649fb..9bf9100 100644
--- a/drivers/pinctrl/pinctrl-ingenic.c
+++ b/drivers/pinctrl/pinctrl-ingenic.c
@@ -89,6 +89,7 @@ enum jz_version {
ID_JZ4755,
ID_JZ4760,
ID_JZ4770,
+   ID_JZ4775,
ID_JZ4780,
ID_X1000,
ID_X1500,
@@ -1261,6 +1262,275 @@ static const struct ingenic_chip_info 
jz4770_chip_info = {

.pull_downs = jz4770_pull_downs,
 };

+static const u32 jz4775_pull_ups[7] = {
+	0x28ff00ff, 0xf030f3fc, 0x0fff, 0xfffe4000, 0xf0fc, 
0xf00f, 0xf3c0,

+};
+
+static const u32 jz4775_pull_downs[7] = {
+	0x, 0x00030c03, 0x, 0x8000, 0x0403, 
0x0ff0, 0x00030c00,

+};
+
+static int jz4775_uart0_data_pins[] = { 0xa0, 0xa3, };
+static int jz4775_uart0_hwflow_pins[] = { 0xa1, 0xa2, };
+static int jz4775_uart1_data_pins[] = { 0x7a, 0x7c, };
+static int jz4775_uart1_hwflow_pins[] = { 0x7b, 0x7d, };
+static int jz4775_uart2_data_c_pins[] = { 0x54, 0x4a, };
+static int jz4775_uart2_data_f_pins[] = { 0xa5, 0xa4, };
+static int jz4775_uart3_data_pins[] = { 0x1e, 0x1f, };
+static int jz4775_ssi_dt_a_pins[] = { 0x13, };
+static int jz4775_ssi_dt_d_pins[] = { 0x75, };
+static int jz4775_ssi_dr_a_pins[] = { 0x14, };
+static int jz4775_ssi_dr_d_pins[] = { 0x74, };
+static int jz4775_ssi_clk_a_pins[] = { 0x12, };
+static int jz4775_ssi_clk_d_pins[] = { 0x78, };
+static int jz4775_ssi_gpc_pins[] = { 0x76, };
+static int jz4775_ssi_ce0_a_pins[] = { 0x17, };
+static int jz4775_ssi_ce0_d_pins[] = { 0x79, };
+static int jz4775_ssi_ce1_pins[] = { 0x77, };
+static int jz4775_mmc0_1bit_a_pins[] = { 0x12, 0x13, 0x14, };
+static int jz4775_mmc0_4bit_a_pins[] = { 0x15, 0x16, 0x17, };
+static int jz4775_mmc0_8bit_a_pins[] = { 0x04, 0x05, 0x06, 0x07, };
+static int jz4775_mmc0_1bit_e_pins[] = { 0x9c, 0x9d, 0x94, };
+static int jz4775_mmc0_4bit_e_pins[] = { 0x95, 0x96, 0x97, };
+static int jz4775_mmc1_1bit_d_pins[] = { 0x78, 0x79, 0x74, };
+static int jz4775_mmc1_4bit_d_pins[] = { 0x75, 0x76, 0x77, };
+static int jz4775_mmc1_1bit_e_pins[] = { 0x9c, 0x9d, 0x94, };
+static int jz4775_mmc1_4bit_e_pins[] = { 0x95, 0x96, 0x97, };
+static int jz4775_mmc2_1bit_b_pins[] = { 0x3c, 0x3d, 0x34, };
+static int jz4775_mmc2_4bit_b_pins[] = { 0x35, 0x3e, 0x3f, };
+static int jz4775_mmc2_1bit_e_pins[] = { 0x9c, 0x9d, 0x94, };
+static int jz4775_mmc2_4bit_e_pins[] = { 0x95, 0x96, 0x97, };
+static int jz4775_nemc_8bit_data_pins[] = {
+   0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+};
+static int jz4775_nemc_16bit_data_pins[] = {
+   0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1,
+};
+static int jz4775_nemc_cle_ale_pins[] = { 0x20, 0x21, };
+static int jz4775_nemc_addr_pins[] = { 0x22, 0x23, 0x24, 0x25, };
+static int jz4775_nemc_rd_we_pins[] = { 0x10, 0x11, };
+static int jz4775_nemc_frd_fwe_pins[] = { 0x12, 0x13, };
+static int jz4775_nemc_wait_pins[] = { 0x1b, };
+static int jz4775_nemc_cs1_pins[] = { 0x15, };
+static int jz4775_nemc_cs2_pins[] = { 0x16, };
+static int jz4775_nemc_cs3_pins[] = { 0x17, };
+static int jz4775_i2c0_pins[] = { 0x7e, 0x7f, };
+static int jz4775_i2c1_pins[] = { 0x9e, 0x9f, };
+static int jz4775_i2c2_pins[] = { 0x80, 0x83, };
+static int jz4775_i2s_data_tx_pins[] = { 0xa3, };
+static int jz4775_i2s_data_rx_pins[] = { 0xa2, };
+static int jz4775_i2s_clk_txrx_pins[] = { 0xa0, 0xa1, };
+static int jz4775_i2s_sysclk_pins[] = { 0x83, };
+static int jz4775_cim_pins[] = {
+   0x26, 0x27, 0x28, 0x29,
+   0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31,
+};
+static int jz4775_lcd_8bit_pins[] = {
+   0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x4c, 0x4d,
+   0x48, 0x52, 0x53,
+};
+static int jz4775_lcd_16bit_pins[] = {
+   0x4e, 0x4f, 0x50, 0x51, 0x56, 0x57, 0x58, 0x59,
+};
+static int jz4775_lcd_18bit_pins[] = {
+   0x5a, 0x5b,
+};
+static int jz4775_lcd_24bit_pins[] = {
+   0x40, 0x41, 0x4a, 0x4b, 0x54, 0x55,
+};
+static int jz4775_lcd_special_pins[] = { 0x54, 0x4a, 0x41, 0x40, };
+static int jz4775_lcd_generic_pins[] = { 0x49, };
+static int jz4775_pwm_pwm0_pins[] = { 0x80, };
+static int jz4775_pwm_pwm1_pins[] = { 0x81, };
+static int jz4775_pwm_pwm2_pins[] = { 0x82, };
+static int jz4775_pwm_pwm3_pins[] = { 0x83, };
+static int jz4775_mac_rmii_pins[] = {
+   0xa9, 0xab, 0xaa, 0xac, 0xa5, 0xa4, 0xad, 0xae, 0xa6, 0xa8,
+};
+static int jz4

Re: [PATCH v5 09/11] pinctrl: Ingenic: Add pinctrl driver for JZ4755.

2021-04-17 Thread Paul Cercueil

Hi Zhou,

Le sam. 17 avril 2021 à 0:14, 周琰杰 (Zhou Yanjie) 
 a écrit :

Add support for probing the pinctrl-ingenic driver on the
JZ4755 SoC from Ingenic.

Signed-off-by: 周琰杰 (Zhou Yanjie) 
Reviewed-by: Andy Shevchenko 


Reviewed-by: Paul Cercueil 

Cheers,
-Paul


---

Notes:
v3:
New patch.

v3->v4:
1.Split lcd pins into several groups.
2.Drop "lcd-no-pins" which is pointless.

v4->v5:
No change.

 drivers/pinctrl/pinctrl-ingenic.c | 139 
++

 1 file changed, 139 insertions(+)

diff --git a/drivers/pinctrl/pinctrl-ingenic.c 
b/drivers/pinctrl/pinctrl-ingenic.c

index 02fe3bf..3b649fb 100644
--- a/drivers/pinctrl/pinctrl-ingenic.c
+++ b/drivers/pinctrl/pinctrl-ingenic.c
@@ -86,6 +86,7 @@ enum jz_version {
ID_JZ4740,
ID_JZ4725B,
ID_JZ4750,
+   ID_JZ4755,
ID_JZ4760,
ID_JZ4770,
ID_JZ4780,
@@ -562,6 +563,138 @@ static const struct ingenic_chip_info 
jz4750_chip_info = {

.pull_downs = jz4750_pull_downs,
 };

+static const u32 jz4755_pull_ups[6] = {
+	0x, 0x, 0x0fff, 0x, 0x33dc3fff, 
0xfc00,

+};
+
+static const u32 jz4755_pull_downs[6] = {
+	0x, 0x, 0x, 0x, 0x, 
0x,

+};
+
+static int jz4755_uart0_data_pins[] = { 0x7c, 0x7d, };
+static int jz4755_uart0_hwflow_pins[] = { 0x7e, 0x7f, };
+static int jz4755_uart1_data_pins[] = { 0x97, 0x99, };
+static int jz4755_uart2_data_pins[] = { 0x9f, };
+static int jz4755_mmc0_1bit_pins[] = { 0x2f, 0x50, 0x5c, };
+static int jz4755_mmc0_4bit_pins[] = { 0x5d, 0x5b, 0x51, };
+static int jz4755_mmc1_1bit_pins[] = { 0x3a, 0x3d, 0x3c, };
+static int jz4755_mmc1_4bit_pins[] = { 0x3b, 0x3e, 0x3f, };
+static int jz4755_i2c_pins[] = { 0x8c, 0x8d, };
+static int jz4755_cim_pins[] = {
+   0x89, 0x8b, 0x8a, 0x88,
+   0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+};
+static int jz4755_lcd_8bit_pins[] = {
+   0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+   0x72, 0x73, 0x74,
+};
+static int jz4755_lcd_16bit_pins[] = {
+   0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+};
+static int jz4755_lcd_18bit_pins[] = { 0x70, 0x71, };
+static int jz4755_lcd_24bit_pins[] = { 0x76, 0x77, 0x78, 0x79, 0x7a, 
0x7b, };

+static int jz4755_lcd_special_pins[] = { 0x76, 0x77, 0x78, 0x79, };
+static int jz4755_lcd_generic_pins[] = { 0x75, };
+static int jz4755_nand_cs1_pins[] = { 0x55, };
+static int jz4755_nand_cs2_pins[] = { 0x56, };
+static int jz4755_nand_cs3_pins[] = { 0x57, };
+static int jz4755_nand_cs4_pins[] = { 0x58, };
+static int jz4755_nand_fre_fwe_pins[] = { 0x5c, 0x5d, };
+static int jz4755_pwm_pwm0_pins[] = { 0x94, };
+static int jz4755_pwm_pwm1_pins[] = { 0xab, };
+static int jz4755_pwm_pwm2_pins[] = { 0x96, };
+static int jz4755_pwm_pwm3_pins[] = { 0x97, };
+static int jz4755_pwm_pwm4_pins[] = { 0x98, };
+static int jz4755_pwm_pwm5_pins[] = { 0x99, };
+
+static u8 jz4755_mmc0_1bit_funcs[] = { 2, 2, 1, };
+static u8 jz4755_mmc0_4bit_funcs[] = { 1, 0, 1, };
+static u8 jz4755_lcd_24bit_funcs[] = { 1, 1, 1, 1, 0, 0, };
+
+static const struct group_desc jz4755_groups[] = {
+   INGENIC_PIN_GROUP("uart0-data", jz4755_uart0_data, 0),
+   INGENIC_PIN_GROUP("uart0-hwflow", jz4755_uart0_hwflow, 0),
+   INGENIC_PIN_GROUP("uart1-data", jz4755_uart1_data, 0),
+   INGENIC_PIN_GROUP("uart2-data", jz4755_uart2_data, 1),
+   INGENIC_PIN_GROUP_FUNCS("mmc0-1bit", jz4755_mmc0_1bit,
+   jz4755_mmc0_1bit_funcs),
+   INGENIC_PIN_GROUP_FUNCS("mmc0-4bit", jz4755_mmc0_4bit,
+   jz4755_mmc0_4bit_funcs),
+   INGENIC_PIN_GROUP("mmc1-1bit", jz4755_mmc1_1bit, 1),
+   INGENIC_PIN_GROUP("mmc1-4bit", jz4755_mmc1_4bit, 1),
+   INGENIC_PIN_GROUP("i2c-data", jz4755_i2c, 0),
+   INGENIC_PIN_GROUP("cim-data", jz4755_cim, 0),
+   INGENIC_PIN_GROUP("lcd-8bit", jz4755_lcd_8bit, 0),
+   INGENIC_PIN_GROUP("lcd-16bit", jz4755_lcd_16bit, 0),
+   INGENIC_PIN_GROUP("lcd-18bit", jz4755_lcd_18bit, 0),
+   INGENIC_PIN_GROUP_FUNCS("lcd-24bit", jz4755_lcd_24bit,
+   jz4755_lcd_24bit_funcs),
+   INGENIC_PIN_GROUP("lcd-special", jz4755_lcd_special, 0),
+   INGENIC_PIN_GROUP("lcd-generic", jz4755_lcd_generic, 0),
+   INGENIC_PIN_GROUP("nand-cs1", jz4755_nand_cs1, 0),
+   INGENIC_PIN_GROUP("nand-cs2", jz4755_nand_cs2, 0),
+   INGENIC_PIN_GROUP("nand-cs3", jz4755_nand_cs3, 0),
+   INGENIC_PIN_GROUP("nand-cs4", jz4755_nand_cs4, 0),
+   INGENIC_PIN_GROUP("nand-fre-fwe", jz4755_nand_fre_fwe, 0),
+   INGENIC_PIN_GROUP("pwm0", jz4755_pwm_pwm0, 0),
+   INGENIC_PIN_GROUP("pwm1", jz4755_pwm_pwm1, 1)

Re: [PATCH v5 08/11] pinctrl: Ingenic: Add pinctrl driver for JZ4750.

2021-04-17 Thread Paul Cercueil

Hi Zhou,


Le sam. 17 avril 2021 à 0:14, 周琰杰 (Zhou Yanjie) 
 a écrit :

Add support for probing the pinctrl-ingenic driver on the
JZ4750 SoC from Ingenic.

Signed-off-by: 周琰杰 (Zhou Yanjie) 
Reviewed-by: Andy Shevchenko 
---

Notes:
v3:
New patch.

v3->v4:
1.Use "lcd-special" and "lcd-generic" instead "lcd-18bit-tft".
2.Drop "lcd-no-pins" which is pointless.

v4->v5:
No change.

 drivers/pinctrl/pinctrl-ingenic.c | 139 
++

 1 file changed, 139 insertions(+)

diff --git a/drivers/pinctrl/pinctrl-ingenic.c 
b/drivers/pinctrl/pinctrl-ingenic.c

index 4c48250..02fe3bf 100644
--- a/drivers/pinctrl/pinctrl-ingenic.c
+++ b/drivers/pinctrl/pinctrl-ingenic.c
@@ -85,6 +85,7 @@ enum jz_version {
ID_JZ4730,
ID_JZ4740,
ID_JZ4725B,
+   ID_JZ4750,
ID_JZ4760,
ID_JZ4770,
ID_JZ4780,
@@ -427,6 +428,140 @@ static const struct ingenic_chip_info 
jz4725b_chip_info = {

.pull_downs = jz4740_pull_downs,
 };

+static const u32 jz4750_pull_ups[6] = {
+	0x, 0x, 0x3fff, 0x7fff, 0x1fff3fff, 
0x00ff,

+};
+
+static const u32 jz4750_pull_downs[6] = {
+	0x, 0x, 0x, 0x, 0x, 
0x,

+};
+
+static int jz4750_uart0_data_pins[] = { 0xa4, 0xa5, };
+static int jz4750_uart0_hwflow_pins[] = { 0xa6, 0xa7, };
+static int jz4750_uart1_data_pins[] = { 0x90, 0x91, };
+static int jz4750_uart1_hwflow_pins[] = { 0x92, 0x93, };
+static int jz4750_uart2_data_pins[] = { 0x9b, 0x9a, };
+static int jz4750_uart3_data_pins[] = { 0xb0, 0xb1, };
+static int jz4750_uart3_hwflow_pins[] = { 0xb2, 0xb3, };
+static int jz4750_mmc0_1bit_pins[] = { 0xa8, 0xa9, 0xa0, };
+static int jz4750_mmc0_4bit_pins[] = { 0xa1, 0xa2, 0xa3, };
+static int jz4750_mmc0_8bit_pins[] = { 0xa4, 0xa5, 0xa6, 0xa7, };
+static int jz4750_mmc1_1bit_pins[] = { 0xae, 0xaf, 0xaa, };
+static int jz4750_mmc1_4bit_pins[] = { 0xab, 0xac, 0xad, };
+static int jz4750_i2c_pins[] = { 0x8c, 0x8d, };
+static int jz4750_cim_pins[] = {
+   0x89, 0x8b, 0x8a, 0x88,
+   0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+};
+static int jz4750_lcd_8bit_pins[] = {
+   0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+   0x72, 0x73, 0x74,
+};
+static int jz4750_lcd_16bit_pins[] = {
+   0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+};
+static int jz4750_lcd_18bit_pins[] = { 0x70, 0x71, };
+static int jz4750_lcd_special_pins[] = { 0x76, 0x77, 0x78, 0x79, };
+static int jz4750_lcd_generic_pins[] = { 0x75, };
+static int jz4750_nand_cs1_pins[] = { 0x55, };
+static int jz4750_nand_cs2_pins[] = { 0x56, };
+static int jz4750_nand_cs3_pins[] = { 0x57, };
+static int jz4750_nand_cs4_pins[] = { 0x58, };
+static int jz4750_nand_fre_fwe_pins[] = { 0x5c, 0x5d, };
+static int jz4750_pwm_pwm0_pins[] = { 0x94, };
+static int jz4750_pwm_pwm1_pins[] = { 0x95, };
+static int jz4750_pwm_pwm2_pins[] = { 0x96, };
+static int jz4750_pwm_pwm3_pins[] = { 0x97, };
+static int jz4750_pwm_pwm4_pins[] = { 0x98, };
+static int jz4750_pwm_pwm5_pins[] = { 0x99, };
+
+static const struct group_desc jz4750_groups[] = {
+   INGENIC_PIN_GROUP("uart0-data", jz4750_uart0_data, 1),
+   INGENIC_PIN_GROUP("uart0-hwflow", jz4750_uart0_hwflow, 1),
+   INGENIC_PIN_GROUP("uart1-data", jz4750_uart1_data, 0),
+   INGENIC_PIN_GROUP("uart1-hwflow", jz4750_uart1_hwflow, 0),
+   INGENIC_PIN_GROUP("uart2-data", jz4750_uart2_data, 1),
+   INGENIC_PIN_GROUP("uart3-data", jz4750_uart3_data, 0),
+   INGENIC_PIN_GROUP("uart3-hwflow", jz4750_uart3_hwflow, 0),
+   INGENIC_PIN_GROUP("mmc0-1bit", jz4750_mmc0_1bit, 0),
+   INGENIC_PIN_GROUP("mmc0-4bit", jz4750_mmc0_4bit, 0),
+   INGENIC_PIN_GROUP("mmc0-8bit", jz4750_mmc0_8bit, 0),
+   INGENIC_PIN_GROUP("mmc1-1bit", jz4750_mmc1_1bit, 0),
+   INGENIC_PIN_GROUP("mmc1-4bit", jz4750_mmc1_4bit, 0),
+   INGENIC_PIN_GROUP("i2c-data", jz4750_i2c, 0),
+   INGENIC_PIN_GROUP("cim-data", jz4750_cim, 0),
+   INGENIC_PIN_GROUP("lcd-8bit", jz4750_lcd_8bit, 0),
+   INGENIC_PIN_GROUP("lcd-16bit", jz4750_lcd_16bit, 0),
+   INGENIC_PIN_GROUP("lcd-18bit", jz4750_lcd_18bit, 0),


Missing lcd-24bit, but it can always be added later.

Reviewed-by: Paul Cercueil 

Cheers,
-Paul


+   INGENIC_PIN_GROUP("lcd-special", jz4750_lcd_special, 0),
+   INGENIC_PIN_GROUP("lcd-generic", jz4750_lcd_generic, 0),
+   INGENIC_PIN_GROUP("nand-cs1", jz4750_nand_cs1, 0),
+   INGENIC_PIN_GROUP("nand-cs2", jz4750_nand_cs2, 0),
+   INGENIC_PIN_GROUP("nand-cs3", jz4750_nand_cs3, 0),
+   INGENIC_PIN_GROUP("nand-cs4", jz4750_nand_cs4, 0),
+   INGENIC_PIN_GROUP("nand-fre-fwe", jz4750_n

Re: [PATCH v5 07/11] pinctrl: Ingenic: Add pinctrl driver for JZ4730.

2021-04-17 Thread Paul Cercueil

Hi Zhou,

Le sam. 17 avril 2021 à 0:14, 周琰杰 (Zhou Yanjie) 
 a écrit :

Add support for probing the pinctrl-ingenic driver on the
JZ4730 SoC from Ingenic.

This driver is derived from Paul Boddie. It is worth to
noting that the JZ4730 SoC is special in having two control
registers (upper/lower), so add code to handle the JZ4730
specific register offsets and some register pairs which have
2 bits for each GPIO pin.

Tested-by: H. Nikolaus Schaller   # on Letux400
Co-developed-by: Paul Boddie 
Signed-off-by: Paul Boddie 
Signed-off-by: H. Nikolaus Schaller 
Signed-off-by: 周琰杰 (Zhou Yanjie) 
Reviewed-by: Andy Shevchenko 
---

Notes:
v3:
New patch.

v3->v4:
1.Use "lcd-special" and "lcd-generic" instead "lcd-16bit-tft".
2.Adjust function names to avoid confusion.
3.Improve the structure of some functions.
4.Modify the format of comment.
5.Simplify code using GENMASK.
6.Drop unnecessary mask.

v4->v5:
No change.

 drivers/pinctrl/pinctrl-ingenic.c | 232 
+++---

 1 file changed, 216 insertions(+), 16 deletions(-)

diff --git a/drivers/pinctrl/pinctrl-ingenic.c 
b/drivers/pinctrl/pinctrl-ingenic.c

index 009901b..4c48250 100644
--- a/drivers/pinctrl/pinctrl-ingenic.c
+++ b/drivers/pinctrl/pinctrl-ingenic.c
@@ -3,8 +3,8 @@
  * Ingenic SoCs pinctrl driver
  *
  * Copyright (c) 2017 Paul Cercueil 
- * Copyright (c) 2019 周琰杰 (Zhou Yanjie) 


  * Copyright (c) 2017, 2019 Paul Boddie 
+ * Copyright (c) 2019, 2020 周琰杰 (Zhou Yanjie) 


  */

 #include 
@@ -29,6 +29,17 @@
 #define GPIO_PIN   0x00
 #define GPIO_MSK   0x20

+#define JZ4730_GPIO_DATA   0x00
+#define JZ4730_GPIO_GPDIR  0x04
+#define JZ4730_GPIO_GPPUR  0x0c
+#define JZ4730_GPIO_GPALR  0x10
+#define JZ4730_GPIO_GPAUR  0x14
+#define JZ4730_GPIO_GPIDLR 0x18
+#define JZ4730_GPIO_GPIDUR 0x1c
+#define JZ4730_GPIO_GPIER  0x20
+#define JZ4730_GPIO_GPIMR  0x24
+#define JZ4730_GPIO_GPFR   0x28
+
 #define JZ4740_GPIO_DATA   0x10
 #define JZ4740_GPIO_PULL_DIS   0x30
 #define JZ4740_GPIO_FUNC   0x40
@@ -57,6 +68,7 @@
 #define GPIO_PULL_DOWN 2

 #define PINS_PER_GPIO_CHIP 32
+#define JZ4730_PINS_PER_PAIRED_REG 16

 #define INGENIC_PIN_GROUP_FUNCS(name, id, funcs)   \
{   \
@@ -70,6 +82,7 @@
INGENIC_PIN_GROUP_FUNCS(name, id, (void *)(func))

 enum jz_version {
+   ID_JZ4730,
ID_JZ4740,
ID_JZ4725B,
ID_JZ4760,
@@ -110,6 +123,99 @@ struct ingenic_gpio_chip {
unsigned int irq, reg_base;
 };

+static const u32 jz4730_pull_ups[4] = {
+   0x3fa3320f, 0xf200, 0x, 0x,
+};
+
+static const u32 jz4730_pull_downs[4] = {
+   0x0df0, 0x0dff, 0x, 0x,
+};
+
+static int jz4730_mmc_1bit_pins[] = { 0x27, 0x26, 0x22, };
+static int jz4730_mmc_4bit_pins[] = { 0x23, 0x24, 0x25, };
+static int jz4730_uart0_data_pins[] = { 0x7e, 0x7f, };
+static int jz4730_uart1_data_pins[] = { 0x18, 0x19, };
+static int jz4730_uart2_data_pins[] = { 0x6f, 0x7d, };
+static int jz4730_uart3_data_pins[] = { 0x10, 0x15, };
+static int jz4730_uart3_hwflow_pins[] = { 0x11, 0x17, };
+static int jz4730_lcd_8bit_pins[] = {
+   0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+   0x3a, 0x39, 0x38,
+};
+static int jz4730_lcd_16bit_pins[] = {
+   0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+};
+static int jz4730_lcd_special_pins[] = { 0x3d, 0x3c, 0x3e, 0x3f, };
+static int jz4730_lcd_generic_pins[] = { 0x3b, };
+static int jz4730_nand_cs1_pins[] = { 0x53, };
+static int jz4730_nand_cs2_pins[] = { 0x54, };
+static int jz4730_nand_cs3_pins[] = { 0x55, };
+static int jz4730_nand_cs4_pins[] = { 0x56, };
+static int jz4730_nand_cs5_pins[] = { 0x57, };
+static int jz4730_pwm_pwm0_pins[] = { 0x5e, };
+static int jz4730_pwm_pwm1_pins[] = { 0x5f, };
+
+static u8 jz4730_lcd_8bit_funcs[] = { 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 
2, };

+
+static const struct group_desc jz4730_groups[] = {
+   INGENIC_PIN_GROUP("mmc-1bit", jz4730_mmc_1bit, 1),
+   INGENIC_PIN_GROUP("mmc-4bit", jz4730_mmc_4bit, 1),
+   INGENIC_PIN_GROUP("uart0-data", jz4730_uart0_data, 1),
+   INGENIC_PIN_GROUP("uart1-data", jz4730_uart1_data, 1),
+   INGENIC_PIN_GROUP("uart2-data", jz4730_uart2_data, 1),
+   INGENIC_PIN_GROUP("uart3-data", jz4730_uart3_data, 1),
+   INGENIC_PIN_GROUP("uart3-hwflow", jz4730_uart3_hwflow, 1),
+	INGENIC_PIN_GROUP_FUNCS("lcd-8bit", jz4730_lcd_8bit, 
jz4730_lcd_8bit_funcs),

+  

Re: [PATCH v5 04/11] pinctrl: Ingenic: Improve LCD pins related code.

2021-04-17 Thread Paul Cercueil

Hi Zhou,

Le sam. 17 avril 2021 à 0:13, 周琰杰 (Zhou Yanjie) 
 a écrit :
1.In the JZ4740 part, remove pointless "lcd-no-pins", use 
"lcd-special"
  and "lcd-generic" instead "lcd-18bit-tft". Currently, in the 
mainline,
  no other devicetree out there is using the "lcd-18bit-tft" ABI, so 
we

  should be able to replace it safely.
2.In the JZ4725B part, adjust the location of the LCD pins related 
code

  to keep them consistent with the style of other parts.
3.In the JZ4760 part, add the missing comma and adjust element order 
in
  "jz4760_lcd_special_pins[]", keep them in the order of 
CLS/SPL/PS/REV

  like other "lcd_special_pins" arrays. And adjust the location of the
  "jz4760_lcd_generic" related code to keep them consistent with the
  style of other parts.
4.In the JZ4770 part, remove pointless "lcd-no-pins", add the missing
  "lcd-16bit", "lcd-18bit", "lcd-special", "lcd-generic".
5.In the X1000 part and the X1500 part, remove pointless 
"lcd-no-pins".

6.In the X1830 part, replace "lcd-rgb-18bit" with "lcd-tft-8bit" and
  "lcd-tft-24bit", because of the description of the TRANS_CONFIG.MODE
  register bits in the PM manual of the X1830, shows that the X1830 
only

  supppots 24bit mode and 8bit mode for tft interface, only 18 pins in
  the GPIO table are because of the data[17:16], the data[9:8], and 
the

  data[1:0] has not been connected. And according to the description,
  the two interfaces supported by X1830 are respectively referred to 
as
  "TFT interface" and "SLCD interface", so the "lcd-rgb-xxx" is 
replaced

  with "lcd-tft-xxx" to avoid confusion.

Signed-off-by: 周琰杰 (Zhou Yanjie) 


Reviewed-by: Paul Cercueil 

Cheers,
-Paul


---

Notes:
v4:
New patch.

v4->v5:
No change.

 drivers/pinctrl/pinctrl-ingenic.c | 110 
+-

 1 file changed, 61 insertions(+), 49 deletions(-)

diff --git a/drivers/pinctrl/pinctrl-ingenic.c 
b/drivers/pinctrl/pinctrl-ingenic.c

index 72d9daa..8ed62a4 100644
--- a/drivers/pinctrl/pinctrl-ingenic.c
+++ b/drivers/pinctrl/pinctrl-ingenic.c
@@ -113,13 +113,15 @@ static int jz4740_uart0_data_pins[] = { 0x7a, 
0x79, };

 static int jz4740_uart0_hwflow_pins[] = { 0x7e, 0x7f, };
 static int jz4740_uart1_data_pins[] = { 0x7e, 0x7f, };
 static int jz4740_lcd_8bit_pins[] = {
-   0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x52, 0x53, 0x54,
+   0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+   0x52, 0x53, 0x54,
 };
 static int jz4740_lcd_16bit_pins[] = {
-   0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x55,
+   0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
 };
 static int jz4740_lcd_18bit_pins[] = { 0x50, 0x51, };
-static int jz4740_lcd_18bit_tft_pins[] = { 0x56, 0x57, 0x31, 0x32, };
+static int jz4740_lcd_special_pins[] = { 0x31, 0x32, 0x56, 0x57, };
+static int jz4740_lcd_generic_pins[] = { 0x55, };
 static int jz4740_nand_cs1_pins[] = { 0x39, };
 static int jz4740_nand_cs2_pins[] = { 0x3a, };
 static int jz4740_nand_cs3_pins[] = { 0x3b, };
@@ -155,8 +157,8 @@ static const struct group_desc jz4740_groups[] = {
INGENIC_PIN_GROUP("lcd-8bit", jz4740_lcd_8bit, 0),
INGENIC_PIN_GROUP("lcd-16bit", jz4740_lcd_16bit, 0),
INGENIC_PIN_GROUP("lcd-18bit", jz4740_lcd_18bit, 0),
-   INGENIC_PIN_GROUP("lcd-18bit-tft", jz4740_lcd_18bit_tft, 0),
-   { "lcd-no-pins", },
+   INGENIC_PIN_GROUP("lcd-special", jz4740_lcd_special, 0),
+   INGENIC_PIN_GROUP("lcd-generic", jz4740_lcd_generic, 0),
INGENIC_PIN_GROUP("nand-cs1", jz4740_nand_cs1, 0),
INGENIC_PIN_GROUP("nand-cs2", jz4740_nand_cs2, 0),
INGENIC_PIN_GROUP("nand-cs3", jz4740_nand_cs3, 0),
@@ -176,7 +178,7 @@ static const char *jz4740_mmc_groups[] = { 
"mmc-1bit", "mmc-4bit", };
 static const char *jz4740_uart0_groups[] = { "uart0-data", 
"uart0-hwflow", };

 static const char *jz4740_uart1_groups[] = { "uart1-data", };
 static const char *jz4740_lcd_groups[] = {
-	"lcd-8bit", "lcd-16bit", "lcd-18bit", "lcd-18bit-tft", 
"lcd-no-pins",

+   "lcd-8bit", "lcd-16bit", "lcd-18bit", "lcd-special", "lcd-generic",
 };
 static const char *jz4740_nand_groups[] = {
"nand-cs1", "nand-cs2", "nand-cs3", "nand-cs4", "nand-fre-fwe",
@@ -223,6 +225,17 @@ static int jz4725b_mmc0_4bit_pins[] = { 0x5d, 
0x5b, 0x56, };

 static int jz4725b_mmc1_1bit_pins[] = { 0x7a, 0x7b, 0x7c, };
 static int jz4725b_mmc1_4bit_pins[] = { 0x7d, 0x7e, 0x7f, };
 static int jz4725b_uart_data_pins[] = { 0x4c, 0x

Re: [PATCH v3 2/3] drm: bridge: add it66121 driver

2021-04-14 Thread Paul Cercueil

Hi Neil,

Le mer. 14 avril 2021 à 8:17, Neil Armstrong  
a écrit :

Hi,

Le 13/04/2021 à 22:56, Paul Cercueil a écrit :

 Hi Neil,

 I get build failures locally:

 drivers/gpu/drm/bridge/ite-it66121.c: In function 
‘it66121_hw_reset’:
 drivers/gpu/drm/bridge/ite-it66121.c:242:2: error: implicit 
declaration of function ‘gpiod_set_value’ 
[-Werror=implicit-function-declaration]

 242 | gpiod_set_value(ctx->gpio_reset, 1);
 | ^~~
 drivers/gpu/drm/bridge/ite-it66121.c: In function 
‘it66121_probe’:
 drivers/gpu/drm/bridge/ite-it66121.c:1016:16: error: implicit 
declaration of function ‘FIELD_GET’; did you mean 
‘FOLL_GET’? [-Werror=implicit-function-declaration]
 1016 | revision_id = FIELD_GET(IT66121_REVISION_MASK, 
device_ids[1]);

 | ^
 | FOLL_GET

 Nothing difficult to fix, but the includes should be added 
nonetheless.


Exact, I got the CI build failures, I'll fix these for v4.

Were you able to test on your setup ?
The v2 always forced DDR mode, with this v3, I also switch to normal 
24input mode, but totally untested.


It triggers a warning:

[  277.870247] WARNING: CPU: 0 PID: 310 at 
drivers/gpu/drm/drm_bridge.c:892 
drm_atomic_bridge_chain_check+0x304/0x324

[  277.870290] Modules linked in:
[  277.870306] CPU: 0 PID: 310 Comm: modetest Tainted: GW   
 5.12.0-rc7-opendingux-00121-g828a3020b5d3 #371
[  277.870322] Stack : 83f62580 80163b58  0004  
b1f39d7e 83581a9c 80ab42b0
[  277.870367] 808a 808a 835c82f0 808a0dab 80ab42b0 
0001 83581a48 b1f39d7e
[  277.870412]   807e9030  00b8 
835818fc  7875676e
[  277.870456] 3130302d 80abaa43 80abaa9f 672d3132 808a 
8000 0009 037c
[  277.870500]   82a2d0f8 83043b80  
fffc 2098 80ab

[  277.870544] ...
[  277.870556] Call Trace:
[  277.870560] [<80109010>] show_stack+0x40/0x128
[  277.870588] [<80123350>] __warn+0xe0/0x154
[  277.870608] [<80123428>] warn_slowpath_fmt+0x64/0xb8
[  277.870625] [<80504e70>] drm_atomic_bridge_chain_check+0x304/0x324
[  277.870642] [<804e3244>] drm_atomic_helper_check_modeset+0x9f4/0xc58
[  277.870667] [<804e4338>] drm_atomic_helper_check+0x20/0xa8
[  277.870685] [<80503644>] drm_atomic_check_only+0x538/0x98c
[  277.870700] [<80503ab4>] drm_atomic_commit+0x1c/0x70
[  277.870716] [<8051c3e4>] drm_mode_atomic_ioctl+0x920/0xb44
[  277.870736] [<804f033c>] drm_ioctl+0x20c/0x3d8
[  277.870754] [<80283658>] sys_ioctl+0x358/0x860
[  277.870772] [<801107ec>] syscall_common+0x34/0x58

[  277.870795] ---[ end trace e973f3b21c63aa1d ]---

That causes my atomic commit to fail, so I can't test it further.

Cheers,
-Paul


Thanks,
Neil



 Cheers,
 -Paul


 Le lun. 12 avril 2021 à 17:46, Neil Armstrong 
 a écrit :

 From: Phong LE 

 This commit is a simple driver for bridge HMDI it66121.
 The input format is RBG and there is no color conversion.
 Audio, HDCP and CEC are not supported yet.

 Signed-off-by: Phong LE 
 Signed-off-by: Neil Armstrong 
 ---
  drivers/gpu/drm/bridge/Kconfig   |8 +
  drivers/gpu/drm/bridge/Makefile  |1 +
  drivers/gpu/drm/bridge/ite-it66121.c | 1081 
++

  3 files changed, 1090 insertions(+)
  create mode 100644 drivers/gpu/drm/bridge/ite-it66121.c

 diff --git a/drivers/gpu/drm/bridge/Kconfig 
b/drivers/gpu/drm/bridge/Kconfig

 index e4110d6ca7b3..6915c38fa459 100644
 --- a/drivers/gpu/drm/bridge/Kconfig
 +++ b/drivers/gpu/drm/bridge/Kconfig
 @@ -74,6 +74,14 @@ config DRM_LONTIUM_LT9611UXC
HDMI signals
Please say Y if you have such hardware.

 +config DRM_ITE_IT66121
 +tristate "ITE IT66121 HDMI bridge"
 +depends on OF
 +select DRM_KMS_HELPER
 +select REGMAP_I2C
 +help
 +  Support for ITE IT66121 HDMI bridge.
 +
  config DRM_LVDS_CODEC
  tristate "Transparent LVDS encoders and decoders support"
  depends on OF
 diff --git a/drivers/gpu/drm/bridge/Makefile 
b/drivers/gpu/drm/bridge/Makefile

 index 86e7acc76f8d..4f725753117c 100644
 --- a/drivers/gpu/drm/bridge/Makefile
 +++ b/drivers/gpu/drm/bridge/Makefile
 @@ -24,6 +24,7 @@ obj-$(CONFIG_DRM_TI_SN65DSI86) += ti-sn65dsi86.o
  obj-$(CONFIG_DRM_TI_TFP410) += ti-tfp410.o
  obj-$(CONFIG_DRM_TI_TPD12S015) += ti-tpd12s015.o
  obj-$(CONFIG_DRM_NWL_MIPI_DSI) += nwl-dsi.o
 +obj-$(CONFIG_DRM_ITE_IT66121) += ite-it66121.o

  obj-y += analogix/
  obj-y += cadence/
 diff --git a/drivers/gpu/drm/bridge/ite-it66121.c 
b/drivers/gpu/drm/bridge/ite-it66121.c

 new file mode 100644
 index ..73af49b29dfa
 --- /dev/null
 +++ b/drivers/gpu/drm/bridge/ite-it66121.c
 @@ -0,0 +1,1081 @@
 +// SPDX-License-Identifier: GPL-2.0-only
 +/*
 + * Copyright (C) 2020 BayLibre, SAS
 + * Author: Phong LE 
 + * Copyright (C) 2018-2019, Artem Mygaiev
 + * Copyright (C) 2017, Fresco Logic, Incorporated.
 

Re: [PATCH v3 2/3] drm: bridge: add it66121 driver

2021-04-14 Thread Paul Cercueil




Le mer. 14 avril 2021 à 8:17, Neil Armstrong  
a écrit :

Hi,

Le 13/04/2021 à 22:56, Paul Cercueil a écrit :

 Hi Neil,

 I get build failures locally:

 drivers/gpu/drm/bridge/ite-it66121.c: In function 
‘it66121_hw_reset’:
 drivers/gpu/drm/bridge/ite-it66121.c:242:2: error: implicit 
declaration of function ‘gpiod_set_value’ 
[-Werror=implicit-function-declaration]

 242 | gpiod_set_value(ctx->gpio_reset, 1);
 | ^~~
 drivers/gpu/drm/bridge/ite-it66121.c: In function 
‘it66121_probe’:
 drivers/gpu/drm/bridge/ite-it66121.c:1016:16: error: implicit 
declaration of function ‘FIELD_GET’; did you mean 
‘FOLL_GET’? [-Werror=implicit-function-declaration]
 1016 | revision_id = FIELD_GET(IT66121_REVISION_MASK, 
device_ids[1]);

 | ^
 | FOLL_GET

 Nothing difficult to fix, but the includes should be added 
nonetheless.


Exact, I got the CI build failures, I'll fix these for v4.

Were you able to test on your setup ?
The v2 always forced DDR mode, with this v3, I also switch to normal 
24input mode, but totally untested.


I will try to find some time today to test after work.

-Paul



Thanks,
Neil



 Cheers,
 -Paul


 Le lun. 12 avril 2021 à 17:46, Neil Armstrong 
 a écrit :

 From: Phong LE 

 This commit is a simple driver for bridge HMDI it66121.
 The input format is RBG and there is no color conversion.
 Audio, HDCP and CEC are not supported yet.

 Signed-off-by: Phong LE 
 Signed-off-by: Neil Armstrong 
 ---
  drivers/gpu/drm/bridge/Kconfig   |8 +
  drivers/gpu/drm/bridge/Makefile  |1 +
  drivers/gpu/drm/bridge/ite-it66121.c | 1081 
++

  3 files changed, 1090 insertions(+)
  create mode 100644 drivers/gpu/drm/bridge/ite-it66121.c

 diff --git a/drivers/gpu/drm/bridge/Kconfig 
b/drivers/gpu/drm/bridge/Kconfig

 index e4110d6ca7b3..6915c38fa459 100644
 --- a/drivers/gpu/drm/bridge/Kconfig
 +++ b/drivers/gpu/drm/bridge/Kconfig
 @@ -74,6 +74,14 @@ config DRM_LONTIUM_LT9611UXC
HDMI signals
Please say Y if you have such hardware.

 +config DRM_ITE_IT66121
 +tristate "ITE IT66121 HDMI bridge"
 +depends on OF
 +select DRM_KMS_HELPER
 +select REGMAP_I2C
 +help
 +  Support for ITE IT66121 HDMI bridge.
 +
  config DRM_LVDS_CODEC
  tristate "Transparent LVDS encoders and decoders support"
  depends on OF
 diff --git a/drivers/gpu/drm/bridge/Makefile 
b/drivers/gpu/drm/bridge/Makefile

 index 86e7acc76f8d..4f725753117c 100644
 --- a/drivers/gpu/drm/bridge/Makefile
 +++ b/drivers/gpu/drm/bridge/Makefile
 @@ -24,6 +24,7 @@ obj-$(CONFIG_DRM_TI_SN65DSI86) += ti-sn65dsi86.o
  obj-$(CONFIG_DRM_TI_TFP410) += ti-tfp410.o
  obj-$(CONFIG_DRM_TI_TPD12S015) += ti-tpd12s015.o
  obj-$(CONFIG_DRM_NWL_MIPI_DSI) += nwl-dsi.o
 +obj-$(CONFIG_DRM_ITE_IT66121) += ite-it66121.o

  obj-y += analogix/
  obj-y += cadence/
 diff --git a/drivers/gpu/drm/bridge/ite-it66121.c 
b/drivers/gpu/drm/bridge/ite-it66121.c

 new file mode 100644
 index ..73af49b29dfa
 --- /dev/null
 +++ b/drivers/gpu/drm/bridge/ite-it66121.c
 @@ -0,0 +1,1081 @@
 +// SPDX-License-Identifier: GPL-2.0-only
 +/*
 + * Copyright (C) 2020 BayLibre, SAS
 + * Author: Phong LE 
 + * Copyright (C) 2018-2019, Artem Mygaiev
 + * Copyright (C) 2017, Fresco Logic, Incorporated.
 + *
 + */
 +
 +#include 
 +#include 
 +#include 
 +#include 
 +#include 
 +#include 
 +#include 
 +#include 
 +#include 
 +
 +#include 
 +#include 
 +#include 
 +#include 
 +#include 
 +#include 
 +#include 
 +
 +#define IT66121_VENDOR_ID0_REG0x00
 +#define IT66121_VENDOR_ID1_REG0x01
 +#define IT66121_DEVICE_ID0_REG0x02
 +#define IT66121_DEVICE_ID1_REG0x03
 +
 +#define IT66121_VENDOR_ID00x54
 +#define IT66121_VENDOR_ID10x49
 +#define IT66121_DEVICE_ID00x12
 +#define IT66121_DEVICE_ID10x06
 +#define IT66121_REVISION_MASKGENMASK(7, 4)
 +#define IT66121_DEVICE_ID1_MASKGENMASK(3, 0)
 +
 +#define IT66121_MASTER_SEL_REG0x10
 +#define IT66121_MASTER_SEL_HOSTBIT(0)
 +
 +#define IT66121_AFE_DRV_REG0x61
 +#define IT66121_AFE_DRV_RSTBIT(4)
 +#define IT66121_AFE_DRV_PWDBIT(5)
 +
 +#define IT66121_INPUT_MODE_REG0x70
 +#define IT66121_INPUT_MODE_RGB(0 << 6)
 +#define IT66121_INPUT_MODE_YUV422BIT(6)
 +#define IT66121_INPUT_MODE_YUV444(2 << 6)
 +#define IT66121_INPUT_MODE_CCIR656BIT(4)
 +#define IT66121_INPUT_MODE_SYNCEMBBIT(3)
 +#define IT66121_INPUT_MODE_DDRBIT(2)
 +
 +#define IT66121_INPUT_CSC_REG0x72
 +#define IT66121_INPUT_CSC_ENDITHERBIT(7)
 +#define IT66121_INPUT_CSC_ENUDFILTERBIT(6)
 +#define IT66121_INPUT_CSC_DNFREE_GOBIT(5)
 +#define IT66121_INPUT_CSC_RGB_TO_YUV0x02
 +#define IT66121_INPUT_CSC_YUV_TO_RGB0x03
 +#define IT66121_INPUT_CSC_NO_CONV0

Re: [PATCH v3 2/3] drm: bridge: add it66121 driver

2021-04-13 Thread Paul Cercueil

Hi Neil,

I get build failures locally:

drivers/gpu/drm/bridge/ite-it66121.c: In function 
‘it66121_hw_reset’:
drivers/gpu/drm/bridge/ite-it66121.c:242:2: error: implicit declaration 
of function ‘gpiod_set_value’ 
[-Werror=implicit-function-declaration]

 242 | gpiod_set_value(ctx->gpio_reset, 1);
 | ^~~
drivers/gpu/drm/bridge/ite-it66121.c: In function ‘it66121_probe’:
drivers/gpu/drm/bridge/ite-it66121.c:1016:16: error: implicit 
declaration of function ‘FIELD_GET’; did you mean ‘FOLL_GET’? 
[-Werror=implicit-function-declaration]

1016 | revision_id = FIELD_GET(IT66121_REVISION_MASK, device_ids[1]);
 | ^
 | FOLL_GET

Nothing difficult to fix, but the includes should be added nonetheless.

Cheers,
-Paul


Le lun. 12 avril 2021 à 17:46, Neil Armstrong 
 a écrit :

From: Phong LE 

This commit is a simple driver for bridge HMDI it66121.
The input format is RBG and there is no color conversion.
Audio, HDCP and CEC are not supported yet.

Signed-off-by: Phong LE 
Signed-off-by: Neil Armstrong 
---
 drivers/gpu/drm/bridge/Kconfig   |8 +
 drivers/gpu/drm/bridge/Makefile  |1 +
 drivers/gpu/drm/bridge/ite-it66121.c | 1081 
++

 3 files changed, 1090 insertions(+)
 create mode 100644 drivers/gpu/drm/bridge/ite-it66121.c

diff --git a/drivers/gpu/drm/bridge/Kconfig 
b/drivers/gpu/drm/bridge/Kconfig

index e4110d6ca7b3..6915c38fa459 100644
--- a/drivers/gpu/drm/bridge/Kconfig
+++ b/drivers/gpu/drm/bridge/Kconfig
@@ -74,6 +74,14 @@ config DRM_LONTIUM_LT9611UXC
  HDMI signals
  Please say Y if you have such hardware.

+config DRM_ITE_IT66121
+   tristate "ITE IT66121 HDMI bridge"
+   depends on OF
+   select DRM_KMS_HELPER
+   select REGMAP_I2C
+   help
+ Support for ITE IT66121 HDMI bridge.
+
 config DRM_LVDS_CODEC
tristate "Transparent LVDS encoders and decoders support"
depends on OF
diff --git a/drivers/gpu/drm/bridge/Makefile 
b/drivers/gpu/drm/bridge/Makefile

index 86e7acc76f8d..4f725753117c 100644
--- a/drivers/gpu/drm/bridge/Makefile
+++ b/drivers/gpu/drm/bridge/Makefile
@@ -24,6 +24,7 @@ obj-$(CONFIG_DRM_TI_SN65DSI86) += ti-sn65dsi86.o
 obj-$(CONFIG_DRM_TI_TFP410) += ti-tfp410.o
 obj-$(CONFIG_DRM_TI_TPD12S015) += ti-tpd12s015.o
 obj-$(CONFIG_DRM_NWL_MIPI_DSI) += nwl-dsi.o
+obj-$(CONFIG_DRM_ITE_IT66121) += ite-it66121.o

 obj-y += analogix/
 obj-y += cadence/
diff --git a/drivers/gpu/drm/bridge/ite-it66121.c 
b/drivers/gpu/drm/bridge/ite-it66121.c

new file mode 100644
index ..73af49b29dfa
--- /dev/null
+++ b/drivers/gpu/drm/bridge/ite-it66121.c
@@ -0,0 +1,1081 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2020 BayLibre, SAS
+ * Author: Phong LE 
+ * Copyright (C) 2018-2019, Artem Mygaiev
+ * Copyright (C) 2017, Fresco Logic, Incorporated.
+ *
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define IT66121_VENDOR_ID0_REG 0x00
+#define IT66121_VENDOR_ID1_REG 0x01
+#define IT66121_DEVICE_ID0_REG 0x02
+#define IT66121_DEVICE_ID1_REG 0x03
+
+#define IT66121_VENDOR_ID0 0x54
+#define IT66121_VENDOR_ID1 0x49
+#define IT66121_DEVICE_ID0 0x12
+#define IT66121_DEVICE_ID1 0x06
+#define IT66121_REVISION_MASK  GENMASK(7, 4)
+#define IT66121_DEVICE_ID1_MASKGENMASK(3, 0)
+
+#define IT66121_MASTER_SEL_REG 0x10
+#define IT66121_MASTER_SEL_HOSTBIT(0)
+
+#define IT66121_AFE_DRV_REG0x61
+#define IT66121_AFE_DRV_RSTBIT(4)
+#define IT66121_AFE_DRV_PWDBIT(5)
+
+#define IT66121_INPUT_MODE_REG 0x70
+#define IT66121_INPUT_MODE_RGB (0 << 6)
+#define IT66121_INPUT_MODE_YUV422  BIT(6)
+#define IT66121_INPUT_MODE_YUV444  (2 << 6)
+#define IT66121_INPUT_MODE_CCIR656 BIT(4)
+#define IT66121_INPUT_MODE_SYNCEMB BIT(3)
+#define IT66121_INPUT_MODE_DDR BIT(2)
+
+#define IT66121_INPUT_CSC_REG  0x72
+#define IT66121_INPUT_CSC_ENDITHER BIT(7)
+#define IT66121_INPUT_CSC_ENUDFILTER   BIT(6)
+#define IT66121_INPUT_CSC_DNFREE_GOBIT(5)
+#define IT66121_INPUT_CSC_RGB_TO_YUV   0x02
+#define IT66121_INPUT_CSC_YUV_TO_RGB   0x03
+#define IT66121_INPUT_CSC_NO_CONV  0x00
+
+#define IT66121_AFE_XP_REG 0x62
+#define IT66121_AFE_XP_GAINBIT BIT(7)
+#define IT66121_AFE_XP_PWDPLL  BIT(6)
+#define IT66121_AFE_XP_ENI BIT(5)
+#define IT66121_AFE_XP_ENO BIT(4)
+#define IT66121_AFE_XP_RESETB  BIT(3)
+#define 

Re: [PATCH v3 1/3] dt-bindings: display: bridge: add it66121 bindings

2021-04-13 Thread Paul Cercueil

Hi Neil,

Le lun. 12 avril 2021 à 17:46, Neil Armstrong 
 a écrit :

From: Phong LE 

Add the ITE bridge HDMI it66121 bindings.

Signed-off-by: Phong LE 
Signed-off-by: Neil Armstrong 
---
 .../bindings/display/bridge/ite,it66121.yaml  | 123 
++

 1 file changed, 123 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/display/bridge/ite,it66121.yaml


diff --git 
a/Documentation/devicetree/bindings/display/bridge/ite,it66121.yaml 
b/Documentation/devicetree/bindings/display/bridge/ite,it66121.yaml

new file mode 100644
index ..61ed6dc7740b
--- /dev/null
+++ 
b/Documentation/devicetree/bindings/display/bridge/ite,it66121.yaml

@@ -0,0 +1,123 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/bridge/ite,it66121.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: ITE it66121 HDMI bridge Device Tree Bindings
+
+maintainers:
+  - Phong LE 
+  - Neil Armstrong 
+
+description: |
+  The IT66121 is a high-performance and low-power single channel HDMI
+  transmitter, fully compliant with HDMI 1.3a, HDCP 1.2 and backward 
compatible

+  to DVI 1.0 specifications.
+
+properties:
+  compatible:
+const: ite,it66121
+
+  reg:
+maxItems: 1
+description: base I2C address of the device
+
+  reset-gpios:
+maxItems: 1
+description: GPIO connected to active low reset
+
+  vrf12-supply:
+description: Regulator for 1.2V analog core power.
+
+  vcn33-supply:
+description: Regulator for 3.3V digital core power.
+
+  vcn18-supply:
+description: Regulator for 1.8V IO core power.
+
+  interrupts:
+maxItems: 1
+
+  ports:
+$ref: /schemas/graph.yaml#/properties/ports
+
+properties:
+  port@0:
+$ref: /schemas/graph.yaml#/$defs/port-base
+unevaluatedProperties: false
+description: DPI input port.
+
+properties:
+  endpoint:
+$ref: /schemas/graph.yaml#/$defs/endpoint-base
+unevaluatedProperties: false
+
+properties:
+  bus-width:
+description:
+  Endpoint bus width.
+enum:
+  - 12  # 12 data lines connected and dual-edge mode
+  - 24  # 24 data lines connected and single-edge 
mode

+default: 24
+
+  port@1:
+$ref: /schemas/graph.yaml#/properties/port
+description: HDMI Connector port.
+
+required:
+  - port@0
+  - port@1


Should port@1 really be required? Since the chip itself handles the 
hotplug detection and stuff like DCC, I'm not sure what to connect here.


Cheers,
-Paul


+
+required:
+  - compatible
+  - reg
+  - reset-gpios
+  - vrf12-supply
+  - vcn33-supply
+  - vcn18-supply
+  - interrupts
+  - ports
+
+additionalProperties: false
+
+examples:
+  - |
+i2c {
+  #address-cells = <1>;
+  #size-cells = <0>;
+
+  it66121hdmitx: it66121hdmitx@4c {
+compatible = "ite,it66121";
+pinctrl-names = "default";
+pinctrl-0 = <_pins_default>;
+vcn33-supply = <_vcn33_wifi_reg>;
+vcn18-supply = <_vcn18_reg>;
+vrf12-supply = <_vrf12_reg>;
+reset-gpios = < 160 1 /* GPIO_ACTIVE_LOW */>;
+interrupt-parent = <>;
+interrupts = <4 8 /* IRQ_TYPE_LEVEL_LOW */>;
+reg = <0x4c>;
+
+ports {
+  #address-cells = <1>;
+  #size-cells = <0>;
+
+  port@0 {
+reg = <0>;
+it66121_in: endpoint {
+  bus-width = <12>;
+  remote-endpoint = <_out>;
+};
+  };
+
+  port@1 {
+reg = <1>;
+hdmi_conn_out: endpoint {
+  remote-endpoint = <_conn_in>;
+};
+  };
+};
+  };
+};
--
2.25.1






Re: [PATCH] drm/ingenic: Fix pixclock rate for 24-bit serial panels

2021-04-12 Thread Paul Cercueil

Hi,

Can I have an ACK for this patch?

Then I can apply it to drm-misc-next-fixes.

Cheers,
-Paul


Le mar. 23 mars 2021 à 14:40, Paul Cercueil  a 
écrit :

When using a 24-bit panel on a 8-bit serial bus, the pixel clock
requested by the panel has to be multiplied by 3, since the subpixels
are shifted sequentially.

The code (in ingenic_drm_encoder_atomic_check) already computed
crtc_state->adjusted_mode->crtc_clock accordingly, but clk_set_rate()
used crtc_state->adjusted_mode->clock instead.

Fixes: 28ab7d35b6e0 ("drm/ingenic: Properly compute timings when 
using a 3x8-bit panel")

Cc: sta...@vger.kernel.org # v5.10
Signed-off-by: Paul Cercueil 
---
 drivers/gpu/drm/ingenic/ingenic-drm-drv.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c 
b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c

index d60e1eefc9d1..cba68bf52ec5 100644
--- a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c
+++ b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c
@@ -342,7 +342,7 @@ static void ingenic_drm_crtc_atomic_flush(struct 
drm_crtc *crtc,

if (priv->update_clk_rate) {
mutex_lock(>clk_mutex);
clk_set_rate(priv->pix_clk,
-crtc_state->adjusted_mode.clock * 1000);
+crtc_state->adjusted_mode.crtc_clock * 1000);
priv->update_clk_rate = false;
mutex_unlock(>clk_mutex);
}
--
2.30.2






Re: [PATCH 2/2] drm/ingenic: Don't request full modeset if property is not modified

2021-04-12 Thread Paul Cercueil

Can I have an ACK for this patch?

Cheers,
-Paul

Le lun. 29 mars 2021 à 18:50, Paul Cercueil  a 
écrit :

Avoid requesting a full modeset if the sharpness property is not
modified, because then we don't actually need it.

Fixes: fc1acf317b01 ("drm/ingenic: Add support for the IPU")
Cc:  # 5.8+
Signed-off-by: Paul Cercueil 
---
 drivers/gpu/drm/ingenic/ingenic-ipu.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/ingenic/ingenic-ipu.c 
b/drivers/gpu/drm/ingenic/ingenic-ipu.c

index 3b1091e7c0cd..95b665c4a7b0 100644
--- a/drivers/gpu/drm/ingenic/ingenic-ipu.c
+++ b/drivers/gpu/drm/ingenic/ingenic-ipu.c
@@ -640,10 +640,12 @@ ingenic_ipu_plane_atomic_set_property(struct 
drm_plane *plane,

 {
struct ingenic_ipu *ipu = plane_to_ingenic_ipu(plane);
struct drm_crtc_state *crtc_state;
+   bool mode_changed;

if (property != ipu->sharpness_prop)
return -EINVAL;

+   mode_changed = val != ipu->sharpness;
ipu->sharpness = val;

if (state->crtc) {
@@ -651,7 +653,7 @@ ingenic_ipu_plane_atomic_set_property(struct 
drm_plane *plane,

if (WARN_ON(!crtc_state))
return -EINVAL;

-   crtc_state->mode_changed = true;
+   crtc_state->mode_changed |= mode_changed;
}

return 0;
--
2.30.2






[tip: timers/core] dt-bindings: timer: ingenic: Add compatible strings for JZ4760(B)

2021-04-09 Thread tip-bot2 for Paul Cercueil
The following commit has been merged into the timers/core branch of tip:

Commit-ID: 507d8c5a418a5d413bf9751d4ff94b259e947736
Gitweb:
https://git.kernel.org/tip/507d8c5a418a5d413bf9751d4ff94b259e947736
Author:Paul Cercueil 
AuthorDate:Mon, 08 Mar 2021 21:23:00 
Committer: Daniel Lezcano 
CommitterDate: Thu, 08 Apr 2021 13:23:22 +02:00

dt-bindings: timer: ingenic: Add compatible strings for JZ4760(B)

Add compatible strings to support the system timer, clocksource, OST,
watchdog and PWM blocks of the JZ4760 and JZ4760B SoCs.

Newer SoCs which behave like the JZ4760 or JZ4760B now see their
compatible string require a fallback compatible string that corresponds
to one of these two SoCs.

Signed-off-by: Paul Cercueil 
Reviewed-by: Rob Herring 
Signed-off-by: Daniel Lezcano 
Link: https://lore.kernel.org/r/20210308212302.10288-1-p...@crapouillou.net
---
 Documentation/devicetree/bindings/timer/ingenic,tcu.yaml | 30 +--
 1 file changed, 22 insertions(+), 8 deletions(-)

diff --git a/Documentation/devicetree/bindings/timer/ingenic,tcu.yaml 
b/Documentation/devicetree/bindings/timer/ingenic,tcu.yaml
index 024bcad..8165df4 100644
--- a/Documentation/devicetree/bindings/timer/ingenic,tcu.yaml
+++ b/Documentation/devicetree/bindings/timer/ingenic,tcu.yaml
@@ -20,6 +20,8 @@ select:
 enum:
   - ingenic,jz4740-tcu
   - ingenic,jz4725b-tcu
+  - ingenic,jz4760-tcu
+  - ingenic,jz4760b-tcu
   - ingenic,jz4770-tcu
   - ingenic,jz4780-tcu
   - ingenic,x1000-tcu
@@ -52,12 +54,15 @@ properties:
   - enum:
   - ingenic,jz4740-tcu
   - ingenic,jz4725b-tcu
-  - ingenic,jz4770-tcu
+  - ingenic,jz4760-tcu
   - ingenic,x1000-tcu
   - const: simple-mfd
   - items:
-  - const: ingenic,jz4780-tcu
-  - const: ingenic,jz4770-tcu
+  - enum:
+  - ingenic,jz4780-tcu
+  - ingenic,jz4770-tcu
+  - ingenic,jz4760b-tcu
+  - const: ingenic,jz4760-tcu
   - const: simple-mfd
 
   reg:
@@ -118,6 +123,8 @@ patternProperties:
   - items:
   - enum:
   - ingenic,jz4770-watchdog
+  - ingenic,jz4760b-watchdog
+  - ingenic,jz4760-watchdog
   - ingenic,jz4725b-watchdog
   - const: ingenic,jz4740-watchdog
 
@@ -147,6 +154,8 @@ patternProperties:
   - ingenic,jz4725b-pwm
   - items:
   - enum:
+  - ingenic,jz4760-pwm
+  - ingenic,jz4760b-pwm
   - ingenic,jz4770-pwm
   - ingenic,jz4780-pwm
   - const: ingenic,jz4740-pwm
@@ -183,10 +192,15 @@ patternProperties:
 oneOf:
   - enum:
   - ingenic,jz4725b-ost
-  - ingenic,jz4770-ost
+  - ingenic,jz4760b-ost
   - items:
-  - const: ingenic,jz4780-ost
-  - const: ingenic,jz4770-ost
+  - const: ingenic,jz4760-ost
+  - const: ingenic,jz4725b-ost
+  - items:
+  - enum:
+  - ingenic,jz4780-ost
+  - ingenic,jz4770-ost
+  - const: ingenic,jz4760b-ost
 
   reg:
 maxItems: 1
@@ -226,7 +240,7 @@ examples:
 #include 
 #include 
 tcu: timer@10002000 {
-  compatible = "ingenic,jz4770-tcu", "simple-mfd";
+  compatible = "ingenic,jz4770-tcu", "ingenic,jz4760-tcu", "simple-mfd";
   reg = <0x10002000 0x1000>;
   #address-cells = <1>;
   #size-cells = <1>;
@@ -272,7 +286,7 @@ examples:
   };
 
   ost: timer@e0 {
-compatible = "ingenic,jz4770-ost";
+compatible = "ingenic,jz4770-ost", "ingenic,jz4760b-ost";
 reg = <0xe0 0x20>;
 
 clocks = < TCU_CLK_OST>;


[tip: timers/core] clocksource/drivers/ingenic: Add support for the JZ4760

2021-04-09 Thread tip-bot2 for Paul Cercueil
The following commit has been merged into the timers/core branch of tip:

Commit-ID: 8a3f717f35a3e9a28a935f8e4459c72ba00e90ca
Gitweb:
https://git.kernel.org/tip/8a3f717f35a3e9a28a935f8e4459c72ba00e90ca
Author:Paul Cercueil 
AuthorDate:Mon, 08 Mar 2021 21:23:01 
Committer: Daniel Lezcano 
CommitterDate: Thu, 08 Apr 2021 13:23:22 +02:00

clocksource/drivers/ingenic: Add support for the JZ4760

Add support for the TCU (Timer/Counter Unit) of the JZ4760 and JZ4760B
SoCs.

Signed-off-by: Paul Cercueil 
Signed-off-by: Daniel Lezcano 
Link: https://lore.kernel.org/r/20210308212302.10288-2-p...@crapouillou.net
---
 drivers/clocksource/ingenic-timer.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/clocksource/ingenic-timer.c 
b/drivers/clocksource/ingenic-timer.c
index 905fd6b..24ed0f1 100644
--- a/drivers/clocksource/ingenic-timer.c
+++ b/drivers/clocksource/ingenic-timer.c
@@ -264,6 +264,7 @@ static const struct ingenic_soc_info jz4725b_soc_info = {
 static const struct of_device_id ingenic_tcu_of_match[] = {
{ .compatible = "ingenic,jz4740-tcu", .data = _soc_info, },
{ .compatible = "ingenic,jz4725b-tcu", .data = _soc_info, },
+   { .compatible = "ingenic,jz4760-tcu", .data = _soc_info, },
{ .compatible = "ingenic,jz4770-tcu", .data = _soc_info, },
{ .compatible = "ingenic,x1000-tcu", .data = _soc_info, },
{ /* sentinel */ }
@@ -358,6 +359,7 @@ err_free_ingenic_tcu:
 
 TIMER_OF_DECLARE(jz4740_tcu_intc,  "ingenic,jz4740-tcu",  ingenic_tcu_init);
 TIMER_OF_DECLARE(jz4725b_tcu_intc, "ingenic,jz4725b-tcu", ingenic_tcu_init);
+TIMER_OF_DECLARE(jz4760_tcu_intc,  "ingenic,jz4760-tcu",  ingenic_tcu_init);
 TIMER_OF_DECLARE(jz4770_tcu_intc,  "ingenic,jz4770-tcu",  ingenic_tcu_init);
 TIMER_OF_DECLARE(x1000_tcu_intc,  "ingenic,x1000-tcu",  ingenic_tcu_init);
 


[tip: timers/core] clocksource/drivers/ingenic-ost: Add support for the JZ4760B

2021-04-09 Thread tip-bot2 for Paul Cercueil
The following commit has been merged into the timers/core branch of tip:

Commit-ID: 352408aff91d06fd2f0e35d52079bd0cd70cd29e
Gitweb:
https://git.kernel.org/tip/352408aff91d06fd2f0e35d52079bd0cd70cd29e
Author:Paul Cercueil 
AuthorDate:Mon, 08 Mar 2021 21:23:02 
Committer: Daniel Lezcano 
CommitterDate: Thu, 08 Apr 2021 13:23:23 +02:00

clocksource/drivers/ingenic-ost: Add support for the JZ4760B

The OST in the JZ4760B SoC works exactly the same as in the JZ4770. But
since the JZ4760B is older, its Device Tree string does not fall back to
the JZ4770 one; so add support for the JZ4760B compatible string here.

Signed-off-by: Paul Cercueil 
Signed-off-by: Daniel Lezcano 
Link: https://lore.kernel.org/r/20210308212302.10288-3-p...@crapouillou.net
---
 drivers/clocksource/ingenic-ost.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/clocksource/ingenic-ost.c 
b/drivers/clocksource/ingenic-ost.c
index 029efc2..d2d6646 100644
--- a/drivers/clocksource/ingenic-ost.c
+++ b/drivers/clocksource/ingenic-ost.c
@@ -167,13 +167,14 @@ static const struct ingenic_ost_soc_info 
jz4725b_ost_soc_info = {
.is64bit = false,
 };
 
-static const struct ingenic_ost_soc_info jz4770_ost_soc_info = {
+static const struct ingenic_ost_soc_info jz4760b_ost_soc_info = {
.is64bit = true,
 };
 
 static const struct of_device_id ingenic_ost_of_match[] = {
{ .compatible = "ingenic,jz4725b-ost", .data = _ost_soc_info, },
-   { .compatible = "ingenic,jz4770-ost", .data = _ost_soc_info, },
+   { .compatible = "ingenic,jz4760b-ost", .data = _ost_soc_info, },
+   { .compatible = "ingenic,jz4770-ost", .data = _ost_soc_info, },
{ }
 };
 


Re: [PATCH 1/2] linux/kconfig.h: replace IF_ENABLED() with PTR_IF() in

2021-04-09 Thread Paul Cercueil




Le ven. 9 avril 2021 à 17:30, Masahiro Yamada  a 
écrit :
On Fri, Apr 9, 2021 at 5:15 PM Paul Cercueil  
wrote:


 Hi Masahiro,

 Le ven. 9 avril 2021 à 5:58, Masahiro Yamada 
 a

 écrit :
 >  is included from all the kernel-space source 
files,

 > including C, assembly, linker scripts. It is intended to contain
 > minimal
 > set of macros to evaluate CONFIG options.
 >
 > IF_ENABLED() is an intruder here because (x ? y : z) is C code, 
which

 > should not be included from assembly files or linker scripts.
 >
 > Also,  is no longer self-contained because NULL 
is

 > defined in .
 >
 > Move IF_ENABLED() out to  as PTR_IF().
 >
 > PTR_IF(IS_ENABLED(CONFIG_FOO), ...) is slightly longer than
 > IF_ENABLED(CONFIG_FOO, ...), but it is not a big deal because
 > sub-systems often define dedicated macros such as of_match_ptr(),
 > pm_ptr() etc. for common use-cases.

 What's the idea behind changing IF_ENABLED() to PTR_IF()? You didn't
 explain that. What's wrong with IF_ENABLED()?



PTR_IF() is a more generalized variant, which I believe is
a better fit in 
The first parameter does not need to be a CONFIG option,
but any expression.


Fair enough, but we could still have IF_ENABLED as a specialized 
variant of PTR_IF:


#define IF_ENABLED(cfg, ptr) PTR_IF(IS_ENABLED(cfg), (ptr))

-Paul





 Cheers,
 -Paul

 > Signed-off-by: Masahiro Yamada 
 > ---
 >
 >  drivers/pinctrl/pinctrl-ingenic.c | 20 ++--
 >  include/linux/kconfig.h   |  6 --
 >  include/linux/kernel.h|  2 ++
 >  3 files changed, 12 insertions(+), 16 deletions(-)
 >
 > diff --git a/drivers/pinctrl/pinctrl-ingenic.c
 > b/drivers/pinctrl/pinctrl-ingenic.c
 > index f2746125b077..b21e2ae4528d 100644
 > --- a/drivers/pinctrl/pinctrl-ingenic.c
 > +++ b/drivers/pinctrl/pinctrl-ingenic.c
 > @@ -2496,43 +2496,43 @@ static int __init
 > ingenic_pinctrl_probe(struct platform_device *pdev)
 >  static const struct of_device_id ingenic_pinctrl_of_match[] = {
 >   {
 >   .compatible = "ingenic,jz4740-pinctrl",
 > - .data = IF_ENABLED(CONFIG_MACH_JZ4740, 
_chip_info)
 > + .data = PTR_IF(IS_ENABLED(CONFIG_MACH_JZ4740), 
_chip_info)

 >   },
 >   {
 >   .compatible = "ingenic,jz4725b-pinctrl",
 > - .data = IF_ENABLED(CONFIG_MACH_JZ4725B, 
_chip_info)
 > + .data = PTR_IF(IS_ENABLED(CONFIG_MACH_JZ4725B), 
_chip_info)

 >   },
 >   {
 >   .compatible = "ingenic,jz4760-pinctrl",
 > - .data = IF_ENABLED(CONFIG_MACH_JZ4760, 
_chip_info)
 > + .data = PTR_IF(IS_ENABLED(CONFIG_MACH_JZ4760), 
_chip_info)

 >   },
 >   {
 >   .compatible = "ingenic,jz4760b-pinctrl",
 > - .data = IF_ENABLED(CONFIG_MACH_JZ4760, 
_chip_info)
 > + .data = PTR_IF(IS_ENABLED(CONFIG_MACH_JZ4760), 
_chip_info)

 >   },
 >   {
 >   .compatible = "ingenic,jz4770-pinctrl",
 > - .data = IF_ENABLED(CONFIG_MACH_JZ4770, 
_chip_info)
 > + .data = PTR_IF(IS_ENABLED(CONFIG_MACH_JZ4770), 
_chip_info)

 >   },
 >   {
 >   .compatible = "ingenic,jz4780-pinctrl",
 > - .data = IF_ENABLED(CONFIG_MACH_JZ4780, 
_chip_info)
 > + .data = PTR_IF(IS_ENABLED(CONFIG_MACH_JZ4780), 
_chip_info)

 >   },
 >   {
 >   .compatible = "ingenic,x1000-pinctrl",
 > - .data = IF_ENABLED(CONFIG_MACH_X1000, 
_chip_info)
 > + .data = PTR_IF(IS_ENABLED(CONFIG_MACH_X1000), 
_chip_info)

 >   },
 >   {
 >   .compatible = "ingenic,x1000e-pinctrl",
 > - .data = IF_ENABLED(CONFIG_MACH_X1000, 
_chip_info)
 > + .data = PTR_IF(IS_ENABLED(CONFIG_MACH_X1000), 
_chip_info)

 >   },
 >   {
 >   .compatible = "ingenic,x1500-pinctrl",
 > - .data = IF_ENABLED(CONFIG_MACH_X1500, 
_chip_info)
 > + .data = PTR_IF(IS_ENABLED(CONFIG_MACH_X1500), 
_chip_info)

 >   },
 >   {
 >   .compatible = "ingenic,x1830-pinctrl",
 > - .data = IF_ENABLED(CONFIG_MACH_X1830, 
_chip_info)
 > + .data = PTR_IF(IS_ENABLED(CONFIG_MACH_X1830), 
_chip_info)

 >   },
 >   { /* sentinel */ },
 >  };
 > diff --git a/include/linux/kconfig.h b/include/linux/kconfig.h
 > index 24a59cb06963..cc8fa109cfa3 100644
 > --- a/include/linux/kconfig.h
 > +++ b/include/linux/kconfig.h
 > @@ -70,10 +70,4 @@
 >   */
 >  #define IS_ENABLED(option) __or(IS_BUILTIN(option),
 > IS_MODULE(option))
 >
 > -/*
 > - * IF_ENABLED(CONFIG_FOO, ptr) evalu

Re: [PATCH 1/2] linux/kconfig.h: replace IF_ENABLED() with PTR_IF() in

2021-04-09 Thread Paul Cercueil

Hi Masahiro,

Le ven. 9 avril 2021 à 5:58, Masahiro Yamada  a 
écrit :

 is included from all the kernel-space source files,
including C, assembly, linker scripts. It is intended to contain 
minimal

set of macros to evaluate CONFIG options.

IF_ENABLED() is an intruder here because (x ? y : z) is C code, which
should not be included from assembly files or linker scripts.

Also,  is no longer self-contained because NULL is
defined in .

Move IF_ENABLED() out to  as PTR_IF().

PTR_IF(IS_ENABLED(CONFIG_FOO), ...) is slightly longer than
IF_ENABLED(CONFIG_FOO, ...), but it is not a big deal because
sub-systems often define dedicated macros such as of_match_ptr(),
pm_ptr() etc. for common use-cases.


What's the idea behind changing IF_ENABLED() to PTR_IF()? You didn't 
explain that. What's wrong with IF_ENABLED()?


Cheers,
-Paul


Signed-off-by: Masahiro Yamada 
---

 drivers/pinctrl/pinctrl-ingenic.c | 20 ++--
 include/linux/kconfig.h   |  6 --
 include/linux/kernel.h|  2 ++
 3 files changed, 12 insertions(+), 16 deletions(-)

diff --git a/drivers/pinctrl/pinctrl-ingenic.c 
b/drivers/pinctrl/pinctrl-ingenic.c

index f2746125b077..b21e2ae4528d 100644
--- a/drivers/pinctrl/pinctrl-ingenic.c
+++ b/drivers/pinctrl/pinctrl-ingenic.c
@@ -2496,43 +2496,43 @@ static int __init 
ingenic_pinctrl_probe(struct platform_device *pdev)

 static const struct of_device_id ingenic_pinctrl_of_match[] = {
{
.compatible = "ingenic,jz4740-pinctrl",
-   .data = IF_ENABLED(CONFIG_MACH_JZ4740, _chip_info)
+   .data = PTR_IF(IS_ENABLED(CONFIG_MACH_JZ4740), 
_chip_info)
},
{
.compatible = "ingenic,jz4725b-pinctrl",
-   .data = IF_ENABLED(CONFIG_MACH_JZ4725B, _chip_info)
+   .data = PTR_IF(IS_ENABLED(CONFIG_MACH_JZ4725B), 
_chip_info)
},
{
.compatible = "ingenic,jz4760-pinctrl",
-   .data = IF_ENABLED(CONFIG_MACH_JZ4760, _chip_info)
+   .data = PTR_IF(IS_ENABLED(CONFIG_MACH_JZ4760), 
_chip_info)
},
{
.compatible = "ingenic,jz4760b-pinctrl",
-   .data = IF_ENABLED(CONFIG_MACH_JZ4760, _chip_info)
+   .data = PTR_IF(IS_ENABLED(CONFIG_MACH_JZ4760), 
_chip_info)
},
{
.compatible = "ingenic,jz4770-pinctrl",
-   .data = IF_ENABLED(CONFIG_MACH_JZ4770, _chip_info)
+   .data = PTR_IF(IS_ENABLED(CONFIG_MACH_JZ4770), 
_chip_info)
},
{
.compatible = "ingenic,jz4780-pinctrl",
-   .data = IF_ENABLED(CONFIG_MACH_JZ4780, _chip_info)
+   .data = PTR_IF(IS_ENABLED(CONFIG_MACH_JZ4780), 
_chip_info)
},
{
.compatible = "ingenic,x1000-pinctrl",
-   .data = IF_ENABLED(CONFIG_MACH_X1000, _chip_info)
+   .data = PTR_IF(IS_ENABLED(CONFIG_MACH_X1000), _chip_info)
},
{
.compatible = "ingenic,x1000e-pinctrl",
-   .data = IF_ENABLED(CONFIG_MACH_X1000, _chip_info)
+   .data = PTR_IF(IS_ENABLED(CONFIG_MACH_X1000), _chip_info)
},
{
.compatible = "ingenic,x1500-pinctrl",
-   .data = IF_ENABLED(CONFIG_MACH_X1500, _chip_info)
+   .data = PTR_IF(IS_ENABLED(CONFIG_MACH_X1500), _chip_info)
},
{
.compatible = "ingenic,x1830-pinctrl",
-   .data = IF_ENABLED(CONFIG_MACH_X1830, _chip_info)
+   .data = PTR_IF(IS_ENABLED(CONFIG_MACH_X1830), _chip_info)
},
{ /* sentinel */ },
 };
diff --git a/include/linux/kconfig.h b/include/linux/kconfig.h
index 24a59cb06963..cc8fa109cfa3 100644
--- a/include/linux/kconfig.h
+++ b/include/linux/kconfig.h
@@ -70,10 +70,4 @@
  */
 #define IS_ENABLED(option) __or(IS_BUILTIN(option), 
IS_MODULE(option))


-/*
- * IF_ENABLED(CONFIG_FOO, ptr) evaluates to (ptr) if CONFIG_FOO is 
set to 'y'

- * or 'm', NULL otherwise.
- */
-#define IF_ENABLED(option, ptr) (IS_ENABLED(option) ? (ptr) : NULL)
-
 #endif /* __LINUX_KCONFIG_H */
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index 5b7ed6dc99ac..8685ca4cf287 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -38,6 +38,8 @@
 #define PTR_ALIGN_DOWN(p, a)	((typeof(p))ALIGN_DOWN((unsigned 
long)(p), (a)))

 #define IS_ALIGNED(x, a)   (((x) & ((typeof(x))(a) - 1)) == 0)

+#define PTR_IF(cond, ptr)  ((cond) ? (ptr) : NULL)
+
 /* generic data direction definitions */
 #define READ   0
 #define WRITE  1
--
2.27.0






Re: [PATCH 1/2] drm/ingenic: Switch IPU plane to type OVERLAY

2021-03-30 Thread Paul Cercueil

Hi Simon,

Le mar. 30 mars 2021 à 7:23, Simon Ser  a écrit :

 It should have been an OVERLAY from the beginning. The documentation
 stipulates that there should be an unique PRIMARY plane per CRTC.


Thanks for the quick patch! One comment below…


 Fixes: fc1acf317b01 ("drm/ingenic: Add support for the IPU")
 Cc:  # 5.8+
 Signed-off-by: Paul Cercueil 
 ---
  drivers/gpu/drm/ingenic/ingenic-drm-drv.c | 11 +--
  drivers/gpu/drm/ingenic/ingenic-ipu.c |  2 +-
  2 files changed, 6 insertions(+), 7 deletions(-)

 diff --git a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c 
b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c

 index 29742ec5ab95..09225b770bb8 100644
 --- a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c
 +++ b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c
 @@ -419,7 +419,7 @@ static void ingenic_drm_plane_enable(struct 
ingenic_drm *priv,

unsigned int en_bit;

if (priv->soc_info->has_osd) {
 -  if (plane->type == DRM_PLANE_TYPE_PRIMARY)
 +  if (plane != >f0)


I don't know about this driver but… is this really the same as the 
previous
condition? The previous condition would match two planes, this one 
seems to

match only a single plane. What am I missing?


There are three planes, which we will call here f0, f1, and ipu.

Previously, the "plane->type == DRM_PLANE_TYPE_PRIMARY" matched f1 and 
ipu. Since ipu is now OVERLAY we have to change the condition or the 
behaviour will be different, as otherwise it would only match the f1 
plane.


Cheers,
-Paul




[PATCH 0/2] drm/ingenic: IPU plane fixes

2021-03-29 Thread Paul Cercueil
Hi,

A set of two fixes for the IPU plane of the ingenic-drm driver.

Patch [1/2] changes the type of the IPU plane from PRIMARY to OVERLAY,
since there can only be one PRIMARY plane per CRTC.

Patch [2/2] enforces that a full modeset is only performed when the
"sharpness" property is modified.

Cheers,
-Paul

Paul Cercueil (2):
  drm/ingenic: Switch IPU plane to type OVERLAY
  drm/ingenic: Don't request full modeset if property is not modified

 drivers/gpu/drm/ingenic/ingenic-drm-drv.c | 11 +--
 drivers/gpu/drm/ingenic/ingenic-ipu.c |  6 --
 2 files changed, 9 insertions(+), 8 deletions(-)

-- 
2.30.2



[PATCH 1/2] drm/ingenic: Switch IPU plane to type OVERLAY

2021-03-29 Thread Paul Cercueil
It should have been an OVERLAY from the beginning. The documentation
stipulates that there should be an unique PRIMARY plane per CRTC.

Fixes: fc1acf317b01 ("drm/ingenic: Add support for the IPU")
Cc:  # 5.8+
Signed-off-by: Paul Cercueil 
---
 drivers/gpu/drm/ingenic/ingenic-drm-drv.c | 11 +--
 drivers/gpu/drm/ingenic/ingenic-ipu.c |  2 +-
 2 files changed, 6 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c 
b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c
index 29742ec5ab95..09225b770bb8 100644
--- a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c
+++ b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c
@@ -419,7 +419,7 @@ static void ingenic_drm_plane_enable(struct ingenic_drm 
*priv,
unsigned int en_bit;
 
if (priv->soc_info->has_osd) {
-   if (plane->type == DRM_PLANE_TYPE_PRIMARY)
+   if (plane != >f0)
en_bit = JZ_LCD_OSDC_F1EN;
else
en_bit = JZ_LCD_OSDC_F0EN;
@@ -434,7 +434,7 @@ void ingenic_drm_plane_disable(struct device *dev, struct 
drm_plane *plane)
unsigned int en_bit;
 
if (priv->soc_info->has_osd) {
-   if (plane->type == DRM_PLANE_TYPE_PRIMARY)
+   if (plane != >f0)
en_bit = JZ_LCD_OSDC_F1EN;
else
en_bit = JZ_LCD_OSDC_F0EN;
@@ -461,8 +461,7 @@ void ingenic_drm_plane_config(struct device *dev,
 
ingenic_drm_plane_enable(priv, plane);
 
-   if (priv->soc_info->has_osd &&
-   plane->type == DRM_PLANE_TYPE_PRIMARY) {
+   if (priv->soc_info->has_osd && plane != >f0) {
switch (fourcc) {
case DRM_FORMAT_XRGB1555:
ctrl |= JZ_LCD_OSDCTRL_RGB555;
@@ -510,7 +509,7 @@ void ingenic_drm_plane_config(struct device *dev,
}
 
if (priv->soc_info->has_osd) {
-   if (plane->type == DRM_PLANE_TYPE_PRIMARY) {
+   if (plane != >f0) {
xy_reg = JZ_REG_LCD_XYP1;
size_reg = JZ_REG_LCD_SIZE1;
} else {
@@ -561,7 +560,7 @@ static void ingenic_drm_plane_atomic_update(struct 
drm_plane *plane,
height = newstate->src_h >> 16;
cpp = newstate->fb->format->cpp[0];
 
-   if (!priv->soc_info->has_osd || plane->type == 
DRM_PLANE_TYPE_OVERLAY)
+   if (!priv->soc_info->has_osd || plane == >f0)
hwdesc = >dma_hwdescs->hwdesc_f0;
else
hwdesc = >dma_hwdescs->hwdesc_f1;
diff --git a/drivers/gpu/drm/ingenic/ingenic-ipu.c 
b/drivers/gpu/drm/ingenic/ingenic-ipu.c
index 5ae6adab8306..3b1091e7c0cd 100644
--- a/drivers/gpu/drm/ingenic/ingenic-ipu.c
+++ b/drivers/gpu/drm/ingenic/ingenic-ipu.c
@@ -767,7 +767,7 @@ static int ingenic_ipu_bind(struct device *dev, struct 
device *master, void *d)
 
err = drm_universal_plane_init(drm, plane, 1, _ipu_plane_funcs,
   soc_info->formats, soc_info->num_formats,
-  NULL, DRM_PLANE_TYPE_PRIMARY, NULL);
+  NULL, DRM_PLANE_TYPE_OVERLAY, NULL);
if (err) {
dev_err(dev, "Failed to init plane: %i\n", err);
return err;
-- 
2.30.2



[PATCH 2/2] drm/ingenic: Don't request full modeset if property is not modified

2021-03-29 Thread Paul Cercueil
Avoid requesting a full modeset if the sharpness property is not
modified, because then we don't actually need it.

Fixes: fc1acf317b01 ("drm/ingenic: Add support for the IPU")
Cc:  # 5.8+
Signed-off-by: Paul Cercueil 
---
 drivers/gpu/drm/ingenic/ingenic-ipu.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/ingenic/ingenic-ipu.c 
b/drivers/gpu/drm/ingenic/ingenic-ipu.c
index 3b1091e7c0cd..95b665c4a7b0 100644
--- a/drivers/gpu/drm/ingenic/ingenic-ipu.c
+++ b/drivers/gpu/drm/ingenic/ingenic-ipu.c
@@ -640,10 +640,12 @@ ingenic_ipu_plane_atomic_set_property(struct drm_plane 
*plane,
 {
struct ingenic_ipu *ipu = plane_to_ingenic_ipu(plane);
struct drm_crtc_state *crtc_state;
+   bool mode_changed;
 
if (property != ipu->sharpness_prop)
return -EINVAL;
 
+   mode_changed = val != ipu->sharpness;
ipu->sharpness = val;
 
if (state->crtc) {
@@ -651,7 +653,7 @@ ingenic_ipu_plane_atomic_set_property(struct drm_plane 
*plane,
if (WARN_ON(!crtc_state))
return -EINVAL;
 
-   crtc_state->mode_changed = true;
+   crtc_state->mode_changed |= mode_changed;
}
 
return 0;
-- 
2.30.2



Re: [PATCH] drm: DON'T require each CRTC to have a unique primary plane

2021-03-29 Thread Paul Cercueil




Le lun. 29 mars 2021 à 15:42, Simon Ser  a écrit 
:
On Monday, March 29th, 2021 at 5:39 PM, Paul Cercueil 
 wrote:



 Ok, I read that as "all drivers should provide AT LEAST one primary
 plane per CRTC", and not as "all drivers should provide ONE AND ONLY
 ONE primary plane per CRTC". My bad.


Yeah, it's a little complicated to document, because it's possible for
a primary plane to be compatible with multiple CRTCs… We tried to
improve this [1] recently.

[1]: 
https://dri.freedesktop.org/docs/drm/gpu/drm-kms.html#plane-abstraction


Ok, that is definitely much clearer :)

-Paul




Re: [PATCH v4 2/3] drm/encoder: Add macro drmm_plain_encoder_alloc()

2021-03-29 Thread Paul Cercueil




Le dim. 28 mars 2021 à 1:05, Laurent Pinchart 
 a écrit :

Hi Paul,

Thank you for the patch.

On Sat, Mar 27, 2021 at 11:57:41AM +, Paul Cercueil wrote:

 This performs the same operation as drmm_encoder_alloc(), but
 only allocates and returns a struct drm_encoder instance.

 v4: Rename macro drmm_plain_encoder_alloc() and move to
 . Since it's not "simple" anymore it
 will now take funcs/name arguments as well.

 Signed-off-by: Paul Cercueil 


Reviewed-by: Laurent Pinchart 


Patchset applied to drm-misc-next.

Thanks!

-Paul


 ---
  include/drm/drm_encoder.h | 18 ++
  1 file changed, 18 insertions(+)

 diff --git a/include/drm/drm_encoder.h b/include/drm/drm_encoder.h
 index 5bf78b5bcb2b..6e91a0280f31 100644
 --- a/include/drm/drm_encoder.h
 +++ b/include/drm/drm_encoder.h
 @@ -224,6 +224,24 @@ void *__drmm_encoder_alloc(struct drm_device 
*dev,

  offsetof(type, member), funcs, \
  encoder_type, name, ##__VA_ARGS__))

 +/**
 + * drmm_plain_encoder_alloc - Allocate and initialize an encoder
 + * @dev: drm device
 + * @funcs: callbacks for this encoder (optional)
 + * @encoder_type: user visible type of the encoder
 + * @name: printf style format string for the encoder name, or NULL 
for default name

 + *
 + * This is a simplified version of drmm_encoder_alloc(), which 
only allocates

 + * and returns a struct drm_encoder instance, with no subclassing.
 + *
 + * Returns:
 + * Pointer to the new drm_encoder struct, or ERR_PTR on failure.
 + */
 +#define drmm_plain_encoder_alloc(dev, funcs, encoder_type, name, 
...) \

 +  ((struct drm_encoder *) \
 +   __drmm_encoder_alloc(dev, sizeof(struct drm_encoder), \
 +0, funcs, encoder_type, name, ##__VA_ARGS__))
 +
  /**
   * drm_encoder_index - find the index of a registered encoder
   * @encoder: encoder to find index for


--
Regards,

Laurent Pinchart





Re: [PATCH] drm: DON'T require each CRTC to have a unique primary plane

2021-03-29 Thread Paul Cercueil




Le lun. 29 mars 2021 à 17:35, Maxime Ripard  a 
écrit :

On Mon, Mar 29, 2021 at 04:15:28PM +0100, Paul Cercueil wrote:

 Hi Maxime,

 Le lun. 29 mars 2021 à 16:07, Maxime Ripard  a 
écrit :

 > On Sat, Mar 27, 2021 at 11:22:14AM +0000, Paul Cercueil wrote:
 > >  The ingenic-drm driver has two mutually exclusive primary 
planes
 > >  already; so the fact that a CRTC must have one and only one 
primary

 > >  plane is an invalid assumption.
 >
 > I mean, no? It's been documented for a while that a CRTC should 
only
 > have a single primary, so I'd say that the invalid assumption was 
that

 > it was possible to have multiple primary planes for a CRTC.

 Documented where?

 I did read the doc of "enum drm_plane_type" in , 
and the

 DRM_PLANE_TYPE_PRIMARY describes my two planes, so I went with that.


At least since 4.9, this was in the documentation generated for DRM:
https://elixir.bootlin.com/linux/v4.9.263/source/drivers/gpu/drm/drm_plane.c#L43


Ok, I read that as "all drivers should provide AT LEAST one primary 
plane per CRTC", and not as "all drivers should provide ONE AND ONLY 
ONE primary plane per CRTC". My bad.


-Paul




Re: [PATCH] drm: DON'T require each CRTC to have a unique primary plane

2021-03-29 Thread Paul Cercueil

Hi Simon,

Le lun. 29 mars 2021 à 14:11, Simon Ser  a écrit 
:
On Monday, March 29th, 2021 at 4:07 PM, Maxime Ripard 
 wrote:


 Since it looks like you have two mutually exclusive planes, just 
expose

 one and be done with it?


You can expose the other as an overlay. Clever user-space will be able
to figure out that the more advanced plane can be used if the primary
plane is disabled.

But yeah, I don't think exposing two primary planes makes sense. The
"primary" bit is just there for legacy user-space, it's a hint that
it's the best plane to light up for fullscreen content. It has no 
other

significance than that, and in particular it doesn't mean that it's
incompatible with other primary planes.


Yes, from what I understood when writing the driver, there is not much 
of a difference with primary vs. overlay planes when dealing with the 
atomic DRM API, which I used exclusively.


Making the second plane an overlay would break the ABI, which is never 
something I'm happy to do; but I'd prefer to do it now than later.


I still have concerns about the user-space being "clever" enough to 
know it can disable the primary plane. Can e.g. wlroots handle that?


Cheers,
-Paul




Re: [PATCH] drm: DON'T require each CRTC to have a unique primary plane

2021-03-29 Thread Paul Cercueil




Le lun. 29 mars 2021 à 17:35, Pekka Paalanen  a 
écrit :

On Mon, 29 Mar 2021 12:41:00 +0100
Paul Cercueil  wrote:


 Hi,

 Le lun. 29 mars 2021 à 11:15, Pekka Paalanen  
a

 écrit :
 > On Sat, 27 Mar 2021 11:26:26 +
 > Paul Cercueil  wrote:
 >
 >>  It has two mutually exclusive background planes (same Z level) 
+ one

 >>  overlay plane.
 >
 > What's the difference between the two background planes?
 >
 > How will generic userspace know to pick the "right" one?

 First primary plane cannot scale, supports RGB and C8. Second 
primary

 plane goes through the IPU, and as such can scale and convert pixel
 formats; it supports RGB, non-planar YUV, and multi-planar YUV.

 Right now the userspace apps we have will simply pick the first one
 that fits the bill.


What would be the downside of exposing just one "virtual" primary
plane, and then have the driver pick one of the two hardware planes as
appropriate per modeset?


The IPU plane is in a different driver, so all the callbacks are 
different. That sounds like it would be a mess.


-Paul


Thanks,
pq


 >>  Le sam. 27 mars 2021 à 11:24, Simon Ser  a
 >> écrit
 >>  :
 >>  > On Saturday, March 27th, 2021 at 12:22 PM, Paul Cercueil
 >>  >  wrote:
 >>  >
 >>  >>  The ingenic-drm driver has two mutually exclusive primary 
planes

 >>  >>  already; so the fact that a CRTC must have one and only one
 >> primary
 >>  >>  plane is an invalid assumption.
 >>  >
 >>  > Why does this driver expose two primary planes, if it only 
has a

 >>  > single
 >>  > CRTC?
 >>
 >>
 >>  ___
 >>  dri-devel mailing list
 >>  dri-de...@lists.freedesktop.org
 >>  https://lists.freedesktop.org/mailman/listinfo/dri-devel
 >









Re: [PATCH] drm: DON'T require each CRTC to have a unique primary plane

2021-03-29 Thread Paul Cercueil

Hi Maxime,

Le lun. 29 mars 2021 à 16:07, Maxime Ripard  a 
écrit :

On Sat, Mar 27, 2021 at 11:22:14AM +, Paul Cercueil wrote:

 The ingenic-drm driver has two mutually exclusive primary planes
 already; so the fact that a CRTC must have one and only one primary
 plane is an invalid assumption.


I mean, no? It's been documented for a while that a CRTC should only
have a single primary, so I'd say that the invalid assumption was that
it was possible to have multiple primary planes for a CRTC.


Documented where?

I did read the doc of "enum drm_plane_type" in , and 
the DRM_PLANE_TYPE_PRIMARY describes my two planes, so I went with that.


-Paul

Since it looks like you have two mutually exclusive planes, just 
expose

one and be done with it?

Maxime





Re: [PATCH] drm: DON'T require each CRTC to have a unique primary plane

2021-03-29 Thread Paul Cercueil

Hi,

Le lun. 29 mars 2021 à 11:15, Pekka Paalanen  a 
écrit :

On Sat, 27 Mar 2021 11:26:26 +
Paul Cercueil  wrote:


 It has two mutually exclusive background planes (same Z level) + one
 overlay plane.


What's the difference between the two background planes?

How will generic userspace know to pick the "right" one?


First primary plane cannot scale, supports RGB and C8. Second primary 
plane goes through the IPU, and as such can scale and convert pixel 
formats; it supports RGB, non-planar YUV, and multi-planar YUV.


Right now the userspace apps we have will simply pick the first one 
that fits the bill.


Cheers,
-Paul

 Le sam. 27 mars 2021 à 11:24, Simon Ser  a 
écrit

 :
 > On Saturday, March 27th, 2021 at 12:22 PM, Paul Cercueil
 >  wrote:
 >
 >>  The ingenic-drm driver has two mutually exclusive primary planes
 >>  already; so the fact that a CRTC must have one and only one 
primary

 >>  plane is an invalid assumption.
 >
 > Why does this driver expose two primary planes, if it only has a
 > single
 > CRTC?


 ___
 dri-devel mailing list
 dri-de...@lists.freedesktop.org
 https://lists.freedesktop.org/mailman/listinfo/dri-devel







Re: [PATCH v3 10/10] pinctrl: Ingenic: Add pinctrl driver for X2000.

2021-03-27 Thread Paul Cercueil

Hi Zhou,

Le jeu. 25 mars 2021 à 17:03, Zhou Yanjie  
a écrit :

Hi Paul,

On 2021/3/23 上午2:39, Paul Cercueil wrote:



 Le mer. 17 mars 2021 à 17:58, 周琰杰 (Zhou Yanjie) 
 a écrit :

Add support for probing the pinctrl-ingenic driver on the
 X2000 SoC from Ingenic.

 Signed-off-by: 周琰杰 (Zhou Yanjie) 
 ---

 Notes:
 v3:
 New patch.

  drivers/pinctrl/pinctrl-ingenic.c | 502 
+-

  1 file changed, 493 insertions(+), 9 deletions(-)

 diff --git a/drivers/pinctrl/pinctrl-ingenic.c 
b/drivers/pinctrl/pinctrl-ingenic.c

 index eb4912d..538d1b5 100644
 --- a/drivers/pinctrl/pinctrl-ingenic.c
 +++ b/drivers/pinctrl/pinctrl-ingenic.c
 @@ -57,6 +57,10 @@
  #define X1830_GPIO_PEL0x110
  #define X1830_GPIO_PEH0x120

 +#define X2000_GPIO_EDG0x70
 +#define X2000_GPIO_PEPU0x80
 +#define X2000_GPIO_PEPD0x90
 +
  #define REG_SET(x)((x) + 0x4)
  #define REG_CLEAR(x)((x) + 0x8)

 @@ -94,6 +98,7 @@ enum jz_version {
  ID_X1000,
  ID_X1500,
  ID_X1830,
 +ID_X2000,
  };

  struct ingenic_chip_info {
 @@ -2273,6 +2278,439 @@ static const struct ingenic_chip_info 
x1830_chip_info = {

  .pull_downs = x1830_pull_downs,
  };

 +static const u32 x2000_pull_ups[5] = {
 +0x0003, 0x, 0x1ff0, 0xc7fe3f3f, 0x8fff003f,
 +};
 +
 +static const u32 x2000_pull_downs[5] = {
 +0x0003, 0x, 0x1ff0, 0x, 0x8fff003f,
 +};
 +
 +static int x2000_uart0_data_pins[] = { 0x77, 0x78, };
 +static int x2000_uart0_hwflow_pins[] = { 0x79, 0x7a, };
 +static int x2000_uart1_data_pins[] = { 0x57, 0x58, };
 +static int x2000_uart1_hwflow_pins[] = { 0x55, 0x56, };
 +static int x2000_uart2_data_pins[] = { 0x7e, 0x7f, };
 +static int x2000_uart3_data_c_pins[] = { 0x59, 0x5a, };
 +static int x2000_uart3_data_d_pins[] = { 0x62, 0x63, };
 +static int x2000_uart3_hwflow_c_pins[] = { 0x5b, 0x5c, };
 +static int x2000_uart3_hwflow_d_pins[] = { 0x60, 0x61, };
 +static int x2000_uart4_data_a_pins[] = { 0x02, 0x03, };
 +static int x2000_uart4_data_c_pins[] = { 0x4b, 0x4c, };
 +static int x2000_uart4_hwflow_a_pins[] = { 0x00, 0x01, };
 +static int x2000_uart4_hwflow_c_pins[] = { 0x49, 0x4a, };
 +static int x2000_uart5_data_a_pins[] = { 0x04, 0x05, };
 +static int x2000_uart5_data_c_pins[] = { 0x45, 0x46, };
 +static int x2000_uart6_data_a_pins[] = { 0x06, 0x07, };
 +static int x2000_uart6_data_c_pins[] = { 0x47, 0x48, };
 +static int x2000_uart7_data_a_pins[] = { 0x08, 0x09, };
 +static int x2000_uart7_data_c_pins[] = { 0x41, 0x42, };
 +static int x2000_uart8_data_pins[] = { 0x3c, 0x3d, };
 +static int x2000_uart9_data_pins[] = { 0x3e, 0x3f, };
 +static int x2000_sfc0_d_pins[] = { 0x73, 0x74, 0x75, 0x76, 0x71, 
0x72, };
 +static int x2000_sfc0_e_pins[] = { 0x92, 0x93, 0x94, 0x95, 0x90, 
0x91, };

 +static int x2000_sfc1_pins[] = { 0x77, 0x78, 0x79, 0x7a, };
 +static int x2000_ssi0_dt_b_pins[] = { 0x3e, };
 +static int x2000_ssi0_dt_d_pins[] = { 0x69, };
 +static int x2000_ssi0_dr_b_pins[] = { 0x3d, };
 +static int x2000_ssi0_dr_d_pins[] = { 0x6a, };
 +static int x2000_ssi0_clk_b_pins[] = { 0x3f, };
 +static int x2000_ssi0_clk_d_pins[] = { 0x68, };
 +static int x2000_ssi0_ce0_b_pins[] = { 0x3c, };
 +static int x2000_ssi0_ce0_d_pins[] = { 0x6d, };
 +static int x2000_ssi1_dt_c_pins[] = { 0x4b, };
 +static int x2000_ssi1_dt_d_pins[] = { 0x72, };
 +static int x2000_ssi1_dt_e_pins[] = { 0x91, };
 +static int x2000_ssi1_dr_c_pins[] = { 0x4a, };
 +static int x2000_ssi1_dr_d_pins[] = { 0x73, };
 +static int x2000_ssi1_dr_e_pins[] = { 0x92, };
 +static int x2000_ssi1_clk_c_pins[] = { 0x4c, };
 +static int x2000_ssi1_clk_d_pins[] = { 0x71, };
 +static int x2000_ssi1_clk_e_pins[] = { 0x90, };
 +static int x2000_ssi1_ce0_c_pins[] = { 0x49, };
 +static int x2000_ssi1_ce0_d_pins[] = { 0x76, };
 +static int x2000_ssi1_ce0_e_pins[] = { 0x95, };
 +static int x2000_mmc0_1bit_pins[] = { 0x71, 0x72, 0x73, };
 +static int x2000_mmc0_4bit_pins[] = { 0x74, 0x75, 0x75, };
 +static int x2000_mmc0_8bit_pins[] = { 0x77, 0x78, 0x79, 0x7a, };
 +static int x2000_mmc1_1bit_pins[] = { 0x68, 0x69, 0x6a, };
 +static int x2000_mmc1_4bit_pins[] = { 0x6b, 0x6c, 0x6d, };
 +static int x2000_mmc2_1bit_pins[] = { 0x80, 0x81, 0x82, };
 +static int x2000_mmc2_4bit_pins[] = { 0x83, 0x84, 0x85, };
 +static int x2000_emc_8bit_data_pins[] = {
 +0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
 +};
 +static int x2000_emc_16bit_data_pins[] = {
 +0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
 +};
 +static int x2000_emc_addr_pins[] = {
 +0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
 +0x28, 0x29, 0x2a, 0x2b, 0x2c,
 +};
 +static int x2000_emc_rd_we_pins[] = { 0x2d, 0x2e, };
 +static int x2000_emc_wait_pins[] = { 0x2f, };
 +static int x2000_emc_cs1_pins[] = { 0x57, };
 +static int x2000_emc_cs2_pins[] = { 0x58, };
 +static int x2000_i2c0_pins[] = { 0x4e, 0x4d, };
 +static int

Re: [PATCH v3 08/10] pinctrl: Ingenic: Add pinctrl driver for JZ4755.

2021-03-27 Thread Paul Cercueil

Hi Zhou,

Le jeu. 25 mars 2021 à 16:38, Zhou Yanjie  
a écrit :

Hi,

On 2021/3/23 上午2:24, Paul Cercueil wrote:



Le mer. 17 mars 2021 à 17:58, 周琰杰 (Zhou Yanjie) 
 a écrit :

Add support for probing the pinctrl-ingenic driver on the
JZ4755 SoC from Ingenic.

Signed-off-by: 周琰杰 (Zhou Yanjie) 
---

Notes:
v3:
New patch.

 drivers/pinctrl/pinctrl-ingenic.c | 132 
++

 1 file changed, 132 insertions(+)

diff --git a/drivers/pinctrl/pinctrl-ingenic.c 
b/drivers/pinctrl/pinctrl-ingenic.c

index d98767b..d8b37fa 100644
--- a/drivers/pinctrl/pinctrl-ingenic.c
+++ b/drivers/pinctrl/pinctrl-ingenic.c
@@ -86,6 +86,7 @@ enum jz_version {
 ID_JZ4740,
 ID_JZ4725B,
 ID_JZ4750,
+ID_JZ4755,
 ID_JZ4760,
 ID_JZ4770,
 ID_JZ4780,
@@ -557,6 +558,131 @@ static const struct ingenic_chip_info 
jz4750_chip_info = {

 .pull_downs = jz4750_pull_downs,
 };

+static const u32 jz4755_pull_ups[6] = {
+0x, 0x, 0x0fff, 0x, 0x33dc3fff, 
0xfc00,

+};
+
+static const u32 jz4755_pull_downs[6] = {
+0x, 0x, 0x, 0x, 0x, 
0x,

+};
+
+static int jz4755_uart0_data_pins[] = { 0x7c, 0x7d, };
+static int jz4755_uart0_hwflow_pins[] = { 0x7e, 0x7f, };
+static int jz4755_uart1_data_pins[] = { 0x97, 0x99, };
+static int jz4755_uart2_data_pins[] = { 0x9f, };
+static int jz4755_mmc0_1bit_pins[] = { 0x2f, 0x50, 0x5c, };
+static int jz4755_mmc0_4bit_pins[] = { 0x5d, 0x5b, 0x51, };
+static int jz4755_mmc1_1bit_pins[] = { 0x3a, 0x3d, 0x3c, };
+static int jz4755_mmc1_4bit_pins[] = { 0x3b, 0x3e, 0x3f, };
+static int jz4755_i2c_pins[] = { 0x8c, 0x8d, };
+static int jz4755_cim_pins[] = {
+0x89, 0x8b, 0x8a, 0x88,
+0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+};
+static int jz4755_lcd_24bit_pins[] = {
+0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
+0x78, 0x79, 0x7a, 0x7b,
+};
+static int jz4755_nand_cs1_pins[] = { 0x55, };
+static int jz4755_nand_cs2_pins[] = { 0x56, };
+static int jz4755_nand_cs3_pins[] = { 0x57, };
+static int jz4755_nand_cs4_pins[] = { 0x58, };
+static int jz4755_nand_fre_fwe_pins[] = { 0x5c, 0x5d, };
+static int jz4755_pwm_pwm0_pins[] = { 0x94, };
+static int jz4755_pwm_pwm1_pins[] = { 0xab, };
+static int jz4755_pwm_pwm2_pins[] = { 0x96, };
+static int jz4755_pwm_pwm3_pins[] = { 0x97, };
+static int jz4755_pwm_pwm4_pins[] = { 0x98, };
+static int jz4755_pwm_pwm5_pins[] = { 0x99, };
+
+static u8 jz4755_mmc0_1bit_funcs[] = { 2, 2, 1, };
+static u8 jz4755_mmc0_4bit_funcs[] = { 1, 0, 1, };
+static u8 jz4755_lcd_24bit_funcs[] = {
+0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 1, 1,
+1, 1, 0, 0,
+};
+
+static const struct group_desc jz4755_groups[] = {
+INGENIC_PIN_GROUP("uart0-data", jz4755_uart0_data, 0),
+INGENIC_PIN_GROUP("uart0-hwflow", jz4755_uart0_hwflow, 0),
+INGENIC_PIN_GROUP("uart1-data", jz4755_uart1_data, 0),
+INGENIC_PIN_GROUP("uart2-data", jz4755_uart2_data, 1),
+INGENIC_PIN_GROUP_FUNCS("mmc0-1bit", jz4755_mmc0_1bit,
+jz4755_mmc0_1bit_funcs),
+INGENIC_PIN_GROUP_FUNCS("mmc0-4bit", jz4755_mmc0_4bit,
+jz4755_mmc0_4bit_funcs),
+INGENIC_PIN_GROUP("mmc1-1bit", jz4755_mmc1_1bit, 1),
+INGENIC_PIN_GROUP("mmc1-4bit", jz4755_mmc1_4bit, 1),
+INGENIC_PIN_GROUP("i2c-data", jz4755_i2c, 0),
+INGENIC_PIN_GROUP("cim-data", jz4755_cim, 0),
+INGENIC_PIN_GROUP_FUNCS("lcd-24bit", jz4755_lcd_24bit,
+jz4755_lcd_24bit_funcs),


Coud you either split this into several groups (lcd-8bit, lcd-16bit, 
lcd-18bit, lcd-24bit, lcd-special, lcd-generic) like it is done for 
the JZ4725B? Same for the other SoCs.




Sure, and do we need to change the JZ4740 (and the previous JZ4750) 
to the lcd-special + lcd-generic model? It looks more reasonable than 
the original lcd-tft and makes the style more uniform.


Yes, please change it for the JZ4750 too.

For the JZ4740, in theory it is too late - these are ABI and we 
shouldn't change them.


With that said - the only board that has a JZ4740 and is still 
supported (although untested, so it's not even sure it still boots) is 
the Ben Nanonote, which only uses the "lcd-8bit" group. So it's 
probably fine.


Cheers,
-Paul


Alternatively just remove the "lcd" function for now.


+{ "lcd-no-pins", },


And remove this.

Cheers,
-Paul


+INGENIC_PIN_GROUP("nand-cs1", jz4755_nand_cs1, 0),
+INGENIC_PIN_GROUP("nand-cs2", jz4755_nand_cs2, 0),
+INGENIC_PIN_GROUP("nand-cs3", jz4755_nand_cs3, 0),
+INGENIC_PIN_GROUP("nand-cs4", jz4755_nand_cs4, 0),
+INGENIC_PIN_GROUP("nand-fre-fwe", jz4755_nand_f

[PATCH v4 3/3] drm/ingenic: Register devm action to cleanup encoders

2021-03-27 Thread Paul Cercueil
Since the encoders have been devm-allocated, they will be freed way
before drm_mode_config_cleanup() is called. To avoid use-after-free
conditions, we then must ensure that drm_encoder_cleanup() is called
before the encoders are freed.

v2: Use the new __drmm_simple_encoder_alloc() function

v3: Use the new drmm_plain_simple_encoder_alloc() macro

v4: Use drmm_plain_encoder_alloc() macro

Fixes: c369cb27c267 ("drm/ingenic: Support multiple panels/bridges")
Cc:  # 5.8+
Signed-off-by: Paul Cercueil 
Reviewed-by: Laurent Pinchart 
---
 drivers/gpu/drm/ingenic/ingenic-drm-drv.c | 17 +++--
 1 file changed, 7 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c 
b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c
index d60e1eefc9d1..29742ec5ab95 100644
--- a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c
+++ b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c
@@ -24,6 +24,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -37,7 +38,6 @@
 #include 
 #include 
 #include 
-#include 
 #include 
 
 struct ingenic_dma_hwdesc {
@@ -1024,20 +1024,17 @@ static int ingenic_drm_bind(struct device *dev, bool 
has_components)
bridge = devm_drm_panel_bridge_add_typed(dev, panel,
 
DRM_MODE_CONNECTOR_DPI);
 
-   encoder = devm_kzalloc(dev, sizeof(*encoder), GFP_KERNEL);
-   if (!encoder)
-   return -ENOMEM;
+   encoder = drmm_plain_encoder_alloc(drm, NULL, 
DRM_MODE_ENCODER_DPI, NULL);
+   if (IS_ERR(encoder)) {
+   ret = PTR_ERR(encoder);
+   dev_err(dev, "Failed to init encoder: %d\n", ret);
+   return ret;
+   }
 
encoder->possible_crtcs = 1;
 
drm_encoder_helper_add(encoder, 
_drm_encoder_helper_funcs);
 
-   ret = drm_simple_encoder_init(drm, encoder, 
DRM_MODE_ENCODER_DPI);
-   if (ret) {
-   dev_err(dev, "Failed to init encoder: %d\n", ret);
-   return ret;
-   }
-
ret = drm_bridge_attach(encoder, bridge, NULL, 0);
if (ret) {
dev_err(dev, "Unable to attach bridge\n");
-- 
2.30.2



[PATCH v4 1/3] drm: bridge/panel: Cleanup connector on bridge detach

2021-03-27 Thread Paul Cercueil
If we don't call drm_connector_cleanup() manually in
panel_bridge_detach(), the connector will be cleaned up with the other
DRM objects in the call to drm_mode_config_cleanup(). However, since our
drm_connector is devm-allocated, by the time drm_mode_config_cleanup()
will be called, our connector will be long gone. Therefore, the
connector must be cleaned up when the bridge is detached to avoid
use-after-free conditions.

v2: Cleanup connector only if it was created

v3: Add FIXME

v4: (Use connector->dev) directly in if() block

Fixes: 13dfc0540a57 ("drm/bridge: Refactor out the panel wrapper from the 
lvds-encoder bridge.")
Cc:  # 4.12+
Cc: Andrzej Hajda 
Cc: Neil Armstrong 
Cc: Laurent Pinchart 
Cc: Jonas Karlman 
Cc: Jernej Skrabec 
Signed-off-by: Paul Cercueil 
Reviewed-by: Laurent Pinchart 
---
 drivers/gpu/drm/bridge/panel.c | 12 
 1 file changed, 12 insertions(+)

diff --git a/drivers/gpu/drm/bridge/panel.c b/drivers/gpu/drm/bridge/panel.c
index 0ddc37551194..c916f4b8907e 100644
--- a/drivers/gpu/drm/bridge/panel.c
+++ b/drivers/gpu/drm/bridge/panel.c
@@ -87,6 +87,18 @@ static int panel_bridge_attach(struct drm_bridge *bridge,
 
 static void panel_bridge_detach(struct drm_bridge *bridge)
 {
+   struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge);
+   struct drm_connector *connector = _bridge->connector;
+
+   /*
+* Cleanup the connector if we know it was initialized.
+*
+* FIXME: This wouldn't be needed if the panel_bridge structure was
+* allocated with drmm_kzalloc(). This might be tricky since the
+* drm_device pointer can only be retrieved when the bridge is attached.
+*/
+   if (connector->dev)
+   drm_connector_cleanup(connector);
 }
 
 static void panel_bridge_pre_enable(struct drm_bridge *bridge)
-- 
2.30.2



[PATCH v4 0/3] Fixes to bridge/panel and ingenic-drm

2021-03-27 Thread Paul Cercueil
Hi,

This is the V4 of my patchset that attempts to fix use-after-free errors
in bridge/panel.c and in the ingenic-drm driver.

Changes from v3:
- [1/3]: the code now checks (connector->dev) instead of
  (!!panel_bridge->connector.dev)
- [2/3]: the macro is now called drmm_plain_encoder_alloc(), and moved
  to . It also takes funcs/name parameters to be more
  similar to drmm_encoder_alloc(), although these parameters can very
  well be NULL.
- [3/3] uses the new macro.

V3 had a 4th patch, which was already applied as it received a
reviewed-by tag and could be applied independently.

Cheers,
-Paul

Paul Cercueil (3):
  drm: bridge/panel: Cleanup connector on bridge detach
  drm/encoder: Add macro drmm_plain_encoder_alloc()
  drm/ingenic: Register devm action to cleanup encoders

 drivers/gpu/drm/bridge/panel.c| 12 
 drivers/gpu/drm/ingenic/ingenic-drm-drv.c | 17 +++--
 include/drm/drm_encoder.h | 18 ++
 3 files changed, 37 insertions(+), 10 deletions(-)

-- 
2.30.2



[PATCH v4 2/3] drm/encoder: Add macro drmm_plain_encoder_alloc()

2021-03-27 Thread Paul Cercueil
This performs the same operation as drmm_encoder_alloc(), but
only allocates and returns a struct drm_encoder instance.

v4: Rename macro drmm_plain_encoder_alloc() and move to
. Since it's not "simple" anymore it
will now take funcs/name arguments as well.

Signed-off-by: Paul Cercueil 
---
 include/drm/drm_encoder.h | 18 ++
 1 file changed, 18 insertions(+)

diff --git a/include/drm/drm_encoder.h b/include/drm/drm_encoder.h
index 5bf78b5bcb2b..6e91a0280f31 100644
--- a/include/drm/drm_encoder.h
+++ b/include/drm/drm_encoder.h
@@ -224,6 +224,24 @@ void *__drmm_encoder_alloc(struct drm_device *dev,
  offsetof(type, member), funcs, \
  encoder_type, name, ##__VA_ARGS__))
 
+/**
+ * drmm_plain_encoder_alloc - Allocate and initialize an encoder
+ * @dev: drm device
+ * @funcs: callbacks for this encoder (optional)
+ * @encoder_type: user visible type of the encoder
+ * @name: printf style format string for the encoder name, or NULL for default 
name
+ *
+ * This is a simplified version of drmm_encoder_alloc(), which only allocates
+ * and returns a struct drm_encoder instance, with no subclassing.
+ *
+ * Returns:
+ * Pointer to the new drm_encoder struct, or ERR_PTR on failure.
+ */
+#define drmm_plain_encoder_alloc(dev, funcs, encoder_type, name, ...) \
+   ((struct drm_encoder *) \
+__drmm_encoder_alloc(dev, sizeof(struct drm_encoder), \
+ 0, funcs, encoder_type, name, ##__VA_ARGS__))
+
 /**
  * drm_encoder_index - find the index of a registered encoder
  * @encoder: encoder to find index for
-- 
2.30.2



Re: [PATCH] drm: DON'T require each CRTC to have a unique primary plane

2021-03-27 Thread Paul Cercueil
It has two mutually exclusive background planes (same Z level) + one 
overlay plane.


-Paul


Le sam. 27 mars 2021 à 11:24, Simon Ser  a écrit 
:
On Saturday, March 27th, 2021 at 12:22 PM, Paul Cercueil 
 wrote:



 The ingenic-drm driver has two mutually exclusive primary planes
 already; so the fact that a CRTC must have one and only one primary
 plane is an invalid assumption.


Why does this driver expose two primary planes, if it only has a 
single

CRTC?





[PATCH] drm: DON'T require each CRTC to have a unique primary plane

2021-03-27 Thread Paul Cercueil
The ingenic-drm driver has two mutually exclusive primary planes
already; so the fact that a CRTC must have one and only one primary
plane is an invalid assumption.

Fixes: 96962e3de725 ("drm: require each CRTC to have a unique primary plane")
Cc:  # 5.11
Signed-off-by: Paul Cercueil 
---
 drivers/gpu/drm/drm_mode_config.c | 11 ---
 1 file changed, 11 deletions(-)

diff --git a/drivers/gpu/drm/drm_mode_config.c 
b/drivers/gpu/drm/drm_mode_config.c
index 37b4b9f0e468..d86621c41047 100644
--- a/drivers/gpu/drm/drm_mode_config.c
+++ b/drivers/gpu/drm/drm_mode_config.c
@@ -626,9 +626,7 @@ void drm_mode_config_validate(struct drm_device *dev)
 {
struct drm_encoder *encoder;
struct drm_crtc *crtc;
-   struct drm_plane *plane;
u32 primary_with_crtc = 0, cursor_with_crtc = 0;
-   unsigned int num_primary = 0;
 
if (!drm_core_check_feature(dev, DRIVER_MODESET))
return;
@@ -676,13 +674,4 @@ void drm_mode_config_validate(struct drm_device *dev)
cursor_with_crtc |= drm_plane_mask(crtc->cursor);
}
}
-
-   drm_for_each_plane(plane, dev) {
-   if (plane->type == DRM_PLANE_TYPE_PRIMARY)
-   num_primary++;
-   }
-
-   WARN(num_primary != dev->mode_config.num_crtc,
-"Must have as many primary planes as there are CRTCs, but have %u 
primary planes and %u CRTCs",
-num_primary, dev->mode_config.num_crtc);
 }
-- 
2.30.2



Re: [PATCH v3 0/4] Fixes to bridge/panel and ingenic-drm

2021-03-23 Thread Paul Cercueil




Le mer. 24 févr. 2021 à 13:44, Paul Cercueil  a 
écrit :

Hi,

Some feedback for patches 1-3? Laurent?


1-month anniversary ping :)

Cheers,
-Paul


Cheers,
-Paul


Le dim. 24 janv. 2021 à 8:55, Paul Cercueil  a 
écrit :

Hi,

Here are three independent fixes. The first one addresses a
use-after-free in bridge/panel.c; the second one addresses a
use-after-free in the ingenic-drm driver; finally, the third one 
makes

the ingenic-drm driver work again on older Ingenic SoCs.

Changes from v2:
- patch [1/4] added a FIXME.
- patch [2/4] is new. It introduces a 
drmm_plain_simple_encoder_alloc()

  macro that will be used in patch [3/4].
- patch [3/4] uses the macro introduced in patch [2/4].
- patch [4/4] is unmodified.

Note to linux-stable guys: patch [v2 2/3] will only apply on the 
current
drm-misc-next branch, to fix it for v5.11 and older kernels, use the 
V1

of that patch.

Cheers,
-Paul

Paul Cercueil (4):
  drm: bridge/panel: Cleanup connector on bridge detach
  drm/simple_kms_helper: Add macro drmm_plain_simple_encoder_alloc()
  drm/ingenic: Register devm action to cleanup encoders
  drm/ingenic: Fix non-OSD mode

 drivers/gpu/drm/bridge/panel.c| 12 +++
 drivers/gpu/drm/ingenic/ingenic-drm-drv.c | 26 
+++

 include/drm/drm_simple_kms_helper.h   | 17 +++
 3 files changed, 42 insertions(+), 13 deletions(-)

--
2.29.2








Re: [PATCH 6/6] clk: ingenic: Add support for the JZ4760

2021-03-23 Thread Paul Cercueil

Hi Zhou,

Le mar. 23 mars 2021 à 23:41, Zhou Yanjie  
a écrit :

Hi Paul,

On 2021/3/23 上午1:40, Paul Cercueil wrote:

Hi Zhou,

Le mer. 17 mars 2021 à 20:41, Zhou Yanjie 
 a écrit :

Hi Paul,

On 2021/3/7 下午10:17, Paul Cercueil wrote:
Add the CGU code and the compatible string to the TCU driver to 
support

the JZ4760 SoC.

Signed-off-by: Paul Cercueil 
---
  drivers/clk/ingenic/Kconfig|  10 +
  drivers/clk/ingenic/Makefile   |   1 +
  drivers/clk/ingenic/jz4760-cgu.c   | 433 
+

  drivers/clk/ingenic/tcu.c  |   2 +
  include/dt-bindings/clock/jz4760-cgu.h |  54 +++
  5 files changed, 500 insertions(+)
  create mode 100644 drivers/clk/ingenic/jz4760-cgu.c
  create mode 100644 include/dt-bindings/clock/jz4760-cgu.h

diff --git a/drivers/clk/ingenic/Kconfig 
b/drivers/clk/ingenic/Kconfig

index 580b0cf69ed5..898f1bc478c9 100644
--- a/drivers/clk/ingenic/Kconfig
+++ b/drivers/clk/ingenic/Kconfig
@@ -25,6 +25,16 @@ config INGENIC_CGU_JZ4725B
  If building for a JZ4725B SoC, you want to say Y here.
  +config INGENIC_CGU_JZ4760
+bool "Ingenic JZ4760 CGU driver"
+default MACH_JZ4760
+select INGENIC_CGU_COMMON
+help
+  Support the clocks provided by the CGU hardware on Ingenic 
JZ4760

+  and compatible SoCs.
+
+  If building for a JZ4760 SoC, you want to say Y here.
+
  config INGENIC_CGU_JZ4770
  bool "Ingenic JZ4770 CGU driver"
  default MACH_JZ4770
diff --git a/drivers/clk/ingenic/Makefile 
b/drivers/clk/ingenic/Makefile

index aaa4bffe03c6..9edfaf4610b9 100644
--- a/drivers/clk/ingenic/Makefile
+++ b/drivers/clk/ingenic/Makefile
@@ -2,6 +2,7 @@
  obj-$(CONFIG_INGENIC_CGU_COMMON)+= cgu.o pm.o
  obj-$(CONFIG_INGENIC_CGU_JZ4740)+= jz4740-cgu.o
  obj-$(CONFIG_INGENIC_CGU_JZ4725B)+= jz4725b-cgu.o
+obj-$(CONFIG_INGENIC_CGU_JZ4760)+= jz4760-cgu.o
  obj-$(CONFIG_INGENIC_CGU_JZ4770)+= jz4770-cgu.o
  obj-$(CONFIG_INGENIC_CGU_JZ4780)+= jz4780-cgu.o
  obj-$(CONFIG_INGENIC_CGU_X1000)+= x1000-cgu.o
diff --git a/drivers/clk/ingenic/jz4760-cgu.c 
b/drivers/clk/ingenic/jz4760-cgu.c

new file mode 100644
index ..a45327cba7d1
--- /dev/null
+++ b/drivers/clk/ingenic/jz4760-cgu.c
@@ -0,0 +1,433 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * JZ4760 SoC CGU driver
+ * Copyright 2018, Paul Cercueil 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+#include 
+
+#include "cgu.h"
+#include "pm.h"
+
+#define MHZ (1000 * 1000)
+
+/*
+ * CPM registers offset address definition
+ */
+#define CGU_REG_CPCCR0x00
+#define CGU_REG_LCR0x04
+#define CGU_REG_CPPCR00x10
+#define CGU_REG_CLKGR00x20
+#define CGU_REG_OPCR0x24
+#define CGU_REG_CLKGR10x28
+#define CGU_REG_CPPCR10x30
+#define CGU_REG_USBPCR0x3c
+#define CGU_REG_USBCDR0x50
+#define CGU_REG_I2SCDR0x60
+#define CGU_REG_LPCDR0x64
+#define CGU_REG_MSCCDR0x68
+#define CGU_REG_UHCCDR0x6c
+#define CGU_REG_SSICDR0x74
+#define CGU_REG_CIMCDR0x7c
+#define CGU_REG_GPSCDR0x80
+#define CGU_REG_PCMCDR0x84
+#define CGU_REG_GPUCDR0x88
+
+static const s8 pll_od_encoding[8] = {
+0x0, 0x1, -1, 0x2, -1, -1, -1, 0x3,
+};
+
+static const u8 jz4760_cgu_cpccr_div_table[] = {
+1, 2, 3, 4, 6, 8,
+};
+
+static const u8 jz4760_cgu_pll_half_div_table[] = {
+2, 1,
+};
+
+static void
+jz4760_cgu_calc_m_n_od(const struct ingenic_cgu_pll_info 
*pll_info,

+   unsigned long rate, unsigned long parent_rate,
+   unsigned int *pm, unsigned int *pn, unsigned int 
*pod)

+{
+unsigned int m, n, od;
+
+/* The output of the PLL must be between 500 and 1500 MHz. */
+rate = clamp_val(rate, 500ul * MHZ, 1500ul * MHZ);
+
+/* The frequency after the N divider must be between 1 and 50 
MHz. */

+n = parent_rate / (1 * MHZ);
+
+/* The N divider must be >= 2. */
+n = clamp_val(n, 2, 1 << pll_info->n_bits);
+
+for (;;) {
+od = 0;
+
+do {
+m = (rate / MHZ) * ++od * n / (parent_rate / MHZ);



Please correct me if I am wrong, according to the PM, when the 
register value of OD is 0, 1, 2, 3, the value corresponding 
participating PL frequency calculation is 1, 2, 4, 8. Therefore, 
change


m = (rate / MHZ) * ++od * n / (parent_rate / MHZ); to m = (rate / 
MHZ) * (2 ^ od++) * n / (parent_rate / MHZ); seems to be more 
appropriate, it can avoid 3, 5, 6, and 7 that should not exist.




I found a mistake. My brain must have been broken at that time. The 2 
^ od here I intended to express the meaning of od power of 2, but it 
should be written as 1 << od, otherwise it becomes a XOR operation.


Yes, don't worry - I understood it as (1 << od).

I'll send a v2 soon.

Cheers,
-Paul


You are totally correct. I will send a revised version.

Thanks

[PATCH] drm/ingenic: Fix pixclock rate for 24-bit serial panels

2021-03-23 Thread Paul Cercueil
When using a 24-bit panel on a 8-bit serial bus, the pixel clock
requested by the panel has to be multiplied by 3, since the subpixels
are shifted sequentially.

The code (in ingenic_drm_encoder_atomic_check) already computed
crtc_state->adjusted_mode->crtc_clock accordingly, but clk_set_rate()
used crtc_state->adjusted_mode->clock instead.

Fixes: 28ab7d35b6e0 ("drm/ingenic: Properly compute timings when using a 
3x8-bit panel")
Cc: sta...@vger.kernel.org # v5.10
Signed-off-by: Paul Cercueil 
---
 drivers/gpu/drm/ingenic/ingenic-drm-drv.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c 
b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c
index d60e1eefc9d1..cba68bf52ec5 100644
--- a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c
+++ b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c
@@ -342,7 +342,7 @@ static void ingenic_drm_crtc_atomic_flush(struct drm_crtc 
*crtc,
if (priv->update_clk_rate) {
mutex_lock(>clk_mutex);
clk_set_rate(priv->pix_clk,
-crtc_state->adjusted_mode.clock * 1000);
+crtc_state->adjusted_mode.crtc_clock * 1000);
priv->update_clk_rate = false;
mutex_unlock(>clk_mutex);
}
-- 
2.30.2



Re: [PATCH v3 10/10] pinctrl: Ingenic: Add pinctrl driver for X2000.

2021-03-22 Thread Paul Cercueil




Le mer. 17 mars 2021 à 17:58, 周琰杰 (Zhou Yanjie) 
 a écrit :

Add support for probing the pinctrl-ingenic driver on the
X2000 SoC from Ingenic.

Signed-off-by: 周琰杰 (Zhou Yanjie) 
---

Notes:
v3:
New patch.

 drivers/pinctrl/pinctrl-ingenic.c | 502 
+-

 1 file changed, 493 insertions(+), 9 deletions(-)

diff --git a/drivers/pinctrl/pinctrl-ingenic.c 
b/drivers/pinctrl/pinctrl-ingenic.c

index eb4912d..538d1b5 100644
--- a/drivers/pinctrl/pinctrl-ingenic.c
+++ b/drivers/pinctrl/pinctrl-ingenic.c
@@ -57,6 +57,10 @@
 #define X1830_GPIO_PEL 0x110
 #define X1830_GPIO_PEH 0x120

+#define X2000_GPIO_EDG 0x70
+#define X2000_GPIO_PEPU0x80
+#define X2000_GPIO_PEPD0x90
+
 #define REG_SET(x) ((x) + 0x4)
 #define REG_CLEAR(x)   ((x) + 0x8)

@@ -94,6 +98,7 @@ enum jz_version {
ID_X1000,
ID_X1500,
ID_X1830,
+   ID_X2000,
 };

 struct ingenic_chip_info {
@@ -2273,6 +2278,439 @@ static const struct ingenic_chip_info 
x1830_chip_info = {

.pull_downs = x1830_pull_downs,
 };

+static const u32 x2000_pull_ups[5] = {
+   0x0003, 0x, 0x1ff0, 0xc7fe3f3f, 0x8fff003f,
+};
+
+static const u32 x2000_pull_downs[5] = {
+   0x0003, 0x, 0x1ff0, 0x, 0x8fff003f,
+};
+
+static int x2000_uart0_data_pins[] = { 0x77, 0x78, };
+static int x2000_uart0_hwflow_pins[] = { 0x79, 0x7a, };
+static int x2000_uart1_data_pins[] = { 0x57, 0x58, };
+static int x2000_uart1_hwflow_pins[] = { 0x55, 0x56, };
+static int x2000_uart2_data_pins[] = { 0x7e, 0x7f, };
+static int x2000_uart3_data_c_pins[] = { 0x59, 0x5a, };
+static int x2000_uart3_data_d_pins[] = { 0x62, 0x63, };
+static int x2000_uart3_hwflow_c_pins[] = { 0x5b, 0x5c, };
+static int x2000_uart3_hwflow_d_pins[] = { 0x60, 0x61, };
+static int x2000_uart4_data_a_pins[] = { 0x02, 0x03, };
+static int x2000_uart4_data_c_pins[] = { 0x4b, 0x4c, };
+static int x2000_uart4_hwflow_a_pins[] = { 0x00, 0x01, };
+static int x2000_uart4_hwflow_c_pins[] = { 0x49, 0x4a, };
+static int x2000_uart5_data_a_pins[] = { 0x04, 0x05, };
+static int x2000_uart5_data_c_pins[] = { 0x45, 0x46, };
+static int x2000_uart6_data_a_pins[] = { 0x06, 0x07, };
+static int x2000_uart6_data_c_pins[] = { 0x47, 0x48, };
+static int x2000_uart7_data_a_pins[] = { 0x08, 0x09, };
+static int x2000_uart7_data_c_pins[] = { 0x41, 0x42, };
+static int x2000_uart8_data_pins[] = { 0x3c, 0x3d, };
+static int x2000_uart9_data_pins[] = { 0x3e, 0x3f, };
+static int x2000_sfc0_d_pins[] = { 0x73, 0x74, 0x75, 0x76, 0x71, 
0x72, };
+static int x2000_sfc0_e_pins[] = { 0x92, 0x93, 0x94, 0x95, 0x90, 
0x91, };

+static int x2000_sfc1_pins[] = { 0x77, 0x78, 0x79, 0x7a, };
+static int x2000_ssi0_dt_b_pins[] = { 0x3e, };
+static int x2000_ssi0_dt_d_pins[] = { 0x69, };
+static int x2000_ssi0_dr_b_pins[] = { 0x3d, };
+static int x2000_ssi0_dr_d_pins[] = { 0x6a, };
+static int x2000_ssi0_clk_b_pins[] = { 0x3f, };
+static int x2000_ssi0_clk_d_pins[] = { 0x68, };
+static int x2000_ssi0_ce0_b_pins[] = { 0x3c, };
+static int x2000_ssi0_ce0_d_pins[] = { 0x6d, };
+static int x2000_ssi1_dt_c_pins[] = { 0x4b, };
+static int x2000_ssi1_dt_d_pins[] = { 0x72, };
+static int x2000_ssi1_dt_e_pins[] = { 0x91, };
+static int x2000_ssi1_dr_c_pins[] = { 0x4a, };
+static int x2000_ssi1_dr_d_pins[] = { 0x73, };
+static int x2000_ssi1_dr_e_pins[] = { 0x92, };
+static int x2000_ssi1_clk_c_pins[] = { 0x4c, };
+static int x2000_ssi1_clk_d_pins[] = { 0x71, };
+static int x2000_ssi1_clk_e_pins[] = { 0x90, };
+static int x2000_ssi1_ce0_c_pins[] = { 0x49, };
+static int x2000_ssi1_ce0_d_pins[] = { 0x76, };
+static int x2000_ssi1_ce0_e_pins[] = { 0x95, };
+static int x2000_mmc0_1bit_pins[] = { 0x71, 0x72, 0x73, };
+static int x2000_mmc0_4bit_pins[] = { 0x74, 0x75, 0x75, };
+static int x2000_mmc0_8bit_pins[] = { 0x77, 0x78, 0x79, 0x7a, };
+static int x2000_mmc1_1bit_pins[] = { 0x68, 0x69, 0x6a, };
+static int x2000_mmc1_4bit_pins[] = { 0x6b, 0x6c, 0x6d, };
+static int x2000_mmc2_1bit_pins[] = { 0x80, 0x81, 0x82, };
+static int x2000_mmc2_4bit_pins[] = { 0x83, 0x84, 0x85, };
+static int x2000_emc_8bit_data_pins[] = {
+   0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+};
+static int x2000_emc_16bit_data_pins[] = {
+   0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+};
+static int x2000_emc_addr_pins[] = {
+   0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+   0x28, 0x29, 0x2a, 0x2b, 0x2c,
+};
+static int x2000_emc_rd_we_pins[] = { 0x2d, 0x2e, };
+static int x2000_emc_wait_pins[] = { 0x2f, };
+static int x2000_emc_cs1_pins[] = { 0x57, };
+static int x2000_emc_cs2_pins[] = { 0x58, };
+static int x2000_i2c0_pins[] = { 0x4e, 0x4d, };
+static int x2000_i2c1_c_pins[] = { 0x58, 0x57, };
+static int x2000_i2c1_d_pins[] = { 0x6c, 0x6b, };
+static int 

Re: [PATCH v3 09/10] pinctrl: Ingenic: Add pinctrl driver for JZ4775.

2021-03-22 Thread Paul Cercueil




Le mer. 17 mars 2021 à 17:58, 周琰杰 (Zhou Yanjie) 
 a écrit :

Add support for probing the pinctrl-ingenic driver on the
JZ4775 SoC from Ingenic.

Signed-off-by: 周琰杰 (Zhou Yanjie) 
---

Notes:
v3:
New patch.

 drivers/pinctrl/pinctrl-ingenic.c | 259 
++

 1 file changed, 259 insertions(+)

diff --git a/drivers/pinctrl/pinctrl-ingenic.c 
b/drivers/pinctrl/pinctrl-ingenic.c

index d8b37fa..eb4912d 100644
--- a/drivers/pinctrl/pinctrl-ingenic.c
+++ b/drivers/pinctrl/pinctrl-ingenic.c
@@ -89,6 +89,7 @@ enum jz_version {
ID_JZ4755,
ID_JZ4760,
ID_JZ4770,
+   ID_JZ4775,
ID_JZ4780,
ID_X1000,
ID_X1500,
@@ -1237,6 +1238,259 @@ static const struct ingenic_chip_info 
jz4770_chip_info = {

.pull_downs = jz4770_pull_downs,
 };

+static const u32 jz4775_pull_ups[7] = {
+	0x28ff00ff, 0xf030f3fc, 0x0fff, 0xfffe4000, 0xf0fc, 
0xf00f, 0xf3c0,

+};
+
+static const u32 jz4775_pull_downs[7] = {
+	0x, 0x00030c03, 0x, 0x8000, 0x0403, 
0x0ff0, 0x00030c00,

+};
+
+static int jz4775_uart0_data_pins[] = { 0xa0, 0xa3, };
+static int jz4775_uart0_hwflow_pins[] = { 0xa1, 0xa2, };
+static int jz4775_uart1_data_pins[] = { 0x7a, 0x7c, };
+static int jz4775_uart1_hwflow_pins[] = { 0x7b, 0x7d, };
+static int jz4775_uart2_data_c_pins[] = { 0x54, 0x4a, };
+static int jz4775_uart2_data_f_pins[] = { 0xa5, 0xa4, };
+static int jz4775_uart3_data_pins[] = { 0x1e, 0x1f, };
+static int jz4775_ssi_dt_a_pins[] = { 0x13, };
+static int jz4775_ssi_dt_d_pins[] = { 0x75, };
+static int jz4775_ssi_dr_a_pins[] = { 0x14, };
+static int jz4775_ssi_dr_d_pins[] = { 0x74, };
+static int jz4775_ssi_clk_a_pins[] = { 0x12, };
+static int jz4775_ssi_clk_d_pins[] = { 0x78, };
+static int jz4775_ssi_gpc_pins[] = { 0x76, };
+static int jz4775_ssi_ce0_a_pins[] = { 0x17, };
+static int jz4775_ssi_ce0_d_pins[] = { 0x79, };
+static int jz4775_ssi_ce1_pins[] = { 0x77, };
+static int jz4775_mmc0_1bit_a_pins[] = { 0x12, 0x13, 0x14, };
+static int jz4775_mmc0_4bit_a_pins[] = { 0x15, 0x16, 0x17, };
+static int jz4775_mmc0_8bit_a_pins[] = { 0x04, 0x05, 0x06, 0x07, };
+static int jz4775_mmc0_1bit_e_pins[] = { 0x9c, 0x9d, 0x94, };
+static int jz4775_mmc0_4bit_e_pins[] = { 0x95, 0x96, 0x97, };
+static int jz4775_mmc1_1bit_d_pins[] = { 0x78, 0x79, 0x74, };
+static int jz4775_mmc1_4bit_d_pins[] = { 0x75, 0x76, 0x77, };
+static int jz4775_mmc1_1bit_e_pins[] = { 0x9c, 0x9d, 0x94, };
+static int jz4775_mmc1_4bit_e_pins[] = { 0x95, 0x96, 0x97, };
+static int jz4775_mmc2_1bit_b_pins[] = { 0x3c, 0x3d, 0x34, };
+static int jz4775_mmc2_4bit_b_pins[] = { 0x35, 0x3e, 0x3f, };
+static int jz4775_mmc2_1bit_e_pins[] = { 0x9c, 0x9d, 0x94, };
+static int jz4775_mmc2_4bit_e_pins[] = { 0x95, 0x96, 0x97, };
+static int jz4775_nemc_8bit_data_pins[] = {
+   0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+};
+static int jz4775_nemc_16bit_data_pins[] = {
+   0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1,
+};
+static int jz4775_nemc_cle_ale_pins[] = { 0x20, 0x21, };
+static int jz4775_nemc_addr_pins[] = { 0x22, 0x23, 0x24, 0x25, };
+static int jz4775_nemc_rd_we_pins[] = { 0x10, 0x11, };
+static int jz4775_nemc_frd_fwe_pins[] = { 0x12, 0x13, };
+static int jz4775_nemc_wait_pins[] = { 0x1b, };
+static int jz4775_nemc_cs1_pins[] = { 0x15, };
+static int jz4775_nemc_cs2_pins[] = { 0x16, };
+static int jz4775_nemc_cs3_pins[] = { 0x17, };
+static int jz4775_i2c0_pins[] = { 0x7e, 0x7f, };
+static int jz4775_i2c1_pins[] = { 0x9e, 0x9f, };
+static int jz4775_i2c2_pins[] = { 0x80, 0x83, };
+static int jz4775_i2s_data_tx_pins[] = { 0xa3, };
+static int jz4775_i2s_data_rx_pins[] = { 0xa2, };
+static int jz4775_i2s_clk_txrx_pins[] = { 0xa0, 0xa1, };
+static int jz4775_i2s_sysclk_pins[] = { 0x83, };
+static int jz4775_cim_pins[] = {
+   0x26, 0x27, 0x28, 0x29,
+   0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31,
+};
+static int jz4775_lcd_24bit_pins[] = {
+   0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+   0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+   0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+   0x58, 0x59, 0x5a, 0x5b,
+};
+static int jz4775_pwm_pwm0_pins[] = { 0x80, };
+static int jz4775_pwm_pwm1_pins[] = { 0x81, };
+static int jz4775_pwm_pwm2_pins[] = { 0x82, };
+static int jz4775_pwm_pwm3_pins[] = { 0x83, };
+static int jz4775_mac_rmii_pins[] = {
+   0xa9, 0xab, 0xaa, 0xac, 0xa5, 0xa4, 0xad, 0xae, 0xa6, 0xa8,
+};
+static int jz4775_mac_mii_pins[] = {
+   0x7b, 0x7a, 0x7d, 0x7c, 0xa7, 0x24, 0xaf,
+};
+static int jz4775_mac_rgmii_pins[] = {
+   0xa9, 0x7b, 0x7a, 0xab, 0xaa, 0xac, 0x7d, 0x7c, 0xa5, 0xa4,
+   0xad, 0xae, 0xa7, 0xa6,
+};
+static int jz4775_mac_gmii_pins[] = {
+   0x31, 0x30, 0x2f, 0x2e, 0x2d, 0x2c, 0x2b, 0x2a,
+   0xa8, 0x28, 0x24, 0xaf,
+};
+static int jz4775_otg_pins[] = { 0x8a, };
+
+static u8 jz4775_uart3_data_funcs[] = { 0, 1, };
+static u8 jz4775_mac_mii_funcs[] = { 1, 1, 1, 1, 

Re: [PATCH v3 08/10] pinctrl: Ingenic: Add pinctrl driver for JZ4755.

2021-03-22 Thread Paul Cercueil




Le mer. 17 mars 2021 à 17:58, 周琰杰 (Zhou Yanjie) 
 a écrit :

Add support for probing the pinctrl-ingenic driver on the
JZ4755 SoC from Ingenic.

Signed-off-by: 周琰杰 (Zhou Yanjie) 
---

Notes:
v3:
New patch.

 drivers/pinctrl/pinctrl-ingenic.c | 132 
++

 1 file changed, 132 insertions(+)

diff --git a/drivers/pinctrl/pinctrl-ingenic.c 
b/drivers/pinctrl/pinctrl-ingenic.c

index d98767b..d8b37fa 100644
--- a/drivers/pinctrl/pinctrl-ingenic.c
+++ b/drivers/pinctrl/pinctrl-ingenic.c
@@ -86,6 +86,7 @@ enum jz_version {
ID_JZ4740,
ID_JZ4725B,
ID_JZ4750,
+   ID_JZ4755,
ID_JZ4760,
ID_JZ4770,
ID_JZ4780,
@@ -557,6 +558,131 @@ static const struct ingenic_chip_info 
jz4750_chip_info = {

.pull_downs = jz4750_pull_downs,
 };

+static const u32 jz4755_pull_ups[6] = {
+	0x, 0x, 0x0fff, 0x, 0x33dc3fff, 
0xfc00,

+};
+
+static const u32 jz4755_pull_downs[6] = {
+	0x, 0x, 0x, 0x, 0x, 
0x,

+};
+
+static int jz4755_uart0_data_pins[] = { 0x7c, 0x7d, };
+static int jz4755_uart0_hwflow_pins[] = { 0x7e, 0x7f, };
+static int jz4755_uart1_data_pins[] = { 0x97, 0x99, };
+static int jz4755_uart2_data_pins[] = { 0x9f, };
+static int jz4755_mmc0_1bit_pins[] = { 0x2f, 0x50, 0x5c, };
+static int jz4755_mmc0_4bit_pins[] = { 0x5d, 0x5b, 0x51, };
+static int jz4755_mmc1_1bit_pins[] = { 0x3a, 0x3d, 0x3c, };
+static int jz4755_mmc1_4bit_pins[] = { 0x3b, 0x3e, 0x3f, };
+static int jz4755_i2c_pins[] = { 0x8c, 0x8d, };
+static int jz4755_cim_pins[] = {
+   0x89, 0x8b, 0x8a, 0x88,
+   0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+};
+static int jz4755_lcd_24bit_pins[] = {
+   0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+   0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+   0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
+   0x78, 0x79, 0x7a, 0x7b,
+};
+static int jz4755_nand_cs1_pins[] = { 0x55, };
+static int jz4755_nand_cs2_pins[] = { 0x56, };
+static int jz4755_nand_cs3_pins[] = { 0x57, };
+static int jz4755_nand_cs4_pins[] = { 0x58, };
+static int jz4755_nand_fre_fwe_pins[] = { 0x5c, 0x5d, };
+static int jz4755_pwm_pwm0_pins[] = { 0x94, };
+static int jz4755_pwm_pwm1_pins[] = { 0xab, };
+static int jz4755_pwm_pwm2_pins[] = { 0x96, };
+static int jz4755_pwm_pwm3_pins[] = { 0x97, };
+static int jz4755_pwm_pwm4_pins[] = { 0x98, };
+static int jz4755_pwm_pwm5_pins[] = { 0x99, };
+
+static u8 jz4755_mmc0_1bit_funcs[] = { 2, 2, 1, };
+static u8 jz4755_mmc0_4bit_funcs[] = { 1, 0, 1, };
+static u8 jz4755_lcd_24bit_funcs[] = {
+   0, 0, 0, 0, 0, 0, 0, 0,
+   0, 0, 0, 0, 0, 0, 0, 0,
+   0, 0, 0, 0, 0, 0, 1, 1,
+   1, 1, 0, 0,
+};
+
+static const struct group_desc jz4755_groups[] = {
+   INGENIC_PIN_GROUP("uart0-data", jz4755_uart0_data, 0),
+   INGENIC_PIN_GROUP("uart0-hwflow", jz4755_uart0_hwflow, 0),
+   INGENIC_PIN_GROUP("uart1-data", jz4755_uart1_data, 0),
+   INGENIC_PIN_GROUP("uart2-data", jz4755_uart2_data, 1),
+   INGENIC_PIN_GROUP_FUNCS("mmc0-1bit", jz4755_mmc0_1bit,
+   jz4755_mmc0_1bit_funcs),
+   INGENIC_PIN_GROUP_FUNCS("mmc0-4bit", jz4755_mmc0_4bit,
+   jz4755_mmc0_4bit_funcs),
+   INGENIC_PIN_GROUP("mmc1-1bit", jz4755_mmc1_1bit, 1),
+   INGENIC_PIN_GROUP("mmc1-4bit", jz4755_mmc1_4bit, 1),
+   INGENIC_PIN_GROUP("i2c-data", jz4755_i2c, 0),
+   INGENIC_PIN_GROUP("cim-data", jz4755_cim, 0),
+   INGENIC_PIN_GROUP_FUNCS("lcd-24bit", jz4755_lcd_24bit,
+   jz4755_lcd_24bit_funcs),


Coud you either split this into several groups (lcd-8bit, lcd-16bit, 
lcd-18bit, lcd-24bit, lcd-special, lcd-generic) like it is done for the 
JZ4725B? Same for the other SoCs.


Alternatively just remove the "lcd" function for now.


+   { "lcd-no-pins", },


And remove this.

Cheers,
-Paul


+   INGENIC_PIN_GROUP("nand-cs1", jz4755_nand_cs1, 0),
+   INGENIC_PIN_GROUP("nand-cs2", jz4755_nand_cs2, 0),
+   INGENIC_PIN_GROUP("nand-cs3", jz4755_nand_cs3, 0),
+   INGENIC_PIN_GROUP("nand-cs4", jz4755_nand_cs4, 0),
+   INGENIC_PIN_GROUP("nand-fre-fwe", jz4755_nand_fre_fwe, 0),
+   INGENIC_PIN_GROUP("pwm0", jz4755_pwm_pwm0, 0),
+   INGENIC_PIN_GROUP("pwm1", jz4755_pwm_pwm1, 1),
+   INGENIC_PIN_GROUP("pwm2", jz4755_pwm_pwm2, 0),
+   INGENIC_PIN_GROUP("pwm3", jz4755_pwm_pwm3, 0),
+   INGENIC_PIN_GROUP("pwm4", jz4755_pwm_pwm4, 0),
+   INGENIC_PIN_GROUP("pwm5", jz4755_pwm_pwm5, 0),
+};
+
+static const char *jz4755_uart0_groups[] = { "uart0-data", 
"uart0-hwflow", };

+static const char *jz4755_uart1_groups[] = { "uart1-data", };
+static const char *jz4755_uart2_groups[] = { "uart2-data", };
+static const char *jz4755_mmc0_groups[] = { "mmc0-1bit", 
"mmc0-4bit", };
+static const char *jz4755_mmc1_groups[] = { "mmc0-1bit", 
"mmc0-4bit", };

+static const char 

Re: [PATCH v3 07/10] pinctrl: Ingenic: Add pinctrl driver for JZ4750.

2021-03-22 Thread Paul Cercueil




Le mer. 17 mars 2021 à 17:58, 周琰杰 (Zhou Yanjie) 
 a écrit :

Add support for probing the pinctrl-ingenic driver on the
JZ4750 SoC from Ingenic.

Signed-off-by: 周琰杰 (Zhou Yanjie) 
---

Notes:
v3:
New patch.

 drivers/pinctrl/pinctrl-ingenic.c | 137 
++

 1 file changed, 137 insertions(+)

diff --git a/drivers/pinctrl/pinctrl-ingenic.c 
b/drivers/pinctrl/pinctrl-ingenic.c

index 25458d6..d98767b 100644
--- a/drivers/pinctrl/pinctrl-ingenic.c
+++ b/drivers/pinctrl/pinctrl-ingenic.c
@@ -85,6 +85,7 @@ enum jz_version {
ID_JZ4730,
ID_JZ4740,
ID_JZ4725B,
+   ID_JZ4750,
ID_JZ4760,
ID_JZ4770,
ID_JZ4780,
@@ -424,6 +425,138 @@ static const struct ingenic_chip_info 
jz4725b_chip_info = {

.pull_downs = jz4740_pull_downs,
 };

+static const u32 jz4750_pull_ups[6] = {
+	0x, 0x, 0x3fff, 0x7fff, 0x1fff3fff, 
0x00ff,

+};
+
+static const u32 jz4750_pull_downs[6] = {
+	0x, 0x, 0x, 0x, 0x, 
0x,

+};
+
+static int jz4750_uart0_data_pins[] = { 0xa4, 0xa5, };
+static int jz4750_uart0_hwflow_pins[] = { 0xa6, 0xa7, };
+static int jz4750_uart1_data_pins[] = { 0x90, 0x91, };
+static int jz4750_uart1_hwflow_pins[] = { 0x92, 0x93, };
+static int jz4750_uart2_data_pins[] = { 0x9b, 0x9a, };
+static int jz4750_uart3_data_pins[] = { 0xb0, 0xb1, };
+static int jz4750_uart3_hwflow_pins[] = { 0xb2, 0xb3, };
+static int jz4750_mmc0_1bit_pins[] = { 0xa8, 0xa9, 0xa0, };
+static int jz4750_mmc0_4bit_pins[] = { 0xa1, 0xa2, 0xa3, };
+static int jz4750_mmc0_8bit_pins[] = { 0xa4, 0xa5, 0xa6, 0xa7, };
+static int jz4750_mmc1_1bit_pins[] = { 0xae, 0xaf, 0xaa, };
+static int jz4750_mmc1_4bit_pins[] = { 0xab, 0xac, 0xad, };
+static int jz4750_i2c_pins[] = { 0x8c, 0x8d, };
+static int jz4750_cim_pins[] = {
+   0x89, 0x8b, 0x8a, 0x88,
+   0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+};
+static int jz4750_lcd_8bit_pins[] = {
+   0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x72, 0x73, 0x74,
+};
+static int jz4750_lcd_16bit_pins[] = {
+   0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x75,
+};
+static int jz4750_lcd_18bit_pins[] = { 0x70, 0x71, };
+static int jz4750_lcd_18bit_tft_pins[] = { 0x78, 0x79, 0x76, 0x77, };
+static int jz4750_nand_cs1_pins[] = { 0x55, };
+static int jz4750_nand_cs2_pins[] = { 0x56, };
+static int jz4750_nand_cs3_pins[] = { 0x57, };
+static int jz4750_nand_cs4_pins[] = { 0x58, };
+static int jz4750_nand_fre_fwe_pins[] = { 0x5c, 0x5d, };
+static int jz4750_pwm_pwm0_pins[] = { 0x94, };
+static int jz4750_pwm_pwm1_pins[] = { 0x95, };
+static int jz4750_pwm_pwm2_pins[] = { 0x96, };
+static int jz4750_pwm_pwm3_pins[] = { 0x97, };
+static int jz4750_pwm_pwm4_pins[] = { 0x98, };
+static int jz4750_pwm_pwm5_pins[] = { 0x99, };
+
+static const struct group_desc jz4750_groups[] = {
+   INGENIC_PIN_GROUP("uart0-data", jz4750_uart0_data, 1),
+   INGENIC_PIN_GROUP("uart0-hwflow", jz4750_uart0_hwflow, 1),
+   INGENIC_PIN_GROUP("uart1-data", jz4750_uart1_data, 0),
+   INGENIC_PIN_GROUP("uart1-hwflow", jz4750_uart1_hwflow, 0),
+   INGENIC_PIN_GROUP("uart2-data", jz4750_uart2_data, 1),
+   INGENIC_PIN_GROUP("uart3-data", jz4750_uart3_data, 0),
+   INGENIC_PIN_GROUP("uart3-hwflow", jz4750_uart3_hwflow, 0),
+   INGENIC_PIN_GROUP("mmc0-1bit", jz4750_mmc0_1bit, 0),
+   INGENIC_PIN_GROUP("mmc0-4bit", jz4750_mmc0_4bit, 0),
+   INGENIC_PIN_GROUP("mmc0-8bit", jz4750_mmc0_8bit, 0),
+   INGENIC_PIN_GROUP("mmc1-1bit", jz4750_mmc1_1bit, 0),
+   INGENIC_PIN_GROUP("mmc1-4bit", jz4750_mmc1_4bit, 0),
+   INGENIC_PIN_GROUP("i2c-data", jz4750_i2c, 0),
+   INGENIC_PIN_GROUP("cim-data", jz4750_cim, 0),
+   INGENIC_PIN_GROUP("lcd-8bit", jz4750_lcd_8bit, 0),
+   INGENIC_PIN_GROUP("lcd-16bit", jz4750_lcd_16bit, 0),
+   INGENIC_PIN_GROUP("lcd-18bit", jz4750_lcd_18bit, 0),
+   INGENIC_PIN_GROUP("lcd-18bit-tft", jz4750_lcd_18bit_tft, 0),
+   { "lcd-no-pins", },


Please drop "lcd-no-pins" from your patches, it is pointless.

Cheers,
-Paul


+   INGENIC_PIN_GROUP("nand-cs1", jz4750_nand_cs1, 0),
+   INGENIC_PIN_GROUP("nand-cs2", jz4750_nand_cs2, 0),
+   INGENIC_PIN_GROUP("nand-cs3", jz4750_nand_cs3, 0),
+   INGENIC_PIN_GROUP("nand-cs4", jz4750_nand_cs4, 0),
+   INGENIC_PIN_GROUP("nand-fre-fwe", jz4750_nand_fre_fwe, 0),
+   INGENIC_PIN_GROUP("pwm0", jz4750_pwm_pwm0, 0),
+   INGENIC_PIN_GROUP("pwm1", jz4750_pwm_pwm1, 0),
+   INGENIC_PIN_GROUP("pwm2", jz4750_pwm_pwm2, 0),
+   INGENIC_PIN_GROUP("pwm3", jz4750_pwm_pwm3, 0),
+   INGENIC_PIN_GROUP("pwm4", jz4750_pwm_pwm4, 0),
+   INGENIC_PIN_GROUP("pwm5", jz4750_pwm_pwm5, 0),
+};
+
+static const char *jz4750_uart0_groups[] = { "uart0-data", 
"uart0-hwflow", };
+static const char *jz4750_uart1_groups[] = { "uart1-data", 
"uart1-hwflow", };

+static const char *jz4750_uart2_groups[] = { "uart2-data", };

Re: [PATCH v3 06/10] pinctrl: Ingenic: Add pinctrl driver for JZ4730.

2021-03-22 Thread Paul Cercueil




Le mer. 17 mars 2021 à 17:58, 周琰杰 (Zhou Yanjie) 
 a écrit :

Add support for probing the pinctrl-ingenic driver on the
JZ4730 SoC from Ingenic.

This driver is derived from Paul Boddie. It is worth to
noting that the JZ4730 SoC is special in having two control
registers (upper/lower), so add code to handle the JZ4730
specific register offsets and some register pairs which have
2 bits for each GPIO pin.

Tested-by: H. Nikolaus Schaller   # on Letux400
Co-developed-by: Paul Boddie 
Signed-off-by: Paul Boddie 
Signed-off-by: H. Nikolaus Schaller 
Signed-off-by: 周琰杰 (Zhou Yanjie) 
---

Notes:
v3:
New patch.

 drivers/pinctrl/pinctrl-ingenic.c | 222 
+++---

 1 file changed, 206 insertions(+), 16 deletions(-)

diff --git a/drivers/pinctrl/pinctrl-ingenic.c 
b/drivers/pinctrl/pinctrl-ingenic.c

index b8165f5..25458d6 100644
--- a/drivers/pinctrl/pinctrl-ingenic.c
+++ b/drivers/pinctrl/pinctrl-ingenic.c
@@ -3,8 +3,8 @@
  * Ingenic SoCs pinctrl driver
  *
  * Copyright (c) 2017 Paul Cercueil 
- * Copyright (c) 2019 周琰杰 (Zhou Yanjie) 


  * Copyright (c) 2017, 2019 Paul Boddie 
+ * Copyright (c) 2019, 2020 周琰杰 (Zhou Yanjie) 


  */

 #include 
@@ -29,6 +29,17 @@
 #define GPIO_PIN   0x00
 #define GPIO_MSK   0x20

+#define JZ4730_GPIO_DATA   0x00
+#define JZ4730_GPIO_GPDIR  0x04
+#define JZ4730_GPIO_GPPUR  0x0c
+#define JZ4730_GPIO_GPALR  0x10
+#define JZ4730_GPIO_GPAUR  0x14
+#define JZ4730_GPIO_GPIDLR 0x18
+#define JZ4730_GPIO_GPIDUR 0x1c
+#define JZ4730_GPIO_GPIER  0x20
+#define JZ4730_GPIO_GPIMR  0x24
+#define JZ4730_GPIO_GPFR   0x28
+
 #define JZ4740_GPIO_DATA   0x10
 #define JZ4740_GPIO_PULL_DIS   0x30
 #define JZ4740_GPIO_FUNC   0x40
@@ -57,6 +68,7 @@
 #define GPIO_PULL_DOWN 2

 #define PINS_PER_GPIO_CHIP 32
+#define JZ4730_PINS_PER_PAIRED_REG 16

 #define INGENIC_PIN_GROUP_FUNCS(name, id, funcs)   \
{   \
@@ -70,6 +82,7 @@
INGENIC_PIN_GROUP_FUNCS(name, id, (void *)(func))

 enum jz_version {
+   ID_JZ4730,
ID_JZ4740,
ID_JZ4725B,
ID_JZ4760,
@@ -110,6 +123,96 @@ struct ingenic_gpio_chip {
unsigned int irq, reg_base;
 };

+static const u32 jz4730_pull_ups[4] = {
+   0x3fa3320f, 0xf200, 0x, 0x,
+};
+
+static const u32 jz4730_pull_downs[4] = {
+   0x0df0, 0x0dff, 0x, 0x,
+};
+
+static int jz4730_mmc_1bit_pins[] = { 0x27, 0x26, 0x22, };
+static int jz4730_mmc_4bit_pins[] = { 0x23, 0x24, 0x25, };
+static int jz4730_uart0_data_pins[] = { 0x7e, 0x7f, };
+static int jz4730_uart1_data_pins[] = { 0x18, 0x19, };
+static int jz4730_uart2_data_pins[] = { 0x6f, 0x7d, };
+static int jz4730_uart3_data_pins[] = { 0x10, 0x15, };
+static int jz4730_uart3_hwflow_pins[] = { 0x11, 0x17, };
+static int jz4730_lcd_8bit_pins[] = {
+   0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x3a, 0x39, 0x38,
+};
+static int jz4730_lcd_16bit_pins[] = {
+   0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x3b,
+};
+static int jz4730_lcd_16bit_tft_pins[] = { 0x3e, 0x3f, 0x3d, 0x3c, };
+static int jz4730_nand_cs1_pins[] = { 0x53, };
+static int jz4730_nand_cs2_pins[] = { 0x54, };
+static int jz4730_nand_cs3_pins[] = { 0x55, };
+static int jz4730_nand_cs4_pins[] = { 0x56, };
+static int jz4730_nand_cs5_pins[] = { 0x57, };
+static int jz4730_pwm_pwm0_pins[] = { 0x5e, };
+static int jz4730_pwm_pwm1_pins[] = { 0x5f, };
+
+static u8 jz4730_lcd_8bit_funcs[] = { 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 
2, };

+
+static const struct group_desc jz4730_groups[] = {
+   INGENIC_PIN_GROUP("mmc-1bit", jz4730_mmc_1bit, 1),
+   INGENIC_PIN_GROUP("mmc-4bit", jz4730_mmc_4bit, 1),
+   INGENIC_PIN_GROUP("uart0-data", jz4730_uart0_data, 1),
+   INGENIC_PIN_GROUP("uart1-data", jz4730_uart1_data, 1),
+   INGENIC_PIN_GROUP("uart2-data", jz4730_uart2_data, 1),
+   INGENIC_PIN_GROUP("uart3-data", jz4730_uart3_data, 1),
+   INGENIC_PIN_GROUP("uart3-hwflow", jz4730_uart3_hwflow, 1),
+	INGENIC_PIN_GROUP_FUNCS("lcd-8bit", jz4730_lcd_8bit, 
jz4730_lcd_8bit_funcs),

+   INGENIC_PIN_GROUP("lcd-16bit", jz4730_lcd_16bit, 1),
+   INGENIC_PIN_GROUP("lcd-16bit-tft", jz4730_lcd_16bit_tft, 1),
+   INGENIC_PIN_GROUP("nand-cs1", jz4730_nand_cs1, 1),
+   INGENIC_PIN_GROUP("nand-cs2", jz4730_nand_cs2, 1),
+   INGENIC_PIN_GROUP("nand-cs3", jz4730_nand_cs3, 1),
+   INGENIC_PIN_GROUP("nand-cs4", jz4730_nand_cs4, 1),
+   INGENIC_PIN_GROUP(

Re: [PATCH v3 05/10] dt-bindings: pinctrl: Add bindings for new Ingenic SoCs.

2021-03-22 Thread Paul Cercueil




Le mer. 17 mars 2021 à 17:57, 周琰杰 (Zhou Yanjie) 
 a écrit :

Add the pinctrl bindings for the JZ4730 SoC, the JZ4750 SoC,
the JZ4755 SoC, the JZ4775 SoC and the X2000 SoC from Ingenic.

Signed-off-by: 周琰杰 (Zhou Yanjie) 
---

Notes:
v2:
New patch.

v2->v3:
No change.

 .../bindings/pinctrl/ingenic,pinctrl.yaml  | 23 
++

 1 file changed, 19 insertions(+), 4 deletions(-)

diff --git 
a/Documentation/devicetree/bindings/pinctrl/ingenic,pinctrl.yaml 
b/Documentation/devicetree/bindings/pinctrl/ingenic,pinctrl.yaml

index 44c04d1..60604fc 100644
--- a/Documentation/devicetree/bindings/pinctrl/ingenic,pinctrl.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/ingenic,pinctrl.yaml
@@ -17,10 +17,12 @@ description: >
   naming scheme "PxN" where x is a character identifying the GPIO 
port with
   which the pin is associated and N is an integer from 0 to 31 
identifying the
   pin within that GPIO port. For example PA0 is the first pin in 
GPIO port A,
-  and PB31 is the last pin in GPIO port B. The JZ4740, the X1000 and 
the X1830
-  contains 4 GPIO ports, PA to PD, for a total of 128 pins. The 
JZ4760, the
-  JZ4770 and the JZ4780 contains 6 GPIO ports, PA to PF, for a total 
of 192

-  pins.
+  and PB31 is the last pin in GPIO port B. The JZ4730, the JZ4740, 
the X1000
+  and the X1830 contains 4 GPIO ports, PA to PD, for a total of 128 
pins. The
+  X2000 contains 5 GPIO ports, PA to PE, for a total of 160 pins. 
The JZ4750,
+  the JZ4755 the JZ4760, the JZ4770 and the JZ4780 contains 6 GPIO 
ports, PA
+  to PF, for a total of 192 pins. The JZ4775 contains 7 GPIO ports, 
PA to PG,

+  for a total of 224 pins.


While we're at it, the JZ4725B has also 4 GPIO ports.



 maintainers:
   - Paul Cercueil 
@@ -32,20 +34,28 @@ properties:
   compatible:
 oneOf:
   - enum:
+  - ingenic,jz4730-pinctrl
   - ingenic,jz4740-pinctrl
   - ingenic,jz4725b-pinctrl
+  - ingenic,jz4750-pinctrl
+  - ingenic,jz4755-pinctrl
   - ingenic,jz4760-pinctrl
   - ingenic,jz4770-pinctrl
+  - ingenic,jz4775-pinctrl
   - ingenic,jz4780-pinctrl
   - ingenic,x1000-pinctrl
   - ingenic,x1500-pinctrl
   - ingenic,x1830-pinctrl
+  - ingenic,x2000-pinctrl
   - items:
   - const: ingenic,jz4760b-pinctrl
   - const: ingenic,jz4760-pinctrl
   - items:
   - const: ingenic,x1000e-pinctrl
   - const: ingenic,x1000-pinctrl
+  - items:
+  - const: ingenic,x2000e-pinctrl
+  - const: ingenic,x2000-pinctrl

   reg:
 maxItems: 1
@@ -62,14 +72,19 @@ patternProperties:
 properties:
   compatible:
 enum:
+  - ingenic,jz4730-gpio
   - ingenic,jz4740-gpio
   - ingenic,jz4725b-gpio
+  - ingenic,jz4750-gpio
+  - ingenic,jz4755-gpio
   - ingenic,jz4760-gpio
   - ingenic,jz4770-gpio
+  - ingenic,jz4775-gpio
   - ingenic,jz4780-gpio
   - ingenic,x1000-gpio
   - ingenic,x1500-gpio
   - ingenic,x1830-gpio
+  - ingenic,x2000-gpio

   reg:
 items:
--
2.7.4






Re: [PATCH v3 02/10] pinctrl: Ingenic: Add support for read the pin configuration of X1830.

2021-03-22 Thread Paul Cercueil




Le mer. 17 mars 2021 à 17:57, 周琰杰 (Zhou Yanjie) 
 a écrit :

Add X1830 support in "ingenic_pinconf_get()", so that it can read the
configuration of X1830 SoC correctly.

Fixes: d7da2a1e4e08 ("pinctrl: Ingenic: Add pinctrl driver for 
X1830.")


Signed-off-by: 周琰杰 (Zhou Yanjie) 
---

Notes:
v2:
New patch.

v2->v3:
1.Add fixes tag.
2.Adjust the code, simplify the ingenic_pinconf_get() function.

 drivers/pinctrl/pinctrl-ingenic.c | 38 
++

 1 file changed, 30 insertions(+), 8 deletions(-)

diff --git a/drivers/pinctrl/pinctrl-ingenic.c 
b/drivers/pinctrl/pinctrl-ingenic.c

index 05dfa0a..1d43b98 100644
--- a/drivers/pinctrl/pinctrl-ingenic.c
+++ b/drivers/pinctrl/pinctrl-ingenic.c
@@ -2109,26 +2109,48 @@ static int ingenic_pinconf_get(struct 
pinctrl_dev *pctldev,

enum pin_config_param param = pinconf_to_config_param(*config);
unsigned int idx = pin % PINS_PER_GPIO_CHIP;
unsigned int offt = pin / PINS_PER_GPIO_CHIP;
-   bool pull;
+   unsigned int bias;
+   bool pull, pullup, pulldown;

-   if (jzpc->info->version >= ID_JZ4770)
-   pull = !ingenic_get_pin_config(jzpc, pin, JZ4770_GPIO_PEN);
-   else
-   pull = !ingenic_get_pin_config(jzpc, pin, JZ4740_GPIO_PULL_DIS);
+   if (jzpc->info->version >= ID_X1830) {
+   unsigned int half = PINS_PER_GPIO_CHIP / 2;
+   unsigned int idxh = pin % half * 2;


I had to look up operator precedence in C, '*' and '%' have the same 
priority so this reads left-to-right.


I'd suggest adding parentheses around the '%' to make it more obvious.

With that:

Reviewed-by: Paul Cercueil 

Cheers,
-Paul


+
+   if (idx < half)
+   regmap_read(jzpc->map, offt * jzpc->info->reg_offset +
+   X1830_GPIO_PEL, );
+   else
+   regmap_read(jzpc->map, offt * jzpc->info->reg_offset +
+   X1830_GPIO_PEH, );
+
+   bias = (bias >> idxh) & (GPIO_PULL_UP | GPIO_PULL_DOWN);
+
+		pullup = (bias == GPIO_PULL_UP) && (jzpc->info->pull_ups[offt] & 
BIT(idx));
+		pulldown = (bias == GPIO_PULL_DOWN) && 
(jzpc->info->pull_downs[offt] & BIT(idx));

+
+   } else {
+   if (jzpc->info->version >= ID_JZ4770)
+   pull = !ingenic_get_pin_config(jzpc, pin, 
JZ4770_GPIO_PEN);
+   else
+   pull = !ingenic_get_pin_config(jzpc, pin, 
JZ4740_GPIO_PULL_DIS);
+
+   pullup = pull && (jzpc->info->pull_ups[offt] & BIT(idx));
+   pulldown = pull && (jzpc->info->pull_downs[offt] & BIT(idx));
+   }

switch (param) {
case PIN_CONFIG_BIAS_DISABLE:
-   if (pull)
+   if (pullup || pulldown)
return -EINVAL;
break;

case PIN_CONFIG_BIAS_PULL_UP:
-   if (!pull || !(jzpc->info->pull_ups[offt] & BIT(idx)))
+   if (!pullup)
return -EINVAL;
break;

case PIN_CONFIG_BIAS_PULL_DOWN:
-   if (!pull || !(jzpc->info->pull_downs[offt] & BIT(idx)))
+   if (!pulldown)
return -EINVAL;
break;

--
2.7.4






Re: [PATCH v3 01/10] pinctrl: Ingenic: Add missing pins to the JZ4770 MAC MII group.

2021-03-22 Thread Paul Cercueil

Hi Zhou,


Le mer. 17 mars 2021 à 17:57, 周琰杰 (Zhou Yanjie) 
 a écrit :

The MII group of JZ4770's MAC should have 7 pins, add missing
pins to the MII group.

Fixes: 5de1a73e78ed ("Pinctrl: Ingenic: Add missing parts for JZ4770 
and JZ4780.")


This fixes a commit that was introduced in an older kernel (than the 
one in -rc phase). Therefore you need to Cc linux-stable. Like this:


Cc:  # v5.0


Signed-off-by: 周琰杰 (Zhou Yanjie) 


With that said:

Reviewed-by: Paul Cercueil 

Cheers,
-Paul


---

Notes:
v2:
New patch.

v2->v3:
Add fixes tag.

 drivers/pinctrl/pinctrl-ingenic.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/pinctrl/pinctrl-ingenic.c 
b/drivers/pinctrl/pinctrl-ingenic.c

index f274612..05dfa0a 100644
--- a/drivers/pinctrl/pinctrl-ingenic.c
+++ b/drivers/pinctrl/pinctrl-ingenic.c
@@ -667,7 +667,9 @@ static int jz4770_pwm_pwm7_pins[] = { 0x6b, };
 static int jz4770_mac_rmii_pins[] = {
0xa9, 0xab, 0xaa, 0xac, 0xa5, 0xa4, 0xad, 0xae, 0xa6, 0xa8,
 };
-static int jz4770_mac_mii_pins[] = { 0xa7, 0xaf, };
+static int jz4770_mac_mii_pins[] = {
+   0x7b, 0x7a, 0x7d, 0x7c, 0xa7, 0x24, 0xaf,
+};

 static const struct group_desc jz4770_groups[] = {
INGENIC_PIN_GROUP("uart0-data", jz4770_uart0_data, 0),
--
2.7.4






Re: [PATCH 6/6] clk: ingenic: Add support for the JZ4760

2021-03-22 Thread Paul Cercueil

Hi Zhou,

Le mer. 17 mars 2021 à 20:41, Zhou Yanjie  
a écrit :

Hi Paul,

On 2021/3/7 下午10:17, Paul Cercueil wrote:
Add the CGU code and the compatible string to the TCU driver to 
support

the JZ4760 SoC.

Signed-off-by: Paul Cercueil 
---
  drivers/clk/ingenic/Kconfig|  10 +
  drivers/clk/ingenic/Makefile   |   1 +
  drivers/clk/ingenic/jz4760-cgu.c   | 433 
+

  drivers/clk/ingenic/tcu.c  |   2 +
  include/dt-bindings/clock/jz4760-cgu.h |  54 +++
  5 files changed, 500 insertions(+)
  create mode 100644 drivers/clk/ingenic/jz4760-cgu.c
  create mode 100644 include/dt-bindings/clock/jz4760-cgu.h

diff --git a/drivers/clk/ingenic/Kconfig 
b/drivers/clk/ingenic/Kconfig

index 580b0cf69ed5..898f1bc478c9 100644
--- a/drivers/clk/ingenic/Kconfig
+++ b/drivers/clk/ingenic/Kconfig
@@ -25,6 +25,16 @@ config INGENIC_CGU_JZ4725B
     If building for a JZ4725B SoC, you want to say Y here.
  +config INGENIC_CGU_JZ4760
+   bool "Ingenic JZ4760 CGU driver"
+   default MACH_JZ4760
+   select INGENIC_CGU_COMMON
+   help
+ Support the clocks provided by the CGU hardware on Ingenic JZ4760
+ and compatible SoCs.
+
+ If building for a JZ4760 SoC, you want to say Y here.
+
  config INGENIC_CGU_JZ4770
bool "Ingenic JZ4770 CGU driver"
default MACH_JZ4770
diff --git a/drivers/clk/ingenic/Makefile 
b/drivers/clk/ingenic/Makefile

index aaa4bffe03c6..9edfaf4610b9 100644
--- a/drivers/clk/ingenic/Makefile
+++ b/drivers/clk/ingenic/Makefile
@@ -2,6 +2,7 @@
  obj-$(CONFIG_INGENIC_CGU_COMMON)  += cgu.o pm.o
  obj-$(CONFIG_INGENIC_CGU_JZ4740)  += jz4740-cgu.o
  obj-$(CONFIG_INGENIC_CGU_JZ4725B) += jz4725b-cgu.o
+obj-$(CONFIG_INGENIC_CGU_JZ4760)   += jz4760-cgu.o
  obj-$(CONFIG_INGENIC_CGU_JZ4770)  += jz4770-cgu.o
  obj-$(CONFIG_INGENIC_CGU_JZ4780)  += jz4780-cgu.o
  obj-$(CONFIG_INGENIC_CGU_X1000)   += x1000-cgu.o
diff --git a/drivers/clk/ingenic/jz4760-cgu.c 
b/drivers/clk/ingenic/jz4760-cgu.c

new file mode 100644
index ..a45327cba7d1
--- /dev/null
+++ b/drivers/clk/ingenic/jz4760-cgu.c
@@ -0,0 +1,433 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * JZ4760 SoC CGU driver
+ * Copyright 2018, Paul Cercueil 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+#include 
+
+#include "cgu.h"
+#include "pm.h"
+
+#define MHZ (1000 * 1000)
+
+/*
+ * CPM registers offset address definition
+ */
+#define CGU_REG_CPCCR  0x00
+#define CGU_REG_LCR0x04
+#define CGU_REG_CPPCR0 0x10
+#define CGU_REG_CLKGR0 0x20
+#define CGU_REG_OPCR   0x24
+#define CGU_REG_CLKGR1 0x28
+#define CGU_REG_CPPCR1 0x30
+#define CGU_REG_USBPCR 0x3c
+#define CGU_REG_USBCDR 0x50
+#define CGU_REG_I2SCDR 0x60
+#define CGU_REG_LPCDR  0x64
+#define CGU_REG_MSCCDR 0x68
+#define CGU_REG_UHCCDR 0x6c
+#define CGU_REG_SSICDR 0x74
+#define CGU_REG_CIMCDR 0x7c
+#define CGU_REG_GPSCDR 0x80
+#define CGU_REG_PCMCDR 0x84
+#define CGU_REG_GPUCDR 0x88
+
+static const s8 pll_od_encoding[8] = {
+   0x0, 0x1, -1, 0x2, -1, -1, -1, 0x3,
+};
+
+static const u8 jz4760_cgu_cpccr_div_table[] = {
+   1, 2, 3, 4, 6, 8,
+};
+
+static const u8 jz4760_cgu_pll_half_div_table[] = {
+   2, 1,
+};
+
+static void
+jz4760_cgu_calc_m_n_od(const struct ingenic_cgu_pll_info *pll_info,
+  unsigned long rate, unsigned long parent_rate,
+  unsigned int *pm, unsigned int *pn, unsigned int *pod)
+{
+   unsigned int m, n, od;
+
+   /* The output of the PLL must be between 500 and 1500 MHz. */
+   rate = clamp_val(rate, 500ul * MHZ, 1500ul * MHZ);
+
+	/* The frequency after the N divider must be between 1 and 50 MHz. 
*/

+   n = parent_rate / (1 * MHZ);
+
+   /* The N divider must be >= 2. */
+   n = clamp_val(n, 2, 1 << pll_info->n_bits);
+
+   for (;;) {
+   od = 0;
+
+   do {
+   m = (rate / MHZ) * ++od * n / (parent_rate / MHZ);



Please correct me if I am wrong, according to the PM, when the 
register value of OD is 0, 1, 2, 3, the value corresponding 
participating PL frequency calculation is 1, 2, 4, 8. Therefore, 
change


m = (rate / MHZ) * ++od * n / (parent_rate / MHZ); to m = (rate / 
MHZ) * (2 ^ od++) * n / (parent_rate / MHZ); seems to be more 
appropriate, it can avoid 3, 5, 6, and 7 that should not exist.


You are totally correct. I will send a revised version.

Thanks!

Cheers,
-Paul


+   } while (m < pll_info->m_offset || m & 1);
+
+   if (m <= (1 << pll_info->m_bits) - 2)
+   break;
+
+   n >>= 1;
+   }
+
+   *pm = m;
+   *pn = n;
+   *pod = od;



If we change the above fo

[PATCH] MIPS: generic: Support linking with LLVM ld.lld

2021-03-21 Thread Paul Cercueil
LLVM's ld.lld chokes on the 64-bit sign-extended load addresses. Use
32-bit addresses if the linker is LLVM's ld.lld.

Signed-off-by: Paul Cercueil 
---
 arch/mips/generic/Platform | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/mips/generic/Platform b/arch/mips/generic/Platform
index b871af16b5b6..19b7d92a4ca7 100644
--- a/arch/mips/generic/Platform
+++ b/arch/mips/generic/Platform
@@ -12,8 +12,8 @@
 cflags-$(CONFIG_MACH_INGENIC_SOC)  += 
-I$(srctree)/arch/mips/include/asm/mach-ingenic
 cflags-$(CONFIG_MIPS_GENERIC)  += 
-I$(srctree)/arch/mips/include/asm/mach-generic
 
-load-$(CONFIG_MIPS_GENERIC)+= 0x8010
-zload-$(CONFIG_MIPS_GENERIC)   += 0x8100
+load-$(CONFIG_MIPS_GENERIC)+= $(if 
$(CONFIG_LD_IS_LLD),0x8010,0x8010)
+zload-$(CONFIG_MIPS_GENERIC)   += $(if 
$(CONFIG_LD_IS_LLD),0x8100,0x8100)
 all-$(CONFIG_MIPS_GENERIC) := vmlinux.gz.itb
 
 its-y  := vmlinux.its.S
-- 
2.30.2



[PATCH] MIPS: vmlinux.lds.S: Fix appended dtb not properly aligned

2021-03-16 Thread Paul Cercueil
Commit 6654111c893f ("MIPS: vmlinux.lds.S: align raw appended dtb to 8
bytes") changed the alignment from STRUCT_ALIGNMENT bytes to 8 bytes.

The commit's message makes it sound like it was actually done on
purpose, but this is not the case. The commit was written when raw
appended dtb were not aligned at all. The STRUCT_ALIGN() was added a few
days before, in commit 7a05293af39f ("MIPS: boot/compressed: Copy DTB to
aligned address"). The true purpose of the commit was not to align
specifically to 8 bytes, but to make sure that the generated vmlinux'
size was properly padded to the alignment required for DTBs.

While the switch to 8-byte alignment worked for vmlinux-appended dtb
blobs, it broke vmlinuz-appended dtb blobs, as the decompress routine
moves the blob to a STRUCT_ALIGNMENT aligned address.

Fix this by changing the raw appended dtb blob alignment from 8 bytes
back to STRUCT_ALIGNMENT bytes in vmlinux.lds.S.

Fixes: 6654111c893f ("MIPS: vmlinux.lds.S: align raw appended dtb to 8 bytes")
Cc: Bjørn Mork 
Signed-off-by: Paul Cercueil 
---
 arch/mips/kernel/vmlinux.lds.S | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S
index 1234834cc4c4..1f98947fe715 100644
--- a/arch/mips/kernel/vmlinux.lds.S
+++ b/arch/mips/kernel/vmlinux.lds.S
@@ -176,7 +176,7 @@ SECTIONS
.fill : {
FILL(0);
BYTE(0);
-   . = ALIGN(8);
+   STRUCT_ALIGN();
}
__appended_dtb = .;
/* leave space for appended DTB */
-- 
2.30.2



Re: [PATCH v2 4/5] drm: Add and export function drm_gem_cma_sync_data

2021-03-15 Thread Paul Cercueil

Hi Thomas,

Le lun. 15 mars 2021 à 8:43, Thomas Zimmermann  a 
écrit :

Hi

Am 11.03.21 um 13:33 schrieb Paul Cercueil:



Le jeu. 11 mars 2021 à 12:28, Christoph Hellwig  
a écrit :

On Sun, Mar 07, 2021 at 08:28:34PM +, Paul Cercueil wrote:

 +drm_atomic_for_each_plane_damage(, ) {
 +for (i = 0; i < finfo->num_planes; i++) {
 +daddr = drm_fb_cma_get_gem_addr(state->fb, state, i);
 +
 +/* Ignore x1/x2 values, invalidate complete lines */
 +offset = clip.y1 * state->fb->pitches[i];
 +
 +dma_sync_single_for_device(dev, daddr + offset,
 +   (clip.y2 - clip.y1) * 
state->fb->pitches[i],

 +   DMA_TO_DEVICE);


Are these helpers only ever used to transfer data to the device and
never from it?  If so please clearly document that.


Yes. In the DRM world, are there cases where we transfer data from 
the device? I assume these cases are handled by v4l2 instead.


Software rendering (i.e., anything wrt dumb buffers) likely reads 
back framebuffer content during blit operations. For devices where 
this is a slow operation (e.g., PCI read) we set struct 
drm_mode_config.prefer_shadow to hint renderers to use shadow 
buffering.


This has been brought up a few times already. I answered that in the 
cover letter. In my case, *writes* (e.g. dumb memcpy) are also slower 
with a write-combine buffer than with a non-coherent buffer + cache 
sync. So a shadow buffer does nothing for me.


Cheers,
-Paul




Re: [PATCH 1/2] clk: Add clk_get_first_to_set_rate

2021-03-13 Thread Paul Cercueil

Hi Stephen,


Le sam. 13 mars 2021 à 14:28, Stephen Boyd  a écrit 
:

Quoting Paul Cercueil (2021-03-07 09:07:41)

 The purpose of this function is to be used along with the notifier
 mechanism.

 When a parent clock can see its rate externally changed at any 
moment,
 and a driver needs a specific clock rate to function, it can 
register a
 notifier on the parent clock, and call clk_set_rate() on the base 
clock

 to adjust its frequency according to the new parent clock.


Can the driver use the rate locking mechanism to get a certain rate
instead of registering for notifiers and trying to react to changes?


You mean with clk_rate_exclusive_get()? That sounds like a good idea, 
but what would happen when a different driver calls the non-exclusive 
clk_set_rate() on this clock (or the parent), would it return -EBUSY, 
lock on a mutex? ...


Cheers,
-Paul





 This works fine, until the base clock has the CLK_SET_RATE_PARENT 
flag
 set. In that case, calling clk_set_rate() on the base clock will 
call

 clk_set_rate() on the parent clock, which will trigger the notifier
 again, and we're in a loop.

 For that reason, we need to register the notifier on the parent 
clock of
 the first ancestor of the base clock that will effectively modify 
its

 rate when clk_set_rate() is called, which we can now obtain with
 clk_get_first_to_set_rate().

 Signed-off-by: Paul Cercueil 





Re: [PATCH v2 6/6] pinctrl: Ingenic: Add support for new Ingenic SoCs.

2021-03-12 Thread Paul Cercueil

Hi Zhou,

Le jeu. 11 mars 2021 à 23:21, 周琰杰 (Zhou Yanjie) 
 a écrit :

Add support for probing the pinctrl-ingenic driver on the JZ4730 SoC,
the JZ4750 SoC, the JZ4755 SoC, the JZ4775 SoC and the X2000 SoC from
Ingenic.

The driver of JZ4730 is derived from Paul Boddie. It is worth noting
that the JZ4730 is special in having two control registers 
(upper/lower),

so add code to handle the jz4730 specific register offsets and some
register pairs have 2 bits for each GPIO pin.


Can you split this patch again, one commit per SoC?

Cheers,
-Paul

Tested-by: H. Nikolaus Schaller   # on 
Letux400/JZ4730

Signed-off-by: Paul Boddie   # for JZ4730
Signed-off-by: H. Nikolaus Schaller   # for JZ4730
Signed-off-by: 周琰杰 (Zhou Yanjie) 
---

Notes:
v1->v2:
Fix the uninitialized warning.
Reported-by: Dan Carpenter 

 drivers/pinctrl/pinctrl-ingenic.c | 1256 
-

 1 file changed, 1231 insertions(+), 25 deletions(-)

diff --git a/drivers/pinctrl/pinctrl-ingenic.c 
b/drivers/pinctrl/pinctrl-ingenic.c

index ac5ad8a..1628a1a 100644
--- a/drivers/pinctrl/pinctrl-ingenic.c
+++ b/drivers/pinctrl/pinctrl-ingenic.c
@@ -3,8 +3,8 @@
  * Ingenic SoCs pinctrl driver
  *
  * Copyright (c) 2017 Paul Cercueil 
- * Copyright (c) 2019 周琰杰 (Zhou Yanjie) 


  * Copyright (c) 2017, 2019 Paul Boddie 
+ * Copyright (c) 2019, 2020 周琰杰 (Zhou Yanjie) 


  */

 #include 
@@ -29,6 +29,17 @@
 #define GPIO_PIN   0x00
 #define GPIO_MSK   0x20

+#define JZ4730_GPIO_DATA   0x00
+#define JZ4730_GPIO_GPDIR  0x04
+#define JZ4730_GPIO_GPPUR  0x0c
+#define JZ4730_GPIO_GPALR  0x10
+#define JZ4730_GPIO_GPAUR  0x14
+#define JZ4730_GPIO_GPIDLR 0x18
+#define JZ4730_GPIO_GPIDUR 0x1c
+#define JZ4730_GPIO_GPIER  0x20
+#define JZ4730_GPIO_GPIMR  0x24
+#define JZ4730_GPIO_GPFR   0x28
+
 #define JZ4740_GPIO_DATA   0x10
 #define JZ4740_GPIO_PULL_DIS   0x30
 #define JZ4740_GPIO_FUNC   0x40
@@ -46,6 +57,10 @@
 #define X1830_GPIO_PEL 0x110
 #define X1830_GPIO_PEH 0x120

+#define X2000_GPIO_EDG 0x70
+#define X2000_GPIO_PEPU0x80
+#define X2000_GPIO_PEPD0x90
+
 #define REG_SET(x) ((x) + 0x4)
 #define REG_CLEAR(x)   ((x) + 0x8)

@@ -57,6 +72,7 @@
 #define GPIO_PULL_DOWN 2

 #define PINS_PER_GPIO_CHIP 32
+#define JZ4730_PINS_PER_PAIRED_REG 16

 #define INGENIC_PIN_GROUP_FUNCS(name, id, funcs)   \
{   \
@@ -70,14 +86,19 @@
INGENIC_PIN_GROUP_FUNCS(name, id, (void *)(func))

 enum jz_version {
+   ID_JZ4730,
ID_JZ4740,
ID_JZ4725B,
+   ID_JZ4750,
+   ID_JZ4755,
ID_JZ4760,
ID_JZ4770,
+   ID_JZ4775,
ID_JZ4780,
ID_X1000,
ID_X1500,
ID_X1830,
+   ID_X2000,
 };

 struct ingenic_chip_info {
@@ -110,6 +131,96 @@ struct ingenic_gpio_chip {
unsigned int irq, reg_base;
 };

+static const u32 jz4730_pull_ups[4] = {
+   0x3fa3320f, 0xf200, 0x, 0x,
+};
+
+static const u32 jz4730_pull_downs[4] = {
+   0x0df0, 0x0dff, 0x, 0x,
+};
+
+static int jz4730_mmc_1bit_pins[] = { 0x27, 0x26, 0x22, };
+static int jz4730_mmc_4bit_pins[] = { 0x23, 0x24, 0x25, };
+static int jz4730_uart0_data_pins[] = { 0x7e, 0x7f, };
+static int jz4730_uart1_data_pins[] = { 0x18, 0x19, };
+static int jz4730_uart2_data_pins[] = { 0x6f, 0x7d, };
+static int jz4730_uart3_data_pins[] = { 0x10, 0x15, };
+static int jz4730_uart3_hwflow_pins[] = { 0x11, 0x17, };
+static int jz4730_lcd_8bit_pins[] = {
+   0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x3a, 0x39, 0x38,
+};
+static int jz4730_lcd_16bit_pins[] = {
+   0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x3b,
+};
+static int jz4730_lcd_16bit_tft_pins[] = { 0x3e, 0x3f, 0x3d, 0x3c, };
+static int jz4730_nand_cs1_pins[] = { 0x53, };
+static int jz4730_nand_cs2_pins[] = { 0x54, };
+static int jz4730_nand_cs3_pins[] = { 0x55, };
+static int jz4730_nand_cs4_pins[] = { 0x56, };
+static int jz4730_nand_cs5_pins[] = { 0x57, };
+static int jz4730_pwm_pwm0_pins[] = { 0x5e, };
+static int jz4730_pwm_pwm1_pins[] = { 0x5f, };
+
+static u8 jz4730_lcd_8bit_funcs[] = { 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 
2, };

+
+static const struct group_desc jz4730_groups[] = {
+   INGENIC_PIN_GROUP("mmc-1bit", jz4730_mmc_1bit, 1),
+   INGENIC_PIN_GROUP("mmc-4bit", jz4730_mmc_4bit, 1),
+   INGENIC_PIN_GROUP("uart0-data", jz4730_uart0_data, 1),

Re: [PATCH v2 4/6] pinctrl: Ingenic: Reformat the code.

2021-03-12 Thread Paul Cercueil




Le jeu. 11 mars 2021 à 23:21, 周琰杰 (Zhou Yanjie) 
 a écrit :

1.Move the "INGENIC_PIN_GROUP_FUNCS" to the macro definition section.
2.Add tabs before values to align the code in the macro definition 
section.


Signed-off-by: 周琰杰 (Zhou Yanjie) 


Reviewed-by: Paul Cercueil 

Cheers,
-Paul


---

Notes:
v2:
New patch.

 drivers/pinctrl/pinctrl-ingenic.c | 71 
+++

 1 file changed, 35 insertions(+), 36 deletions(-)

diff --git a/drivers/pinctrl/pinctrl-ingenic.c 
b/drivers/pinctrl/pinctrl-ingenic.c

index 607ba0b..ac5ad8a 100644
--- a/drivers/pinctrl/pinctrl-ingenic.c
+++ b/drivers/pinctrl/pinctrl-ingenic.c
@@ -26,37 +26,48 @@
 #include "pinconf.h"
 #include "pinmux.h"

-#define GPIO_PIN   0x00
-#define GPIO_MSK   0x20
+#define GPIO_PIN   0x00
+#define GPIO_MSK   0x20

-#define JZ4740_GPIO_DATA   0x10
-#define JZ4740_GPIO_PULL_DIS   0x30
-#define JZ4740_GPIO_FUNC   0x40
-#define JZ4740_GPIO_SELECT 0x50
-#define JZ4740_GPIO_DIR0x60
-#define JZ4740_GPIO_TRIG   0x70
-#define JZ4740_GPIO_FLAG   0x80
+#define JZ4740_GPIO_DATA   0x10
+#define JZ4740_GPIO_PULL_DIS   0x30
+#define JZ4740_GPIO_FUNC   0x40
+#define JZ4740_GPIO_SELECT 0x50
+#define JZ4740_GPIO_DIR0x60
+#define JZ4740_GPIO_TRIG   0x70
+#define JZ4740_GPIO_FLAG   0x80

-#define JZ4770_GPIO_INT0x10
-#define JZ4770_GPIO_PAT1   0x30
-#define JZ4770_GPIO_PAT0   0x40
-#define JZ4770_GPIO_FLAG   0x50
-#define JZ4770_GPIO_PEN0x70
+#define JZ4770_GPIO_INT0x10
+#define JZ4770_GPIO_PAT1   0x30
+#define JZ4770_GPIO_PAT0   0x40
+#define JZ4770_GPIO_FLAG   0x50
+#define JZ4770_GPIO_PEN0x70

-#define X1830_GPIO_PEL 0x110
-#define X1830_GPIO_PEH 0x120
+#define X1830_GPIO_PEL 0x110
+#define X1830_GPIO_PEH 0x120

-#define REG_SET(x) ((x) + 0x4)
-#define REG_CLEAR(x) ((x) + 0x8)
+#define REG_SET(x) ((x) + 0x4)
+#define REG_CLEAR(x)   ((x) + 0x8)

-#define REG_PZ_BASE(x) ((x) * 7)
-#define REG_PZ_GID2LD(x) ((x) * 7 + 0xf0)
+#define REG_PZ_BASE(x) ((x) * 7)
+#define REG_PZ_GID2LD(x)   ((x) * 7 + 0xf0)

-#define GPIO_PULL_DIS  0
-#define GPIO_PULL_UP   1
-#define GPIO_PULL_DOWN 2
+#define GPIO_PULL_DIS  0
+#define GPIO_PULL_UP   1
+#define GPIO_PULL_DOWN 2

-#define PINS_PER_GPIO_CHIP 32
+#define PINS_PER_GPIO_CHIP 32
+
+#define INGENIC_PIN_GROUP_FUNCS(name, id, funcs)   \
+   {   \
+   name,   \
+   id##_pins,  \
+   ARRAY_SIZE(id##_pins),  \
+   funcs,  \
+   }
+
+#define INGENIC_PIN_GROUP(name, id, func)  \
+   INGENIC_PIN_GROUP_FUNCS(name, id, (void *)(func))

 enum jz_version {
ID_JZ4740,
@@ -134,18 +145,6 @@ static int jz4740_pwm_pwm5_pins[] = { 0x7c, };
 static int jz4740_pwm_pwm6_pins[] = { 0x7e, };
 static int jz4740_pwm_pwm7_pins[] = { 0x7f, };

-
-#define INGENIC_PIN_GROUP_FUNCS(name, id, funcs)   \
-   {   \
-   name,   \
-   id##_pins,  \
-   ARRAY_SIZE(id##_pins),  \
-   funcs,  \
-   }
-
-#define INGENIC_PIN_GROUP(name, id, func)  \
-   INGENIC_PIN_GROUP_FUNCS(name, id, (void *)(func))
-
 static const struct group_desc jz4740_groups[] = {
INGENIC_PIN_GROUP("mmc-1bit", jz4740_mmc_1bit, 0),
INGENIC_PIN_GROUP("mmc-4bit", jz4740_mmc_4bit, 0),
--
2.7.4






Re: [PATCH v2 3/6] pinctrl: Ingenic: Adjust the sequence of X1830 SSI pin groups.

2021-03-12 Thread Paul Cercueil




Le jeu. 11 mars 2021 à 23:21, 周琰杰 (Zhou Yanjie) 
 a écrit :

Adjust the sequence of X1830's SSI related codes to make it consistent
with other Ingenic SoCs.

Signed-off-by: 周琰杰 (Zhou Yanjie) 


Reviewed-by: Paul Cercueil 

Cheers,
-Paul


---

Notes:
v2:
New patch.

 drivers/pinctrl/pinctrl-ingenic.c | 10 +-
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/pinctrl/pinctrl-ingenic.c 
b/drivers/pinctrl/pinctrl-ingenic.c

index 0a88aab..607ba0b 100644
--- a/drivers/pinctrl/pinctrl-ingenic.c
+++ b/drivers/pinctrl/pinctrl-ingenic.c
@@ -1473,16 +1473,16 @@ static int x1830_ssi0_gpc_pins[] = { 0x4d, };
 static int x1830_ssi0_ce0_pins[] = { 0x50, };
 static int x1830_ssi0_ce1_pins[] = { 0x4e, };
 static int x1830_ssi1_dt_c_pins[] = { 0x53, };
-static int x1830_ssi1_dr_c_pins[] = { 0x54, };
-static int x1830_ssi1_clk_c_pins[] = { 0x57, };
-static int x1830_ssi1_gpc_c_pins[] = { 0x55, };
-static int x1830_ssi1_ce0_c_pins[] = { 0x58, };
-static int x1830_ssi1_ce1_c_pins[] = { 0x56, };
 static int x1830_ssi1_dt_d_pins[] = { 0x62, };
+static int x1830_ssi1_dr_c_pins[] = { 0x54, };
 static int x1830_ssi1_dr_d_pins[] = { 0x63, };
+static int x1830_ssi1_clk_c_pins[] = { 0x57, };
 static int x1830_ssi1_clk_d_pins[] = { 0x66, };
+static int x1830_ssi1_gpc_c_pins[] = { 0x55, };
 static int x1830_ssi1_gpc_d_pins[] = { 0x64, };
+static int x1830_ssi1_ce0_c_pins[] = { 0x58, };
 static int x1830_ssi1_ce0_d_pins[] = { 0x67, };
+static int x1830_ssi1_ce1_c_pins[] = { 0x56, };
 static int x1830_ssi1_ce1_d_pins[] = { 0x65, };
 static int x1830_mmc0_1bit_pins[] = { 0x24, 0x25, 0x20, };
 static int x1830_mmc0_4bit_pins[] = { 0x21, 0x22, 0x23, };
--
2.7.4






Re: [PATCH v2 2/6] pinctrl: Ingenic: Add support for read the pin configuration of X1830.

2021-03-12 Thread Paul Cercueil

Hi Zhou,

Le jeu. 11 mars 2021 à 23:21, 周琰杰 (Zhou Yanjie) 
 a écrit :

Add X1830 support in "ingenic_pinconf_get()", so that it can read the
configuration of X1830 SoC correctly.

Signed-off-by: 周琰杰 (Zhou Yanjie) 


This is a fix, so it needs a Fixes: tag, and you need to Cc 
linux-stable.



---

Notes:
v2:
New patch.

 drivers/pinctrl/pinctrl-ingenic.c | 76 
+--

 1 file changed, 57 insertions(+), 19 deletions(-)

diff --git a/drivers/pinctrl/pinctrl-ingenic.c 
b/drivers/pinctrl/pinctrl-ingenic.c

index 05dfa0a..0a88aab 100644
--- a/drivers/pinctrl/pinctrl-ingenic.c
+++ b/drivers/pinctrl/pinctrl-ingenic.c
@@ -2109,31 +2109,69 @@ static int ingenic_pinconf_get(struct 
pinctrl_dev *pctldev,

enum pin_config_param param = pinconf_to_config_param(*config);
unsigned int idx = pin % PINS_PER_GPIO_CHIP;
unsigned int offt = pin / PINS_PER_GPIO_CHIP;
+   unsigned int bias;
bool pull;

-   if (jzpc->info->version >= ID_JZ4770)
-   pull = !ingenic_get_pin_config(jzpc, pin, JZ4770_GPIO_PEN);
-   else
-   pull = !ingenic_get_pin_config(jzpc, pin, JZ4740_GPIO_PULL_DIS);
+   if (jzpc->info->version >= ID_X1830) {
+   unsigned int half = PINS_PER_GPIO_CHIP / 2;
+   unsigned int idxh = pin % half * 2;

-   switch (param) {
-   case PIN_CONFIG_BIAS_DISABLE:
-   if (pull)
-   return -EINVAL;
-   break;
+   if (idx < half)
+   regmap_read(jzpc->map, offt * jzpc->info->reg_offset +
+   X1830_GPIO_PEL, );
+   else
+   regmap_read(jzpc->map, offt * jzpc->info->reg_offset +
+   X1830_GPIO_PEH, );

-   case PIN_CONFIG_BIAS_PULL_UP:
-   if (!pull || !(jzpc->info->pull_ups[offt] & BIT(idx)))
-   return -EINVAL;
-   break;
+   bias = (bias >> idxh) & 3;


You can do:

u32 mask = GENMASK(idxh + 1, idxh);

bias = FIELD_GET(mask, bias);

(macros in )



-   case PIN_CONFIG_BIAS_PULL_DOWN:
-   if (!pull || !(jzpc->info->pull_downs[offt] & BIT(idx)))
-   return -EINVAL;
-   break;
+   switch (param) {
+   case PIN_CONFIG_BIAS_DISABLE:
+   if (bias)
+   return -EINVAL;
+   break;

-   default:
-   return -ENOTSUPP;
+   case PIN_CONFIG_BIAS_PULL_UP:
+   if ((bias != PIN_CONFIG_BIAS_PULL_UP) ||
+   !(jzpc->info->pull_ups[offt] & 
BIT(idx)))


"bias" is a 2-bit value (because of the & 3 mask), and 
PIN_CONFIG_BIAS_PULL_UP == 5.


So this clearly won't work. You are comparing hardware values with 
public API enums.



+   return -EINVAL;
+   break;
+
+   case PIN_CONFIG_BIAS_PULL_DOWN:
+   if ((bias != PIN_CONFIG_BIAS_PULL_DOWN) ||
+   !(jzpc->info->pull_downs[offt] & 
BIT(idx)))
+   return -EINVAL;
+   break;
+
+   default:
+   return -ENOTSUPP;
+   }
+
+   } else {
+   if (jzpc->info->version >= ID_JZ4770)
+   pull = !ingenic_get_pin_config(jzpc, pin, 
JZ4770_GPIO_PEN);
+   else
+   pull = !ingenic_get_pin_config(jzpc, pin, 
JZ4740_GPIO_PULL_DIS);


I think you can keep the switch outside the if/else block, if you use 
pullup/pulldown variables.


These can be initialized (in the non-X1830 case) to:

pullup = pull && (jzpc->info->pull_ups[offt] & BIT(idx));
pulldown = pull && (jzpc->info->pull_downs[offt] & BIT(idx));

In the X1830 case you'd initialize these variables from 'bias'.


+
+   switch (param) {
+   case PIN_CONFIG_BIAS_DISABLE:
+   if (pull)


Here would change to if (pullup || pulldown)


+   return -EINVAL;
+   break;
+
+   case PIN_CONFIG_BIAS_PULL_UP:
+   if (!pull || !(jzpc->info->pull_ups[offt] & BIT(idx)))


if (!pullup)


+   return -EINVAL;
+   break;
+
+   case PIN_CONFIG_BIAS_PULL_DOWN:
+   if (!pull || !(jzpc->info->pull_downs[offt] & BIT(idx)))


if (!pulldown)

Cheers,
-Paul


+   return -EINVAL;
+   break;
+
+   default:
+   return -ENOTSUPP;
+   }
}

*config = pinconf_to_config_packed(param, 1);
--
2.7.4






Re: [PATCH v2 1/6] pinctrl: Ingenic: Add missing pins to the JZ4770 MAC MII group.

2021-03-12 Thread Paul Cercueil

Hi,

Le jeu. 11 mars 2021 à 23:21, 周琰杰 (Zhou Yanjie) 
 a écrit :

The MII group of JZ4770's MAC should have 7 pins, add missing
pins to the MII group.

Signed-off-by: 周琰杰 (Zhou Yanjie) 


No Fixes: tag?
And if the bug wasn't introduced in 5.12-rc1 you'll need to Cc 
linux-stable as well.



---

Notes:
v2:
New patch.

 drivers/pinctrl/pinctrl-ingenic.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/pinctrl/pinctrl-ingenic.c 
b/drivers/pinctrl/pinctrl-ingenic.c

index f274612..05dfa0a 100644
--- a/drivers/pinctrl/pinctrl-ingenic.c
+++ b/drivers/pinctrl/pinctrl-ingenic.c
@@ -667,7 +667,9 @@ static int jz4770_pwm_pwm7_pins[] = { 0x6b, };
 static int jz4770_mac_rmii_pins[] = {
0xa9, 0xab, 0xaa, 0xac, 0xa5, 0xa4, 0xad, 0xae, 0xa6, 0xa8,
 };
-static int jz4770_mac_mii_pins[] = { 0xa7, 0xaf, };
+static int jz4770_mac_mii_pins[] = {
+   0x7b, 0x7a, 0x7d, 0x7c, 0xa7, 0x24, 0xaf,


Maybe list them in order?

And are you sure that's the whole list? The PM (section 12.2 in 
jz4770_pm_part3.pdf) lists more pins.


Cheers,
-Paul


+};

 static const struct group_desc jz4770_groups[] = {
INGENIC_PIN_GROUP("uart0-data", jz4770_uart0_data, 0),
--
2.7.4






Re: [PATCH v2 3/5] drm: Add and export function drm_gem_cma_mmap_noncoherent

2021-03-12 Thread Paul Cercueil




Le jeu. 11 mars 2021 à 12:36, Christoph Hellwig  a 
écrit :

On Thu, Mar 11, 2021 at 12:32:27PM +, Paul Cercueil wrote:

 > dma_to_phys must not be used by drivers.
 >
 > I have a proper helper for this waiting for users:
 >
 > 
http://git.infradead.org/users/hch/misc.git/commitdiff/96a546e7229ec53aadbdb7936d1e5e6cb5958952

 >
 > If you can confirm the helpers works for you I can try to still 
sneak

 > it to Linus for 5.12 to ease the merge pain.

 I can try. How do I get a page pointer from a dma_addr_t?


You don't - you get it from using virt_to_page on the pointer returned
from dma_alloc_noncoherent.  That beind said to keep the API sane I
should probably add a wrapper that does that for you.


I tested using:

ret = dma_mmap_pages(cma_obj->base.dev->dev,
vma, vma->vm_end - vma->vm_start,
virt_to_page(cma_obj->vaddr));

It works fine.

I think I can use remap_pfn_range() for now, and switch to your new API 
once it's available in drm-misc-next.


Cheers,
-Paul




Re: [PATCH v2 5/5] drm/ingenic: Add option to alloc cached GEM buffers

2021-03-12 Thread Paul Cercueil




Le jeu. 11 mars 2021 à 12:30, Christoph Hellwig  a 
écrit :

On Sun, Mar 07, 2021 at 08:28:35PM +, Paul Cercueil wrote:
 With the module parameter ingenic-drm.cached_gem_buffers, it is 
possible

 to specify that we want GEM buffers backed by non-coherent memory.


Shouldn't there be a way to discover this through a DT property?


Good question. My original way of thinking was that as this feature 
speeds up only software rendering, this is really 
application-dependent: a modern desktop where everything is rendered 
via the GPU wouldn't benefit much from it. With that in mind, it is 
fine as a module option.


On the other hand... the "software rendering is faster with 
non-coherent buffers" really is a SoC property, since it is only true 
for some generations of Ingenic SoCs and not others. So it would make 
sense to have a DT property for it.


-Paul




Re: [PATCH v2 4/5] drm: Add and export function drm_gem_cma_sync_data

2021-03-12 Thread Paul Cercueil




Le jeu. 11 mars 2021 à 12:28, Christoph Hellwig  a 
écrit :

On Sun, Mar 07, 2021 at 08:28:34PM +, Paul Cercueil wrote:

 +  drm_atomic_for_each_plane_damage(, ) {
 +  for (i = 0; i < finfo->num_planes; i++) {
 +  daddr = drm_fb_cma_get_gem_addr(state->fb, state, i);
 +
 +  /* Ignore x1/x2 values, invalidate complete lines */
 +  offset = clip.y1 * state->fb->pitches[i];
 +
 +  dma_sync_single_for_device(dev, daddr + offset,
 + (clip.y2 - clip.y1) * 
state->fb->pitches[i],
 + DMA_TO_DEVICE);


Are these helpers only ever used to transfer data to the device and
never from it?  If so please clearly document that.


Yes. In the DRM world, are there cases where we transfer data from the 
device? I assume these cases are handled by v4l2 instead.


-Paul




Re: [PATCH v2 3/5] drm: Add and export function drm_gem_cma_mmap_noncoherent

2021-03-11 Thread Paul Cercueil

Hi Christoph,

Le jeu. 11 mars 2021 à 12:26, Christoph Hellwig  a 
écrit :

 +int drm_gem_cma_mmap_noncoherent(struct drm_gem_object *obj,
 +   struct vm_area_struct *vma)
 +{
 +  struct drm_gem_cma_object *cma_obj;
 +  unsigned long pfn;
 +  int ret;
 +
 +  /*
 +	 * Clear the VM_PFNMAP flag that was set by drm_gem_mmap(), and 
set the
 +	 * vm_pgoff (used as a fake buffer offset by DRM) to 0 as we want 
to map

 +   * the whole buffer.
 +   */
 +  vma->vm_pgoff -= drm_vma_node_start(>vma_node);
 +  vma->vm_flags &= ~VM_PFNMAP;
 +  vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
 +
 +  cma_obj = to_drm_gem_cma_obj(obj);
 +
 +	pfn = PHYS_PFN(dma_to_phys(cma_obj->base.dev->dev, 
cma_obj->paddr));

 +
 +  ret = remap_pfn_range(vma, vma->vm_start, pfn,
 +vma->vm_end - vma->vm_start,
 +vma->vm_page_prot);


dma_to_phys must not be used by drivers.

I have a proper helper for this waiting for users:

http://git.infradead.org/users/hch/misc.git/commitdiff/96a546e7229ec53aadbdb7936d1e5e6cb5958952

If you can confirm the helpers works for you I can try to still sneak
it to Linus for 5.12 to ease the merge pain.


I can try. How do I get a page pointer from a dma_addr_t?

-Paul




Re: [PATCH v2 5/5] drm/ingenic: Add option to alloc cached GEM buffers

2021-03-11 Thread Paul Cercueil




Le jeu. 11 mars 2021 à 10:27, Hillf Danton  a écrit 
:

On Wed, 10 Mar 2021 19:01:01 + Paul Cercueil wrote:

Le lun. 8 mars 2021  11:47, Hillf Danton  a crit :

 On Sun,  7 Mar 2021 20:28:35 +  Paul Cercueil wrote:

  With the module parameter ingenic-drm.cached_gem_buffers, it is
 possible
  to specify that we want GEM buffers backed by non-coherent 
memory.


  This dramatically speeds up software rendering on Ingenic SoCs,
 even for
  tasks where write-combine memory should in theory be faster (e.g.
 simple
  blits).


 Wondering if it is due to the tricks at [1].

 If so, is dma_alloc_noncoherent() necessary in this patchset?


You confuse non-contiguous with non-coherent, which are two different
things.


You misunderstood me. From [1] we know coherent caching is arch thing,
so your proposal is not mandatory on ARM IMHO - what baffles me is
noncoherent back memory can speed up device, coherent ot not, 
regardless

of arch. Can you point me to the reasons behind your speedup?


Well, I did write in the cover letter that it would help *some* SoCs, 
so it is not meant to be a default setting. As you can see in the last 
patch, it is opt-in. Ingenic SoCs are MIPS SoCs, btw.


One thing I should add is that this speeds up *software* rendering (vs. 
write-combine). It makes perfect sense that it speeds up things like 
alpha-blending, but I can't explain why it speeds up standard blits. My 
guess is that cache line invalidation is just extremely fast on this 
SoC.


-Paul



Cheers,
-Paul


 Christoph can you give us a concise lesson on noncoherency covering
 at least
 noncoherent device, noncoherent memory(used in this work), no 
coherent
 caching(in [1]), their links to speedup, and the thumb rule to 
handle

 noncoherency in workdays. It feels toe curling every time I see
 noncoherence
 going downtown with speedup hand in hand.

 [1] Subject: [PATCH 6/6] media: uvcvideo: Use 
dma_alloc_noncontiguos

 API
 https://lore.kernel.org/lkml/20210301085236.947011-7-...@lst.de/#t



  Leave it disabled by default, since it is specific to one 
use-case

  (software rendering).

  v2: Rework code to work with new DRM APIs regarding plane states

  Signed-off-by: Paul Cercueil 
  ---
   drivers/gpu/drm/ingenic/ingenic-drm-drv.c | 49
 ++-
   drivers/gpu/drm/ingenic/ingenic-drm.h |  4 ++
   drivers/gpu/drm/ingenic/ingenic-ipu.c | 14 ++-
   3 files changed, 63 insertions(+), 4 deletions(-)

  diff --git a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c
 b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c
  index d60e1eefc9d1..ba1ac0fcda74 100644
  --- a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c
  +++ b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c
  @@ -9,6 +9,7 @@
   #include 
   #include 
   #include 
  +#include 
   #include 
   #include 
   #include 
  @@ -23,6 +24,7 @@
   #include 
   #include 
   #include 
  +#include 
   #include 
   #include 
   #include 
  @@ -99,6 +101,11 @@ struct ingenic_drm {
struct notifier_block clock_nb;
   };

  +static bool ingenic_drm_cached_gem_buf;
  +module_param_named(cached_gem_buffers, 
ingenic_drm_cached_gem_buf,

 bool, 0400);
  +MODULE_PARM_DESC(cached_gem_buffers,
  +  "Enable fully cached GEM buffers [default=false]");
  +
   static bool ingenic_drm_writeable_reg(struct device *dev, 
unsigned

 int reg)
   {
switch (reg) {
  @@ -410,6 +417,8 @@ static int
 ingenic_drm_plane_atomic_check(struct drm_plane *plane,
 old_plane_state->fb->format->format !=
 new_plane_state->fb->format->format))
crtc_state->mode_changed = true;

  + drm_atomic_helper_check_plane_damage(state, new_plane_state);
  +
return 0;
   }

  @@ -541,10 +550,20 @@ static void 
ingenic_drm_update_palette(struct

 ingenic_drm *priv,
}
   }

  +void ingenic_drm_sync_data(struct device *dev,
  +struct drm_plane_state *old_state,
  +struct drm_plane_state *state)
  +{
  + if (ingenic_drm_cached_gem_buf)
  + drm_gem_cma_sync_data(dev, old_state, state);
  +}
  +
   static void ingenic_drm_plane_atomic_update(struct drm_plane
 *plane,
struct drm_atomic_state *state)
   {
struct ingenic_drm *priv = drm_device_get_priv(plane->dev);
  + struct drm_plane_state *oldstate =
 drm_atomic_get_old_plane_state(state,
  +   
plane);
struct drm_plane_state *newstate =
 drm_atomic_get_new_plane_state(state,
  
plane);
struct drm_crtc_state *crtc_state;
  @@ -554,6 +573,8 @@ static void
 ingenic_drm_plane_atomic_update(struct drm_plane *plane,
u32 fourcc;

if (newstate && newstate->fb) {
  + ingenic_drm_sync_data(priv->dev, oldstate, newstate);
  +
crtc_stat

Re: [PATCH v2 0/5] Add option to mmap GEM buffers cached

2021-03-10 Thread Paul Cercueil

Hi Thomas,

Le lun. 8 mars 2021 à 9:41, Thomas Zimmermann  a 
écrit :

Hi Paul,

having individual functions for each mode only makes sense if the 
decision is at compile time. But in patch 5, you're working around 
your earlier design by introducing in-driver helpers that select the 
correct CMA function.


In SHMEM helpers we have the flag map_wc in the GEM structure that 
selects the pages caching mode (wc vs uncached). I think CMA should 
use this design as well. Have a map_noncoherent flag in the CMA GEM 
object and set it from the driver's implementation of 
gem_create_object.


Is that a new addition? That severely reduces the patchset size, which 
is perfect.


I'll send a V3 then.

Cheers,
-Paul

And in the long run, we could try to consolidate all drivers/helpers 
mapping flags in struct drm_gem_object.


Best regards
Thomas

Am 07.03.21 um 21:28 schrieb Paul Cercueil:

Rework of my previous patchset which added support for GEM buffers
backed by non-coherent memory to the ingenic-drm driver.

Having GEM buffers backed by non-coherent memory is interesting in
the particular case where it is faster to render to a non-coherent
buffer then sync the data cache, than to render to a write-combine
buffer, and (by extension) much faster than using a shadow buffer.
This is true for instance on some Ingenic SoCs, where even simple
blits (e.g. memcpy) are about three times faster using this method.

For the record, the previous patchset was accepted for 5.10 then had
to be reverted, as it conflicted with some changes made to the DMA 
API.


This new patchset is pretty different as it adds the functionality to
the DRM core. The first three patches add variants to existing 
functions
but with the "non-coherent memory" twist, exported as GPL symbols. 
The

fourth patch adds a function to be used with the damage helpers.
Finally, the last patch adds support for non-coherent GEM buffers to 
the

ingenic-drm driver. The functionality is enabled through a module
parameter, and is disabled by default.

Cheers,
-Paul

Paul Cercueil (5):
   drm: Add and export function drm_gem_cma_create_noncoherent
   drm: Add and export function drm_gem_cma_dumb_create_noncoherent
   drm: Add and export function drm_gem_cma_mmap_noncoherent
   drm: Add and export function drm_gem_cma_sync_data
   drm/ingenic: Add option to alloc cached GEM buffers

  drivers/gpu/drm/drm_gem_cma_helper.c  | 223 
+++---

  drivers/gpu/drm/ingenic/ingenic-drm-drv.c |  49 -
  drivers/gpu/drm/ingenic/ingenic-drm.h |   4 +
  drivers/gpu/drm/ingenic/ingenic-ipu.c |  14 +-
  include/drm/drm_gem_cma_helper.h  |  13 ++
  5 files changed, 273 insertions(+), 30 deletions(-)



--
Thomas Zimmermann
Graphics Driver Developer
SUSE Software Solutions Germany GmbH
Maxfeldstr. 5, 90409 Nürnberg, Germany
(HRB 36809, AG Nürnberg)
Geschäftsführer: Felix Imendörffer






Re: [PATCH v2 5/5] drm/ingenic: Add option to alloc cached GEM buffers

2021-03-10 Thread Paul Cercueil

Hi Hillf,

Le lun. 8 mars 2021 à 11:47, Hillf Danton  a écrit :

On Sun,  7 Mar 2021 20:28:35 +  Paul Cercueil wrote:
 With the module parameter ingenic-drm.cached_gem_buffers, it is 
possible

 to specify that we want GEM buffers backed by non-coherent memory.

 This dramatically speeds up software rendering on Ingenic SoCs, 
even for
 tasks where write-combine memory should in theory be faster (e.g. 
simple

 blits).


Wondering if it is due to the tricks at [1].

If so, is dma_alloc_noncoherent() necessary in this patchset?


You confuse non-contiguous with non-coherent, which are two different 
things.


Cheers,
-Paul

Christoph can you give us a concise lesson on noncoherency covering 
at least

noncoherent device, noncoherent memory(used in this work), no coherent
caching(in [1]), their links to speedup, and the thumb rule to handle
noncoherency in workdays. It feels toe curling every time I see 
noncoherence

going downtown with speedup hand in hand.

[1] Subject: [PATCH 6/6] media: uvcvideo: Use dma_alloc_noncontiguos 
API

https://lore.kernel.org/lkml/20210301085236.947011-7-...@lst.de/#t



 Leave it disabled by default, since it is specific to one use-case
 (software rendering).

 v2: Rework code to work with new DRM APIs regarding plane states

 Signed-off-by: Paul Cercueil 
 ---
  drivers/gpu/drm/ingenic/ingenic-drm-drv.c | 49 
++-

  drivers/gpu/drm/ingenic/ingenic-drm.h |  4 ++
  drivers/gpu/drm/ingenic/ingenic-ipu.c | 14 ++-
  3 files changed, 63 insertions(+), 4 deletions(-)

 diff --git a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c 
b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c

 index d60e1eefc9d1..ba1ac0fcda74 100644
 --- a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c
 +++ b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c
 @@ -9,6 +9,7 @@
  #include 
  #include 
  #include 
 +#include 
  #include 
  #include 
  #include 
 @@ -23,6 +24,7 @@
  #include 
  #include 
  #include 
 +#include 
  #include 
  #include 
  #include 
 @@ -99,6 +101,11 @@ struct ingenic_drm {
struct notifier_block clock_nb;
  };

 +static bool ingenic_drm_cached_gem_buf;
 +module_param_named(cached_gem_buffers, ingenic_drm_cached_gem_buf, 
bool, 0400);

 +MODULE_PARM_DESC(cached_gem_buffers,
 +   "Enable fully cached GEM buffers [default=false]");
 +
  static bool ingenic_drm_writeable_reg(struct device *dev, unsigned 
int reg)

  {
switch (reg) {
 @@ -410,6 +417,8 @@ static int 
ingenic_drm_plane_atomic_check(struct drm_plane *plane,
  	 old_plane_state->fb->format->format != 
new_plane_state->fb->format->format))

crtc_state->mode_changed = true;

 +  drm_atomic_helper_check_plane_damage(state, new_plane_state);
 +
return 0;
  }

 @@ -541,10 +550,20 @@ static void ingenic_drm_update_palette(struct 
ingenic_drm *priv,

}
  }

 +void ingenic_drm_sync_data(struct device *dev,
 + struct drm_plane_state *old_state,
 + struct drm_plane_state *state)
 +{
 +  if (ingenic_drm_cached_gem_buf)
 +  drm_gem_cma_sync_data(dev, old_state, state);
 +}
 +
  static void ingenic_drm_plane_atomic_update(struct drm_plane 
*plane,

struct drm_atomic_state *state)
  {
struct ingenic_drm *priv = drm_device_get_priv(plane->dev);
 +	struct drm_plane_state *oldstate = 
drm_atomic_get_old_plane_state(state,

 +
plane);
  	struct drm_plane_state *newstate = 
drm_atomic_get_new_plane_state(state,

  
plane);
struct drm_crtc_state *crtc_state;
 @@ -554,6 +573,8 @@ static void 
ingenic_drm_plane_atomic_update(struct drm_plane *plane,

u32 fourcc;

if (newstate && newstate->fb) {
 +  ingenic_drm_sync_data(priv->dev, oldstate, newstate);
 +
crtc_state = newstate->crtc->state;

addr = drm_fb_cma_get_gem_addr(newstate->fb, newstate, 0);
 @@ -743,6 +764,26 @@ static void ingenic_drm_disable_vblank(struct 
drm_crtc *crtc)
  	regmap_update_bits(priv->map, JZ_REG_LCD_CTRL, 
JZ_LCD_CTRL_EOF_IRQ, 0);

  }

 +static struct drm_framebuffer *
 +ingenic_drm_gem_fb_create(struct drm_device *dev, struct drm_file 
*file,

 +const struct drm_mode_fb_cmd2 *mode_cmd)
 +{
 +  if (ingenic_drm_cached_gem_buf)
 +  return drm_gem_fb_create_with_dirty(dev, file, mode_cmd);
 +
 +  return drm_gem_fb_create(dev, file, mode_cmd);
 +}
 +
 +static int ingenic_drm_gem_cma_dumb_create(struct drm_file 
*file_priv,

 + struct drm_device *drm,
 + struct drm_mode_create_dumb *args)
 +{
 +  if (ingenic_drm_cached_gem_buf)
 +  return drm_gem_cma_dumb_create_noncoherent(file_

Re: [PATCH 1/3] pinctrl: Ingenic: Fix bug and reformat the code.

2021-03-10 Thread Paul Cercueil




Le mer. 10 mars 2021 à 16:03, Andy Shevchenko 
 a écrit :

On Tue, Mar 9, 2021 at 6:42 PM 周琰杰 (Zhou Yanjie)
 wrote:


 1.Add tabs before values to align the code in the macro definition 
section.
 2.Fix bugs related to the MAC of JZ4770, add missing pins to the 
MII group.
 3.Adjust the sequence of X1830's SSI related codes to make it 
consistent

   with other Ingenic SoCs.
 4.Fix bug in "ingenic_pinconf_get()", so that it can read the 
configuration

   of X1830 SoC correctly.



Split to 4 patches then.
It's quite hard for everybody to handle regression fixes like this.


Agreed. And the fixes should have a Fixes: tag.

-Paul




[irqchip: irq/irqchip-next] dt-bindings/irq: Add compatible string for the JZ4760B

2021-03-09 Thread irqchip-bot for Paul Cercueil
The following commit has been merged into the irq/irqchip-next branch of 
irqchip:

Commit-ID: 673433e7c288927f7244658788f203c660d7a6f6
Gitweb:
https://git.kernel.org/pub/scm/linux/kernel/git/maz/arm-platforms/673433e7c288927f7244658788f203c660d7a6f6
Author:Paul Cercueil 
AuthorDate:Sun, 07 Mar 2021 17:20:13 
Committer: Marc Zyngier 
CommitterDate: Tue, 09 Mar 2021 08:45:11 

dt-bindings/irq: Add compatible string for the JZ4760B

Add the ingenic,jz4760b-intc compatible string with a fallback to the
ingenic,jz4760-intc compatible string.

Signed-off-by: Paul Cercueil 
Acked-by: Rob Herring 
Signed-off-by: Marc Zyngier 
Link: https://lore.kernel.org/r/20210307172014.73481-1-p...@crapouillou.net
---
 Documentation/devicetree/bindings/interrupt-controller/ingenic,intc.yaml | 1 +
 1 file changed, 1 insertion(+)

diff --git 
a/Documentation/devicetree/bindings/interrupt-controller/ingenic,intc.yaml 
b/Documentation/devicetree/bindings/interrupt-controller/ingenic,intc.yaml
index 0a046be..0358a77 100644
--- a/Documentation/devicetree/bindings/interrupt-controller/ingenic,intc.yaml
+++ b/Documentation/devicetree/bindings/interrupt-controller/ingenic,intc.yaml
@@ -23,6 +23,7 @@ properties:
   - enum:
   - ingenic,jz4775-intc
   - ingenic,jz4770-intc
+  - ingenic,jz4760b-intc
   - const: ingenic,jz4760-intc
   - items:
   - const: ingenic,x1000-intc


[irqchip: irq/irqchip-next] irqchip/ingenic: Add support for the JZ4760

2021-03-09 Thread irqchip-bot for Paul Cercueil
The following commit has been merged into the irq/irqchip-next branch of 
irqchip:

Commit-ID: 5fbecd2389f48e1415799c63130d0cdce1cf3f60
Gitweb:
https://git.kernel.org/pub/scm/linux/kernel/git/maz/arm-platforms/5fbecd2389f48e1415799c63130d0cdce1cf3f60
Author:Paul Cercueil 
AuthorDate:Sun, 07 Mar 2021 17:20:14 
Committer: Marc Zyngier 
CommitterDate: Tue, 09 Mar 2021 08:45:17 

irqchip/ingenic: Add support for the JZ4760

Add support for the interrupt controller found in the JZ4760 SoC, which
works exactly like the one in the JZ4770.

Signed-off-by: Paul Cercueil 
Signed-off-by: Marc Zyngier 
Link: https://lore.kernel.org/r/20210307172014.73481-2-p...@crapouillou.net
---
 drivers/irqchip/irq-ingenic-tcu.c | 1 +
 drivers/irqchip/irq-ingenic.c | 1 +
 2 files changed, 2 insertions(+)

diff --git a/drivers/irqchip/irq-ingenic-tcu.c 
b/drivers/irqchip/irq-ingenic-tcu.c
index 7a7222d..b938d1d 100644
--- a/drivers/irqchip/irq-ingenic-tcu.c
+++ b/drivers/irqchip/irq-ingenic-tcu.c
@@ -179,5 +179,6 @@ err_free_tcu:
 }
 IRQCHIP_DECLARE(jz4740_tcu_irq, "ingenic,jz4740-tcu", ingenic_tcu_irq_init);
 IRQCHIP_DECLARE(jz4725b_tcu_irq, "ingenic,jz4725b-tcu", ingenic_tcu_irq_init);
+IRQCHIP_DECLARE(jz4760_tcu_irq, "ingenic,jz4760-tcu", ingenic_tcu_irq_init);
 IRQCHIP_DECLARE(jz4770_tcu_irq, "ingenic,jz4770-tcu", ingenic_tcu_irq_init);
 IRQCHIP_DECLARE(x1000_tcu_irq, "ingenic,x1000-tcu", ingenic_tcu_irq_init);
diff --git a/drivers/irqchip/irq-ingenic.c b/drivers/irqchip/irq-ingenic.c
index b61a890..ea36bb0 100644
--- a/drivers/irqchip/irq-ingenic.c
+++ b/drivers/irqchip/irq-ingenic.c
@@ -155,6 +155,7 @@ static int __init intc_2chip_of_init(struct device_node 
*node,
 {
return ingenic_intc_of_init(node, 2);
 }
+IRQCHIP_DECLARE(jz4760_intc, "ingenic,jz4760-intc", intc_2chip_of_init);
 IRQCHIP_DECLARE(jz4770_intc, "ingenic,jz4770-intc", intc_2chip_of_init);
 IRQCHIP_DECLARE(jz4775_intc, "ingenic,jz4775-intc", intc_2chip_of_init);
 IRQCHIP_DECLARE(jz4780_intc, "ingenic,jz4780-intc", intc_2chip_of_init);


[PATCH v2 2/3] clocksource: ingenic: Add support for the JZ4760

2021-03-08 Thread Paul Cercueil
Add support for the TCU (Timer/Counter Unit) of the JZ4760 and JZ4760B
SoCs.

Signed-off-by: Paul Cercueil 
---

Notes:
v2: No change

 drivers/clocksource/ingenic-timer.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/clocksource/ingenic-timer.c 
b/drivers/clocksource/ingenic-timer.c
index 905fd6b163a8..24ed0f1f089b 100644
--- a/drivers/clocksource/ingenic-timer.c
+++ b/drivers/clocksource/ingenic-timer.c
@@ -264,6 +264,7 @@ static const struct ingenic_soc_info jz4725b_soc_info = {
 static const struct of_device_id ingenic_tcu_of_match[] = {
{ .compatible = "ingenic,jz4740-tcu", .data = _soc_info, },
{ .compatible = "ingenic,jz4725b-tcu", .data = _soc_info, },
+   { .compatible = "ingenic,jz4760-tcu", .data = _soc_info, },
{ .compatible = "ingenic,jz4770-tcu", .data = _soc_info, },
{ .compatible = "ingenic,x1000-tcu", .data = _soc_info, },
{ /* sentinel */ }
@@ -358,6 +359,7 @@ static int __init ingenic_tcu_init(struct device_node *np)
 
 TIMER_OF_DECLARE(jz4740_tcu_intc,  "ingenic,jz4740-tcu",  ingenic_tcu_init);
 TIMER_OF_DECLARE(jz4725b_tcu_intc, "ingenic,jz4725b-tcu", ingenic_tcu_init);
+TIMER_OF_DECLARE(jz4760_tcu_intc,  "ingenic,jz4760-tcu",  ingenic_tcu_init);
 TIMER_OF_DECLARE(jz4770_tcu_intc,  "ingenic,jz4770-tcu",  ingenic_tcu_init);
 TIMER_OF_DECLARE(x1000_tcu_intc,  "ingenic,x1000-tcu",  ingenic_tcu_init);
 
-- 
2.30.1



[PATCH v2 3/3] clocksource: ingenic-ost: Add support for the JZ4760B

2021-03-08 Thread Paul Cercueil
The OST in the JZ4760B SoC works exactly the same as in the JZ4770. But
since the JZ4760B is older, its Device Tree string does not fall back to
the JZ4770 one; so add support for the JZ4760B compatible string here.

Signed-off-by: Paul Cercueil 
---

Notes:
v2: No change

 drivers/clocksource/ingenic-ost.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/clocksource/ingenic-ost.c 
b/drivers/clocksource/ingenic-ost.c
index 029efc2731b4..d2d664601441 100644
--- a/drivers/clocksource/ingenic-ost.c
+++ b/drivers/clocksource/ingenic-ost.c
@@ -167,13 +167,14 @@ static const struct ingenic_ost_soc_info 
jz4725b_ost_soc_info = {
.is64bit = false,
 };
 
-static const struct ingenic_ost_soc_info jz4770_ost_soc_info = {
+static const struct ingenic_ost_soc_info jz4760b_ost_soc_info = {
.is64bit = true,
 };
 
 static const struct of_device_id ingenic_ost_of_match[] = {
{ .compatible = "ingenic,jz4725b-ost", .data = _ost_soc_info, },
-   { .compatible = "ingenic,jz4770-ost", .data = _ost_soc_info, },
+   { .compatible = "ingenic,jz4760b-ost", .data = _ost_soc_info, },
+   { .compatible = "ingenic,jz4770-ost", .data = _ost_soc_info, },
{ }
 };
 
-- 
2.30.1



[PATCH v2 1/3] dt-bindings/timer: ingenic: Add compatible strings for JZ4760(B)

2021-03-08 Thread Paul Cercueil
Add compatible strings to support the system timer, clocksource, OST,
watchdog and PWM blocks of the JZ4760 and JZ4760B SoCs.

Newer SoCs which behave like the JZ4760 or JZ4760B now see their
compatible string require a fallback compatible string that corresponds
to one of these two SoCs.

Signed-off-by: Paul Cercueil 
---

Notes:
v2: - Fix indentation
- Fix example not using correct compatible strings

 .../bindings/timer/ingenic,tcu.yaml   | 30 ++-
 1 file changed, 22 insertions(+), 8 deletions(-)

diff --git a/Documentation/devicetree/bindings/timer/ingenic,tcu.yaml 
b/Documentation/devicetree/bindings/timer/ingenic,tcu.yaml
index 024bcad75101..8165df4599cf 100644
--- a/Documentation/devicetree/bindings/timer/ingenic,tcu.yaml
+++ b/Documentation/devicetree/bindings/timer/ingenic,tcu.yaml
@@ -20,6 +20,8 @@ select:
 enum:
   - ingenic,jz4740-tcu
   - ingenic,jz4725b-tcu
+  - ingenic,jz4760-tcu
+  - ingenic,jz4760b-tcu
   - ingenic,jz4770-tcu
   - ingenic,jz4780-tcu
   - ingenic,x1000-tcu
@@ -52,12 +54,15 @@ properties:
   - enum:
   - ingenic,jz4740-tcu
   - ingenic,jz4725b-tcu
-  - ingenic,jz4770-tcu
+  - ingenic,jz4760-tcu
   - ingenic,x1000-tcu
   - const: simple-mfd
   - items:
-  - const: ingenic,jz4780-tcu
-  - const: ingenic,jz4770-tcu
+  - enum:
+  - ingenic,jz4780-tcu
+  - ingenic,jz4770-tcu
+  - ingenic,jz4760b-tcu
+  - const: ingenic,jz4760-tcu
   - const: simple-mfd
 
   reg:
@@ -118,6 +123,8 @@ patternProperties:
   - items:
   - enum:
   - ingenic,jz4770-watchdog
+  - ingenic,jz4760b-watchdog
+  - ingenic,jz4760-watchdog
   - ingenic,jz4725b-watchdog
   - const: ingenic,jz4740-watchdog
 
@@ -147,6 +154,8 @@ patternProperties:
   - ingenic,jz4725b-pwm
   - items:
   - enum:
+  - ingenic,jz4760-pwm
+  - ingenic,jz4760b-pwm
   - ingenic,jz4770-pwm
   - ingenic,jz4780-pwm
   - const: ingenic,jz4740-pwm
@@ -183,10 +192,15 @@ patternProperties:
 oneOf:
   - enum:
   - ingenic,jz4725b-ost
-  - ingenic,jz4770-ost
+  - ingenic,jz4760b-ost
   - items:
-  - const: ingenic,jz4780-ost
-  - const: ingenic,jz4770-ost
+  - const: ingenic,jz4760-ost
+  - const: ingenic,jz4725b-ost
+  - items:
+  - enum:
+  - ingenic,jz4780-ost
+  - ingenic,jz4770-ost
+  - const: ingenic,jz4760b-ost
 
   reg:
 maxItems: 1
@@ -226,7 +240,7 @@ examples:
 #include 
 #include 
 tcu: timer@10002000 {
-  compatible = "ingenic,jz4770-tcu", "simple-mfd";
+  compatible = "ingenic,jz4770-tcu", "ingenic,jz4760-tcu", "simple-mfd";
   reg = <0x10002000 0x1000>;
   #address-cells = <1>;
   #size-cells = <1>;
@@ -272,7 +286,7 @@ examples:
   };
 
   ost: timer@e0 {
-compatible = "ingenic,jz4770-ost";
+compatible = "ingenic,jz4770-ost", "ingenic,jz4760b-ost";
 reg = <0xe0 0x20>;
 
 clocks = < TCU_CLK_OST>;
-- 
2.30.1



Re: [PATCH 1/3] dt-bindings/timer: ingenic: Add compatible strings for JZ4760(B)

2021-03-08 Thread Paul Cercueil




Le lun. 8 mars 2021 à 10:39, Rob Herring  a écrit :

On Sun, 07 Mar 2021 17:15:51 +, Paul Cercueil wrote:
 Add compatible strings to support the system timer, clocksource, 
OST,

 watchdog and PWM blocks of the JZ4760 and JZ4760B SoCs.

 Newer SoCs which behave like the JZ4760 or JZ4760B now see their
 compatible string require a fallback compatible string that 
corresponds

 to one of these two SoCs.

 Signed-off-by: Paul Cercueil 
 ---
  .../bindings/timer/ingenic,tcu.yaml   | 28 
++-

  1 file changed, 21 insertions(+), 7 deletions(-)



My bot found errors running 'make dt_binding_check' on your patch:

yamllint warnings/errors:
./Documentation/devicetree/bindings/timer/ingenic,tcu.yaml:62:13: 
[warning] wrong indentation: expected 14 but found 12 (indentation)
./Documentation/devicetree/bindings/timer/ingenic,tcu.yaml:201:17: 
[warning] wrong indentation: expected 18 but found 16 (indentation)


dtschema/dtc warnings/errors:
/builds/robherring/linux-dt-review/Documentation/devicetree/bindings/timer/ingenic,tcu.example.dt.yaml: 
timer@10002000: timer@e0:compatible: 'oneOf' conditional failed, one 
must be fixed:

['ingenic,jz4770-ost'] is too short
	'ingenic,jz4770-ost' is not one of ['ingenic,jz4725b-ost', 
'ingenic,jz4760b-ost']

'ingenic,jz4760-ost' was expected
	From schema: 
/builds/robherring/linux-dt-review/Documentation/devicetree/bindings/timer/ingenic,tcu.yaml


Totally my fault, looks like I didn't check the bindings before sending 
the patchset. I'll V2.


-Paul


See https://patchwork.ozlabs.org/patch/1448709

This check can fail if there are any dependencies. The base for a 
patch

series is generally the most recent rc1.

If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up 
to

date:

pip3 install dtschema --upgrade

Please check and re-submit.





Re: [PATCH 2/2] mmc: jz4740: Add support for monitoring PLL clock rate changes

2021-03-08 Thread Paul Cercueil




Le dim. 7 mars 2021 à 17:07, Paul Cercueil  a 
écrit :

The main PLL can have its rate changed at any moment. To keep the MMC
clock running at a rate that fits the specifications, we need to
recompute the MMC clock rate every time the PLL rate changes.

Use a mutex to ensure that the MMC is idle before performing the PLL 
and

MMC rate changes.

Signed-off-by: Paul Cercueil 
---
 drivers/mmc/host/jz4740_mmc.c | 70 
++-

 1 file changed, 69 insertions(+), 1 deletion(-)

diff --git a/drivers/mmc/host/jz4740_mmc.c 
b/drivers/mmc/host/jz4740_mmc.c

index b3c636edbb46..1197b8c6b6ed 100644
--- a/drivers/mmc/host/jz4740_mmc.c
+++ b/drivers/mmc/host/jz4740_mmc.c
@@ -18,6 +18,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -149,6 +150,10 @@ struct jz4740_mmc_host {
struct platform_device *pdev;
struct clk *clk;

+   atomic_t clk_mutex_count;
+   struct mutex clk_mutex;
+   struct notifier_block clock_nb;
+
enum jz4740_mmc_version version;

int irq;
@@ -338,6 +343,9 @@ static void jz4740_mmc_pre_request(struct 
mmc_host *mmc,

struct jz4740_mmc_host *host = mmc_priv(mmc);
struct mmc_data *data = mrq->data;

+   if (atomic_inc_and_test(>clk_mutex_count))
+   mutex_lock(>clk_mutex);


There's an obvious race here, let me rewrite this using the proper 
locking mechanism.


-Paul


+
if (!host->use_dma)
return;

@@ -353,6 +361,9 @@ static void jz4740_mmc_post_request(struct 
mmc_host *mmc,

struct jz4740_mmc_host *host = mmc_priv(mmc);
struct mmc_data *data = mrq->data;

+   if (atomic_dec_return(>clk_mutex_count) == -1)
+   mutex_unlock(>clk_mutex);
+
if (data && data->host_cookie != COOKIE_UNMAPPED)
jz4740_mmc_dma_unmap(host, data);

@@ -955,6 +966,48 @@ static const struct mmc_host_ops jz4740_mmc_ops 
= {

.enable_sdio_irq = jz4740_mmc_enable_sdio_irq,
 };

+static inline struct jz4740_mmc_host *
+jz4740_mmc_nb_get_priv(struct notifier_block *nb)
+{
+   return container_of(nb, struct jz4740_mmc_host, clock_nb);
+}
+
+static struct clk *jz4740_mmc_get_parent_clk(struct clk *clk)
+{
+   /*
+* Return the first clock above the one that will effectively modify
+* its rate when clk_set_rate(clk) is called.
+*/
+   clk = clk_get_first_to_set_rate(clk);
+
+   return clk_get_parent(clk);
+}
+
+static int jz4740_mmc_update_clk(struct notifier_block *nb,
+unsigned long action,
+void *data)
+{
+   struct jz4740_mmc_host *host = jz4740_mmc_nb_get_priv(nb);
+
+   /*
+	 * PLL may have changed its frequency; our clock may be running 
above
+	 * spec. Wait until MMC is idle (using host->clk_mutex) before 
changing

+* the PLL clock, and after it's done, reset our clock rate.
+*/
+
+   switch (action) {
+   case PRE_RATE_CHANGE:
+   mutex_lock(>clk_mutex);
+   break;
+   default:
+   clk_set_rate(host->clk, host->mmc->f_max);
+   mutex_unlock(>clk_mutex);
+   break;
+   }
+
+   return NOTIFY_OK;
+}
+
 static const struct of_device_id jz4740_mmc_of_match[] = {
 	{ .compatible = "ingenic,jz4740-mmc", .data = (void *) 
JZ_MMC_JZ4740 },
 	{ .compatible = "ingenic,jz4725b-mmc", .data = (void 
*)JZ_MMC_JZ4725B },
@@ -971,6 +1024,7 @@ static int jz4740_mmc_probe(struct 
platform_device* pdev)

struct mmc_host *mmc;
struct jz4740_mmc_host *host;
const struct of_device_id *match;
+   struct clk *parent_clk;

mmc = mmc_alloc_host(sizeof(struct jz4740_mmc_host), >dev);
if (!mmc) {
@@ -1058,12 +1112,24 @@ static int jz4740_mmc_probe(struct 
platform_device* pdev)

goto err_free_irq;
host->use_dma = !ret;

+   atomic_set(>clk_mutex_count, -1);
+   mutex_init(>clk_mutex);
+   host->clock_nb.notifier_call = jz4740_mmc_update_clk;
+
+   parent_clk = jz4740_mmc_get_parent_clk(host->clk);
+
+   ret = clk_notifier_register(parent_clk, >clock_nb);
+   if (ret) {
+   dev_err(>dev, "Unable to register clock notifier\n");
+   goto err_release_dma;
+   }
+
platform_set_drvdata(pdev, host);
ret = mmc_add_host(mmc);

if (ret) {
dev_err(>dev, "Failed to add mmc host: %d\n", ret);
-   goto err_release_dma;
+   goto err_unregister_clk_notifier;
}
dev_info(>dev, "Ingenic SD/MMC card driver registered\n");

@@ -1074,6 +1140,8 @@ static int jz4740_mmc_probe(struct 
platform_device* pdev)


return 0;

+err_unregister_clk_notifier:
+   clk_notifier_unregister(parent_clk, >clock_nb);
 err_release_dma:
if (host->use_dma)
jz4740_mmc_release_dma_channels(host);
--
2.30.1






[PATCH v3 3/3] input: gpio-keys: Use hrtimer for software debounce, if possible

2021-03-07 Thread Paul Cercueil
We want to be able to report the input event as soon as the debounce
delay elapsed. However, the current code does not really ensure that,
as it uses the jiffies-based schedule_delayed_work() API. With a small
enough HZ value (HZ <= 100), this results in some input events being
lost, when a key is quickly pressed then released (on a human's time
scale).

Switching to hrtimers fixes this issue, and will work even on extremely
low HZ values (tested at HZ=24). This is however only possible if
reading the GPIO is possible without sleeping. If this condition is not
met, the previous approach of using a jiffies-based timer is taken.

Signed-off-by: Paul Cercueil 
---

Notes:
v2: HRTIMER_MODE_REL_SOFT -> HRTIMER_MODE_REL

v3: Only use a hrtimer-based timer if we know that reading the GPIO
will never sleep.

 drivers/input/keyboard/gpio_keys.c | 69 --
 1 file changed, 56 insertions(+), 13 deletions(-)

diff --git a/drivers/input/keyboard/gpio_keys.c 
b/drivers/input/keyboard/gpio_keys.c
index 4b92f49decef..046d9dffa171 100644
--- a/drivers/input/keyboard/gpio_keys.c
+++ b/drivers/input/keyboard/gpio_keys.c
@@ -41,6 +41,7 @@ struct gpio_button_data {
unsigned int release_delay; /* in msecs, for IRQ-only buttons */
 
struct delayed_work work;
+   struct hrtimer debounce_timer;
unsigned int software_debounce; /* in msecs, for GPIO-driven buttons */
 
unsigned int irq;
@@ -49,6 +50,7 @@ struct gpio_button_data {
bool disabled;
bool key_pressed;
bool suspended;
+   bool debounce_use_hrtimer;
 };
 
 struct gpio_keys_drvdata {
@@ -144,10 +146,12 @@ static void gpio_keys_disable_button(struct 
gpio_button_data *bdata)
 */
disable_irq(bdata->irq);
 
-   if (bdata->gpiod)
-   cancel_delayed_work_sync(>work);
-   else
+   if (!bdata->gpiod)
hrtimer_cancel(>release_timer);
+   else if (bdata->debounce_use_hrtimer)
+   hrtimer_cancel(>debounce_timer);
+   else
+   cancel_delayed_work_sync(>work);
 
bdata->disabled = true;
}
@@ -361,7 +365,10 @@ static void gpio_keys_gpio_report_event(struct 
gpio_button_data *bdata)
unsigned int type = button->type ?: EV_KEY;
int state;
 
-   state = gpiod_get_value_cansleep(bdata->gpiod);
+   if (bdata->debounce_use_hrtimer)
+   state = gpiod_get_value(bdata->gpiod);
+   else
+   state = gpiod_get_value_cansleep(bdata->gpiod);
if (state < 0) {
dev_err(input->dev.parent,
"failed to get gpio state: %d\n", state);
@@ -376,11 +383,8 @@ static void gpio_keys_gpio_report_event(struct 
gpio_button_data *bdata)
}
 }
 
-static void gpio_keys_gpio_work_func(struct work_struct *work)
+static void gpio_keys_debounce_event(struct gpio_button_data *bdata)
 {
-   struct gpio_button_data *bdata =
-   container_of(work, struct gpio_button_data, work.work);
-
gpio_keys_gpio_report_event(bdata);
input_sync(bdata->input);
 
@@ -388,6 +392,26 @@ static void gpio_keys_gpio_work_func(struct work_struct 
*work)
pm_relax(bdata->input->dev.parent);
 }
 
+static void gpio_keys_gpio_work_func(struct work_struct *work)
+{
+   struct gpio_button_data *bdata = container_of(work,
+ struct gpio_button_data,
+ work.work);
+
+   gpio_keys_debounce_event(bdata);
+}
+
+static enum hrtimer_restart gpio_keys_debounce_timer(struct hrtimer *t)
+{
+   struct gpio_button_data *bdata = container_of(t,
+ struct gpio_button_data,
+ debounce_timer);
+
+   gpio_keys_debounce_event(bdata);
+
+   return HRTIMER_NORESTART;
+}
+
 static irqreturn_t gpio_keys_gpio_isr(int irq, void *dev_id)
 {
struct gpio_button_data *bdata = dev_id;
@@ -409,9 +433,15 @@ static irqreturn_t gpio_keys_gpio_isr(int irq, void 
*dev_id)
}
}
 
-   mod_delayed_work(system_wq,
->work,
-msecs_to_jiffies(bdata->software_debounce));
+   if (bdata->debounce_use_hrtimer) {
+   hrtimer_start(>debounce_timer,
+ ms_to_ktime(bdata->software_debounce),
+ HRTIMER_MODE_REL);
+   } else {
+   mod_delayed_work(system_wq,
+>work,
+msecs_to_jiffies(bdata->software_debounce));
+   }
 
return IRQ_HANDLED;
 }
@@ -471,10 +501,12 @@ static void gpio_keys_quiesc

[PATCH v3 2/3] input: gpio-keys: Use hrtimer for release timer

2021-03-07 Thread Paul Cercueil
Dealing with input, timing is important; if the button should be
released in one millisecond, then it should be done in one millisecond
and not a hundred milliseconds.

Therefore, the standard timer API is not really suitable for this task.

Convert the gpio-keys driver to use a hrtimer instead of the standard
timer to address this issue.

Note that by using a hard IRQ for the hrtimer callback, we can get rid
of the spin_lock_irqsave() and spin_unlock_irqrestore().

Signed-off-by: Paul Cercueil 
---

Notes:
v2-v3: No change

 drivers/input/keyboard/gpio_keys.c | 27 ---
 1 file changed, 16 insertions(+), 11 deletions(-)

diff --git a/drivers/input/keyboard/gpio_keys.c 
b/drivers/input/keyboard/gpio_keys.c
index 7fcb2c35c5cc..4b92f49decef 100644
--- a/drivers/input/keyboard/gpio_keys.c
+++ b/drivers/input/keyboard/gpio_keys.c
@@ -8,6 +8,7 @@
 
 #include 
 
+#include 
 #include 
 #include 
 #include 
@@ -36,7 +37,7 @@ struct gpio_button_data {
 
unsigned short *code;
 
-   struct timer_list release_timer;
+   struct hrtimer release_timer;
unsigned int release_delay; /* in msecs, for IRQ-only buttons */
 
struct delayed_work work;
@@ -146,7 +147,7 @@ static void gpio_keys_disable_button(struct 
gpio_button_data *bdata)
if (bdata->gpiod)
cancel_delayed_work_sync(>work);
else
-   del_timer_sync(>release_timer);
+   hrtimer_cancel(>release_timer);
 
bdata->disabled = true;
}
@@ -415,19 +416,20 @@ static irqreturn_t gpio_keys_gpio_isr(int irq, void 
*dev_id)
return IRQ_HANDLED;
 }
 
-static void gpio_keys_irq_timer(struct timer_list *t)
+static enum hrtimer_restart gpio_keys_irq_timer(struct hrtimer *t)
 {
-   struct gpio_button_data *bdata = from_timer(bdata, t, release_timer);
+   struct gpio_button_data *bdata = container_of(t,
+ struct gpio_button_data,
+ release_timer);
struct input_dev *input = bdata->input;
-   unsigned long flags;
 
-   spin_lock_irqsave(>lock, flags);
if (bdata->key_pressed) {
input_event(input, EV_KEY, *bdata->code, 0);
input_sync(input);
bdata->key_pressed = false;
}
-   spin_unlock_irqrestore(>lock, flags);
+
+   return HRTIMER_NORESTART;
 }
 
 static irqreturn_t gpio_keys_irq_isr(int irq, void *dev_id)
@@ -457,8 +459,9 @@ static irqreturn_t gpio_keys_irq_isr(int irq, void *dev_id)
}
 
if (bdata->release_delay)
-   mod_timer(>release_timer,
-   jiffies + msecs_to_jiffies(bdata->release_delay));
+   hrtimer_start(>release_timer,
+ ms_to_ktime(bdata->release_delay),
+ HRTIMER_MODE_REL_HARD);
 out:
spin_unlock_irqrestore(>lock, flags);
return IRQ_HANDLED;
@@ -471,7 +474,7 @@ static void gpio_keys_quiesce_key(void *data)
if (bdata->gpiod)
cancel_delayed_work_sync(>work);
else
-   del_timer_sync(>release_timer);
+   hrtimer_cancel(>release_timer);
 }
 
 static int gpio_keys_setup_key(struct platform_device *pdev,
@@ -595,7 +598,9 @@ static int gpio_keys_setup_key(struct platform_device *pdev,
}
 
bdata->release_delay = button->debounce_interval;
-   timer_setup(>release_timer, gpio_keys_irq_timer, 0);
+   hrtimer_init(>release_timer,
+CLOCK_REALTIME, HRTIMER_MODE_REL_HARD);
+   bdata->release_timer.function = gpio_keys_irq_timer;
 
isr = gpio_keys_irq_isr;
irqflags = 0;
-- 
2.30.1



[PATCH v3 1/3] input: gpio-keys: Remove extra call to input_sync

2021-03-07 Thread Paul Cercueil
The input_sync() function is already called after the loop in
gpio_keys_report_state(), so it does not need to be called after each
iteration within gpio_keys_gpio_report_event().

Signed-off-by: Paul Cercueil 
---

Notes:
v2: Keep the input_sync() within gpio_keys_report_state() so that it's
not called at every iteration of the loop.

v3: No change

 drivers/input/keyboard/gpio_keys.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/input/keyboard/gpio_keys.c 
b/drivers/input/keyboard/gpio_keys.c
index 77bac4ddf324..7fcb2c35c5cc 100644
--- a/drivers/input/keyboard/gpio_keys.c
+++ b/drivers/input/keyboard/gpio_keys.c
@@ -373,7 +373,6 @@ static void gpio_keys_gpio_report_event(struct 
gpio_button_data *bdata)
} else {
input_event(input, type, *bdata->code, state);
}
-   input_sync(input);
 }
 
 static void gpio_keys_gpio_work_func(struct work_struct *work)
@@ -382,6 +381,7 @@ static void gpio_keys_gpio_work_func(struct work_struct 
*work)
container_of(work, struct gpio_button_data, work.work);
 
gpio_keys_gpio_report_event(bdata);
+   input_sync(bdata->input);
 
if (bdata->button->wakeup)
pm_relax(bdata->input->dev.parent);
-- 
2.30.1



Re: [PATCH 3/3] input: gpio-keys: Use hrtimer for software debounce

2021-03-07 Thread Paul Cercueil

Hi Dmitry,

Le dim. 7 mars 2021 à 12:20, Dmitry Torokhov 
 a écrit :

On Fri, Mar 05, 2021 at 08:00:43PM +, Paul Cercueil wrote:

 Hi Dmitry,

 Le ven. 5 mars 2021 à 10:35, Dmitry Torokhov 
 a

 écrit :
 > Hi Paul,
 >
 > On Fri, Mar 05, 2021 at 05:01:11PM +0000, Paul Cercueil wrote:
 > >  -static void gpio_keys_gpio_work_func(struct work_struct *work)
 > >  +static enum hrtimer_restart gpio_keys_debounce_timer(struct
 > > hrtimer *t)
 > >   {
 > >  -   struct gpio_button_data *bdata =
 > >  -   container_of(work, struct gpio_button_data, work.work);
 > >  +   struct gpio_button_data *bdata = container_of(t,
 > >  + struct gpio_button_data,
 > >  + debounce_timer);
 > >
 > >  gpio_keys_gpio_report_event(bdata);
 >
 > I am not sure how this works. As far as I know, even
 > HRTIMER_MODE_REL_SOFT do not allow sleeping in the timer 
handlers, and
 > gpio_keys_gpio_report_event() use sleeping variant of GPIOD API 
(and

 > that is not going to change).

 Quoting , the "timer callback will be executed in 
soft irq

 context", so sleeping should be possible.


I am afraid you misunderstand what soft irq context is, as softirqs 
and

tasklets still run in interrupt context and therefore can not sleep,
only code running in process context may sleep.


I probably do. My understanding of "softirq" is that the callback runs 
in a threaded interrupt handler.



You can test it yourself by sticking "msleep(1)" in
gpio_keys_debounce_timer() and see if you will get "scheduling while
atomic" in logs.


I tested it, it locks up.



 But I guess in this case I can use HRTIMER_MODE_REL.


This changes selected clock source, but has no effect on whether timer
handler can sleep or not.



 > It seems to me that if you want to use software debounce in gpio 
keys
 > driver you need to set up sufficiently high HZ for your system. 
Maybe we
 > could thrown a warning when we see low debounce delay and low HZ 
to

 > alert system developer.

 This is exactly what we should not do. I certainly don't want to 
have 250+
 timer interrupts per second just so that input events aren't lost, 
to work

 around a sucky debounce implementation. Besides, if you consider the
 hrtimers doc (Documentation/timers/hrtimers.rst), hrtimers really 
are what

 should be used here.


I explained why they can't. They could be if you restrict gpio_keys to
only be used with GPIOs that do not require sleep to read their state,
but I am not willing to accept such restriction. You either need to 
have

longer debounce, higher HZ, or see if you can use GPIO controller that
supports debounce handling. See also if you can enable dynamic
ticks/NO_HZ to limit number of timer interrupts on idle system.


We can also use the hrtimer approach if the GPIO doesn't require sleep, 
and fall back to the standard timer if it does. It's possible to detect 
that with gpiod_cansleep(). The diff would be pretty slim. Would you 
accept something like that?


Switching from HZ=250 to HZ=24 leads to a 3% overall performance 
increase across all apps on our system, so a pretty big optimization, 
and this is the only blocker.


Cheers,
-Paul




[PATCH v2 4/5] drm: Add and export function drm_gem_cma_sync_data

2021-03-07 Thread Paul Cercueil
This function can be used by drivers that use damage clips and have
CMA GEM objects backed by non-coherent memory. Calling this function
in a plane's .atomic_update ensures that all the data in the backing
memory have been written to RAM.

Signed-off-by: Paul Cercueil 
---
 drivers/gpu/drm/drm_gem_cma_helper.c | 43 
 include/drm/drm_gem_cma_helper.h |  5 
 2 files changed, 48 insertions(+)

diff --git a/drivers/gpu/drm/drm_gem_cma_helper.c 
b/drivers/gpu/drm/drm_gem_cma_helper.c
index e39b0464e19d..fdae54a18670 100644
--- a/drivers/gpu/drm/drm_gem_cma_helper.c
+++ b/drivers/gpu/drm/drm_gem_cma_helper.c
@@ -18,9 +18,14 @@
 #include 
 
 #include 
+#include 
 #include 
 #include 
+#include 
+#include 
+#include 
 #include 
+#include 
 #include 
 
 /**
@@ -684,3 +689,41 @@ drm_gem_cma_prime_import_sg_table_vmap(struct drm_device 
*dev,
return obj;
 }
 EXPORT_SYMBOL(drm_gem_cma_prime_import_sg_table_vmap);
+
+/**
+ * drm_gem_cma_sync_data - Sync GEM object to non-coherent backing memory
+ * @dev: DRM device
+ * @old_state: Old plane state
+ * @state: New plane state
+ *
+ * This function can be used by drivers that use damage clips and have
+ * CMA GEM objects backed by non-coherent memory. Calling this function
+ * in a plane's .atomic_update ensures that all the data in the backing
+ * memory have been written to RAM.
+ */
+void drm_gem_cma_sync_data(struct device *dev,
+  struct drm_plane_state *old_state,
+  struct drm_plane_state *state)
+{
+   const struct drm_format_info *finfo = state->fb->format;
+   struct drm_atomic_helper_damage_iter iter;
+   unsigned int offset, i;
+   struct drm_rect clip;
+   dma_addr_t daddr;
+
+   drm_atomic_helper_damage_iter_init(, old_state, state);
+
+   drm_atomic_for_each_plane_damage(, ) {
+   for (i = 0; i < finfo->num_planes; i++) {
+   daddr = drm_fb_cma_get_gem_addr(state->fb, state, i);
+
+   /* Ignore x1/x2 values, invalidate complete lines */
+   offset = clip.y1 * state->fb->pitches[i];
+
+   dma_sync_single_for_device(dev, daddr + offset,
+  (clip.y2 - clip.y1) * 
state->fb->pitches[i],
+  DMA_TO_DEVICE);
+   }
+   }
+}
+EXPORT_SYMBOL_GPL(drm_gem_cma_sync_data);
diff --git a/include/drm/drm_gem_cma_helper.h b/include/drm/drm_gem_cma_helper.h
index 6a3f7e1312cc..cdd3fb456916 100644
--- a/include/drm/drm_gem_cma_helper.h
+++ b/include/drm/drm_gem_cma_helper.h
@@ -7,6 +7,7 @@
 #include 
 
 struct drm_mode_create_dumb;
+struct drm_plane_state;
 
 /**
  * struct drm_gem_cma_object - GEM object backed by CMA memory allocations
@@ -190,4 +191,8 @@ drm_gem_cma_prime_import_sg_table_vmap(struct drm_device 
*drm,
   struct dma_buf_attachment *attach,
   struct sg_table *sgt);
 
+void drm_gem_cma_sync_data(struct device *dev,
+  struct drm_plane_state *old_state,
+  struct drm_plane_state *state);
+
 #endif /* __DRM_GEM_CMA_HELPER_H__ */
-- 
2.30.1



[PATCH v2 5/5] drm/ingenic: Add option to alloc cached GEM buffers

2021-03-07 Thread Paul Cercueil
With the module parameter ingenic-drm.cached_gem_buffers, it is possible
to specify that we want GEM buffers backed by non-coherent memory.

This dramatically speeds up software rendering on Ingenic SoCs, even for
tasks where write-combine memory should in theory be faster (e.g. simple
blits).

Leave it disabled by default, since it is specific to one use-case
(software rendering).

v2: Rework code to work with new DRM APIs regarding plane states

Signed-off-by: Paul Cercueil 
---
 drivers/gpu/drm/ingenic/ingenic-drm-drv.c | 49 ++-
 drivers/gpu/drm/ingenic/ingenic-drm.h |  4 ++
 drivers/gpu/drm/ingenic/ingenic-ipu.c | 14 ++-
 3 files changed, 63 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c 
b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c
index d60e1eefc9d1..ba1ac0fcda74 100644
--- a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c
+++ b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c
@@ -9,6 +9,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -23,6 +24,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -99,6 +101,11 @@ struct ingenic_drm {
struct notifier_block clock_nb;
 };
 
+static bool ingenic_drm_cached_gem_buf;
+module_param_named(cached_gem_buffers, ingenic_drm_cached_gem_buf, bool, 0400);
+MODULE_PARM_DESC(cached_gem_buffers,
+"Enable fully cached GEM buffers [default=false]");
+
 static bool ingenic_drm_writeable_reg(struct device *dev, unsigned int reg)
 {
switch (reg) {
@@ -410,6 +417,8 @@ static int ingenic_drm_plane_atomic_check(struct drm_plane 
*plane,
 old_plane_state->fb->format->format != 
new_plane_state->fb->format->format))
crtc_state->mode_changed = true;
 
+   drm_atomic_helper_check_plane_damage(state, new_plane_state);
+
return 0;
 }
 
@@ -541,10 +550,20 @@ static void ingenic_drm_update_palette(struct ingenic_drm 
*priv,
}
 }
 
+void ingenic_drm_sync_data(struct device *dev,
+  struct drm_plane_state *old_state,
+  struct drm_plane_state *state)
+{
+   if (ingenic_drm_cached_gem_buf)
+   drm_gem_cma_sync_data(dev, old_state, state);
+}
+
 static void ingenic_drm_plane_atomic_update(struct drm_plane *plane,
struct drm_atomic_state *state)
 {
struct ingenic_drm *priv = drm_device_get_priv(plane->dev);
+   struct drm_plane_state *oldstate = drm_atomic_get_old_plane_state(state,
+ 
plane);
struct drm_plane_state *newstate = drm_atomic_get_new_plane_state(state,
  
plane);
struct drm_crtc_state *crtc_state;
@@ -554,6 +573,8 @@ static void ingenic_drm_plane_atomic_update(struct 
drm_plane *plane,
u32 fourcc;
 
if (newstate && newstate->fb) {
+   ingenic_drm_sync_data(priv->dev, oldstate, newstate);
+
crtc_state = newstate->crtc->state;
 
addr = drm_fb_cma_get_gem_addr(newstate->fb, newstate, 0);
@@ -743,6 +764,26 @@ static void ingenic_drm_disable_vblank(struct drm_crtc 
*crtc)
regmap_update_bits(priv->map, JZ_REG_LCD_CTRL, JZ_LCD_CTRL_EOF_IRQ, 0);
 }
 
+static struct drm_framebuffer *
+ingenic_drm_gem_fb_create(struct drm_device *dev, struct drm_file *file,
+ const struct drm_mode_fb_cmd2 *mode_cmd)
+{
+   if (ingenic_drm_cached_gem_buf)
+   return drm_gem_fb_create_with_dirty(dev, file, mode_cmd);
+
+   return drm_gem_fb_create(dev, file, mode_cmd);
+}
+
+static int ingenic_drm_gem_cma_dumb_create(struct drm_file *file_priv,
+  struct drm_device *drm,
+  struct drm_mode_create_dumb *args)
+{
+   if (ingenic_drm_cached_gem_buf)
+   return drm_gem_cma_dumb_create_noncoherent(file_priv, drm, 
args);
+
+   return drm_gem_cma_dumb_create(file_priv, drm, args);
+}
+
 DEFINE_DRM_GEM_CMA_FOPS(ingenic_drm_fops);
 
 static const struct drm_driver ingenic_drm_driver_data = {
@@ -755,7 +796,7 @@ static const struct drm_driver ingenic_drm_driver_data = {
.patchlevel = 0,
 
.fops   = _drm_fops,
-   DRM_GEM_CMA_DRIVER_OPS,
+   
DRM_GEM_CMA_DRIVER_OPS_WITH_DUMB_CREATE(ingenic_drm_gem_cma_dumb_create),
 
.irq_handler= ingenic_drm_irq_handler,
 };
@@ -805,7 +846,7 @@ static const struct drm_encoder_helper_funcs 
ingenic_drm_encoder_helper_funcs =
 };
 
 static const struct drm_mode_config_funcs ingenic_drm_mode_config_funcs = {
-   .fb_create  = drm_gem_fb_create,
+   .fb_create  = ingenic_drm_gem_fb_create,
.output_poll_changed  

[PATCH v2 1/5] drm: Add and export function drm_gem_cma_create_noncoherent

2021-03-07 Thread Paul Cercueil
This function can be used by drivers that need to create a GEM object
with non-coherent backing memory.

Creating non-coherent CMA objects is useful on architectures where
writing to a buffer with the non-coherent cache attribute set then
invalidating the cache is faster than writing to the same buffer with
the write-combine cache attribute set. This is the case for instance on
some Ingenic SoCs.

v2: Add inline doc about why we need this, and improve commit message

Signed-off-by: Paul Cercueil 
---
 drivers/gpu/drm/drm_gem_cma_helper.c | 76 +---
 include/drm/drm_gem_cma_helper.h |  2 +
 2 files changed, 61 insertions(+), 17 deletions(-)

diff --git a/drivers/gpu/drm/drm_gem_cma_helper.c 
b/drivers/gpu/drm/drm_gem_cma_helper.c
index 7942cf05cd93..917b092b23c2 100644
--- a/drivers/gpu/drm/drm_gem_cma_helper.c
+++ b/drivers/gpu/drm/drm_gem_cma_helper.c
@@ -90,21 +90,10 @@ __drm_gem_cma_create(struct drm_device *drm, size_t size)
return ERR_PTR(ret);
 }
 
-/**
- * drm_gem_cma_create - allocate an object with the given size
- * @drm: DRM device
- * @size: size of the object to allocate
- *
- * This function creates a CMA GEM object and allocates a contiguous chunk of
- * memory as backing store. The backing memory has the writecombine attribute
- * set.
- *
- * Returns:
- * A struct drm_gem_cma_object * on success or an ERR_PTR()-encoded negative
- * error code on failure.
- */
-struct drm_gem_cma_object *drm_gem_cma_create(struct drm_device *drm,
- size_t size)
+static struct drm_gem_cma_object *
+drm_gem_cma_create_with_cache_param(struct drm_device *drm,
+   size_t size,
+   bool noncoherent)
 {
struct drm_gem_cma_object *cma_obj;
int ret;
@@ -115,8 +104,16 @@ struct drm_gem_cma_object *drm_gem_cma_create(struct 
drm_device *drm,
if (IS_ERR(cma_obj))
return cma_obj;
 
-   cma_obj->vaddr = dma_alloc_wc(drm->dev, size, _obj->paddr,
- GFP_KERNEL | __GFP_NOWARN);
+   if (noncoherent) {
+   cma_obj->vaddr = dma_alloc_noncoherent(drm->dev, size,
+  _obj->paddr,
+  DMA_TO_DEVICE,
+  GFP_KERNEL | 
__GFP_NOWARN);
+
+   } else {
+   cma_obj->vaddr = dma_alloc_wc(drm->dev, size, _obj->paddr,
+ GFP_KERNEL | __GFP_NOWARN);
+   }
if (!cma_obj->vaddr) {
drm_dbg(drm, "failed to allocate buffer with size %zu\n",
 size);
@@ -130,6 +127,51 @@ struct drm_gem_cma_object *drm_gem_cma_create(struct 
drm_device *drm,
drm_gem_object_put(_obj->base);
return ERR_PTR(ret);
 }
+
+/**
+ * drm_gem_cma_create_noncoherent - allocate an object with the given size
+ * and non-coherent cache attribute
+ * @drm: DRM device
+ * @size: size of the object to allocate
+ *
+ * This function creates a CMA GEM object and allocates a contiguous chunk of
+ * memory as backing store. The backing memory has the noncoherent attribute
+ * set.
+ *
+ * Creating non-coherent CMA objects is useful on architectures where writing
+ * to a buffer with the non-coherent cache attribute set then invalidating the
+ * cache is faster than writing to the same buffer with the write-combine cache
+ * attribute set. This is the case for instance on some Ingenic SoCs.
+ *
+ * Returns:
+ * A struct drm_gem_cma_object * on success or an ERR_PTR()-encoded negative
+ * error code on failure.
+ */
+struct drm_gem_cma_object *
+drm_gem_cma_create_noncoherent(struct drm_device *drm, size_t size)
+{
+   return drm_gem_cma_create_with_cache_param(drm, size, true);
+}
+EXPORT_SYMBOL_GPL(drm_gem_cma_create_noncoherent);
+
+/**
+ * drm_gem_cma_create - allocate an object with the given size
+ * @drm: DRM device
+ * @size: size of the object to allocate
+ *
+ * This function creates a CMA GEM object and allocates a contiguous chunk of
+ * memory as backing store. The backing memory has the writecombine attribute
+ * set.
+ *
+ * Returns:
+ * A struct drm_gem_cma_object * on success or an ERR_PTR()-encoded negative
+ * error code on failure.
+ */
+struct drm_gem_cma_object *drm_gem_cma_create(struct drm_device *drm,
+ size_t size)
+{
+   return drm_gem_cma_create_with_cache_param(drm, size, false);
+}
 EXPORT_SYMBOL_GPL(drm_gem_cma_create);
 
 /**
diff --git a/include/drm/drm_gem_cma_helper.h b/include/drm/drm_gem_cma_helper.h
index 0a9711caa3e8..360771f5f485 100644
--- a/include/drm/drm_gem_cma_helper.h
+++ b/include/drm/drm_gem_cma_helper.h
@@ -79,6 +79,8 @@ int drm_gem_cma_dumb_create(struct drm_file *file_priv,
 /* allocate physical memory */
 struct drm_gem_cma_object

[PATCH v2 3/5] drm: Add and export function drm_gem_cma_mmap_noncoherent

2021-03-07 Thread Paul Cercueil
This function can be used by drivers that need to mmap dumb buffers
created with non-coherent backing memory.

v2: Use dma_to_phys() since cma_obj->paddr isn't a phys_addr_t but a
dma_addr_t.

Signed-off-by: Paul Cercueil 
---
 drivers/gpu/drm/drm_gem_cma_helper.c | 67 +---
 include/drm/drm_gem_cma_helper.h |  1 +
 2 files changed, 63 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/drm_gem_cma_helper.c 
b/drivers/gpu/drm/drm_gem_cma_helper.c
index d100c5f9c140..e39b0464e19d 100644
--- a/drivers/gpu/drm/drm_gem_cma_helper.c
+++ b/drivers/gpu/drm/drm_gem_cma_helper.c
@@ -10,6 +10,7 @@
  */
 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -42,10 +43,20 @@ static const struct drm_gem_object_funcs 
drm_gem_cma_default_funcs = {
.vm_ops = _gem_cma_vm_ops,
 };
 
+static const struct drm_gem_object_funcs drm_gem_cma_noncoherent_funcs = {
+   .free = drm_gem_cma_free_object,
+   .print_info = drm_gem_cma_print_info,
+   .get_sg_table = drm_gem_cma_get_sg_table,
+   .vmap = drm_gem_cma_vmap,
+   .mmap = drm_gem_cma_mmap_noncoherent,
+   .vm_ops = _gem_cma_vm_ops,
+};
+
 /**
  * __drm_gem_cma_create - Create a GEM CMA object without allocating memory
  * @drm: DRM device
  * @size: size of the object to allocate
+ * @noncoherent: if true, will use non-coherent backed memory
  *
  * This function creates and initializes a GEM CMA object of the given size,
  * but doesn't allocate any memory to back the object.
@@ -55,7 +66,7 @@ static const struct drm_gem_object_funcs 
drm_gem_cma_default_funcs = {
  * error code on failure.
  */
 static struct drm_gem_cma_object *
-__drm_gem_cma_create(struct drm_device *drm, size_t size)
+__drm_gem_cma_create(struct drm_device *drm, size_t size, bool noncoherent)
 {
struct drm_gem_cma_object *cma_obj;
struct drm_gem_object *gem_obj;
@@ -68,8 +79,12 @@ __drm_gem_cma_create(struct drm_device *drm, size_t size)
if (!gem_obj)
return ERR_PTR(-ENOMEM);
 
-   if (!gem_obj->funcs)
-   gem_obj->funcs = _gem_cma_default_funcs;
+   if (!gem_obj->funcs) {
+   if (noncoherent)
+   gem_obj->funcs = _gem_cma_noncoherent_funcs;
+   else
+   gem_obj->funcs = _gem_cma_default_funcs;
+   }
 
cma_obj = container_of(gem_obj, struct drm_gem_cma_object, base);
 
@@ -100,7 +115,7 @@ drm_gem_cma_create_with_cache_param(struct drm_device *drm,
 
size = round_up(size, PAGE_SIZE);
 
-   cma_obj = __drm_gem_cma_create(drm, size);
+   cma_obj = __drm_gem_cma_create(drm, size, noncoherent);
if (IS_ERR(cma_obj))
return cma_obj;
 
@@ -503,7 +518,7 @@ drm_gem_cma_prime_import_sg_table(struct drm_device *dev,
return ERR_PTR(-EINVAL);
 
/* Create a CMA GEM buffer. */
-   cma_obj = __drm_gem_cma_create(dev, attach->dmabuf->size);
+   cma_obj = __drm_gem_cma_create(dev, attach->dmabuf->size, false);
if (IS_ERR(cma_obj))
return ERR_CAST(cma_obj);
 
@@ -579,6 +594,48 @@ int drm_gem_cma_mmap(struct drm_gem_object *obj, struct 
vm_area_struct *vma)
 }
 EXPORT_SYMBOL_GPL(drm_gem_cma_mmap);
 
+/**
+ * drm_gem_cma_mmap_noncoherent - memory-map a CMA GEM object with
+ * non-coherent cache attribute
+ * @filp: file object
+ * @vma: VMA for the area to be mapped
+ *
+ * Just like drm_gem_cma_mmap, but for a GEM object backed by non-coherent
+ * memory.
+ *
+ * Returns:
+ * 0 on success or a negative error code on failure.
+ */
+int drm_gem_cma_mmap_noncoherent(struct drm_gem_object *obj,
+struct vm_area_struct *vma)
+{
+   struct drm_gem_cma_object *cma_obj;
+   unsigned long pfn;
+   int ret;
+
+   /*
+* Clear the VM_PFNMAP flag that was set by drm_gem_mmap(), and set the
+* vm_pgoff (used as a fake buffer offset by DRM) to 0 as we want to map
+* the whole buffer.
+*/
+   vma->vm_pgoff -= drm_vma_node_start(>vma_node);
+   vma->vm_flags &= ~VM_PFNMAP;
+   vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
+
+   cma_obj = to_drm_gem_cma_obj(obj);
+
+   pfn = PHYS_PFN(dma_to_phys(cma_obj->base.dev->dev, cma_obj->paddr));
+
+   ret = remap_pfn_range(vma, vma->vm_start, pfn,
+ vma->vm_end - vma->vm_start,
+ vma->vm_page_prot);
+   if (ret)
+   drm_gem_vm_close(vma);
+
+   return ret;
+}
+EXPORT_SYMBOL_GPL(drm_gem_cma_mmap_noncoherent);
+
 /**
  * drm_gem_cma_prime_import_sg_table_vmap - PRIME import another driver's
  * scatter/gather table and get the virtual address of the buffer
diff --git a/include/drm/drm_gem_cma_helper.h b/include/drm/drm_gem_cma_helper.h
index 6b44e7492a63..6a3f7e1312cc 100644
--- a/include/drm/drm_gem_cma_helper.h
+++ b/include/drm/drm_gem_cma

[PATCH v2 2/5] drm: Add and export function drm_gem_cma_dumb_create_noncoherent

2021-03-07 Thread Paul Cercueil
This function can be used by drivers to create dumb buffers with
non-coherent backing memory.

Signed-off-by: Paul Cercueil 
---
 drivers/gpu/drm/drm_gem_cma_helper.c | 37 +---
 include/drm/drm_gem_cma_helper.h |  5 
 2 files changed, 38 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/drm_gem_cma_helper.c 
b/drivers/gpu/drm/drm_gem_cma_helper.c
index 917b092b23c2..d100c5f9c140 100644
--- a/drivers/gpu/drm/drm_gem_cma_helper.c
+++ b/drivers/gpu/drm/drm_gem_cma_helper.c
@@ -181,6 +181,7 @@ EXPORT_SYMBOL_GPL(drm_gem_cma_create);
  * @drm: DRM device
  * @size: size of the object to allocate
  * @handle: return location for the GEM handle
+ * @noncoherent: allocate object with non-coherent cache attribute
  *
  * This function creates a CMA GEM object, allocating a physically contiguous
  * chunk of memory as backing store. The GEM object is then added to the list
@@ -193,13 +194,13 @@ EXPORT_SYMBOL_GPL(drm_gem_cma_create);
 static struct drm_gem_cma_object *
 drm_gem_cma_create_with_handle(struct drm_file *file_priv,
   struct drm_device *drm, size_t size,
-  uint32_t *handle)
+  uint32_t *handle, bool noncoherent)
 {
struct drm_gem_cma_object *cma_obj;
struct drm_gem_object *gem_obj;
int ret;
 
-   cma_obj = drm_gem_cma_create(drm, size);
+   cma_obj = drm_gem_cma_create_with_cache_param(drm, size, noncoherent);
if (IS_ERR(cma_obj))
return cma_obj;
 
@@ -276,7 +277,7 @@ int drm_gem_cma_dumb_create_internal(struct drm_file 
*file_priv,
args->size = args->pitch * args->height;
 
cma_obj = drm_gem_cma_create_with_handle(file_priv, drm, args->size,
->handle);
+>handle, false);
return PTR_ERR_OR_ZERO(cma_obj);
 }
 EXPORT_SYMBOL_GPL(drm_gem_cma_dumb_create_internal);
@@ -309,11 +310,39 @@ int drm_gem_cma_dumb_create(struct drm_file *file_priv,
args->size = args->pitch * args->height;
 
cma_obj = drm_gem_cma_create_with_handle(file_priv, drm, args->size,
->handle);
+>handle, false);
return PTR_ERR_OR_ZERO(cma_obj);
 }
 EXPORT_SYMBOL_GPL(drm_gem_cma_dumb_create);
 
+/**
+ * drm_gem_cma_dumb_create_noncoherent - create a dumb buffer object with
+ * non-coherent cache attribute
+ * @file_priv: DRM file-private structure to create the dumb buffer for
+ * @drm: DRM device
+ * @args: IOCTL data
+ *
+ * Same as drm_gem_cma_dumb_create, but the dumb buffer object created has
+ * the non-coherent cache attribute set.
+ *
+ * Returns:
+ * 0 on success or a negative error code on failure.
+ */
+int drm_gem_cma_dumb_create_noncoherent(struct drm_file *file_priv,
+   struct drm_device *drm,
+   struct drm_mode_create_dumb *args)
+{
+   struct drm_gem_cma_object *cma_obj;
+
+   args->pitch = DIV_ROUND_UP(args->width * args->bpp, 8);
+   args->size = args->pitch * args->height;
+
+   cma_obj = drm_gem_cma_create_with_handle(file_priv, drm, args->size,
+>handle, true);
+   return PTR_ERR_OR_ZERO(cma_obj);
+}
+EXPORT_SYMBOL_GPL(drm_gem_cma_dumb_create_noncoherent);
+
 const struct vm_operations_struct drm_gem_cma_vm_ops = {
.open = drm_gem_vm_open,
.close = drm_gem_vm_close,
diff --git a/include/drm/drm_gem_cma_helper.h b/include/drm/drm_gem_cma_helper.h
index 360771f5f485..6b44e7492a63 100644
--- a/include/drm/drm_gem_cma_helper.h
+++ b/include/drm/drm_gem_cma_helper.h
@@ -76,6 +76,11 @@ int drm_gem_cma_dumb_create(struct drm_file *file_priv,
struct drm_device *drm,
struct drm_mode_create_dumb *args);
 
+/* create non-coherent memory region for DRM framebuffer */
+int drm_gem_cma_dumb_create_noncoherent(struct drm_file *file_priv,
+   struct drm_device *drm,
+   struct drm_mode_create_dumb *args);
+
 /* allocate physical memory */
 struct drm_gem_cma_object *drm_gem_cma_create(struct drm_device *drm,
  size_t size);
-- 
2.30.1



[PATCH v2 0/5] Add option to mmap GEM buffers cached

2021-03-07 Thread Paul Cercueil
Rework of my previous patchset which added support for GEM buffers
backed by non-coherent memory to the ingenic-drm driver.

Having GEM buffers backed by non-coherent memory is interesting in
the particular case where it is faster to render to a non-coherent
buffer then sync the data cache, than to render to a write-combine
buffer, and (by extension) much faster than using a shadow buffer.
This is true for instance on some Ingenic SoCs, where even simple
blits (e.g. memcpy) are about three times faster using this method.

For the record, the previous patchset was accepted for 5.10 then had
to be reverted, as it conflicted with some changes made to the DMA API.

This new patchset is pretty different as it adds the functionality to
the DRM core. The first three patches add variants to existing functions
but with the "non-coherent memory" twist, exported as GPL symbols. The
fourth patch adds a function to be used with the damage helpers.
Finally, the last patch adds support for non-coherent GEM buffers to the
ingenic-drm driver. The functionality is enabled through a module
parameter, and is disabled by default.

Cheers,
-Paul

Paul Cercueil (5):
  drm: Add and export function drm_gem_cma_create_noncoherent
  drm: Add and export function drm_gem_cma_dumb_create_noncoherent
  drm: Add and export function drm_gem_cma_mmap_noncoherent
  drm: Add and export function drm_gem_cma_sync_data
  drm/ingenic: Add option to alloc cached GEM buffers

 drivers/gpu/drm/drm_gem_cma_helper.c  | 223 +++---
 drivers/gpu/drm/ingenic/ingenic-drm-drv.c |  49 -
 drivers/gpu/drm/ingenic/ingenic-drm.h |   4 +
 drivers/gpu/drm/ingenic/ingenic-ipu.c |  14 +-
 include/drm/drm_gem_cma_helper.h  |  13 ++
 5 files changed, 273 insertions(+), 30 deletions(-)

-- 
2.30.1



[PATCH 1/2] dt-bindings: panel/kingdisplay,kd035g6-54nt: Remove spi-cs-high

2021-03-07 Thread Paul Cercueil
The NT39016 panel is a fun beast, even though the documentation states
that the CS line is active-low, it will work just fine if the CS line is
configured as active-high, but it won't work if the CS line is forced
low or forced high.

Since it did actually work with the spi-cs-high property, this is not a
bugfix, but we should nonetheless remove that property from the example
to match the documentation.

Signed-off-by: Paul Cercueil 
---
 .../bindings/display/panel/kingdisplay,kd035g6-54nt.yaml | 1 -
 1 file changed, 1 deletion(-)

diff --git 
a/Documentation/devicetree/bindings/display/panel/kingdisplay,kd035g6-54nt.yaml 
b/Documentation/devicetree/bindings/display/panel/kingdisplay,kd035g6-54nt.yaml
index 6960036975fa..c45c92a3d41f 100644
--- 
a/Documentation/devicetree/bindings/display/panel/kingdisplay,kd035g6-54nt.yaml
+++ 
b/Documentation/devicetree/bindings/display/panel/kingdisplay,kd035g6-54nt.yaml
@@ -47,7 +47,6 @@ examples:
 
 spi-max-frequency = <3125000>;
 spi-3wire;
-spi-cs-high;
 
 reset-gpios = < 2 GPIO_ACTIVE_LOW>;
 
-- 
2.30.1



[PATCH 2/2] MIPS: ingenic: gcw0: SPI panel does not require active-high CS

2021-03-07 Thread Paul Cercueil
The NT39016 panel is a fun beast, even though the documentation states
that the CS line is active-low, it will work just fine if the CS line is
configured as active-high, but it won't work if the CS line is forced
low or forced high.

Since it did actually work with the spi-cs-high property, this is not a
bugfix, but we should nonetheless remove that property to match the
documentation.

Signed-off-by: Paul Cercueil 
---
 arch/mips/boot/dts/ingenic/gcw0.dts | 1 -
 1 file changed, 1 deletion(-)

diff --git a/arch/mips/boot/dts/ingenic/gcw0.dts 
b/arch/mips/boot/dts/ingenic/gcw0.dts
index bc72304a2440..f4c04f2263ea 100644
--- a/arch/mips/boot/dts/ingenic/gcw0.dts
+++ b/arch/mips/boot/dts/ingenic/gcw0.dts
@@ -345,7 +345,6 @@ nt39016@0 {
 
spi-max-frequency = <3125000>;
spi-3wire;
-   spi-cs-high;
 
reset-gpios = < 2 GPIO_ACTIVE_LOW>;
 
-- 
2.30.1



[PATCH v2 2/3] input: gpio-keys: Use hrtimer for release timer

2021-03-07 Thread Paul Cercueil
Dealing with input, timing is important; if the button should be
released in one millisecond, then it should be done in one millisecond
and not a hundred milliseconds.

Therefore, the standard timer API is not really suitable for this task.

Convert the gpio-keys driver to use a hrtimer instead of the standard
timer to address this issue.

Note that by using a hard IRQ for the hrtimer callback, we can get rid
of the spin_lock_irqsave() and spin_unlock_irqrestore().

Signed-off-by: Paul Cercueil 
---

Notes:
v2: No change

 drivers/input/keyboard/gpio_keys.c | 27 ---
 1 file changed, 16 insertions(+), 11 deletions(-)

diff --git a/drivers/input/keyboard/gpio_keys.c 
b/drivers/input/keyboard/gpio_keys.c
index 7fcb2c35c5cc..4b92f49decef 100644
--- a/drivers/input/keyboard/gpio_keys.c
+++ b/drivers/input/keyboard/gpio_keys.c
@@ -8,6 +8,7 @@
 
 #include 
 
+#include 
 #include 
 #include 
 #include 
@@ -36,7 +37,7 @@ struct gpio_button_data {
 
unsigned short *code;
 
-   struct timer_list release_timer;
+   struct hrtimer release_timer;
unsigned int release_delay; /* in msecs, for IRQ-only buttons */
 
struct delayed_work work;
@@ -146,7 +147,7 @@ static void gpio_keys_disable_button(struct 
gpio_button_data *bdata)
if (bdata->gpiod)
cancel_delayed_work_sync(>work);
else
-   del_timer_sync(>release_timer);
+   hrtimer_cancel(>release_timer);
 
bdata->disabled = true;
}
@@ -415,19 +416,20 @@ static irqreturn_t gpio_keys_gpio_isr(int irq, void 
*dev_id)
return IRQ_HANDLED;
 }
 
-static void gpio_keys_irq_timer(struct timer_list *t)
+static enum hrtimer_restart gpio_keys_irq_timer(struct hrtimer *t)
 {
-   struct gpio_button_data *bdata = from_timer(bdata, t, release_timer);
+   struct gpio_button_data *bdata = container_of(t,
+ struct gpio_button_data,
+ release_timer);
struct input_dev *input = bdata->input;
-   unsigned long flags;
 
-   spin_lock_irqsave(>lock, flags);
if (bdata->key_pressed) {
input_event(input, EV_KEY, *bdata->code, 0);
input_sync(input);
bdata->key_pressed = false;
}
-   spin_unlock_irqrestore(>lock, flags);
+
+   return HRTIMER_NORESTART;
 }
 
 static irqreturn_t gpio_keys_irq_isr(int irq, void *dev_id)
@@ -457,8 +459,9 @@ static irqreturn_t gpio_keys_irq_isr(int irq, void *dev_id)
}
 
if (bdata->release_delay)
-   mod_timer(>release_timer,
-   jiffies + msecs_to_jiffies(bdata->release_delay));
+   hrtimer_start(>release_timer,
+ ms_to_ktime(bdata->release_delay),
+ HRTIMER_MODE_REL_HARD);
 out:
spin_unlock_irqrestore(>lock, flags);
return IRQ_HANDLED;
@@ -471,7 +474,7 @@ static void gpio_keys_quiesce_key(void *data)
if (bdata->gpiod)
cancel_delayed_work_sync(>work);
else
-   del_timer_sync(>release_timer);
+   hrtimer_cancel(>release_timer);
 }
 
 static int gpio_keys_setup_key(struct platform_device *pdev,
@@ -595,7 +598,9 @@ static int gpio_keys_setup_key(struct platform_device *pdev,
}
 
bdata->release_delay = button->debounce_interval;
-   timer_setup(>release_timer, gpio_keys_irq_timer, 0);
+   hrtimer_init(>release_timer,
+CLOCK_REALTIME, HRTIMER_MODE_REL_HARD);
+   bdata->release_timer.function = gpio_keys_irq_timer;
 
isr = gpio_keys_irq_isr;
irqflags = 0;
-- 
2.30.1



[PATCH v2 3/3] input: gpio-keys: Use hrtimer for software debounce

2021-03-07 Thread Paul Cercueil
We want to be able to report the input event as soon as the debounce
delay elapsed. However, the current code does not really ensure that,
as it uses the jiffies-based schedule_delayed_work() API. With a small
enough HZ value (HZ <= 100), this results in some input events being
lost, when a key is quickly pressed then released (on a human's time
scale).

Switching to hrtimers fixes this issue, and will work even on extremely
low HZ values (tested at HZ=24).

Signed-off-by: Paul Cercueil 
---

Notes:
v2: HRTIMER_MODE_REL_SOFT -> HRTIMER_MODE_REL

 drivers/input/keyboard/gpio_keys.c | 33 +++---
 1 file changed, 17 insertions(+), 16 deletions(-)

diff --git a/drivers/input/keyboard/gpio_keys.c 
b/drivers/input/keyboard/gpio_keys.c
index 4b92f49decef..566e7950fcef 100644
--- a/drivers/input/keyboard/gpio_keys.c
+++ b/drivers/input/keyboard/gpio_keys.c
@@ -22,7 +22,6 @@
 #include 
 #include 
 #include 
-#include 
 #include 
 #include 
 #include 
@@ -40,7 +39,7 @@ struct gpio_button_data {
struct hrtimer release_timer;
unsigned int release_delay; /* in msecs, for IRQ-only buttons */
 
-   struct delayed_work work;
+   struct hrtimer debounce_timer;
unsigned int software_debounce; /* in msecs, for GPIO-driven buttons */
 
unsigned int irq;
@@ -145,7 +144,7 @@ static void gpio_keys_disable_button(struct 
gpio_button_data *bdata)
disable_irq(bdata->irq);
 
if (bdata->gpiod)
-   cancel_delayed_work_sync(>work);
+   hrtimer_cancel(>debounce_timer);
else
hrtimer_cancel(>release_timer);
 
@@ -376,16 +375,19 @@ static void gpio_keys_gpio_report_event(struct 
gpio_button_data *bdata)
}
 }
 
-static void gpio_keys_gpio_work_func(struct work_struct *work)
+static enum hrtimer_restart gpio_keys_debounce_timer(struct hrtimer *t)
 {
-   struct gpio_button_data *bdata =
-   container_of(work, struct gpio_button_data, work.work);
+   struct gpio_button_data *bdata = container_of(t,
+ struct gpio_button_data,
+ debounce_timer);
 
gpio_keys_gpio_report_event(bdata);
input_sync(bdata->input);
 
if (bdata->button->wakeup)
pm_relax(bdata->input->dev.parent);
+
+   return HRTIMER_NORESTART;
 }
 
 static irqreturn_t gpio_keys_gpio_isr(int irq, void *dev_id)
@@ -409,9 +411,9 @@ static irqreturn_t gpio_keys_gpio_isr(int irq, void *dev_id)
}
}
 
-   mod_delayed_work(system_wq,
->work,
-msecs_to_jiffies(bdata->software_debounce));
+   hrtimer_start(>debounce_timer,
+ ms_to_ktime(bdata->software_debounce),
+ HRTIMER_MODE_REL);
 
return IRQ_HANDLED;
 }
@@ -472,7 +474,7 @@ static void gpio_keys_quiesce_key(void *data)
struct gpio_button_data *bdata = data;
 
if (bdata->gpiod)
-   cancel_delayed_work_sync(>work);
+   hrtimer_cancel(>debounce_timer);
else
hrtimer_cancel(>release_timer);
 }
@@ -562,11 +564,13 @@ static int gpio_keys_setup_key(struct platform_device 
*pdev,
bdata->irq = irq;
}
 
-   INIT_DELAYED_WORK(>work, gpio_keys_gpio_work_func);
-
isr = gpio_keys_gpio_isr;
irqflags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING;
 
+   hrtimer_init(>debounce_timer,
+CLOCK_REALTIME, HRTIMER_MODE_REL);
+   bdata->debounce_timer.function = gpio_keys_debounce_timer;
+
switch (button->wakeup_event_action) {
case EV_ACT_ASSERTED:
bdata->wakeup_trigger_type = active_low ?
@@ -615,10 +619,7 @@ static int gpio_keys_setup_key(struct platform_device 
*pdev,
*bdata->code = button->code;
input_set_capability(input, button->type ?: EV_KEY, *bdata->code);
 
-   /*
-* Install custom action to cancel release timer and
-* workqueue item.
-*/
+   /* Install custom action to cancel timers. */
error = devm_add_action(dev, gpio_keys_quiesce_key, bdata);
if (error) {
dev_err(dev, "failed to register quiesce action, error: %d\n",
-- 
2.30.1



[PATCH v2 1/3] input: gpio-keys: Remove extra call to input_sync

2021-03-07 Thread Paul Cercueil
The input_sync() function is already called after the loop in
gpio_keys_report_state(), so it does not need to be called after each
iteration within gpio_keys_gpio_report_event().

Signed-off-by: Paul Cercueil 
---

Notes:
v2: Keep the input_sync() within gpio_keys_report_state() so that it's
not called at every iteration of the loop.

 drivers/input/keyboard/gpio_keys.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/input/keyboard/gpio_keys.c 
b/drivers/input/keyboard/gpio_keys.c
index 77bac4ddf324..7fcb2c35c5cc 100644
--- a/drivers/input/keyboard/gpio_keys.c
+++ b/drivers/input/keyboard/gpio_keys.c
@@ -373,7 +373,6 @@ static void gpio_keys_gpio_report_event(struct 
gpio_button_data *bdata)
} else {
input_event(input, type, *bdata->code, state);
}
-   input_sync(input);
 }
 
 static void gpio_keys_gpio_work_func(struct work_struct *work)
@@ -382,6 +381,7 @@ static void gpio_keys_gpio_work_func(struct work_struct 
*work)
container_of(work, struct gpio_button_data, work.work);
 
gpio_keys_gpio_report_event(bdata);
+   input_sync(bdata->input);
 
if (bdata->button->wakeup)
pm_relax(bdata->input->dev.parent);
-- 
2.30.1



[PATCH 1/2] dt-bindings/irq: Add compatible string for the JZ4760B

2021-03-07 Thread Paul Cercueil
Add the ingenic,jz4760b-intc compatible string with a fallback to the
ingenic,jz4760-intc compatible string.

Signed-off-by: Paul Cercueil 
---
 .../devicetree/bindings/interrupt-controller/ingenic,intc.yaml   | 1 +
 1 file changed, 1 insertion(+)

diff --git 
a/Documentation/devicetree/bindings/interrupt-controller/ingenic,intc.yaml 
b/Documentation/devicetree/bindings/interrupt-controller/ingenic,intc.yaml
index 0a046be8d1cd..0358a7739c8e 100644
--- a/Documentation/devicetree/bindings/interrupt-controller/ingenic,intc.yaml
+++ b/Documentation/devicetree/bindings/interrupt-controller/ingenic,intc.yaml
@@ -23,6 +23,7 @@ properties:
   - enum:
   - ingenic,jz4775-intc
   - ingenic,jz4770-intc
+  - ingenic,jz4760b-intc
   - const: ingenic,jz4760-intc
   - items:
   - const: ingenic,x1000-intc
-- 
2.30.1



[PATCH 2/2] irqchip: ingenic: Add support for the JZ4760

2021-03-07 Thread Paul Cercueil
Add support for the interrupt controller found in the JZ4760 SoC, which
works exactly like the one in the JZ4770.

Signed-off-by: Paul Cercueil 
---

Notes:
Note that the binding documentation for the ingenic,jz4760-tcu
compatible string has been submitted in a different patchset.

 drivers/irqchip/irq-ingenic-tcu.c | 1 +
 drivers/irqchip/irq-ingenic.c | 1 +
 2 files changed, 2 insertions(+)

diff --git a/drivers/irqchip/irq-ingenic-tcu.c 
b/drivers/irqchip/irq-ingenic-tcu.c
index 7a7222d4c19c..b938d1d04d96 100644
--- a/drivers/irqchip/irq-ingenic-tcu.c
+++ b/drivers/irqchip/irq-ingenic-tcu.c
@@ -179,5 +179,6 @@ static int __init ingenic_tcu_irq_init(struct device_node 
*np,
 }
 IRQCHIP_DECLARE(jz4740_tcu_irq, "ingenic,jz4740-tcu", ingenic_tcu_irq_init);
 IRQCHIP_DECLARE(jz4725b_tcu_irq, "ingenic,jz4725b-tcu", ingenic_tcu_irq_init);
+IRQCHIP_DECLARE(jz4760_tcu_irq, "ingenic,jz4760-tcu", ingenic_tcu_irq_init);
 IRQCHIP_DECLARE(jz4770_tcu_irq, "ingenic,jz4770-tcu", ingenic_tcu_irq_init);
 IRQCHIP_DECLARE(x1000_tcu_irq, "ingenic,x1000-tcu", ingenic_tcu_irq_init);
diff --git a/drivers/irqchip/irq-ingenic.c b/drivers/irqchip/irq-ingenic.c
index b61a8901ef72..ea36bb00be80 100644
--- a/drivers/irqchip/irq-ingenic.c
+++ b/drivers/irqchip/irq-ingenic.c
@@ -155,6 +155,7 @@ static int __init intc_2chip_of_init(struct device_node 
*node,
 {
return ingenic_intc_of_init(node, 2);
 }
+IRQCHIP_DECLARE(jz4760_intc, "ingenic,jz4760-intc", intc_2chip_of_init);
 IRQCHIP_DECLARE(jz4770_intc, "ingenic,jz4770-intc", intc_2chip_of_init);
 IRQCHIP_DECLARE(jz4775_intc, "ingenic,jz4775-intc", intc_2chip_of_init);
 IRQCHIP_DECLARE(jz4780_intc, "ingenic,jz4780-intc", intc_2chip_of_init);
-- 
2.30.1



[PATCH 3/3] clocksource: ingenic-ost: Add support for the JZ4760B

2021-03-07 Thread Paul Cercueil
The OST in the JZ4760B SoC works exactly the same as in the JZ4770. But
since the JZ4760B is older, its Device Tree string does not fall back to
the JZ4770 one; so add support for the JZ4760B compatible string here.

Signed-off-by: Paul Cercueil 
---
 drivers/clocksource/ingenic-ost.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/clocksource/ingenic-ost.c 
b/drivers/clocksource/ingenic-ost.c
index 029efc2731b4..d2d664601441 100644
--- a/drivers/clocksource/ingenic-ost.c
+++ b/drivers/clocksource/ingenic-ost.c
@@ -167,13 +167,14 @@ static const struct ingenic_ost_soc_info 
jz4725b_ost_soc_info = {
.is64bit = false,
 };
 
-static const struct ingenic_ost_soc_info jz4770_ost_soc_info = {
+static const struct ingenic_ost_soc_info jz4760b_ost_soc_info = {
.is64bit = true,
 };
 
 static const struct of_device_id ingenic_ost_of_match[] = {
{ .compatible = "ingenic,jz4725b-ost", .data = _ost_soc_info, },
-   { .compatible = "ingenic,jz4770-ost", .data = _ost_soc_info, },
+   { .compatible = "ingenic,jz4760b-ost", .data = _ost_soc_info, },
+   { .compatible = "ingenic,jz4770-ost", .data = _ost_soc_info, },
{ }
 };
 
-- 
2.30.1



[PATCH 2/3] clocksource: ingenic: Add support for the JZ4760

2021-03-07 Thread Paul Cercueil
Add support for the TCU (Timer/Counter Unit) of the JZ4760 and JZ4760B
SoCs.

Signed-off-by: Paul Cercueil 
---
 drivers/clocksource/ingenic-timer.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/clocksource/ingenic-timer.c 
b/drivers/clocksource/ingenic-timer.c
index 905fd6b163a8..24ed0f1f089b 100644
--- a/drivers/clocksource/ingenic-timer.c
+++ b/drivers/clocksource/ingenic-timer.c
@@ -264,6 +264,7 @@ static const struct ingenic_soc_info jz4725b_soc_info = {
 static const struct of_device_id ingenic_tcu_of_match[] = {
{ .compatible = "ingenic,jz4740-tcu", .data = _soc_info, },
{ .compatible = "ingenic,jz4725b-tcu", .data = _soc_info, },
+   { .compatible = "ingenic,jz4760-tcu", .data = _soc_info, },
{ .compatible = "ingenic,jz4770-tcu", .data = _soc_info, },
{ .compatible = "ingenic,x1000-tcu", .data = _soc_info, },
{ /* sentinel */ }
@@ -358,6 +359,7 @@ static int __init ingenic_tcu_init(struct device_node *np)
 
 TIMER_OF_DECLARE(jz4740_tcu_intc,  "ingenic,jz4740-tcu",  ingenic_tcu_init);
 TIMER_OF_DECLARE(jz4725b_tcu_intc, "ingenic,jz4725b-tcu", ingenic_tcu_init);
+TIMER_OF_DECLARE(jz4760_tcu_intc,  "ingenic,jz4760-tcu",  ingenic_tcu_init);
 TIMER_OF_DECLARE(jz4770_tcu_intc,  "ingenic,jz4770-tcu",  ingenic_tcu_init);
 TIMER_OF_DECLARE(x1000_tcu_intc,  "ingenic,x1000-tcu",  ingenic_tcu_init);
 
-- 
2.30.1



[PATCH 1/3] dt-bindings/timer: ingenic: Add compatible strings for JZ4760(B)

2021-03-07 Thread Paul Cercueil
Add compatible strings to support the system timer, clocksource, OST,
watchdog and PWM blocks of the JZ4760 and JZ4760B SoCs.

Newer SoCs which behave like the JZ4760 or JZ4760B now see their
compatible string require a fallback compatible string that corresponds
to one of these two SoCs.

Signed-off-by: Paul Cercueil 
---
 .../bindings/timer/ingenic,tcu.yaml   | 28 ++-
 1 file changed, 21 insertions(+), 7 deletions(-)

diff --git a/Documentation/devicetree/bindings/timer/ingenic,tcu.yaml 
b/Documentation/devicetree/bindings/timer/ingenic,tcu.yaml
index 024bcad75101..26561fe72076 100644
--- a/Documentation/devicetree/bindings/timer/ingenic,tcu.yaml
+++ b/Documentation/devicetree/bindings/timer/ingenic,tcu.yaml
@@ -20,6 +20,8 @@ select:
 enum:
   - ingenic,jz4740-tcu
   - ingenic,jz4725b-tcu
+  - ingenic,jz4760-tcu
+  - ingenic,jz4760b-tcu
   - ingenic,jz4770-tcu
   - ingenic,jz4780-tcu
   - ingenic,x1000-tcu
@@ -52,12 +54,15 @@ properties:
   - enum:
   - ingenic,jz4740-tcu
   - ingenic,jz4725b-tcu
-  - ingenic,jz4770-tcu
+  - ingenic,jz4760-tcu
   - ingenic,x1000-tcu
   - const: simple-mfd
   - items:
-  - const: ingenic,jz4780-tcu
-  - const: ingenic,jz4770-tcu
+  - enum:
+- ingenic,jz4780-tcu
+- ingenic,jz4770-tcu
+- ingenic,jz4760b-tcu
+  - const: ingenic,jz4760-tcu
   - const: simple-mfd
 
   reg:
@@ -118,6 +123,8 @@ patternProperties:
   - items:
   - enum:
   - ingenic,jz4770-watchdog
+  - ingenic,jz4760b-watchdog
+  - ingenic,jz4760-watchdog
   - ingenic,jz4725b-watchdog
   - const: ingenic,jz4740-watchdog
 
@@ -147,6 +154,8 @@ patternProperties:
   - ingenic,jz4725b-pwm
   - items:
   - enum:
+  - ingenic,jz4760-pwm
+  - ingenic,jz4760b-pwm
   - ingenic,jz4770-pwm
   - ingenic,jz4780-pwm
   - const: ingenic,jz4740-pwm
@@ -183,10 +192,15 @@ patternProperties:
 oneOf:
   - enum:
   - ingenic,jz4725b-ost
-  - ingenic,jz4770-ost
+  - ingenic,jz4760b-ost
+  - items:
+  - const: ingenic,jz4760-ost
+  - const: ingenic,jz4725b-ost
   - items:
-  - const: ingenic,jz4780-ost
-  - const: ingenic,jz4770-ost
+  - enum:
+- ingenic,jz4780-ost
+- ingenic,jz4770-ost
+  - const: ingenic,jz4760b-ost
 
   reg:
 maxItems: 1
@@ -226,7 +240,7 @@ examples:
 #include 
 #include 
 tcu: timer@10002000 {
-  compatible = "ingenic,jz4770-tcu", "simple-mfd";
+  compatible = "ingenic,jz4770-tcu", "ingenic,jz4760-tcu", "simple-mfd";
   reg = <0x10002000 0x1000>;
   #address-cells = <1>;
   #size-cells = <1>;
-- 
2.30.1



[PATCH 0/2] mmc: jz4740: Support PLL frequency changes

2021-03-07 Thread Paul Cercueil
Hi,

This set of two patches enables the MMC driver to cope with the main PLL
updating its rate, typically when the CPU frequency is being updated.

The first patch introduces clk_get_first_to_set_rate(), which will allow
the MMC driver to get a pointer to the clock that will effectively be
modified when calling clk_set_rate(); this is required to avoid a
chicken-and-egg situation with the clock notifier.

If accepted, this function will be reused in a few more drivers which
need to perform the same operation.

The patch to the MMC driver adds a atomic/mutex couple so that the
frequency change will happen when we know that the controller is not in
use.

Cheers,
-Paul

Paul Cercueil (2):
  clk: Add clk_get_first_to_set_rate
  mmc: jz4740: Add support for monitoring PLL clock rate changes

 drivers/clk/clk.c |  9 +
 drivers/mmc/host/jz4740_mmc.c | 70 ++-
 include/linux/clk.h   | 16 
 3 files changed, 94 insertions(+), 1 deletion(-)

-- 
2.30.1



[PATCH 1/2] clk: Add clk_get_first_to_set_rate

2021-03-07 Thread Paul Cercueil
The purpose of this function is to be used along with the notifier
mechanism.

When a parent clock can see its rate externally changed at any moment,
and a driver needs a specific clock rate to function, it can register a
notifier on the parent clock, and call clk_set_rate() on the base clock
to adjust its frequency according to the new parent clock.

This works fine, until the base clock has the CLK_SET_RATE_PARENT flag
set. In that case, calling clk_set_rate() on the base clock will call
clk_set_rate() on the parent clock, which will trigger the notifier
again, and we're in a loop.

For that reason, we need to register the notifier on the parent clock of
the first ancestor of the base clock that will effectively modify its
rate when clk_set_rate() is called, which we can now obtain with
clk_get_first_to_set_rate().

Signed-off-by: Paul Cercueil 
---
 drivers/clk/clk.c   |  9 +
 include/linux/clk.h | 16 
 2 files changed, 25 insertions(+)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 5052541a0986..3fd75e283482 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -2450,6 +2450,15 @@ struct clk *clk_get_parent(struct clk *clk)
 }
 EXPORT_SYMBOL_GPL(clk_get_parent);
 
+struct clk *clk_get_first_to_set_rate(struct clk *clk)
+{
+   while (clk && (clk->core->flags & CLK_SET_RATE_PARENT))
+   clk = clk_get_parent(clk);
+
+   return clk;
+}
+
+
 static struct clk_core *__clk_init_parent(struct clk_core *core)
 {
u8 index = 0;
diff --git a/include/linux/clk.h b/include/linux/clk.h
index 266e8de3cb51..f0ea6ac6aa39 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -766,6 +766,17 @@ struct clk *clk_get_parent(struct clk *clk);
  */
 struct clk *clk_get_sys(const char *dev_id, const char *con_id);
 
+/**
+ * clk_get_first_to_set_rate - get a pointer to the clock that will
+ *   effectively modify its rate when clk_set_rate(clk) is called
+ *   (might be clk itself, or any ancestor)
+ * @clk: clock source
+ *
+ * Returns struct clk corresponding to the matched clock source, or
+ * NULL on error.
+ */
+struct clk *clk_get_first_to_set_rate(struct clk *clk);
+
 /**
  * clk_save_context - save clock context for poweroff
  *
@@ -928,6 +939,11 @@ static inline struct clk *clk_get_parent(struct clk *clk)
return NULL;
 }
 
+static inline struct clk *clk_get_first_to_set_rate(struct clk *clk)
+{
+   return NULL;
+}
+
 static inline struct clk *clk_get_sys(const char *dev_id, const char *con_id)
 {
return NULL;
-- 
2.30.1



[PATCH 2/2] mmc: jz4740: Add support for monitoring PLL clock rate changes

2021-03-07 Thread Paul Cercueil
The main PLL can have its rate changed at any moment. To keep the MMC
clock running at a rate that fits the specifications, we need to
recompute the MMC clock rate every time the PLL rate changes.

Use a mutex to ensure that the MMC is idle before performing the PLL and
MMC rate changes.

Signed-off-by: Paul Cercueil 
---
 drivers/mmc/host/jz4740_mmc.c | 70 ++-
 1 file changed, 69 insertions(+), 1 deletion(-)

diff --git a/drivers/mmc/host/jz4740_mmc.c b/drivers/mmc/host/jz4740_mmc.c
index b3c636edbb46..1197b8c6b6ed 100644
--- a/drivers/mmc/host/jz4740_mmc.c
+++ b/drivers/mmc/host/jz4740_mmc.c
@@ -18,6 +18,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -149,6 +150,10 @@ struct jz4740_mmc_host {
struct platform_device *pdev;
struct clk *clk;
 
+   atomic_t clk_mutex_count;
+   struct mutex clk_mutex;
+   struct notifier_block clock_nb;
+
enum jz4740_mmc_version version;
 
int irq;
@@ -338,6 +343,9 @@ static void jz4740_mmc_pre_request(struct mmc_host *mmc,
struct jz4740_mmc_host *host = mmc_priv(mmc);
struct mmc_data *data = mrq->data;
 
+   if (atomic_inc_and_test(>clk_mutex_count))
+   mutex_lock(>clk_mutex);
+
if (!host->use_dma)
return;
 
@@ -353,6 +361,9 @@ static void jz4740_mmc_post_request(struct mmc_host *mmc,
struct jz4740_mmc_host *host = mmc_priv(mmc);
struct mmc_data *data = mrq->data;
 
+   if (atomic_dec_return(>clk_mutex_count) == -1)
+   mutex_unlock(>clk_mutex);
+
if (data && data->host_cookie != COOKIE_UNMAPPED)
jz4740_mmc_dma_unmap(host, data);
 
@@ -955,6 +966,48 @@ static const struct mmc_host_ops jz4740_mmc_ops = {
.enable_sdio_irq = jz4740_mmc_enable_sdio_irq,
 };
 
+static inline struct jz4740_mmc_host *
+jz4740_mmc_nb_get_priv(struct notifier_block *nb)
+{
+   return container_of(nb, struct jz4740_mmc_host, clock_nb);
+}
+
+static struct clk *jz4740_mmc_get_parent_clk(struct clk *clk)
+{
+   /*
+* Return the first clock above the one that will effectively modify
+* its rate when clk_set_rate(clk) is called.
+*/
+   clk = clk_get_first_to_set_rate(clk);
+
+   return clk_get_parent(clk);
+}
+
+static int jz4740_mmc_update_clk(struct notifier_block *nb,
+unsigned long action,
+void *data)
+{
+   struct jz4740_mmc_host *host = jz4740_mmc_nb_get_priv(nb);
+
+   /*
+* PLL may have changed its frequency; our clock may be running above
+* spec. Wait until MMC is idle (using host->clk_mutex) before changing
+* the PLL clock, and after it's done, reset our clock rate.
+*/
+
+   switch (action) {
+   case PRE_RATE_CHANGE:
+   mutex_lock(>clk_mutex);
+   break;
+   default:
+   clk_set_rate(host->clk, host->mmc->f_max);
+   mutex_unlock(>clk_mutex);
+   break;
+   }
+
+   return NOTIFY_OK;
+}
+
 static const struct of_device_id jz4740_mmc_of_match[] = {
{ .compatible = "ingenic,jz4740-mmc", .data = (void *) JZ_MMC_JZ4740 },
{ .compatible = "ingenic,jz4725b-mmc", .data = (void *)JZ_MMC_JZ4725B },
@@ -971,6 +1024,7 @@ static int jz4740_mmc_probe(struct platform_device* pdev)
struct mmc_host *mmc;
struct jz4740_mmc_host *host;
const struct of_device_id *match;
+   struct clk *parent_clk;
 
mmc = mmc_alloc_host(sizeof(struct jz4740_mmc_host), >dev);
if (!mmc) {
@@ -1058,12 +1112,24 @@ static int jz4740_mmc_probe(struct platform_device* 
pdev)
goto err_free_irq;
host->use_dma = !ret;
 
+   atomic_set(>clk_mutex_count, -1);
+   mutex_init(>clk_mutex);
+   host->clock_nb.notifier_call = jz4740_mmc_update_clk;
+
+   parent_clk = jz4740_mmc_get_parent_clk(host->clk);
+
+   ret = clk_notifier_register(parent_clk, >clock_nb);
+   if (ret) {
+   dev_err(>dev, "Unable to register clock notifier\n");
+   goto err_release_dma;
+   }
+
platform_set_drvdata(pdev, host);
ret = mmc_add_host(mmc);
 
if (ret) {
dev_err(>dev, "Failed to add mmc host: %d\n", ret);
-   goto err_release_dma;
+   goto err_unregister_clk_notifier;
}
dev_info(>dev, "Ingenic SD/MMC card driver registered\n");
 
@@ -1074,6 +1140,8 @@ static int jz4740_mmc_probe(struct platform_device* pdev)
 
return 0;
 
+err_unregister_clk_notifier:
+   clk_notifier_unregister(parent_clk, >clock_nb);
 err_release_dma:
if (host->use_dma)
jz4740_mmc_release_dma_channels(host);
-- 
2.30.1



Re: [PATCH] clk: Fix doc of clk_get_parent

2021-03-07 Thread Paul Cercueil




Le dim. 7 mars 2021 à 14:30, Russell King - ARM Linux admin 
 a écrit :

On Sun, Mar 07, 2021 at 02:29:07PM +, Paul Cercueil wrote:

 Hi,

 Le dim. 7 mars 2021 à 14:27, Russell King - ARM Linux admin
  a écrit :
 > On Sun, Mar 07, 2021 at 02:06:26PM +0000, Paul Cercueil wrote:
 > >  On error, or when the passed parameter is NULL, the return 
value is

 > > NULL
 > >  and not a PTR_ERR()-encoded value.
 >
 > No, the documentation is accurate. The CCF is just an 
implementation

 > of the API, the file you are modifying is the definitive API
 > documentation.

 Well, then the code has to be fixed, because right now it returns 
NULL on

 error, since the 2.6 days.


And you consider NULL to be an error? A NULL clock isn't defined to be
an error by the API.


Fair enough. Ignore my patch then.

Cheers,
-Paul




Re: [PATCH -next] phy: ingenic: Fix a typo in ingenic_usb_phy_probe()

2021-03-07 Thread Paul Cercueil




Le ven. 5 mars 2021 à 3:49, 'Wei Yongjun  a 
écrit :

From: Wei Yongjun 

Fix the return value check typo which testing the wrong variable
in ingenic_usb_phy_probe().

Fixes: 31de313dfdcf ("PHY: Ingenic: Add USB PHY driver using generic 
PHY framework.")

Reported-by: Hulk Robot 
Signed-off-by: Wei Yongjun 


Acked-by: Paul Cercueil 

Cheers,
-Paul


---
 drivers/phy/ingenic/phy-ingenic-usb.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/phy/ingenic/phy-ingenic-usb.c 
b/drivers/phy/ingenic/phy-ingenic-usb.c

index ea127b177f46..28c28d816484 100644
--- a/drivers/phy/ingenic/phy-ingenic-usb.c
+++ b/drivers/phy/ingenic/phy-ingenic-usb.c
@@ -352,8 +352,8 @@ static int ingenic_usb_phy_probe(struct 
platform_device *pdev)

}

priv->phy = devm_phy_create(dev, NULL, _usb_phy_ops);
-   if (IS_ERR(priv))
-   return PTR_ERR(priv);
+   if (IS_ERR(priv->phy))
+   return PTR_ERR(priv->phy);

phy_set_drvdata(priv->phy, priv);







Re: [PATCH] ASoC: codecs/jz4770: Remove superfluous error message

2021-03-07 Thread Paul Cercueil




Le dim. 7 mars 2021 à 15:21, Tang Bin  a 
écrit :

The function devm_platform_ioremap_resource has already contained
error message if failed, so remove superfluous dev_err here.

Signed-off-by: Zhang Shengju 
Signed-off-by: Tang Bin 


Looks good.

Acked-by: Paul Cercueil 

Cheers,
-Paul


---
 sound/soc/codecs/jz4770.c | 7 ++-
 1 file changed, 2 insertions(+), 5 deletions(-)

diff --git a/sound/soc/codecs/jz4770.c b/sound/soc/codecs/jz4770.c
index 298689a07..5a24471a5 100644
--- a/sound/soc/codecs/jz4770.c
+++ b/sound/soc/codecs/jz4770.c
@@ -900,11 +900,8 @@ static int jz4770_codec_probe(struct 
platform_device *pdev)

codec->dev = dev;

codec->base = devm_platform_ioremap_resource(pdev, 0);
-   if (IS_ERR(codec->base)) {
-   ret = PTR_ERR(codec->base);
-   dev_err(dev, "Failed to ioremap mmio memory: %d\n", ret);
-   return ret;
-   }
+   if (IS_ERR(codec->base))
+   return PTR_ERR(codec->base);

codec->regmap = devm_regmap_init(dev, NULL, codec,
_codec_regmap_config);
--
2.20.1.windows.1








Re: [PATCH] clk: Fix doc of clk_get_parent

2021-03-07 Thread Paul Cercueil

Hi,

Le dim. 7 mars 2021 à 14:27, Russell King - ARM Linux admin 
 a écrit :

On Sun, Mar 07, 2021 at 02:06:26PM +, Paul Cercueil wrote:
 On error, or when the passed parameter is NULL, the return value is 
NULL

 and not a PTR_ERR()-encoded value.


No, the documentation is accurate. The CCF is just an implementation
of the API, the file you are modifying is the definitive API
documentation.


Well, then the code has to be fixed, because right now it returns NULL 
on error, since the 2.6 days.


Cheers,
-Paul




  1   2   3   4   5   6   7   8   9   10   >