* [PATCH 5/6] dt-bindings: pinctrl: Add X1500 bindings.
From: Zhou Yanjie @ 2019-07-14 3:53 UTC (permalink / raw)
To: linux-mips
Cc: linux-kernel, linux-gpio, devicetree, paul.burton, linus.walleij,
robh+dt, mark.rutland
In-Reply-To: <1563076436-5338-1-git-send-email-zhouyanjie@zoho.com>
Add the pinctrl bindings for the X1500 Soc from Ingenic.
Signed-off-by: Zhou Yanjie <zhouyanjie@zoho.com>
---
Documentation/devicetree/bindings/pinctrl/ingenic,pinctrl.txt | 1 +
1 file changed, 1 insertion(+)
diff --git a/Documentation/devicetree/bindings/pinctrl/ingenic,pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/ingenic,pinctrl.txt
index 7e2ee46..0014d98 100644
--- a/Documentation/devicetree/bindings/pinctrl/ingenic,pinctrl.txt
+++ b/Documentation/devicetree/bindings/pinctrl/ingenic,pinctrl.txt
@@ -27,6 +27,7 @@ Required properties:
- "ingenic,jz4780-pinctrl"
- "ingenic,x1000-pinctrl"
- "ingenic,x1000e-pinctrl"
+ - "ingenic,x1500-pinctrl"
- reg: Address range of the pinctrl registers.
--
2.7.4
^ permalink raw reply related
* [PATCH 4/6] pinctrl: Ingenic: Add pinctrl driver for X1000 and X1000E.
From: Zhou Yanjie @ 2019-07-14 3:53 UTC (permalink / raw)
To: linux-mips
Cc: linux-kernel, linux-gpio, devicetree, paul.burton, linus.walleij,
robh+dt, mark.rutland
In-Reply-To: <1563076436-5338-1-git-send-email-zhouyanjie@zoho.com>
Add support for probing the pinctrl-ingenic driver on the
X1000 Soc and the X1000E Soc from Ingenic.
Signed-off-by: Zhou Yanjie <zhouyanjie@zoho.com>
---
drivers/pinctrl/pinctrl-ingenic.c | 307 ++++++++++++++++++++++++++++++++++++--
1 file changed, 296 insertions(+), 11 deletions(-)
diff --git a/drivers/pinctrl/pinctrl-ingenic.c b/drivers/pinctrl/pinctrl-ingenic.c
index ec61b083..5bb4ae5 100644
--- a/drivers/pinctrl/pinctrl-ingenic.c
+++ b/drivers/pinctrl/pinctrl-ingenic.c
@@ -41,6 +41,9 @@
#define JZ4760_GPIO_FLAG 0x50
#define JZ4760_GPIO_PEN 0x70
+#define X1000_GPIO_PZ_BASE 0x700
+#define X1000_GPIO_PZ_GID2LD 0x7f0
+
#define REG_SET(x) ((x) + 0x4)
#define REG_CLEAR(x) ((x) + 0x8)
@@ -53,6 +56,8 @@ enum jz_version {
ID_JZ4760B,
ID_JZ4770,
ID_JZ4780,
+ ID_X1000,
+ ID_X1000E,
};
struct ingenic_chip_info {
@@ -1009,6 +1014,210 @@ static const struct ingenic_chip_info jz4780_chip_info = {
.pull_downs = jz4770_pull_downs,
};
+static const u32 x1000_pull_ups[4] = {
+ 0xffffffff, 0x8dffffff, 0x7d3fffff, 0xffffffff,
+};
+
+static const u32 x1000_pull_downs[4] = {
+ 0x00000000, 0x02000000, 0x02000000, 0x00000000,
+};
+
+static int x1000_uart0_data_pins[] = { 0x4a, 0x4b, };
+static int x1000_uart0_hwflow_pins[] = { 0x4c, 0x4d, };
+static int x1000_uart1_data_a_pins[] = { 0x04, 0x05, };
+static int x1000_uart1_data_d_pins[] = { 0x62, 0x63, };
+static int x1000_uart1_hwflow_d_pins[] = { 0x64, 0x65, };
+static int x1000_uart2_data_a_pins[] = { 0x02, 0x03, };
+static int x1000_uart2_data_d_pins[] = { 0x65, 0x64, };
+static int x1000_mmc0_1bit_pins[] = { 0x18, 0x19, 0x17, };
+static int x1000_mmc0_4bit_pins[] = { 0x16, 0x15, 0x14, };
+static int x1000_mmc0_8bit_pins[] = { 0x13, 0x12, 0x11, 0x10, };
+static int x1000_mmc1_1bit_pins[] = { 0x40, 0x41, 0x42, };
+static int x1000_mmc1_4bit_pins[] = { 0x43, 0x44, 0x45, };
+static int x1000_nemc_8bit_data_pins[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+};
+static int x1000_nemc_16bit_data_pins[] = {
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+};
+static int x1000_nemc_addr_pins[] = {
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+};
+static int x1000_nemc_rd_we_pins[] = { 0x30, 0x31, };
+static int x1000_nemc_wait_pins[] = { 0x34, };
+static int x1000_nemc_cs1_pins[] = { 0x32, };
+static int x1000_nemc_cs2_pins[] = { 0x33, };
+static int x1000_i2c0_pins[] = { 0x38, 0x37, };
+static int x1000_i2c1_a_pins[] = { 0x01, 0x00, };
+static int x1000_i2c1_c_pins[] = { 0x5b, 0x5a, };
+static int x1000_i2c2_pins[] = { 0x61, 0x60, };
+static int x1000_cim_pins[] = {
+ 0x08, 0x09, 0x0a, 0x0b,
+ 0x13, 0x12, 0x11, 0x10, 0x0f, 0x0e, 0x0d, 0x0c,
+};
+static int x1000_lcd_8bit_pins[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x30, 0x31, 0x32, 0x33, 0x34,
+};
+static int x1000_lcd_16bit_pins[] = {
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+};
+static int x1000_pwm_pwm0_pins[] = { 0x59, };
+static int x1000_pwm_pwm1_pins[] = { 0x5a, };
+static int x1000_pwm_pwm2_pins[] = { 0x5b, };
+static int x1000_pwm_pwm3_pins[] = { 0x26, };
+static int x1000_pwm_pwm4_pins[] = { 0x58, };
+static int x1000_mac_pins[] = {
+ 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x26,
+};
+
+static int x1000_uart0_data_funcs[] = { 0, 0, };
+static int x1000_uart0_hwflow_funcs[] = { 0, 0, };
+static int x1000_uart1_data_a_funcs[] = { 2, 2, };
+static int x1000_uart1_data_d_funcs[] = { 1, 1, };
+static int x1000_uart1_hwflow_d_funcs[] = { 1, 1, };
+static int x1000_uart2_data_a_funcs[] = { 2, 2, };
+static int x1000_uart2_data_d_funcs[] = { 0, 0, };
+static int x1000_mmc0_1bit_funcs[] = { 1, 1, 1, };
+static int x1000_mmc0_4bit_funcs[] = { 1, 1, 1, };
+static int x1000_mmc0_8bit_funcs[] = { 1, 1, 1, 1, 1, };
+static int x1000_mmc1_1bit_funcs[] = { 0, 0, 0, };
+static int x1000_mmc1_4bit_funcs[] = { 0, 0, 0, };
+static int x1000_nemc_8bit_data_funcs[] = { 0, 0, 0, 0, 0, 0, 0, 0, };
+static int x1000_nemc_16bit_data_funcs[] = { 0, 0, 0, 0, 0, 0, 0, 0, };
+static int x1000_nemc_addr_funcs[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+};
+static int x1000_nemc_rd_we_funcs[] = { 0, 0, };
+static int x1000_nemc_wait_funcs[] = { 0, };
+static int x1000_nemc_cs1_funcs[] = { 0, };
+static int x1000_nemc_cs2_funcs[] = { 0, };
+static int x1000_i2c0_funcs[] = { 0, 0, };
+static int x1000_i2c1_a_funcs[] = { 2, 2, };
+static int x1000_i2c1_c_funcs[] = { 0, 0, };
+static int x1000_i2c2_funcs[] = { 1, 1, };
+static int x1000_cim_funcs[] = { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, };
+static int x1000_lcd_8bit_funcs[] = {
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+};
+static int x1000_lcd_16bit_funcs[] = { 1, 1, 1, 1, 1, 1, 1, 1, };
+static int x1000_pwm_pwm0_funcs[] = { 0, };
+static int x1000_pwm_pwm1_funcs[] = { 1, };
+static int x1000_pwm_pwm2_funcs[] = { 1, };
+static int x1000_pwm_pwm3_funcs[] = { 2, };
+static int x1000_pwm_pwm4_funcs[] = { 0, };
+static int x1000_mac_funcs[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, };
+
+static const struct group_desc x1000_groups[] = {
+ INGENIC_PIN_GROUP("uart0-data", x1000_uart0_data),
+ INGENIC_PIN_GROUP("uart0-hwflow", x1000_uart0_hwflow),
+ INGENIC_PIN_GROUP("uart1-data-a", x1000_uart1_data_a),
+ INGENIC_PIN_GROUP("uart1-data-d", x1000_uart1_data_d),
+ INGENIC_PIN_GROUP("uart1-hwflow-d", x1000_uart1_hwflow_d),
+ INGENIC_PIN_GROUP("uart2-data-a", x1000_uart2_data_a),
+ INGENIC_PIN_GROUP("uart2-data-d", x1000_uart2_data_d),
+ INGENIC_PIN_GROUP("mmc0-1bit", x1000_mmc0_1bit),
+ INGENIC_PIN_GROUP("mmc0-4bit", x1000_mmc0_4bit),
+ INGENIC_PIN_GROUP("mmc0-8bit", x1000_mmc0_8bit),
+ INGENIC_PIN_GROUP("mmc1-1bit", x1000_mmc1_1bit),
+ INGENIC_PIN_GROUP("mmc1-4bit", x1000_mmc1_4bit),
+ INGENIC_PIN_GROUP("nemc-8bit-data", x1000_nemc_8bit_data),
+ INGENIC_PIN_GROUP("nemc-16bit-data", x1000_nemc_16bit_data),
+ INGENIC_PIN_GROUP("nemc-addr", x1000_nemc_addr),
+ INGENIC_PIN_GROUP("nemc-rd-we", x1000_nemc_rd_we),
+ INGENIC_PIN_GROUP("nemc-wait", x1000_nemc_wait),
+ INGENIC_PIN_GROUP("nemc-cs1", x1000_nemc_cs1),
+ INGENIC_PIN_GROUP("nemc-cs2", x1000_nemc_cs2),
+ INGENIC_PIN_GROUP("i2c0-data", x1000_i2c0),
+ INGENIC_PIN_GROUP("i2c1-data-a", x1000_i2c1_a),
+ INGENIC_PIN_GROUP("i2c1-data-c", x1000_i2c1_c),
+ INGENIC_PIN_GROUP("i2c2-data", x1000_i2c2),
+ INGENIC_PIN_GROUP("cim-data", x1000_cim),
+ INGENIC_PIN_GROUP("lcd-8bit", x1000_lcd_8bit),
+ INGENIC_PIN_GROUP("lcd-16bit", x1000_lcd_16bit),
+ { "lcd-no-pins", },
+ INGENIC_PIN_GROUP("pwm0", x1000_pwm_pwm0),
+ INGENIC_PIN_GROUP("pwm1", x1000_pwm_pwm1),
+ INGENIC_PIN_GROUP("pwm2", x1000_pwm_pwm2),
+ INGENIC_PIN_GROUP("pwm3", x1000_pwm_pwm3),
+ INGENIC_PIN_GROUP("pwm4", x1000_pwm_pwm4),
+ INGENIC_PIN_GROUP("mac", x1000_mac),
+};
+
+static const char *x1000_uart0_groups[] = { "uart0-data", "uart0-hwflow", };
+static const char *x1000_uart1_groups[] = {
+ "uart1-data-a", "uart1-data-d", "uart1-hwflow-d",
+};
+static const char *x1000_uart2_groups[] = { "uart2-data-a", "uart2-data-d", };
+static const char *x1000_mmc0_groups[] = {
+ "mmc0-1bit", "mmc0-4bit", "mmc0-8bit",
+};
+static const char *x1000_mmc1_groups[] = {
+ "mmc1-1bit-e", "mmc1-4bit-e",
+};
+static const char *x1000_nemc_groups[] = {
+ "nemc-8bit-data", "nemc-16bit-data",
+ "nemc-addr", "nemc-rd-we", "nemc-wait",
+};
+static const char *x1000_cs1_groups[] = { "nemc-cs1", };
+static const char *x1000_cs2_groups[] = { "nemc-cs2", };
+static const char *x1000_i2c0_groups[] = { "i2c0-data", };
+static const char *x1000_i2c1_groups[] = { "i2c1-data-a", "i2c1-data-c", };
+static const char *x1000_i2c2_groups[] = { "i2c2-data", };
+static const char *x1000_cim_groups[] = { "cim-data", };
+static const char *x1000_lcd_groups[] = {
+ "lcd-8bit", "lcd-16bit", "lcd-no-pins",
+};
+static const char *x1000_pwm0_groups[] = { "pwm0", };
+static const char *x1000_pwm1_groups[] = { "pwm1", };
+static const char *x1000_pwm2_groups[] = { "pwm2", };
+static const char *x1000_pwm3_groups[] = { "pwm3", };
+static const char *x1000_pwm4_groups[] = { "pwm4", };
+static const char *x1000_mac_groups[] = { "mac", };
+
+static const struct function_desc x1000_functions[] = {
+ { "uart0", x1000_uart0_groups, ARRAY_SIZE(x1000_uart0_groups), },
+ { "uart1", x1000_uart1_groups, ARRAY_SIZE(x1000_uart1_groups), },
+ { "uart2", x1000_uart2_groups, ARRAY_SIZE(x1000_uart2_groups), },
+ { "mmc0", x1000_mmc0_groups, ARRAY_SIZE(x1000_mmc0_groups), },
+ { "mmc1", x1000_mmc1_groups, ARRAY_SIZE(x1000_mmc1_groups), },
+ { "nemc", x1000_nemc_groups, ARRAY_SIZE(x1000_nemc_groups), },
+ { "nemc-cs1", x1000_cs1_groups, ARRAY_SIZE(x1000_cs1_groups), },
+ { "nemc-cs2", x1000_cs2_groups, ARRAY_SIZE(x1000_cs2_groups), },
+ { "i2c0", x1000_i2c0_groups, ARRAY_SIZE(x1000_i2c0_groups), },
+ { "i2c1", x1000_i2c1_groups, ARRAY_SIZE(x1000_i2c1_groups), },
+ { "i2c2", x1000_i2c2_groups, ARRAY_SIZE(x1000_i2c2_groups), },
+ { "cim", x1000_cim_groups, ARRAY_SIZE(x1000_cim_groups), },
+ { "lcd", x1000_lcd_groups, ARRAY_SIZE(x1000_lcd_groups), },
+ { "pwm0", x1000_pwm0_groups, ARRAY_SIZE(x1000_pwm0_groups), },
+ { "pwm1", x1000_pwm1_groups, ARRAY_SIZE(x1000_pwm1_groups), },
+ { "pwm2", x1000_pwm2_groups, ARRAY_SIZE(x1000_pwm2_groups), },
+ { "pwm3", x1000_pwm3_groups, ARRAY_SIZE(x1000_pwm3_groups), },
+ { "pwm4", x1000_pwm4_groups, ARRAY_SIZE(x1000_pwm4_groups), },
+ { "mac", x1000_mac_groups, ARRAY_SIZE(x1000_mac_groups), },
+};
+
+static const struct ingenic_chip_info x1000_chip_info = {
+ .num_chips = 4,
+ .groups = x1000_groups,
+ .num_groups = ARRAY_SIZE(x1000_groups),
+ .functions = x1000_functions,
+ .num_functions = ARRAY_SIZE(x1000_functions),
+ .pull_ups = x1000_pull_ups,
+ .pull_downs = x1000_pull_downs,
+};
+
+static const struct ingenic_chip_info x1000e_chip_info = {
+ .num_chips = 4,
+ .groups = x1000_groups,
+ .num_groups = ARRAY_SIZE(x1000_groups),
+ .functions = x1000_functions,
+ .num_functions = ARRAY_SIZE(x1000_functions),
+ .pull_ups = x1000_pull_ups,
+ .pull_downs = x1000_pull_downs,
+};
+
static u32 ingenic_gpio_read_reg(struct ingenic_gpio_chip *jzgc, u8 reg)
{
unsigned int val;
@@ -1029,6 +1238,23 @@ static void ingenic_gpio_set_bit(struct ingenic_gpio_chip *jzgc,
regmap_write(jzgc->jzpc->map, jzgc->reg_base + reg, BIT(offset));
}
+static void ingenic_gpio_shadow_set_bit(struct ingenic_gpio_chip *jzgc,
+ u8 reg, u8 offset, bool set)
+{
+ if (set)
+ reg = REG_SET(reg);
+ else
+ reg = REG_CLEAR(reg);
+
+ regmap_write(jzgc->jzpc->map, X1000_GPIO_PZ_BASE + reg, BIT(offset));
+}
+
+static void ingenic_gpio_shadow_set_bit_load(struct ingenic_gpio_chip *jzgc)
+{
+ regmap_write(jzgc->jzpc->map, X1000_GPIO_PZ_GID2LD,
+ jzgc->gc.base / PINS_PER_GPIO_CHIP);
+}
+
static inline bool ingenic_gpio_get_value(struct ingenic_gpio_chip *jzgc,
u8 offset)
{
@@ -1061,21 +1287,45 @@ static void irq_set_type(struct ingenic_gpio_chip *jzgc,
switch (type) {
case IRQ_TYPE_EDGE_RISING:
- ingenic_gpio_set_bit(jzgc, reg2, offset, true);
- ingenic_gpio_set_bit(jzgc, reg1, offset, true);
+ if (jzgc->jzpc->version >= ID_X1000) {
+ ingenic_gpio_shadow_set_bit(jzgc, reg2, offset, true);
+ ingenic_gpio_shadow_set_bit(jzgc, reg1, offset, true);
+ ingenic_gpio_shadow_set_bit_load(jzgc);
+ } else {
+ ingenic_gpio_set_bit(jzgc, reg2, offset, true);
+ ingenic_gpio_set_bit(jzgc, reg1, offset, true);
+ }
break;
case IRQ_TYPE_EDGE_FALLING:
- ingenic_gpio_set_bit(jzgc, reg2, offset, false);
- ingenic_gpio_set_bit(jzgc, reg1, offset, true);
+ if (jzgc->jzpc->version >= ID_X1000) {
+ ingenic_gpio_shadow_set_bit(jzgc, reg2, offset, false);
+ ingenic_gpio_shadow_set_bit(jzgc, reg1, offset, true);
+ ingenic_gpio_shadow_set_bit_load(jzgc);
+ } else {
+ ingenic_gpio_set_bit(jzgc, reg2, offset, false);
+ ingenic_gpio_set_bit(jzgc, reg1, offset, true);
+ }
break;
case IRQ_TYPE_LEVEL_HIGH:
- ingenic_gpio_set_bit(jzgc, reg2, offset, true);
- ingenic_gpio_set_bit(jzgc, reg1, offset, false);
+ if (jzgc->jzpc->version >= ID_X1000) {
+ ingenic_gpio_shadow_set_bit(jzgc, reg2, offset, true);
+ ingenic_gpio_shadow_set_bit(jzgc, reg1, offset, false);
+ ingenic_gpio_shadow_set_bit_load(jzgc);
+ } else {
+ ingenic_gpio_set_bit(jzgc, reg2, offset, true);
+ ingenic_gpio_set_bit(jzgc, reg1, offset, false);
+ }
break;
case IRQ_TYPE_LEVEL_LOW:
default:
- ingenic_gpio_set_bit(jzgc, reg2, offset, false);
- ingenic_gpio_set_bit(jzgc, reg1, offset, false);
+ if (jzgc->jzpc->version >= ID_X1000) {
+ ingenic_gpio_shadow_set_bit(jzgc, reg2, offset, false);
+ ingenic_gpio_shadow_set_bit(jzgc, reg1, offset, false);
+ ingenic_gpio_shadow_set_bit_load(jzgc);
+ } else {
+ ingenic_gpio_set_bit(jzgc, reg2, offset, false);
+ ingenic_gpio_set_bit(jzgc, reg1, offset, false);
+ }
break;
}
}
@@ -1248,6 +1498,21 @@ static inline void ingenic_config_pin(struct ingenic_pinctrl *jzpc,
(set ? REG_SET(reg) : REG_CLEAR(reg)), BIT(idx));
}
+static inline void ingenic_shadow_config_pin(struct ingenic_pinctrl *jzpc,
+ unsigned int pin, u8 reg, bool set)
+{
+ unsigned int idx = pin % PINS_PER_GPIO_CHIP;
+
+ regmap_write(jzpc->map, X1000_GPIO_PZ_BASE +
+ (set ? REG_SET(reg) : REG_CLEAR(reg)), BIT(idx));
+}
+
+static inline void ingenic_shadow_config_pin_load(struct ingenic_pinctrl *jzpc,
+ unsigned int pin)
+{
+ regmap_write(jzpc->map, X1000_GPIO_PZ_GID2LD, pin / PINS_PER_GPIO_CHIP);
+}
+
static inline bool ingenic_get_pin_config(struct ingenic_pinctrl *jzpc,
unsigned int pin, u8 reg)
{
@@ -1292,7 +1557,13 @@ static int ingenic_pinmux_set_pin_fn(struct ingenic_pinctrl *jzpc,
dev_dbg(jzpc->dev, "set pin P%c%u to function %u\n",
'A' + offt, idx, func);
- if (jzpc->version >= ID_JZ4760) {
+ if (jzpc->version >= ID_X1000) {
+ ingenic_shadow_config_pin(jzpc, pin, JZ4760_GPIO_INT, false);
+ ingenic_shadow_config_pin(jzpc, pin, GPIO_MSK, false);
+ ingenic_shadow_config_pin(jzpc, pin, JZ4760_GPIO_PAT1, func & 0x2);
+ ingenic_shadow_config_pin(jzpc, pin, JZ4760_GPIO_PAT0, func & 0x1);
+ ingenic_shadow_config_pin_load(jzpc, pin);
+ } else if (jzpc->version >= ID_JZ4760) {
ingenic_config_pin(jzpc, pin, JZ4760_GPIO_INT, false);
ingenic_config_pin(jzpc, pin, GPIO_MSK, false);
ingenic_config_pin(jzpc, pin, JZ4760_GPIO_PAT1, func & 0x2);
@@ -1345,7 +1616,12 @@ static int ingenic_pinmux_gpio_set_direction(struct pinctrl_dev *pctldev,
dev_dbg(pctldev->dev, "set pin P%c%u to %sput\n",
'A' + offt, idx, input ? "in" : "out");
- if (jzpc->version >= ID_JZ4760) {
+ if (jzpc->version >= ID_X1000) {
+ ingenic_shadow_config_pin(jzpc, pin, JZ4760_GPIO_INT, false);
+ ingenic_shadow_config_pin(jzpc, pin, GPIO_MSK, true);
+ ingenic_shadow_config_pin(jzpc, pin, JZ4760_GPIO_PAT1, input);
+ ingenic_shadow_config_pin_load(jzpc, pin);
+ } else if (jzpc->version >= ID_JZ4760) {
ingenic_config_pin(jzpc, pin, JZ4760_GPIO_INT, false);
ingenic_config_pin(jzpc, pin, GPIO_MSK, true);
ingenic_config_pin(jzpc, pin, JZ4760_GPIO_PAT1, input);
@@ -1532,6 +1808,8 @@ static const struct of_device_id ingenic_pinctrl_of_match[] = {
{ .compatible = "ingenic,jz4760b-pinctrl", .data = (void *) ID_JZ4760B },
{ .compatible = "ingenic,jz4770-pinctrl", .data = (void *) ID_JZ4770 },
{ .compatible = "ingenic,jz4780-pinctrl", .data = (void *) ID_JZ4780 },
+ { .compatible = "ingenic,x1000-pinctrl", .data = (void *) ID_X1000 },
+ { .compatible = "ingenic,x1000e-pinctrl", .data = (void *) ID_X1000E },
{},
};
@@ -1540,6 +1818,7 @@ static const struct of_device_id ingenic_gpio_of_match[] __initconst = {
{ .compatible = "ingenic,jz4760-gpio", },
{ .compatible = "ingenic,jz4770-gpio", },
{ .compatible = "ingenic,jz4780-gpio", },
+ { .compatible = "ingenic,x1000-gpio", },
{},
};
@@ -1655,7 +1934,11 @@ static int __init ingenic_pinctrl_probe(struct platform_device *pdev)
else
jzpc->version = (enum jz_version)id->driver_data;
- if (jzpc->version >= ID_JZ4780)
+ if (jzpc->version >= ID_X1000E)
+ chip_info = &x1000e_chip_info;
+ else if (jzpc->version >= ID_X1000)
+ chip_info = &x1000_chip_info;
+ else if (jzpc->version >= ID_JZ4780)
chip_info = &jz4780_chip_info;
else if (jzpc->version >= ID_JZ4770)
chip_info = &jz4770_chip_info;
@@ -1743,6 +2026,8 @@ static const struct platform_device_id ingenic_pinctrl_ids[] = {
{ "jz4760b-pinctrl", ID_JZ4760B },
{ "jz4770-pinctrl", ID_JZ4770 },
{ "jz4780-pinctrl", ID_JZ4780 },
+ { "x1000-pinctrl", ID_X1000 },
+ { "x1000e-pinctrl", ID_X1000E },
{},
};
--
2.7.4
^ permalink raw reply related
* [PATCH 3/6] dt-bindings: pinctrl: Add X1000 and X1000E bindings.
From: Zhou Yanjie @ 2019-07-14 3:53 UTC (permalink / raw)
To: linux-mips
Cc: linux-kernel, linux-gpio, devicetree, paul.burton, linus.walleij,
robh+dt, mark.rutland
In-Reply-To: <1563076436-5338-1-git-send-email-zhouyanjie@zoho.com>
Add the pinctrl bindings for the X1000 Soc and
the X1000E Soc from Ingenic.
Signed-off-by: Zhou Yanjie <zhouyanjie@zoho.com>
---
.../devicetree/bindings/pinctrl/ingenic,pinctrl.txt | 13 ++++++++-----
1 file changed, 8 insertions(+), 5 deletions(-)
diff --git a/Documentation/devicetree/bindings/pinctrl/ingenic,pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/ingenic,pinctrl.txt
index a80ff68..7e2ee46 100644
--- a/Documentation/devicetree/bindings/pinctrl/ingenic,pinctrl.txt
+++ b/Documentation/devicetree/bindings/pinctrl/ingenic,pinctrl.txt
@@ -1,18 +1,18 @@
-Ingenic jz47xx pin controller
+Ingenic XBurst pin controller
Please refer to pinctrl-bindings.txt in this directory for details of the
common pinctrl bindings used by client devices, including the meaning of the
phrase "pin configuration node".
-For the jz47xx SoCs, pin control is tightly bound with GPIO ports. All pins may
+For the XBurst SoCs, pin control is tightly bound with GPIO ports. All pins may
be used as GPIOs, multiplexed device functions are configured within the
GPIO port configuration registers and it is typical to refer to pins using the
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 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.
+PB31 is the last pin in GPIO port B. The jz4740 and the x1000 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.
Required properties:
@@ -25,6 +25,8 @@ Required properties:
- "ingenic,jz4760b-pinctrl"
- "ingenic,jz4770-pinctrl"
- "ingenic,jz4780-pinctrl"
+ - "ingenic,x1000-pinctrl"
+ - "ingenic,x1000e-pinctrl"
- reg: Address range of the pinctrl registers.
@@ -36,6 +38,7 @@ Required properties for sub-nodes (GPIO chips):
- "ingenic,jz4760-gpio"
- "ingenic,jz4770-gpio"
- "ingenic,jz4780-gpio"
+ - "ingenic,x1000-gpio"
- reg: The GPIO bank number.
- interrupt-controller: Marks the device node as an interrupt controller.
- interrupts: Interrupt specifier for the controllers interrupt.
--
2.7.4
^ permalink raw reply related
* [PATCH 2/6] pinctrl: Ingenic: Add pinctrl driver for JZ4760 and JZ4760B.
From: Zhou Yanjie @ 2019-07-14 3:53 UTC (permalink / raw)
To: linux-mips
Cc: linux-kernel, linux-gpio, devicetree, paul.burton, linus.walleij,
robh+dt, mark.rutland
In-Reply-To: <1563076436-5338-1-git-send-email-zhouyanjie@zoho.com>
Add support for probing the pinctrl-ingenic driver on the
JZ4760 Soc and the JZ4760B Soc from Ingenic.
Signed-off-by: Zhou Yanjie <zhouyanjie@zoho.com>
---
drivers/pinctrl/pinctrl-ingenic.c | 336 ++++++++++++++++++++++++++++++++++----
1 file changed, 305 insertions(+), 31 deletions(-)
diff --git a/drivers/pinctrl/pinctrl-ingenic.c b/drivers/pinctrl/pinctrl-ingenic.c
index c8ef3b9..ec61b083 100644
--- a/drivers/pinctrl/pinctrl-ingenic.c
+++ b/drivers/pinctrl/pinctrl-ingenic.c
@@ -35,11 +35,11 @@
#define JZ4740_GPIO_TRIG 0x70
#define JZ4740_GPIO_FLAG 0x80
-#define JZ4770_GPIO_INT 0x10
-#define JZ4770_GPIO_PAT1 0x30
-#define JZ4770_GPIO_PAT0 0x40
-#define JZ4770_GPIO_FLAG 0x50
-#define JZ4770_GPIO_PEN 0x70
+#define JZ4760_GPIO_INT 0x10
+#define JZ4760_GPIO_PAT1 0x30
+#define JZ4760_GPIO_PAT0 0x40
+#define JZ4760_GPIO_FLAG 0x50
+#define JZ4760_GPIO_PEN 0x70
#define REG_SET(x) ((x) + 0x4)
#define REG_CLEAR(x) ((x) + 0x8)
@@ -49,6 +49,8 @@
enum jz_version {
ID_JZ4740,
ID_JZ4725B,
+ ID_JZ4760,
+ ID_JZ4760B,
ID_JZ4770,
ID_JZ4780,
};
@@ -338,6 +340,269 @@ static const struct ingenic_chip_info jz4725b_chip_info = {
.pull_downs = jz4740_pull_downs,
};
+static const u32 jz4760_pull_ups[6] = {
+ 0xffffffff, 0xfffcf3ff, 0xffffffff, 0xffffcfff, 0xfffffb7c, 0xfffff00f,
+};
+
+static const u32 jz4760_pull_downs[6] = {
+ 0x00000000, 0x00030c00, 0x00000000, 0x00003000, 0x00000483, 0x00000ff0,
+};
+
+static int jz4760_uart0_data_pins[] = { 0xa0, 0xa3, };
+static int jz4760_uart0_hwflow_pins[] = { 0xa1, 0xa2, };
+static int jz4760_uart1_data_pins[] = { 0x7a, 0x7c, };
+static int jz4760_uart1_hwflow_pins[] = { 0x7b, 0x7d, };
+static int jz4760_uart2_data_pins[] = { 0x5c, 0x5e, };
+static int jz4760_uart2_hwflow_pins[] = { 0x5d, 0x5f, };
+static int jz4760_uart3_data_pins[] = { 0x6c, 0x85, };
+static int jz4760_uart3_hwflow_pins[] = { 0x88, 0x89, };
+static int jz4760_mmc0_1bit_a_pins[] = { 0x12, 0x13, 0x14, };
+static int jz4760_mmc0_4bit_a_pins[] = { 0x15, 0x16, 0x17, };
+static int jz4760_mmc0_1bit_e_pins[] = { 0x9c, 0x9d, 0x94, };
+static int jz4760_mmc0_4bit_e_pins[] = { 0x95, 0x96, 0x97, };
+static int jz4760_mmc0_8bit_e_pins[] = { 0x98, 0x99, 0x9a, 0x9b, };
+static int jz4760_mmc1_1bit_d_pins[] = { 0x78, 0x79, 0x74, };
+static int jz4760_mmc1_4bit_d_pins[] = { 0x75, 0x76, 0x77, };
+static int jz4760_mmc1_1bit_e_pins[] = { 0x9c, 0x9d, 0x94, };
+static int jz4760_mmc1_4bit_e_pins[] = { 0x95, 0x96, 0x97, };
+static int jz4760_mmc1_8bit_e_pins[] = { 0x98, 0x99, 0x9a, 0x9b, };
+static int jz4760_mmc2_1bit_b_pins[] = { 0x3c, 0x3d, 0x34, };
+static int jz4760_mmc2_4bit_b_pins[] = { 0x35, 0x3e, 0x3f, };
+static int jz4760_mmc2_1bit_e_pins[] = { 0x9c, 0x9d, 0x94, };
+static int jz4760_mmc2_4bit_e_pins[] = { 0x95, 0x96, 0x97, };
+static int jz4760_mmc2_8bit_e_pins[] = { 0x98, 0x99, 0x9a, 0x9b, };
+static int jz4760_nemc_8bit_data_pins[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+};
+static int jz4760_nemc_16bit_data_pins[] = {
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+};
+static int jz4760_nemc_cle_ale_pins[] = { 0x20, 0x21, };
+static int jz4760_nemc_addr_pins[] = { 0x22, 0x23, 0x24, 0x25, };
+static int jz4760_nemc_rd_we_pins[] = { 0x10, 0x11, };
+static int jz4760_nemc_frd_fwe_pins[] = { 0x12, 0x13, };
+static int jz4760_nemc_wait_pins[] = { 0x1b, };
+static int jz4760_nemc_cs1_pins[] = { 0x15, };
+static int jz4760_nemc_cs2_pins[] = { 0x16, };
+static int jz4760_nemc_cs3_pins[] = { 0x17, };
+static int jz4760_nemc_cs4_pins[] = { 0x18, };
+static int jz4760_nemc_cs5_pins[] = { 0x19, };
+static int jz4760_nemc_cs6_pins[] = { 0x1a, };
+static int jz4760_i2c0_pins[] = { 0x7e, 0x7f, };
+static int jz4760_i2c1_pins[] = { 0x9e, 0x9f, };
+static int jz4760_cim_pins[] = {
+ 0x26, 0x27, 0x28, 0x29,
+ 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31,
+};
+static int jz4760_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 jz4760_pwm_pwm0_pins[] = { 0x80, };
+static int jz4760_pwm_pwm1_pins[] = { 0x81, };
+static int jz4760_pwm_pwm2_pins[] = { 0x82, };
+static int jz4760_pwm_pwm3_pins[] = { 0x83, };
+static int jz4760_pwm_pwm4_pins[] = { 0x84, };
+static int jz4760_pwm_pwm5_pins[] = { 0x85, };
+static int jz4760_pwm_pwm6_pins[] = { 0x6a, };
+static int jz4760_pwm_pwm7_pins[] = { 0x6b, };
+
+static int jz4760_uart0_data_funcs[] = { 0, 0, };
+static int jz4760_uart0_hwflow_funcs[] = { 0, 0, };
+static int jz4760_uart1_data_funcs[] = { 0, 0, };
+static int jz4760_uart1_hwflow_funcs[] = { 0, 0, };
+static int jz4760_uart2_data_funcs[] = { 0, 0, };
+static int jz4760_uart2_hwflow_funcs[] = { 0, 0, };
+static int jz4760_uart3_data_funcs[] = { 0, 1, };
+static int jz4760_uart3_hwflow_funcs[] = { 0, 0, };
+static int jz4760_mmc0_1bit_a_funcs[] = { 1, 1, 0, };
+static int jz4760_mmc0_4bit_a_funcs[] = { 1, 1, 1, };
+static int jz4760_mmc0_1bit_e_funcs[] = { 0, 0, 0, };
+static int jz4760_mmc0_4bit_e_funcs[] = { 0, 0, 0, };
+static int jz4760_mmc0_8bit_e_funcs[] = { 0, 0, 0, 0, };
+static int jz4760_mmc1_1bit_d_funcs[] = { 0, 0, 0, };
+static int jz4760_mmc1_4bit_d_funcs[] = { 0, 0, 0, };
+static int jz4760_mmc1_1bit_e_funcs[] = { 1, 1, 1, };
+static int jz4760_mmc1_4bit_e_funcs[] = { 1, 1, 1, };
+static int jz4760_mmc1_8bit_e_funcs[] = { 1, 1, 1, 1, };
+static int jz4760_mmc2_1bit_b_funcs[] = { 0, 0, 0, };
+static int jz4760_mmc2_4bit_b_funcs[] = { 0, 0, 0, };
+static int jz4760_mmc2_1bit_e_funcs[] = { 2, 2, 2, };
+static int jz4760_mmc2_4bit_e_funcs[] = { 2, 2, 2, };
+static int jz4760_mmc2_8bit_e_funcs[] = { 2, 2, 2, 2, };
+static int jz4760_nemc_8bit_data_funcs[] = { 0, 0, 0, 0, 0, 0, 0, 0, };
+static int jz4760_nemc_16bit_data_funcs[] = { 0, 0, 0, 0, 0, 0, 0, 0, };
+static int jz4760_nemc_cle_ale_funcs[] = { 0, 0, };
+static int jz4760_nemc_addr_funcs[] = { 0, 0, 0, 0, };
+static int jz4760_nemc_rd_we_funcs[] = { 0, 0, };
+static int jz4760_nemc_frd_fwe_funcs[] = { 0, 0, };
+static int jz4760_nemc_wait_funcs[] = { 0, };
+static int jz4760_nemc_cs1_funcs[] = { 0, };
+static int jz4760_nemc_cs2_funcs[] = { 0, };
+static int jz4760_nemc_cs3_funcs[] = { 0, };
+static int jz4760_nemc_cs4_funcs[] = { 0, };
+static int jz4760_nemc_cs5_funcs[] = { 0, };
+static int jz4760_nemc_cs6_funcs[] = { 0, };
+static int jz4760_i2c0_funcs[] = { 0, 0, };
+static int jz4760_i2c1_funcs[] = { 0, 0, };
+static int jz4760_cim_funcs[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, };
+static int jz4760_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, 0, 0,
+ 0, 0, 0, 0,
+};
+static int jz4760_pwm_pwm0_funcs[] = { 0, };
+static int jz4760_pwm_pwm1_funcs[] = { 0, };
+static int jz4760_pwm_pwm2_funcs[] = { 0, };
+static int jz4760_pwm_pwm3_funcs[] = { 0, };
+static int jz4760_pwm_pwm4_funcs[] = { 0, };
+static int jz4760_pwm_pwm5_funcs[] = { 0, };
+static int jz4760_pwm_pwm6_funcs[] = { 0, };
+static int jz4760_pwm_pwm7_funcs[] = { 0, };
+
+static const struct group_desc jz4760_groups[] = {
+ INGENIC_PIN_GROUP("uart0-data", jz4760_uart0_data),
+ INGENIC_PIN_GROUP("uart0-hwflow", jz4760_uart0_hwflow),
+ INGENIC_PIN_GROUP("uart1-data", jz4760_uart1_data),
+ INGENIC_PIN_GROUP("uart1-hwflow", jz4760_uart1_hwflow),
+ INGENIC_PIN_GROUP("uart2-data", jz4760_uart2_data),
+ INGENIC_PIN_GROUP("uart2-hwflow", jz4760_uart2_hwflow),
+ INGENIC_PIN_GROUP("uart3-data", jz4760_uart3_data),
+ INGENIC_PIN_GROUP("uart3-hwflow", jz4760_uart3_hwflow),
+ INGENIC_PIN_GROUP("mmc0-1bit-a", jz4760_mmc0_1bit_a),
+ INGENIC_PIN_GROUP("mmc0-4bit-a", jz4760_mmc0_4bit_a),
+ INGENIC_PIN_GROUP("mmc0-1bit-e", jz4760_mmc0_1bit_e),
+ INGENIC_PIN_GROUP("mmc0-4bit-e", jz4760_mmc0_4bit_e),
+ INGENIC_PIN_GROUP("mmc0-8bit-e", jz4760_mmc0_8bit_e),
+ INGENIC_PIN_GROUP("mmc1-1bit-d", jz4760_mmc1_1bit_d),
+ INGENIC_PIN_GROUP("mmc1-4bit-d", jz4760_mmc1_4bit_d),
+ INGENIC_PIN_GROUP("mmc1-1bit-e", jz4760_mmc1_1bit_e),
+ INGENIC_PIN_GROUP("mmc1-4bit-e", jz4760_mmc1_4bit_e),
+ INGENIC_PIN_GROUP("mmc1-8bit-e", jz4760_mmc1_8bit_e),
+ INGENIC_PIN_GROUP("mmc2-1bit-b", jz4760_mmc2_1bit_b),
+ INGENIC_PIN_GROUP("mmc2-4bit-b", jz4760_mmc2_4bit_b),
+ INGENIC_PIN_GROUP("mmc2-1bit-e", jz4760_mmc2_1bit_e),
+ INGENIC_PIN_GROUP("mmc2-4bit-e", jz4760_mmc2_4bit_e),
+ INGENIC_PIN_GROUP("mmc2-8bit-e", jz4760_mmc2_8bit_e),
+ INGENIC_PIN_GROUP("nemc-8bit-data", jz4760_nemc_8bit_data),
+ INGENIC_PIN_GROUP("nemc-16bit-data", jz4760_nemc_16bit_data),
+ INGENIC_PIN_GROUP("nemc-cle-ale", jz4760_nemc_cle_ale),
+ INGENIC_PIN_GROUP("nemc-addr", jz4760_nemc_addr),
+ INGENIC_PIN_GROUP("nemc-rd-we", jz4760_nemc_rd_we),
+ INGENIC_PIN_GROUP("nemc-frd-fwe", jz4760_nemc_frd_fwe),
+ INGENIC_PIN_GROUP("nemc-wait", jz4760_nemc_wait),
+ INGENIC_PIN_GROUP("nemc-cs1", jz4760_nemc_cs1),
+ INGENIC_PIN_GROUP("nemc-cs2", jz4760_nemc_cs2),
+ INGENIC_PIN_GROUP("nemc-cs3", jz4760_nemc_cs3),
+ INGENIC_PIN_GROUP("nemc-cs4", jz4760_nemc_cs4),
+ INGENIC_PIN_GROUP("nemc-cs5", jz4760_nemc_cs5),
+ INGENIC_PIN_GROUP("nemc-cs6", jz4760_nemc_cs6),
+ INGENIC_PIN_GROUP("i2c0-data", jz4760_i2c0),
+ INGENIC_PIN_GROUP("i2c1-data", jz4760_i2c1),
+ INGENIC_PIN_GROUP("cim-data", jz4760_cim),
+ INGENIC_PIN_GROUP("lcd-24bit", jz4760_lcd_24bit),
+ { "lcd-no-pins", },
+ INGENIC_PIN_GROUP("pwm0", jz4760_pwm_pwm0),
+ INGENIC_PIN_GROUP("pwm1", jz4760_pwm_pwm1),
+ INGENIC_PIN_GROUP("pwm2", jz4760_pwm_pwm2),
+ INGENIC_PIN_GROUP("pwm3", jz4760_pwm_pwm3),
+ INGENIC_PIN_GROUP("pwm4", jz4760_pwm_pwm4),
+ INGENIC_PIN_GROUP("pwm5", jz4760_pwm_pwm5),
+ INGENIC_PIN_GROUP("pwm6", jz4760_pwm_pwm6),
+ INGENIC_PIN_GROUP("pwm7", jz4760_pwm_pwm7),
+};
+
+static const char *jz4760_uart0_groups[] = { "uart0-data", "uart0-hwflow", };
+static const char *jz4760_uart1_groups[] = { "uart1-data", "uart1-hwflow", };
+static const char *jz4760_uart2_groups[] = { "uart2-data", "uart2-hwflow", };
+static const char *jz4760_uart3_groups[] = { "uart3-data", "uart3-hwflow", };
+static const char *jz4760_mmc0_groups[] = {
+ "mmc0-1bit-a", "mmc0-4bit-a",
+ "mmc0-1bit-e", "mmc0-4bit-e", "mmc0-8bit-e",
+};
+static const char *jz4760_mmc1_groups[] = {
+ "mmc1-1bit-d", "mmc1-4bit-d",
+ "mmc1-1bit-e", "mmc1-4bit-e", "mmc1-8bit-e",
+};
+static const char *jz4760_mmc2_groups[] = {
+ "mmc2-1bit-b", "mmc2-4bit-b",
+ "mmc2-1bit-e", "mmc2-4bit-e", "mmc2-8bit-e",
+};
+static const char *jz4760_nemc_groups[] = {
+ "nemc-8bit-data", "nemc-16bit-data", "nemc-cle-ale",
+ "nemc-addr", "nemc-rd-we", "nemc-frd-fwe", "nemc-wait",
+};
+static const char *jz4760_cs1_groups[] = { "nemc-cs1", };
+static const char *jz4760_cs2_groups[] = { "nemc-cs2", };
+static const char *jz4760_cs3_groups[] = { "nemc-cs3", };
+static const char *jz4760_cs4_groups[] = { "nemc-cs4", };
+static const char *jz4760_cs5_groups[] = { "nemc-cs5", };
+static const char *jz4760_cs6_groups[] = { "nemc-cs6", };
+static const char *jz4760_i2c0_groups[] = { "i2c0-data", };
+static const char *jz4760_i2c1_groups[] = { "i2c1-data", };
+static const char *jz4760_cim_groups[] = { "cim-data", };
+static const char *jz4760_lcd_groups[] = { "lcd-24bit", "lcd-no-pins", };
+static const char *jz4760_pwm0_groups[] = { "pwm0", };
+static const char *jz4760_pwm1_groups[] = { "pwm1", };
+static const char *jz4760_pwm2_groups[] = { "pwm2", };
+static const char *jz4760_pwm3_groups[] = { "pwm3", };
+static const char *jz4760_pwm4_groups[] = { "pwm4", };
+static const char *jz4760_pwm5_groups[] = { "pwm5", };
+static const char *jz4760_pwm6_groups[] = { "pwm6", };
+static const char *jz4760_pwm7_groups[] = { "pwm7", };
+
+static const struct function_desc jz4760_functions[] = {
+ { "uart0", jz4760_uart0_groups, ARRAY_SIZE(jz4760_uart0_groups), },
+ { "uart1", jz4760_uart1_groups, ARRAY_SIZE(jz4760_uart1_groups), },
+ { "uart2", jz4760_uart2_groups, ARRAY_SIZE(jz4760_uart2_groups), },
+ { "uart3", jz4760_uart3_groups, ARRAY_SIZE(jz4760_uart3_groups), },
+ { "mmc0", jz4760_mmc0_groups, ARRAY_SIZE(jz4760_mmc0_groups), },
+ { "mmc1", jz4760_mmc1_groups, ARRAY_SIZE(jz4760_mmc1_groups), },
+ { "mmc2", jz4760_mmc2_groups, ARRAY_SIZE(jz4760_mmc2_groups), },
+ { "nemc", jz4760_nemc_groups, ARRAY_SIZE(jz4760_nemc_groups), },
+ { "nemc-cs1", jz4760_cs1_groups, ARRAY_SIZE(jz4760_cs1_groups), },
+ { "nemc-cs2", jz4760_cs2_groups, ARRAY_SIZE(jz4760_cs2_groups), },
+ { "nemc-cs3", jz4760_cs3_groups, ARRAY_SIZE(jz4760_cs3_groups), },
+ { "nemc-cs4", jz4760_cs4_groups, ARRAY_SIZE(jz4760_cs4_groups), },
+ { "nemc-cs5", jz4760_cs5_groups, ARRAY_SIZE(jz4760_cs5_groups), },
+ { "nemc-cs6", jz4760_cs6_groups, ARRAY_SIZE(jz4760_cs6_groups), },
+ { "i2c0", jz4760_i2c0_groups, ARRAY_SIZE(jz4760_i2c0_groups), },
+ { "i2c1", jz4760_i2c1_groups, ARRAY_SIZE(jz4760_i2c1_groups), },
+ { "cim", jz4760_cim_groups, ARRAY_SIZE(jz4760_cim_groups), },
+ { "lcd", jz4760_lcd_groups, ARRAY_SIZE(jz4760_lcd_groups), },
+ { "pwm0", jz4760_pwm0_groups, ARRAY_SIZE(jz4760_pwm0_groups), },
+ { "pwm1", jz4760_pwm1_groups, ARRAY_SIZE(jz4760_pwm1_groups), },
+ { "pwm2", jz4760_pwm2_groups, ARRAY_SIZE(jz4760_pwm2_groups), },
+ { "pwm3", jz4760_pwm3_groups, ARRAY_SIZE(jz4760_pwm3_groups), },
+ { "pwm4", jz4760_pwm4_groups, ARRAY_SIZE(jz4760_pwm4_groups), },
+ { "pwm5", jz4760_pwm5_groups, ARRAY_SIZE(jz4760_pwm5_groups), },
+ { "pwm6", jz4760_pwm6_groups, ARRAY_SIZE(jz4760_pwm6_groups), },
+ { "pwm7", jz4760_pwm7_groups, ARRAY_SIZE(jz4760_pwm7_groups), },
+};
+
+static const struct ingenic_chip_info jz4760_chip_info = {
+ .num_chips = 6,
+ .groups = jz4760_groups,
+ .num_groups = ARRAY_SIZE(jz4760_groups),
+ .functions = jz4760_functions,
+ .num_functions = ARRAY_SIZE(jz4760_functions),
+ .pull_ups = jz4760_pull_ups,
+ .pull_downs = jz4760_pull_downs,
+};
+
+static const struct ingenic_chip_info jz4760b_chip_info = {
+ .num_chips = 6,
+ .groups = jz4760_groups,
+ .num_groups = ARRAY_SIZE(jz4760_groups),
+ .functions = jz4760_functions,
+ .num_functions = ARRAY_SIZE(jz4760_functions),
+ .pull_ups = jz4760_pull_ups,
+ .pull_downs = jz4760_pull_downs,
+};
+
static const u32 jz4770_pull_ups[6] = {
0x3fffffff, 0xfff0030c, 0xffffffff, 0xffff4fff, 0xfffffb7c, 0xffa7f00f,
};
@@ -775,8 +1040,8 @@ static inline bool ingenic_gpio_get_value(struct ingenic_gpio_chip *jzgc,
static void ingenic_gpio_set_value(struct ingenic_gpio_chip *jzgc,
u8 offset, int value)
{
- if (jzgc->jzpc->version >= ID_JZ4770)
- ingenic_gpio_set_bit(jzgc, JZ4770_GPIO_PAT0, offset, !!value);
+ if (jzgc->jzpc->version >= ID_JZ4760)
+ ingenic_gpio_set_bit(jzgc, JZ4760_GPIO_PAT0, offset, !!value);
else
ingenic_gpio_set_bit(jzgc, JZ4740_GPIO_DATA, offset, !!value);
}
@@ -786,9 +1051,9 @@ static void irq_set_type(struct ingenic_gpio_chip *jzgc,
{
u8 reg1, reg2;
- if (jzgc->jzpc->version >= ID_JZ4770) {
- reg1 = JZ4770_GPIO_PAT1;
- reg2 = JZ4770_GPIO_PAT0;
+ if (jzgc->jzpc->version >= ID_JZ4760) {
+ reg1 = JZ4760_GPIO_PAT1;
+ reg2 = JZ4760_GPIO_PAT0;
} else {
reg1 = JZ4740_GPIO_TRIG;
reg2 = JZ4740_GPIO_DIR;
@@ -837,8 +1102,8 @@ static void ingenic_gpio_irq_enable(struct irq_data *irqd)
struct ingenic_gpio_chip *jzgc = gpiochip_get_data(gc);
int irq = irqd->hwirq;
- if (jzgc->jzpc->version >= ID_JZ4770)
- ingenic_gpio_set_bit(jzgc, JZ4770_GPIO_INT, irq, true);
+ if (jzgc->jzpc->version >= ID_JZ4760)
+ ingenic_gpio_set_bit(jzgc, JZ4760_GPIO_INT, irq, true);
else
ingenic_gpio_set_bit(jzgc, JZ4740_GPIO_SELECT, irq, true);
@@ -853,8 +1118,8 @@ static void ingenic_gpio_irq_disable(struct irq_data *irqd)
ingenic_gpio_irq_mask(irqd);
- if (jzgc->jzpc->version >= ID_JZ4770)
- ingenic_gpio_set_bit(jzgc, JZ4770_GPIO_INT, irq, false);
+ if (jzgc->jzpc->version >= ID_JZ4760)
+ ingenic_gpio_set_bit(jzgc, JZ4760_GPIO_INT, irq, false);
else
ingenic_gpio_set_bit(jzgc, JZ4740_GPIO_SELECT, irq, false);
}
@@ -878,8 +1143,8 @@ static void ingenic_gpio_irq_ack(struct irq_data *irqd)
irq_set_type(jzgc, irq, IRQ_TYPE_EDGE_RISING);
}
- if (jzgc->jzpc->version >= ID_JZ4770)
- ingenic_gpio_set_bit(jzgc, JZ4770_GPIO_FLAG, irq, false);
+ if (jzgc->jzpc->version >= ID_JZ4760)
+ ingenic_gpio_set_bit(jzgc, JZ4760_GPIO_FLAG, irq, false);
else
ingenic_gpio_set_bit(jzgc, JZ4740_GPIO_DATA, irq, true);
}
@@ -935,8 +1200,8 @@ static void ingenic_gpio_irq_handler(struct irq_desc *desc)
chained_irq_enter(irq_chip, desc);
- if (jzgc->jzpc->version >= ID_JZ4770)
- flag = ingenic_gpio_read_reg(jzgc, JZ4770_GPIO_FLAG);
+ if (jzgc->jzpc->version >= ID_JZ4760)
+ flag = ingenic_gpio_read_reg(jzgc, JZ4760_GPIO_FLAG);
else
flag = ingenic_gpio_read_reg(jzgc, JZ4740_GPIO_FLAG);
@@ -1001,8 +1266,8 @@ static int ingenic_gpio_get_direction(struct gpio_chip *gc, unsigned int offset)
struct ingenic_pinctrl *jzpc = jzgc->jzpc;
unsigned int pin = gc->base + offset;
- if (jzpc->version >= ID_JZ4770)
- return ingenic_get_pin_config(jzpc, pin, JZ4770_GPIO_PAT1);
+ if (jzpc->version >= ID_JZ4760)
+ return ingenic_get_pin_config(jzpc, pin, JZ4760_GPIO_PAT1);
if (ingenic_get_pin_config(jzpc, pin, JZ4740_GPIO_SELECT))
return true;
@@ -1027,11 +1292,11 @@ static int ingenic_pinmux_set_pin_fn(struct ingenic_pinctrl *jzpc,
dev_dbg(jzpc->dev, "set pin P%c%u to function %u\n",
'A' + offt, idx, func);
- if (jzpc->version >= ID_JZ4770) {
- ingenic_config_pin(jzpc, pin, JZ4770_GPIO_INT, false);
+ if (jzpc->version >= ID_JZ4760) {
+ ingenic_config_pin(jzpc, pin, JZ4760_GPIO_INT, false);
ingenic_config_pin(jzpc, pin, GPIO_MSK, false);
- ingenic_config_pin(jzpc, pin, JZ4770_GPIO_PAT1, func & 0x2);
- ingenic_config_pin(jzpc, pin, JZ4770_GPIO_PAT0, func & 0x1);
+ ingenic_config_pin(jzpc, pin, JZ4760_GPIO_PAT1, func & 0x2);
+ ingenic_config_pin(jzpc, pin, JZ4760_GPIO_PAT0, func & 0x1);
} else {
ingenic_config_pin(jzpc, pin, JZ4740_GPIO_FUNC, true);
ingenic_config_pin(jzpc, pin, JZ4740_GPIO_TRIG, func & 0x2);
@@ -1080,10 +1345,10 @@ static int ingenic_pinmux_gpio_set_direction(struct pinctrl_dev *pctldev,
dev_dbg(pctldev->dev, "set pin P%c%u to %sput\n",
'A' + offt, idx, input ? "in" : "out");
- if (jzpc->version >= ID_JZ4770) {
- ingenic_config_pin(jzpc, pin, JZ4770_GPIO_INT, false);
+ if (jzpc->version >= ID_JZ4760) {
+ ingenic_config_pin(jzpc, pin, JZ4760_GPIO_INT, false);
ingenic_config_pin(jzpc, pin, GPIO_MSK, true);
- ingenic_config_pin(jzpc, pin, JZ4770_GPIO_PAT1, input);
+ ingenic_config_pin(jzpc, pin, JZ4760_GPIO_PAT1, input);
} else {
ingenic_config_pin(jzpc, pin, JZ4740_GPIO_SELECT, false);
ingenic_config_pin(jzpc, pin, JZ4740_GPIO_DIR, !input);
@@ -1110,8 +1375,8 @@ static int ingenic_pinconf_get(struct pinctrl_dev *pctldev,
unsigned int offt = pin / PINS_PER_GPIO_CHIP;
bool pull;
- if (jzpc->version >= ID_JZ4770)
- pull = !ingenic_get_pin_config(jzpc, pin, JZ4770_GPIO_PEN);
+ if (jzpc->version >= ID_JZ4760)
+ pull = !ingenic_get_pin_config(jzpc, pin, JZ4760_GPIO_PEN);
else
pull = !ingenic_get_pin_config(jzpc, pin, JZ4740_GPIO_PULL_DIS);
@@ -1142,8 +1407,8 @@ static int ingenic_pinconf_get(struct pinctrl_dev *pctldev,
static void ingenic_set_bias(struct ingenic_pinctrl *jzpc,
unsigned int pin, bool enabled)
{
- if (jzpc->version >= ID_JZ4770)
- ingenic_config_pin(jzpc, pin, JZ4770_GPIO_PEN, !enabled);
+ if (jzpc->version >= ID_JZ4760)
+ ingenic_config_pin(jzpc, pin, JZ4760_GPIO_PEN, !enabled);
else
ingenic_config_pin(jzpc, pin, JZ4740_GPIO_PULL_DIS, !enabled);
}
@@ -1263,6 +1528,8 @@ static const struct regmap_config ingenic_pinctrl_regmap_config = {
static const struct of_device_id ingenic_pinctrl_of_match[] = {
{ .compatible = "ingenic,jz4740-pinctrl", .data = (void *) ID_JZ4740 },
{ .compatible = "ingenic,jz4725b-pinctrl", .data = (void *)ID_JZ4725B },
+ { .compatible = "ingenic,jz4760-pinctrl", .data = (void *) ID_JZ4760 },
+ { .compatible = "ingenic,jz4760b-pinctrl", .data = (void *) ID_JZ4760B },
{ .compatible = "ingenic,jz4770-pinctrl", .data = (void *) ID_JZ4770 },
{ .compatible = "ingenic,jz4780-pinctrl", .data = (void *) ID_JZ4780 },
{},
@@ -1270,6 +1537,7 @@ static const struct of_device_id ingenic_pinctrl_of_match[] = {
static const struct of_device_id ingenic_gpio_of_match[] __initconst = {
{ .compatible = "ingenic,jz4740-gpio", },
+ { .compatible = "ingenic,jz4760-gpio", },
{ .compatible = "ingenic,jz4770-gpio", },
{ .compatible = "ingenic,jz4780-gpio", },
{},
@@ -1391,6 +1659,10 @@ static int __init ingenic_pinctrl_probe(struct platform_device *pdev)
chip_info = &jz4780_chip_info;
else if (jzpc->version >= ID_JZ4770)
chip_info = &jz4770_chip_info;
+ else if (jzpc->version >= ID_JZ4760B)
+ chip_info = &jz4760b_chip_info;
+ else if (jzpc->version >= ID_JZ4760)
+ chip_info = &jz4760_chip_info;
else if (jzpc->version >= ID_JZ4725B)
chip_info = &jz4725b_chip_info;
else
@@ -1467,6 +1739,8 @@ static int __init ingenic_pinctrl_probe(struct platform_device *pdev)
static const struct platform_device_id ingenic_pinctrl_ids[] = {
{ "jz4740-pinctrl", ID_JZ4740 },
{ "jz4725b-pinctrl", ID_JZ4725B },
+ { "jz4760-pinctrl", ID_JZ4760 },
+ { "jz4760b-pinctrl", ID_JZ4760B },
{ "jz4770-pinctrl", ID_JZ4770 },
{ "jz4780-pinctrl", ID_JZ4780 },
{},
--
2.7.4
^ permalink raw reply related
* [PATCH 1/6] dt-bindings: pinctrl: Add JZ4760 and JZ4760B bindings.
From: Zhou Yanjie @ 2019-07-14 3:53 UTC (permalink / raw)
To: linux-mips
Cc: linux-kernel, linux-gpio, devicetree, paul.burton, linus.walleij,
robh+dt, mark.rutland
In-Reply-To: <1563076436-5338-1-git-send-email-zhouyanjie@zoho.com>
Add the pinctrl bindings for the JZ4760 Soc and
the JZ4760B Soc from Ingenic.
Signed-off-by: Zhou Yanjie <zhouyanjie@zoho.com>
---
Documentation/devicetree/bindings/pinctrl/ingenic,pinctrl.txt | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/Documentation/devicetree/bindings/pinctrl/ingenic,pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/ingenic,pinctrl.txt
index af20b0e..a80ff68 100644
--- a/Documentation/devicetree/bindings/pinctrl/ingenic,pinctrl.txt
+++ b/Documentation/devicetree/bindings/pinctrl/ingenic,pinctrl.txt
@@ -11,8 +11,8 @@ 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 contains 4 GPIO ports, PA to
-PD, for a total of 128 pins. The jz4780 contains 6 GPIO ports, PA to PF, for a
-total of 192 pins.
+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.
Required properties:
@@ -21,6 +21,8 @@ Required properties:
- compatible: One of:
- "ingenic,jz4740-pinctrl"
- "ingenic,jz4725b-pinctrl"
+ - "ingenic,jz4760-pinctrl"
+ - "ingenic,jz4760b-pinctrl"
- "ingenic,jz4770-pinctrl"
- "ingenic,jz4780-pinctrl"
- reg: Address range of the pinctrl registers.
@@ -31,6 +33,7 @@ Required properties for sub-nodes (GPIO chips):
- compatible: Must contain one of:
- "ingenic,jz4740-gpio"
+ - "ingenic,jz4760-gpio"
- "ingenic,jz4770-gpio"
- "ingenic,jz4780-gpio"
- reg: The GPIO bank number.
--
2.7.4
^ permalink raw reply related
* Ingenic pinctrl patchs.
From: Zhou Yanjie @ 2019-07-14 3:53 UTC (permalink / raw)
To: linux-mips
Cc: linux-kernel, linux-gpio, devicetree, paul.burton, linus.walleij,
robh+dt, mark.rutland
Add support for Ingenic JZ4760, JZ4760B, X1000, X1000E and X1500.
^ permalink raw reply
* Re: [PATCH 2/3] rtc: Add support for the MediaTek MT2712 RTC
From: Alexandre Belloni @ 2019-07-13 21:12 UTC (permalink / raw)
To: Ran Bi
Cc: Rob Herring, Matthias Brugger, Alessandro Zummo, Mark Rutland,
linux-rtc, devicetree, linux-kernel, linux-arm-kernel,
linux-mediatek, srv_heupstream, YT Shen, Eddie Huang,
Yingjoe Chen, Flora Fu, Sean Wang
In-Reply-To: <20190702032120.16539-3-ran.bi@mediatek.com>
Hi,
On 02/07/2019 11:21:19+0800, Ran Bi wrote:
> diff --git a/drivers/rtc/rtc-mt2712.c b/drivers/rtc/rtc-mt2712.c
> new file mode 100644
> index 000000000000..f98f0ab114c5
> --- /dev/null
> +++ b/drivers/rtc/rtc-mt2712.c
> @@ -0,0 +1,495 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2019 MediaTek Inc.
> + * Author: Ran Bi <ran.bi@mediatek.com>
> + */
> +
> +#include <linux/delay.h>
> +#include <linux/init.h>
> +#include <linux/io.h>
> +#include <linux/irqdomain.h>
> +#include <linux/module.h>
> +#include <linux/of_address.h>
> +#include <linux/of_irq.h>
> +#include <linux/platform_device.h>
> +#include <linux/rtc.h>
> +
> +#define MTK_RTC_DEV KBUILD_MODNAME
> +
> +#define RTC_BBPU 0x0000
> +#define RTC_BBPU_CLRPKY (1U << 4)
Please use BIT(). Also, I don't feel that the RTC prefix is adding any
value. MT2712 would be a better choice here.
> +#define RTC_BBPU_RELOAD (1U << 5)
> +#define RTC_BBPU_CBUSY (1U << 6)
> +#define RTC_BBPU_KEY (0x43 << 8)
> +
> +#define RTC_IRQ_STA 0x0004
> +#define RTC_IRQ_STA_AL (1U << 0)
> +#define RTC_IRQ_STA_TC (1U << 1)
> +
> +#define RTC_IRQ_EN 0x0008
> +#define RTC_IRQ_EN_AL (1U << 0)
> +#define RTC_IRQ_EN_TC (1U << 1)
> +#define RTC_IRQ_EN_ONESHOT (1U << 2)
> +#define RTC_IRQ_EN_ONESHOT_AL (RTC_IRQ_EN_ONESHOT | RTC_IRQ_EN_AL)
> +
> +#define RTC_CII_EN 0x000c
> +
> +#define RTC_AL_MASK 0x0010
> +#define RTC_AL_MASK_DOW (1U << 4)
> +
> +#define RTC_TC_SEC 0x0014
> +#define RTC_TC_MIN 0x0018
> +#define RTC_TC_HOU 0x001c
> +#define RTC_TC_DOM 0x0020
> +#define RTC_TC_DOW 0x0024
> +#define RTC_TC_MTH 0x0028
> +#define RTC_TC_YEA 0x002c
> +
> +#define RTC_AL_SEC 0x0030
> +#define RTC_AL_MIN 0x0034
> +#define RTC_AL_HOU 0x0038
> +#define RTC_AL_DOM 0x003c
> +#define RTC_AL_DOW 0x0040
> +#define RTC_AL_MTH 0x0044
> +#define RTC_AL_YEA 0x0048
> +
> +#define RTC_SEC_MASK 0x003f
> +#define RTC_MIN_MASK 0x003f
> +#define RTC_HOU_MASK 0x001f
> +#define RTC_DOM_MASK 0x001f
> +#define RTC_DOW_MASK 0x0007
> +#define RTC_MTH_MASK 0x000f
> +#define RTC_YEA_MASK 0x007f
> +
> +#define RTC_POWERKEY1 0x004c
> +#define RTC_POWERKEY2 0x0050
> +#define RTC_POWERKEY1_KEY 0xa357
> +#define RTC_POWERKEY2_KEY 0x67d2
> +
> +#define RTC_CON0 0x005c
> +#define RTC_CON1 0x0060
> +
> +#define RTC_PROT 0x0070
> +#define RTC_PROT_UNLOCK1 0x9136
> +#define RTC_PROT_UNLOCK2 0x586a
> +
> +#define RTC_WRTGR 0x0078
> +
> +/* we map HW YEAR 0 to 1968 not 1970 because 2000 is the leap year */
> +#define RTC_MIN_YEAR 1968
> +#define RTC_BASE_YEAR 1900
> +#define RTC_MIN_YEAR_OFFSET (RTC_MIN_YEAR - RTC_BASE_YEAR)
Do not do that. If this RTC range starts in 200, ths is what the driver
has to support, you should not care about dates before 2000. Note that
the RTC core can still properly shift the range if it is absolutely
necessary.
> +
> +#define RTC_DEFAULT_YEA 2010
> +#define RTC_DEFAULT_MTH 1
> +#define RTC_DEFAULT_DOM 1
> +
> +struct mt2712_rtc {
> + struct device *dev;
> + struct rtc_device *rtc_dev;
> + void __iomem *base;
> + struct mutex lock;
> + int irq;
> + u8 irq_wake_enabled;
> +};
> +
> +static inline u32 rtc_readl(struct mt2712_rtc *rtc, u32 reg)
Please use a more descriptive prefix than just rtc_.
> +{
> + return readl(rtc->base + reg);
> +}
> +
> +static inline void rtc_writel(struct mt2712_rtc *rtc, u32 reg, u32 val)
> +{
> + writel(val, rtc->base + reg);
> +}
> +
> +static void rtc_write_trigger(struct mt2712_rtc *rtc)
> +{
> + unsigned long timeout = jiffies + HZ/10;
> +
> + rtc_writel(rtc, RTC_WRTGR, 1);
> + while (1) {
> + if (!(rtc_readl(rtc, RTC_BBPU) & RTC_BBPU_CBUSY))
> + break;
> +
> + if (time_after(jiffies, timeout)) {
> + dev_err(rtc->dev, "%s time out!\n", __func__);
> + break;
> + }
> + cpu_relax();
> + }
> +}
> +
> +static void rtc_writeif_unlock(struct mt2712_rtc *rtc)
> +{
> + rtc_writel(rtc, RTC_PROT, RTC_PROT_UNLOCK1);
> + rtc_write_trigger(rtc);
> + rtc_writel(rtc, RTC_PROT, RTC_PROT_UNLOCK2);
> + rtc_write_trigger(rtc);
> +}
> +
> +static irqreturn_t rtc_irq_handler_thread(int irq, void *data)
> +{
> + struct mt2712_rtc *rtc = data;
> + u16 irqsta, irqen;
> +
> + irqsta = rtc_readl(rtc, RTC_IRQ_STA);
> + if (irqsta & RTC_IRQ_STA_AL) {
> + rtc_update_irq(rtc->rtc_dev, 1, RTC_IRQF | RTC_AF);
> + irqen = irqsta & ~RTC_IRQ_EN_AL;
> +
> + mutex_lock(&rtc->lock);
You should take rtc->rtc_dev->ops_lock. This would remove the need for
rtc->lock.
> + rtc_writel(rtc, RTC_IRQ_EN, irqen);
> + rtc_write_trigger(rtc);
> + mutex_unlock(&rtc->lock);
> + return IRQ_HANDLED;
> + }
> +
> + return IRQ_NONE;
> +}
> +
> +static void __mtk_rtc_read_time(struct mt2712_rtc *rtc,
> + struct rtc_time *tm, int *sec)
> +{
> + mutex_lock(&rtc->lock);
> + tm->tm_sec = rtc_readl(rtc, RTC_TC_SEC) & RTC_SEC_MASK;
> + tm->tm_min = rtc_readl(rtc, RTC_TC_MIN) & RTC_MIN_MASK;
> + tm->tm_hour = rtc_readl(rtc, RTC_TC_HOU) & RTC_HOU_MASK;
> + tm->tm_mday = rtc_readl(rtc, RTC_TC_DOM) & RTC_DOM_MASK;
> + tm->tm_mon = rtc_readl(rtc, RTC_TC_MTH) & RTC_MTH_MASK;
> + tm->tm_year = rtc_readl(rtc, RTC_TC_YEA) & RTC_YEA_MASK;
> +
> + *sec = rtc_readl(rtc, RTC_TC_SEC) & RTC_SEC_MASK;
> + mutex_unlock(&rtc->lock);
> +}
> +
> +static int mtk_rtc_read_time(struct device *dev, struct rtc_time *tm)
> +{
> + struct mt2712_rtc *rtc = dev_get_drvdata(dev);
> + time64_t time;
> + int days, sec;
> +
> + do {
> + __mtk_rtc_read_time(rtc, tm, &sec);
> + } while (sec < tm->tm_sec); /* SEC has carried */
> +
> + /* HW register use 7 bits to store year data, minus
> + * RTC_MIN_YEAR_OFFSET brfore write year data to register, and plus
> + * RTC_MIN_YEAR_OFFSET back after read year from register
> + */
> + tm->tm_year += RTC_MIN_YEAR_OFFSET;
> +
As stated before, do not do that, simply add 100.
> + /* HW register start mon from one, but tm_mon start from zero. */
> + tm->tm_mon--;
> +
> + /* rtc_tm_to_time64 convert Gregorian date to seconds since
> + * 01-01-1970 00:00:00, and this date is Thursday
> + */
> + time = rtc_tm_to_time64(tm);
> + days = div_s64(time, 86400);
> + tm->tm_wday = (days + 4) % 7;
> +
This is not necessary, nobody cares about tm_wday, if you don't have it,
do not set it.
> + return 0;
> +}
> +
> +static int mtk_rtc_set_time(struct device *dev, struct rtc_time *tm)
> +{
> + struct mt2712_rtc *rtc = dev_get_drvdata(dev);
> +
> + mutex_lock(&rtc->lock);
> + tm->tm_year -= RTC_MIN_YEAR_OFFSET;
> + tm->tm_mon++;
> +
> + rtc_writel(rtc, RTC_TC_SEC, tm->tm_sec & RTC_SEC_MASK);
> + rtc_writel(rtc, RTC_TC_MIN, tm->tm_min & RTC_MIN_MASK);
> + rtc_writel(rtc, RTC_TC_HOU, tm->tm_hour & RTC_HOU_MASK);
> + rtc_writel(rtc, RTC_TC_DOM, tm->tm_mday & RTC_DOM_MASK);
> + rtc_writel(rtc, RTC_TC_MTH, tm->tm_mon & RTC_MTH_MASK);
> + rtc_writel(rtc, RTC_TC_YEA, tm->tm_year & RTC_YEA_MASK);
> +
> + rtc_write_trigger(rtc);
> + mutex_unlock(&rtc->lock);
> +
> + return 0;
> +}
> +
> +static int mtk_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
> +{
> + struct mt2712_rtc *rtc = dev_get_drvdata(dev);
> + struct rtc_time *tm = &alm->time;
> + u16 irqen;
> +
> + mutex_lock(&rtc->lock);
> + irqen = rtc_readl(rtc, RTC_IRQ_EN);
> + alm->enabled = !!(irqen & RTC_IRQ_EN_AL);
> +
> + tm->tm_sec = rtc_readl(rtc, RTC_AL_SEC) & RTC_SEC_MASK;
> + tm->tm_min = rtc_readl(rtc, RTC_AL_MIN) & RTC_MIN_MASK;
> + tm->tm_hour = rtc_readl(rtc, RTC_AL_HOU) & RTC_HOU_MASK;
> + tm->tm_mday = rtc_readl(rtc, RTC_AL_DOM) & RTC_DOM_MASK;
> + tm->tm_mon = rtc_readl(rtc, RTC_AL_MTH) & RTC_MTH_MASK;
> + tm->tm_year = rtc_readl(rtc, RTC_AL_YEA) & RTC_YEA_MASK;
> +
> + tm->tm_year += RTC_MIN_YEAR_OFFSET;
> + tm->tm_mon--;
> + mutex_unlock(&rtc->lock);
> +
> + return 0;
> +}
> +
> +static int mtk_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
> +{
> + struct mt2712_rtc *rtc = dev_get_drvdata(dev);
> + struct rtc_time *tm = &alm->time;
> + u16 irqen;
> +
> + dev_info(rtc->dev, "set al time = %04d-%02d-%02d %02d:%02d:%02d (%d)\n",
Do not use dev_info, dev_dbg is probably what you want here. Also, use
%ptR.
> + tm->tm_year + RTC_BASE_YEAR, tm->tm_mon + 1, tm->tm_mday,
> + tm->tm_hour, tm->tm_min, tm->tm_sec, alm->enabled);
> +
> + tm->tm_year -= RTC_MIN_YEAR_OFFSET;
> + tm->tm_mon++;
> +
> + mutex_lock(&rtc->lock);
You probably need to disable the alarm before starting to modify the
registers.
> + rtc_writel(rtc, RTC_AL_SEC,
> + (rtc_readl(rtc, RTC_AL_SEC) & ~(RTC_SEC_MASK)) |
> + (tm->tm_sec & RTC_SEC_MASK));
> + rtc_writel(rtc, RTC_AL_MIN,
> + (rtc_readl(rtc, RTC_AL_MIN) & ~(RTC_MIN_MASK)) |
> + (tm->tm_min & RTC_MIN_MASK));
> + rtc_writel(rtc, RTC_AL_HOU,
> + (rtc_readl(rtc, RTC_AL_HOU) & ~(RTC_HOU_MASK)) |
> + (tm->tm_hour & RTC_HOU_MASK));
> + rtc_writel(rtc, RTC_AL_DOM,
> + (rtc_readl(rtc, RTC_AL_DOM) & ~(RTC_DOM_MASK)) |
> + (tm->tm_mday & RTC_DOM_MASK));
> + rtc_writel(rtc, RTC_AL_MTH,
> + (rtc_readl(rtc, RTC_AL_MTH) & ~(RTC_MTH_MASK)) |
> + (tm->tm_mon & RTC_MTH_MASK));
> + rtc_writel(rtc, RTC_AL_YEA,
> + (rtc_readl(rtc, RTC_AL_YEA) & ~(RTC_YEA_MASK)) |
> + (tm->tm_year & RTC_YEA_MASK));
> +
> + rtc_writel(rtc, RTC_AL_MASK, RTC_AL_MASK_DOW); /* mask DOW */
> +
> + if (alm->enabled) {
> + irqen = rtc_readl(rtc, RTC_IRQ_EN) | RTC_IRQ_EN_ONESHOT_AL;
> + rtc_writel(rtc, RTC_IRQ_EN, irqen);
> + } else {
> + irqen = rtc_readl(rtc, RTC_IRQ_EN) & ~(RTC_IRQ_EN_ONESHOT_AL);
> + rtc_writel(rtc, RTC_IRQ_EN, irqen);
> + }
> + rtc_write_trigger(rtc);
> + mutex_unlock(&rtc->lock);
> +
> + return 0;
> +}
> +
> +static bool valid_rtc_time(struct mt2712_rtc *rtc)
This function is not necessary, see later.
> +{
> + struct rtc_time tm;
> + struct rtc_wkalrm alm;
> +
> + mtk_rtc_read_time(rtc->dev, &tm);
> + if (rtc_valid_tm(&tm))
> + return false;
> +
> + mtk_rtc_read_alarm(rtc->dev, &alm);
> + if (rtc_valid_tm(&alm.time))
> + return false;
> +
> + return true;
> +}
> +
> +static void reset_rtc_time(struct mt2712_rtc *rtc)
> +{
> + rtc_writel(rtc, RTC_TC_YEA, RTC_DEFAULT_YEA - RTC_MIN_YEAR);
> + rtc_writel(rtc, RTC_TC_MTH, RTC_DEFAULT_MTH);
> + rtc_writel(rtc, RTC_TC_DOM, RTC_DEFAULT_DOM);
> + rtc_writel(rtc, RTC_TC_DOW, 1);
> + rtc_writel(rtc, RTC_TC_HOU, 0);
> + rtc_writel(rtc, RTC_TC_MIN, 0);
> + rtc_writel(rtc, RTC_TC_SEC, 0);
> +
> + rtc_writel(rtc, RTC_AL_YEA, 1970 - RTC_MIN_YEAR);
> + rtc_writel(rtc, RTC_AL_MTH, 1);
> + rtc_writel(rtc, RTC_AL_DOM, 1);
> + rtc_writel(rtc, RTC_AL_DOW, 1);
> + rtc_writel(rtc, RTC_AL_HOU, 0);
> + rtc_writel(rtc, RTC_AL_MIN, 0);
> + rtc_writel(rtc, RTC_AL_SEC, 0);
> +
> + rtc_write_trigger(rtc);
> +}
> +
> +/* Init RTC register */
> +static void rtc_hw_init(struct mt2712_rtc *rtc)
> +{
> + u32 p1, p2;
> +
> + rtc_writel(rtc, RTC_BBPU, RTC_BBPU_KEY | RTC_BBPU_RELOAD);
> +
> + rtc_writel(rtc, RTC_IRQ_EN, 0);
Are you sure you want to disable interrupts every time you reboot? I
guess the RTC has its own power domain and may be used across reboots.
> + rtc_writel(rtc, RTC_IRQ_STA, 0);
> + rtc_writel(rtc, RTC_CII_EN, 0);
> + rtc_writel(rtc, RTC_AL_MASK, 0);
> + /* necessary before set RTC_POWERKEY */
> + rtc_writel(rtc, RTC_CON0, 0x4848);
> + rtc_writel(rtc, RTC_CON1, 0x0048);
> +
> + rtc_write_trigger(rtc);
> +
> + rtc_readl(rtc, RTC_IRQ_STA); /* read clear */
> +
> + p1 = rtc_readl(rtc, RTC_POWERKEY1);
> + p2 = rtc_readl(rtc, RTC_POWERKEY2);
> + dev_info(rtc->dev, "%s rtc p1 is %x, p2 is %x!\n", __func__, p1, p2);
This debug message has to be removed.
> +
> + /* RTC need POWERKEY1/2 match, then goto normal work mode */
> + rtc_writel(rtc, RTC_POWERKEY1, RTC_POWERKEY1_KEY);
> + rtc_writel(rtc, RTC_POWERKEY2, RTC_POWERKEY2_KEY);
> + rtc_write_trigger(rtc);
> +
> + rtc_writeif_unlock(rtc);
> +
> + /*
> + * register status was not correct,
> + * need set time and alarm to default
> + */
> + if (p1 != RTC_POWERKEY1_KEY || p2 != RTC_POWERKEY2_KEY
> + || !valid_rtc_time(rtc)) {
> + reset_rtc_time(rtc);
Do not do that. This is valuable information. If the time is invalid,
report it as such in read_time and read_alarm. Resetting the time here
will lead to more issues later (i.e. userspace is not able to know
whether the time is set correctly or not).
> + dev_info(rtc->dev, "first boot init!\n");
> + }
> +}
> +
> +static const struct rtc_class_ops mtk_rtc_ops = {
> + .read_time = mtk_rtc_read_time,
> + .set_time = mtk_rtc_set_time,
> + .read_alarm = mtk_rtc_read_alarm,
> + .set_alarm = mtk_rtc_set_alarm,
> +};
> +
> +static int mtk_rtc_probe(struct platform_device *pdev)
> +{
> + struct resource *res;
> + struct mt2712_rtc *rtc;
> + int ret;
> +
> + rtc = devm_kzalloc(&pdev->dev, sizeof(struct mt2712_rtc), GFP_KERNEL);
> + if (!rtc)
> + return -ENOMEM;
> +
> + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> + rtc->base = devm_ioremap_resource(&pdev->dev, res);
> + if (IS_ERR(rtc->base))
> + return PTR_ERR(rtc->base);
> +
> + rtc->irq = platform_get_irq(pdev, 0);
> + if (rtc->irq < 0) {
> + dev_err(&pdev->dev, "No IRQ resource\n");
> + return rtc->irq;
> + }
> +
> + mutex_init(&rtc->lock);
> + rtc->dev = &pdev->dev;
> + platform_set_drvdata(pdev, rtc);
> +
> + rtc->rtc_dev = devm_rtc_allocate_device(rtc->dev);
> + if (IS_ERR(rtc->rtc_dev))
> + return PTR_ERR(rtc->rtc_dev);
> +
> + ret = request_threaded_irq(rtc->irq, NULL,
devm_request_threaded_irq would remove the need for out_free_irq and
mtk_rtc_remove().
> + rtc_irq_handler_thread,
> + IRQF_ONESHOT | IRQF_TRIGGER_LOW,
> + dev_name(rtc->dev), rtc);
> + if (ret) {
> + dev_err(&pdev->dev, "Failed to request alarm IRQ: %d: %d\n",
> + rtc->irq, ret);
> + return ret;
> + }
> +
> + /* rtc hw init */
> + rtc_hw_init(rtc);
> +
> + device_init_wakeup(&pdev->dev, true);
> +
> + rtc->rtc_dev->ops = &mtk_rtc_ops;
> +
> + ret = rtc_register_device(rtc->rtc_dev);
> + if (ret) {
> + dev_err(&pdev->dev, "register rtc device failed\n");
> + goto out_free_irq;
> + }
> +
> + return 0;
> +
> +out_free_irq:
> + free_irq(rtc->irq, rtc);
> + return ret;
> +}
> +
> +static int mtk_rtc_remove(struct platform_device *pdev)
> +{
> + struct mt2712_rtc *rtc = dev_get_drvdata(&pdev->dev);
> +
> + free_irq(rtc->irq, rtc);
> +
> + return 0;
> +}
> +
> +#ifdef CONFIG_PM_SLEEP
> +static int mt2712_rtc_suspend(struct device *dev)
> +{
> + int wake_status = 0;
> + struct mt2712_rtc *rtc = dev_get_drvdata(dev);
> +
> + if (device_may_wakeup(dev)) {
> + wake_status = enable_irq_wake(rtc->irq);
> + if (!wake_status)
> + rtc->irq_wake_enabled = true;
> + }
> +
> + return 0;
> +}
> +
> +static int mt2712_rtc_resume(struct device *dev)
> +{
> + int wake_status = 0;
> + struct mt2712_rtc *rtc = dev_get_drvdata(dev);
> +
> + if (device_may_wakeup(dev) && rtc->irq_wake_enabled) {
> + wake_status = disable_irq_wake(rtc->irq);
> + if (!wake_status)
> + rtc->irq_wake_enabled = false;
> + }
> +
> + return 0;
> +}
> +
> +static SIMPLE_DEV_PM_OPS(mt2712_pm_ops, mt2712_rtc_suspend,
> + mt2712_rtc_resume);
> +#endif
> +
> +static const struct of_device_id mt2712_rtc_of_match[] = {
> + { .compatible = "mediatek,mt2712-rtc", },
> + { },
> +};
> +
> +MODULE_DEVICE_TABLE(of, mt2712_rtc_of_match)
> +
> +static struct platform_driver mtk_rtc_driver = {
> + .driver = {
> + .name = MTK_RTC_DEV,
> + .of_match_table = mt2712_rtc_of_match,
> + .pm = &mt2712_pm_ops,
> + },
> + .probe = mtk_rtc_probe,
> + .remove = mtk_rtc_remove,
> +};
> +
> +module_platform_driver(mtk_rtc_driver);
> +
> +MODULE_DESCRIPTION("MediaTek MT2712 SoC based RTC Driver");
> +MODULE_AUTHOR("Ran Bi <ran.bi@mediatek.com>");
> +MODULE_LICENSE("GPL");
> --
> 2.18.0
>
--
Alexandre Belloni, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com
^ permalink raw reply
* Re: [PATCH v4 00/11] add thermal driver for h6
From: Vasily Khoruzhick @ 2019-07-13 18:01 UTC (permalink / raw)
To: Yangtao Li
Cc: rui.zhang, Eduardo Valentin, Daniel Lezcano, Rob Herring,
Mark Rutland, Maxime Ripard, Chen-Yu Tsai, David S. Miller,
Greg Kroah-Hartman, Mauro Carvalho Chehab, Linus Walleij,
Nicolas Ferre, paulmck, devicetree, linux-kernel, arm-linux,
Linux PM
In-Reply-To: <CA+E=qVfhDEQER2UTj65hR9erzej9Ey2FrUa9GV=iCFYsWZ2ztw@mail.gmail.com>
On Wed, Jul 10, 2019 at 4:09 PM Vasily Khoruzhick <anarsoul@gmail.com> wrote:
>
> On Sun, Jun 23, 2019 at 9:42 AM Yangtao Li <tiny.windzz@gmail.com> wrote:
> >
> > This patchset add support for H3 and H6 thermal sensor.
> >
> > BTY, do a cleanup in thermal makfile.
> >
> > Yangtao Li (11):
> > thermal: sun8i: add thermal driver for h6
> > dt-bindings: thermal: add binding document for h6 thermal controller
> > thermal: fix indentation in makefile
> > thermal: sun8i: get ths sensor number from device compatible
> > thermal: sun8i: rework for sun8i_ths_get_temp()
> > thermal: sun8i: get ths init func from device compatible
> > thermal: sun8i: rework for ths irq handler func
> > thermal: sun8i: support ahb clocks
> > thermal: sun8i: rework for ths calibrate func
> > dt-bindings: thermal: add binding document for h3 thermal controller
> > thermal: sun8i: add thermal driver for h3
>
> It would be nice to add dts changes to this series. It's unlikely that
> you'll get any "Tested-by" otherwise.
I added A64 support on top of this series, see
https://github.com/anarsoul/linux-2.6/tree/v5.2-thermal
Branch also contains patches to enable DVFS on A64, feel free to
cherry pick only those related to thermal driver if you want to
include A64 support into v5 series.
>
> > .../bindings/thermal/sun8i-thermal.yaml | 94 +++
> > MAINTAINERS | 7 +
> > drivers/thermal/Kconfig | 14 +
> > drivers/thermal/Makefile | 9 +-
> > drivers/thermal/sun8i_thermal.c | 534 ++++++++++++++++++
> > 5 files changed, 654 insertions(+), 4 deletions(-)
> > create mode 100644 Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml
> > create mode 100644 drivers/thermal/sun8i_thermal.c
> >
> > ---
> > v4:
> > -add h3 support
> > -fix yaml file
> > ---
> > 2.17.1
> >
> >
> > _______________________________________________
> > linux-arm-kernel mailing list
> > linux-arm-kernel@lists.infradead.org
> > http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [PATCH v2] ARM: dts: msm8974-FP2: add reboot-mode node
From: Luca Weiss @ 2019-07-13 15:48 UTC (permalink / raw)
To: linux-arm-msm
Cc: ~martijnbraam/pmos-upstream, Luca Weiss, Brian Masney, Andy Gross,
David Brown, Rob Herring, Mark Rutland, devicetree, linux-kernel
This enables userspace to signal the bootloader to go into the
bootloader or recovery mode.
The magic values can be found in both the downstream kernel and the LK
kernel (bootloader).
Reviewed-by: Brian Masney <masneyb@onstation.org>
Signed-off-by: Luca Weiss <luca@z3ntu.xyz>
---
Changes v1 -> v2:
- Move the majority of the node into the board dts, just keep the magic
values in the device-specific dts.
arch/arm/boot/dts/qcom-msm8974-fairphone-fp2.dts | 10 ++++++++++
arch/arm/boot/dts/qcom-msm8974.dtsi | 11 +++++++++++
2 files changed, 21 insertions(+)
diff --git a/arch/arm/boot/dts/qcom-msm8974-fairphone-fp2.dts b/arch/arm/boot/dts/qcom-msm8974-fairphone-fp2.dts
index 643c57f84818..ff4a3e0aa746 100644
--- a/arch/arm/boot/dts/qcom-msm8974-fairphone-fp2.dts
+++ b/arch/arm/boot/dts/qcom-msm8974-fairphone-fp2.dts
@@ -338,6 +338,16 @@
};
};
};
+
+ imem@fe805000 {
+ status = "okay";
+
+ reboot-mode {
+ mode-normal = <0x77665501>;
+ mode-bootloader = <0x77665500>;
+ mode-recovery = <0x77665502>;
+ };
+ };
};
&spmi_bus {
diff --git a/arch/arm/boot/dts/qcom-msm8974.dtsi b/arch/arm/boot/dts/qcom-msm8974.dtsi
index 45b5c8ef0374..1927430bded7 100644
--- a/arch/arm/boot/dts/qcom-msm8974.dtsi
+++ b/arch/arm/boot/dts/qcom-msm8974.dtsi
@@ -1085,6 +1085,17 @@
};
};
};
+
+ imem@fe805000 {
+ status = "disabled";
+ compatible = "syscon", "simple-mfd";
+ reg = <0xfe805000 0x1000>;
+
+ reboot-mode {
+ compatible = "syscon-reboot-mode";
+ offset = <0x65c>;
+ };
+ };
};
smd {
--
2.22.0
^ permalink raw reply related
* Re: [PATCH] ARM: dts: msm8974-FP2: add reboot-mode node
From: Brian Masney @ 2019-07-13 14:31 UTC (permalink / raw)
To: Luca Weiss
Cc: linux-arm-msm, ~martijnbraam/pmos-upstream, Andy Gross,
David Brown, Rob Herring, Mark Rutland, devicetree, linux-kernel
In-Reply-To: <3733253.hEy9q5iLy3@g550jk>
On Sat, Jul 13, 2019 at 01:26:45PM +0200, Luca Weiss wrote:
> Hi Brian,
> how about something like that (formatting is surely broken because I'm not
> sending this with git-send-email^^)?
>
> I'd says this should be work fine with all devices as all modes are defined in
> the device-specific dts but the reg and offset values are in the board dts.
> Should I also add a status = "disabled" to the reboot-mode node in the board
> dts?
>
> diff --git a/arch/arm/boot/dts/qcom-msm8974-fairphone-fp2.dts b/arch/arm/boot/
> dts/qcom-msm8974-fairphone-fp2.dts
> index 643c57f84818..ff4a3e0aa746 100644
> --- a/arch/arm/boot/dts/qcom-msm8974-fairphone-fp2.dts
> +++ b/arch/arm/boot/dts/qcom-msm8974-fairphone-fp2.dts
> @@ -338,6 +338,16 @@
> };
> };
> };
> +
> + imem@fe805000 {
> + status = "okay";
> +
> + reboot-mode {
> + mode-normal = <0x77665501>;
> + mode-bootloader = <0x77665500>;
> + mode-recovery = <0x77665502>;
> + };
> + };
> };
>
> &spmi_bus {
> diff --git a/arch/arm/boot/dts/qcom-msm8974.dtsi b/arch/arm/boot/dts/qcom-
> msm8974.dtsi
> index 45b5c8ef0374..1927430bded7 100644
> --- a/arch/arm/boot/dts/qcom-msm8974.dtsi
> +++ b/arch/arm/boot/dts/qcom-msm8974.dtsi
> @@ -1085,6 +1085,17 @@
> };
> };
> };
> +
> + imem@fe805000 {
> + status = "disabled";
> + compatible = "syscon", "simple-mfd";
> + reg = <0xfe805000 0x1000>;
> +
> + reboot-mode {
> + compatible = "syscon-reboot-mode";
> + offset = <0x65c>;
> + };
> + };
> };
>
> smd {
I think this sounds reasonable.
Reviewed-by: Brian Masney <masneyb@onstation.org>
You should resend this out with git send-email and see what Bjorn says.
Brian
^ permalink raw reply
* Re: [PATCH 2/2] drivers: hwmon: lm75: add support for PCT2075
From: Guenter Roeck @ 2019-07-13 13:30 UTC (permalink / raw)
To: Daniel Mack; +Cc: linux-hwmon, devicetree, jdelvare
In-Reply-To: <20190711124504.7580-2-daniel@zonque.org>
On Thu, Jul 11, 2019 at 02:45:04PM +0200, Daniel Mack wrote:
> The NXP PCT2075 is largely compatible with other chips already supported
> by the LM75 driver. It uses an 11-bit resolution and defaults to 100 ms
> sampling period. The datasheet is here:
>
> https://www.nxp.com/docs/en/data-sheet/PCT2075.pdf
>
> Signed-off-by: Daniel Mack <daniel@zonque.org>
Applied to hwmon-next. Note that I also updated Documentation/hwmon/lm75.rst.
Guenter
> ---
> drivers/hwmon/lm75.c | 10 ++++++++++
> 1 file changed, 10 insertions(+)
>
> diff --git a/drivers/hwmon/lm75.c b/drivers/hwmon/lm75.c
> index 447af07450f1..a8aba628468e 100644
> --- a/drivers/hwmon/lm75.c
> +++ b/drivers/hwmon/lm75.c
> @@ -49,6 +49,7 @@ enum lm75_type { /* keep sorted in alphabetical order */
> max6626,
> max31725,
> mcp980x,
> + pct2075,
> stds75,
> stlm75,
> tcn75,
> @@ -353,6 +354,10 @@ lm75_probe(struct i2c_client *client, const struct i2c_device_id *id)
> data->resolution = 9;
> data->sample_time = MSEC_PER_SEC / 8;
> break;
> + case pct2075:
> + data->resolution = 11;
> + data->sample_time = MSEC_PER_SEC / 10;
> + break;
> case mcp980x:
> data->resolution_limits = 9;
> /* fall through */
> @@ -428,6 +433,7 @@ static const struct i2c_device_id lm75_ids[] = {
> { "max31725", max31725, },
> { "max31726", max31725, },
> { "mcp980x", mcp980x, },
> + { "pct2075", pct2075, },
> { "stds75", stds75, },
> { "stlm75", stlm75, },
> { "tcn75", tcn75, },
> @@ -496,6 +502,10 @@ static const struct of_device_id lm75_of_match[] = {
> .compatible = "maxim,mcp980x",
> .data = (void *)mcp980x
> },
> + {
> + .compatible = "nxp,pct2075",
> + .data = (void *)pct2075
> + },
> {
> .compatible = "st,stds75",
> .data = (void *)stds75
^ permalink raw reply
* Re: [PATCH 1/2] device-tree: bindinds: add NXP PCT2075 as compatible device to LM75
From: Guenter Roeck @ 2019-07-13 13:24 UTC (permalink / raw)
To: Daniel Mack; +Cc: linux-hwmon, devicetree, jdelvare
In-Reply-To: <20190711124504.7580-1-daniel@zonque.org>
On Thu, Jul 11, 2019 at 02:45:03PM +0200, Daniel Mack wrote:
> The PCT2075 is compatible to other chips that are already handled by
> the LM75 driver.
>
> Signed-off-by: Daniel Mack <daniel@zonque.org>
Applied to hwmon-next.
Thanks,
Guenter
> ---
> Documentation/devicetree/bindings/hwmon/lm75.txt | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/Documentation/devicetree/bindings/hwmon/lm75.txt b/Documentation/devicetree/bindings/hwmon/lm75.txt
> index 12d8cf7cf592..bfb22b249708 100644
> --- a/Documentation/devicetree/bindings/hwmon/lm75.txt
> +++ b/Documentation/devicetree/bindings/hwmon/lm75.txt
> @@ -15,6 +15,7 @@ Required properties:
> "maxim,max31725",
> "maxim,max31726",
> "maxim,mcp980x",
> + "nxp,pct2075",
> "st,stds75",
> "st,stlm75",
> "microchip,tcn75",
^ permalink raw reply
* Re: [PATCH] ARM: dts: msm8974-FP2: add reboot-mode node
From: Luca Weiss @ 2019-07-13 11:26 UTC (permalink / raw)
To: Brian Masney
Cc: linux-arm-msm, ~martijnbraam/pmos-upstream, Andy Gross,
David Brown, Rob Herring, Mark Rutland, devicetree, linux-kernel
In-Reply-To: <20190622014302.GA20947@onstation.org>
Hi Brian,
how about something like that (formatting is surely broken because I'm not
sending this with git-send-email^^)?
I'd says this should be work fine with all devices as all modes are defined in
the device-specific dts but the reg and offset values are in the board dts.
Should I also add a status = "disabled" to the reboot-mode node in the board
dts?
diff --git a/arch/arm/boot/dts/qcom-msm8974-fairphone-fp2.dts b/arch/arm/boot/
dts/qcom-msm8974-fairphone-fp2.dts
index 643c57f84818..ff4a3e0aa746 100644
--- a/arch/arm/boot/dts/qcom-msm8974-fairphone-fp2.dts
+++ b/arch/arm/boot/dts/qcom-msm8974-fairphone-fp2.dts
@@ -338,6 +338,16 @@
};
};
};
+
+ imem@fe805000 {
+ status = "okay";
+
+ reboot-mode {
+ mode-normal = <0x77665501>;
+ mode-bootloader = <0x77665500>;
+ mode-recovery = <0x77665502>;
+ };
+ };
};
&spmi_bus {
diff --git a/arch/arm/boot/dts/qcom-msm8974.dtsi b/arch/arm/boot/dts/qcom-
msm8974.dtsi
index 45b5c8ef0374..1927430bded7 100644
--- a/arch/arm/boot/dts/qcom-msm8974.dtsi
+++ b/arch/arm/boot/dts/qcom-msm8974.dtsi
@@ -1085,6 +1085,17 @@
};
};
};
+
+ imem@fe805000 {
+ status = "disabled";
+ compatible = "syscon", "simple-mfd";
+ reg = <0xfe805000 0x1000>;
+
+ reboot-mode {
+ compatible = "syscon-reboot-mode";
+ offset = <0x65c>;
+ };
+ };
};
smd {
Regards,
Luca
^ permalink raw reply related
* [PATCH v4 3/3] iio: Add PAT9125 optical tracker sensor
From: Alexandre Mergnat @ 2019-07-13 8:04 UTC (permalink / raw)
To: robh+dt, mark.rutland, jic23
Cc: linux-kernel, linux-iio, baylibre-upstreaming, dmitry.torokhov,
linux-input, devicetree, Alexandre Mergnat
In-Reply-To: <20190713080455.17513-1-amergnat@baylibre.com>
This adds support for PixArt Imaging’s miniature low power optical
navigation chip using LASER light source enabling digital surface tracking.
Features and datasheet: [0]
This IIO driver allows to read relative position from where the system
started on X and Y axis through two way:
- Punctual "read_raw" which will issue a read in the device registers to
get the delta between last/current read and return the addition of all
the deltas.
- Buffer read. Data can be retrieved using triggered buffer subscription
(i.e. iio_readdev). The buffer payload is:
|32 bits delta X|32 bits delta Y|timestamp|.
The possible I2C addresses are 0x73, 0x75 and 0x79.
X and Y axis CPI resolution can be get/set independently through IIO_SCALE.
The range value is 0-255 which means:
- 0 to ~1,275 Counts Per Inch on flat surface.
- 0 to ~630 Counts Per Rev on 1.0mm diameter STS shaft at 1.0mm distance.
More details on the datasheet.
The "position" directory is added to contain drivers which can provide
position data.
[0]: http://www.pixart.com/products-detail/72/PAT9125EL-TKIT___TKMT
Signed-off-by: Alexandre Mergnat <amergnat@baylibre.com>
---
drivers/iio/Kconfig | 1 +
drivers/iio/Makefile | 1 +
drivers/iio/position/Kconfig | 18 ++
drivers/iio/position/Makefile | 6 +
drivers/iio/position/pat9125.c | 506 +++++++++++++++++++++++++++++++++
5 files changed, 532 insertions(+)
create mode 100644 drivers/iio/position/Kconfig
create mode 100644 drivers/iio/position/Makefile
create mode 100644 drivers/iio/position/pat9125.c
diff --git a/drivers/iio/Kconfig b/drivers/iio/Kconfig
index 5bd51853b15e..aca6fcbceeab 100644
--- a/drivers/iio/Kconfig
+++ b/drivers/iio/Kconfig
@@ -85,6 +85,7 @@ source "drivers/iio/light/Kconfig"
source "drivers/iio/magnetometer/Kconfig"
source "drivers/iio/multiplexer/Kconfig"
source "drivers/iio/orientation/Kconfig"
+source "drivers/iio/position/Kconfig"
if IIO_TRIGGER
source "drivers/iio/trigger/Kconfig"
endif #IIO_TRIGGER
diff --git a/drivers/iio/Makefile b/drivers/iio/Makefile
index bff682ad1cfb..1712011c0f4a 100644
--- a/drivers/iio/Makefile
+++ b/drivers/iio/Makefile
@@ -31,6 +31,7 @@ obj-y += light/
obj-y += magnetometer/
obj-y += multiplexer/
obj-y += orientation/
+obj-y += position/
obj-y += potentiometer/
obj-y += potentiostat/
obj-y += pressure/
diff --git a/drivers/iio/position/Kconfig b/drivers/iio/position/Kconfig
new file mode 100644
index 000000000000..1cf28896511c
--- /dev/null
+++ b/drivers/iio/position/Kconfig
@@ -0,0 +1,18 @@
+#
+# Optical tracker sensors
+#
+# When adding new entries keep the list in alphabetical order
+
+menu "Optical tracker sensors"
+
+config PAT9125
+ tristate "Optical tracker PAT9125 I2C driver"
+ depends on I2C
+ select IIO_BUFFER
+ help
+ Say yes here to build support for PAT9125 optical tracker
+ sensors.
+
+ To compile this driver as a module, say M here: the module will
+ be called pat9125.
+endmenu
diff --git a/drivers/iio/position/Makefile b/drivers/iio/position/Makefile
new file mode 100644
index 000000000000..cf294917ae2c
--- /dev/null
+++ b/drivers/iio/position/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for industrial I/O Optical tracker sensor drivers
+#
+
+# When adding new entries keep the list in alphabetical order
+obj-$(CONFIG_PAT9125) += pat9125.o
diff --git a/drivers/iio/position/pat9125.c b/drivers/iio/position/pat9125.c
new file mode 100644
index 000000000000..2f04777e0790
--- /dev/null
+++ b/drivers/iio/position/pat9125.c
@@ -0,0 +1,506 @@
+// SPDX-License-Identifier: (GPL-2.0)
+/*
+ * Copyright (C) 2019 BayLibre, SAS
+ * Author: Alexandre Mergnat <amergnat@baylibre.com>
+ */
+
+#include <linux/bitops.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/i2c.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/events.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/trigger.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
+#include <linux/iio/kfifo_buf.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+
+/* I2C Address function to ID pin*/
+#define PAT9125_I2C_ADDR_HI 0x73
+#define PAT9125_I2C_ADDR_LO 0x75
+#define PAT9125_I2C_ADDR_NC 0x79
+
+/* Registers */
+#define PAT9125_PRD_ID1_REG 0x00
+#define PAT9125_PRD_ID2_REG 0x01
+#define PAT9125_MOTION_STATUS_REG 0x02
+#define PAT9125_DELTA_X_LO_REG 0x03
+#define PAT9125_DELTA_Y_LO_REG 0x04
+#define PAT9125_OP_MODE_REG 0x05
+#define PAT9125_CONFIG_REG 0x06
+#define PAT9125_WRITE_PROTEC_REG 0x09
+#define PAT9125_SLEEP1_REG 0x0A
+#define PAT9125_SLEEP2_REG 0x0B
+#define PAT9125_RES_X_REG 0x0D
+#define PAT9125_RES_Y_REG 0x0E
+#define PAT9125_DELTA_XY_HI_REG 0x12
+#define PAT9125_SHUTER_REG 0x14
+#define PAT9125_FRAME_AVG_REG 0x17
+#define PAT9125_ORIENTATION_REG 0x19
+
+/* Bits */
+#define PAT9125_VALID_MOTION_DATA_BIT BIT(7)
+#define PAT9125_RESET_BIT BIT(7)
+
+/* Registers' values */
+#define PAT9125_SENSOR_ID_VAL 0x31
+#define PAT9125_DISABLE_WRITE_PROTECT_VAL 0x5A
+#define PAT9125_ENABLE_WRITE_PROTECT_VAL 0x00
+
+/* Default Value of sampled value size */
+#define PAT9125_SAMPLED_VAL_BIT_SIZE 12
+
+struct pat9125_data {
+ struct regmap *regmap;
+ struct iio_trigger *indio_trig; /* Motion detection */
+ s32 position_x;
+ s32 position_y;
+ bool sampling;
+};
+
+static const struct iio_chan_spec pat9125_channels[] = {
+ {
+ .type = IIO_DISTANCE,
+ .modified = 1,
+ .channel2 = IIO_MOD_X,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_SCALE),
+ .scan_index = 0,
+ .scan_type = {
+ .sign = 's',
+ .realbits = 32,
+ .storagebits = 32,
+ .endianness = IIO_CPU,
+ },
+ },
+ {
+ .type = IIO_DISTANCE,
+ .modified = 1,
+ .channel2 = IIO_MOD_Y,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_SCALE),
+ .scan_index = 1,
+ .scan_type = {
+ .sign = 's',
+ .realbits = 32,
+ .storagebits = 32,
+ .endianness = IIO_CPU,
+ },
+ },
+ IIO_CHAN_SOFT_TIMESTAMP(2),
+};
+
+/**
+ * pat9125_write_pretected_reg() - Write value in protected register.
+ *
+ * @regmap: Pointer to I2C register map.
+ * @reg_addr: Register address.
+ * @reg_value: Value to be write in register.
+ *
+ * A value of zero will be returned on success, a negative errno will
+ * be returned in error cases.
+ */
+static int pat9125_write_pretected_reg(struct iio_dev *indio_dev,
+ u8 reg_addr, u8 reg_value)
+{
+ struct pat9125_data *data = iio_priv(indio_dev);
+ int ret;
+
+ ret = regmap_write(data->regmap,
+ PAT9125_WRITE_PROTEC_REG,
+ PAT9125_DISABLE_WRITE_PROTECT_VAL);
+
+ if (!ret)
+ ret = regmap_write(data->regmap, reg_addr, reg_value);
+
+ /* Try to put back write protection everytime */
+ ret |= regmap_write(data->regmap,
+ PAT9125_WRITE_PROTEC_REG,
+ PAT9125_ENABLE_WRITE_PROTECT_VAL);
+
+ return ret;
+}
+/**
+ * pat9125_read_delta() - Read delta value, update delta & position data.
+ *
+ * @data: Driver's data structure.
+ *
+ * A value of zero will be returned on success, a negative errno will
+ * be returned in error cases.
+ */
+static int pat9125_read_delta(struct pat9125_data *data)
+{
+ struct regmap *regmap = data->regmap;
+ int status = 0;
+ int val_x = 0;
+ int val_y = 0;
+ int val_high_nibbles = 0;
+ int ret;
+
+ ret = regmap_read(regmap, PAT9125_MOTION_STATUS_REG, &status);
+ if (ret < 0)
+ return ret;
+
+ /* Check if motion is detected */
+ if (status & PAT9125_VALID_MOTION_DATA_BIT) {
+ ret = regmap_read(regmap, PAT9125_DELTA_X_LO_REG, &val_x);
+ if (ret < 0)
+ return ret;
+
+ ret = regmap_read(regmap, PAT9125_DELTA_Y_LO_REG, &val_y);
+ if (ret < 0)
+ return ret;
+
+ ret = regmap_read(regmap, PAT9125_DELTA_XY_HI_REG,
+ &val_high_nibbles);
+ if (ret < 0)
+ return ret;
+
+ val_x |= (val_high_nibbles << 4) & 0xF00;
+ val_y |= (val_high_nibbles << 8) & 0xF00;
+ val_x = sign_extend32(val_x,
+ PAT9125_SAMPLED_VAL_BIT_SIZE - 1);
+ val_y = sign_extend32(val_y,
+ PAT9125_SAMPLED_VAL_BIT_SIZE - 1);
+ data->position_x += val_x;
+ data->position_y += val_y;
+ }
+ return 0;
+}
+
+/**
+ * pat9125_read_raw() - Sample and return the value(s)
+ * function to the associated channel info enum.
+ *
+ * @indio_dev: Industrial I/O device.
+ * @chan: Specification of a single channel.
+ * @val: Contain the elements making up the returned value.
+ * @val2: Not used.
+ * @mask: (enum iio_chan_info_enum) Type of the info attribute.
+ *
+ * Zero will be returned on success, negative value otherwise.
+ **/
+static int pat9125_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val, int *val2, long mask)
+{
+ struct pat9125_data *data = iio_priv(indio_dev);
+ int ret;
+
+ switch (mask) {
+ case IIO_CHAN_INFO_RAW:
+ ret = pat9125_read_delta(data);
+ if (ret)
+ return ret;
+ switch (chan->channel2) {
+ case IIO_MOD_X:
+ *val = data->position_x;
+ return IIO_VAL_INT;
+ case IIO_MOD_Y:
+ *val = data->position_y;
+ return IIO_VAL_INT;
+ default:
+ return -EINVAL;
+ }
+ case IIO_CHAN_INFO_SCALE:
+ switch (chan->channel2) {
+ case IIO_MOD_X:
+ ret = regmap_read(data->regmap, PAT9125_RES_X_REG, val);
+ if (ret)
+ return ret;
+ else
+ return IIO_VAL_INT;
+ case IIO_MOD_Y:
+ ret = regmap_read(data->regmap, PAT9125_RES_Y_REG, val);
+ if (ret)
+ return ret;
+ else
+ return IIO_VAL_INT;
+ default:
+ return -EINVAL;
+ }
+ default:
+ return -EINVAL;
+ }
+}
+
+/**
+ * pat9125_write_raw() - Write the value(s)
+ * function to the associated channel info enum.
+ *
+ * @indio_dev: Industrial I/O device.
+ * @chan: Specification of a single channel.
+ * @val: Value write in the channel.
+ * @val2: Not used.
+ * @mask: (enum iio_chan_info_enum) Type of the info attribute.
+ *
+ * Zero will be returned on success, negative value otherwise.
+ **/
+static int pat9125_write_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan, int val,
+ int val2, long mask)
+{
+ int ret;
+
+ switch (mask) {
+ case IIO_CHAN_INFO_SCALE:
+ switch (chan->channel2) {
+ case IIO_MOD_X:
+ ret = pat9125_write_pretected_reg(indio_dev,
+ PAT9125_RES_X_REG, val);
+ return ret;
+ case IIO_MOD_Y:
+ ret = pat9125_write_pretected_reg(indio_dev,
+ PAT9125_RES_Y_REG, val);
+ return ret;
+ default:
+ return -EINVAL;
+ }
+ default:
+ return -EINVAL;
+ }
+}
+
+static irqreturn_t pat9125_threaded_trigger_handler(int irq, void *p)
+{
+ struct iio_poll_func *pf = p;
+ struct iio_dev *indio_dev = pf->indio_dev;
+ struct pat9125_data *data = iio_priv(indio_dev);
+ u8 buf[16]; /* Payload: Pos_X (4) | Pos_Y (4) | Timestamp (8) */
+ int ret;
+ s64 timestamp;
+
+ data->sampling = true;
+ ret = pat9125_read_delta(data);
+ if (ret) {
+ dev_err(indio_dev->dev.parent, "Read delta failed %d\n", ret);
+ return IRQ_NONE;
+ }
+ timestamp = iio_get_time_ns(indio_dev);
+ *((s32 *)&buf[0]) = data->position_x;
+ *((s32 *)&buf[sizeof(s32)]) = data->position_y;
+ iio_push_to_buffers_with_timestamp(indio_dev, buf, timestamp);
+ iio_trigger_notify_done(indio_dev->trig);
+ return IRQ_HANDLED;
+}
+
+/**
+ * pat9125_threaded_event_handler() - Threaded motion detection event handler
+ * @irq: The irq being handled.
+ * @private: struct iio_device pointer for the device.
+ */
+static irqreturn_t pat9125_threaded_event_handler(int irq, void *private)
+{
+ struct iio_dev *indio_dev = private;
+ struct pat9125_data *data = iio_priv(indio_dev);
+
+ iio_trigger_poll_chained(data->indio_trig);
+ return IRQ_HANDLED;
+}
+
+/**
+ * pat9125_buffer_postenable() - Buffer post enable actions
+ *
+ * @indio_dev: Industrial I/O device.
+ */
+static int pat9125_buffer_postenable(struct iio_dev *indio_dev)
+{
+ struct pat9125_data *data = iio_priv(indio_dev);
+ int ret = 0;
+
+ ret = iio_triggered_buffer_postenable(indio_dev);
+ if (ret)
+ return ret;
+
+ /* Release interrupt pin on the device */
+ ret = pat9125_read_delta(data);
+
+ /* iio_trigger_detach_poll_func isn't reachable, so use this function */
+ if (ret)
+ ret = iio_triggered_buffer_predisable(indio_dev);
+
+ return ret;
+}
+
+static const struct iio_buffer_setup_ops pat9125_buffer_ops = {
+ .postenable = pat9125_buffer_postenable,
+};
+
+static const struct regmap_config pat9125_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+};
+
+static const struct iio_info pat9125_info = {
+ .read_raw = pat9125_read_raw,
+ .write_raw = pat9125_write_raw,
+};
+
+/*
+ * To detect if a new value is available, register status is checked. This
+ * method is safer than using a flag on GPIO IRQ to track event while sampling
+ * because falling edge is missed when device trig just after a read reg value
+ * (that happen for fast motions or high CPI setting).
+ *
+ * Note: To avoid infinite loop in "iio_trigger_notify_done" when it is not in
+ * buffer mode and kernel warning due to nested IRQ thread,
+ * this function must return 0.
+ */
+static int pat9125_trig_try_reenable(struct iio_trigger *trig)
+{
+ struct pat9125_data *data = iio_trigger_get_drvdata(trig);
+ struct regmap *regmap = data->regmap;
+ int status = 0;
+
+ if (data->sampling) {
+ regmap_read(regmap, PAT9125_MOTION_STATUS_REG, &status);
+ if (status & PAT9125_VALID_MOTION_DATA_BIT) {
+ data->sampling = false;
+ iio_trigger_poll_chained(data->indio_trig);
+ return 0;
+ }
+ }
+ data->sampling = false;
+ return 0;
+}
+
+static const struct iio_trigger_ops pat9125_trigger_ops = {
+ .try_reenable = pat9125_trig_try_reenable,
+};
+
+static int pat9125_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct pat9125_data *data;
+ struct iio_dev *indio_dev;
+ int ret, sensor_pid;
+
+ indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
+ if (!indio_dev) {
+ dev_err(&client->dev, "IIO device allocation failed\n");
+ return -ENOMEM;
+ }
+
+ data = iio_priv(indio_dev);
+ indio_dev->dev.parent = &client->dev;
+ indio_dev->name = id->name;
+ indio_dev->channels = pat9125_channels;
+ indio_dev->num_channels = ARRAY_SIZE(pat9125_channels);
+ indio_dev->info = &pat9125_info;
+ indio_dev->modes = INDIO_DIRECT_MODE;
+
+ ret = devm_iio_triggered_buffer_setup(&client->dev, indio_dev, NULL,
+ pat9125_threaded_trigger_handler, &pat9125_buffer_ops);
+ if (ret) {
+ dev_err(&client->dev, "unable to setup triggered buffer\n");
+ return ret;
+ }
+
+ data->indio_trig = devm_iio_trigger_alloc(&client->dev, "%s-dev%d",
+ indio_dev->name, indio_dev->id);
+ if (!data->indio_trig)
+ return -ENOMEM;
+ data->indio_trig->dev.parent = &client->dev;
+ data->indio_trig->ops = &pat9125_trigger_ops;
+ iio_trigger_set_drvdata(data->indio_trig, data);
+ ret = devm_iio_trigger_register(&client->dev, data->indio_trig);
+ if (ret) {
+ dev_err(&client->dev, "unable to register trigger\n");
+ return ret;
+ }
+
+ data->regmap = devm_regmap_init_i2c(client, &pat9125_regmap_config);
+ if (IS_ERR(data->regmap)) {
+ dev_err(&client->dev, "regmap init failed %ld\n",
+ PTR_ERR(data->regmap));
+ return PTR_ERR(data->regmap);
+ }
+
+ /* Check device ID */
+ ret = regmap_read(data->regmap, PAT9125_PRD_ID1_REG, &sensor_pid);
+ if (ret < 0) {
+ dev_err(&client->dev, "register 0x%x access failed %d\n",
+ PAT9125_PRD_ID1_REG, ret);
+ return ret;
+ }
+ if (sensor_pid != PAT9125_SENSOR_ID_VAL)
+ return -ENODEV;
+
+ /* Switch to bank0 (Magic number)*/
+ ret = regmap_write(data->regmap, 0x7F, 0x00);
+ if (ret < 0) {
+ dev_err(indio_dev->dev.parent, "register 0x%x access failed %d\n",
+ 0x7F, ret);
+ return ret;
+ }
+
+ /* Software reset */
+ ret = regmap_write_bits(data->regmap,
+ PAT9125_CONFIG_REG,
+ PAT9125_RESET_BIT,
+ 1);
+ if (ret < 0) {
+ dev_err(&client->dev, "register 0x%x access failed %d\n",
+ PAT9125_CONFIG_REG, ret);
+ return ret;
+ }
+
+ msleep(20);
+
+ /* Init GPIO IRQ */
+ if (client->irq) {
+ ret = devm_request_threaded_irq(&client->dev,
+ client->irq,
+ NULL,
+ pat9125_threaded_event_handler,
+ IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+ "pat9125",
+ indio_dev);
+ if (ret) {
+ dev_err(&client->dev, "GPIO IRQ init failed\n");
+ return ret;
+ }
+ }
+
+ ret = devm_iio_device_register(&client->dev, indio_dev);
+ if (ret) {
+ dev_err(&client->dev, "IIO device register failed\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static const struct i2c_device_id pat9125_id[] = {
+ { "pat9125", 0 },
+ {}
+};
+MODULE_DEVICE_TABLE(i2c, pat9125_id);
+
+static const unsigned short normal_i2c[] = {
+ PAT9125_I2C_ADDR_HI,
+ PAT9125_I2C_ADDR_LO,
+ PAT9125_I2C_ADDR_NC,
+ I2C_CLIENT_END
+};
+
+static struct i2c_driver pat9125_driver = {
+ .driver = {
+ .name = "pat9125",
+ },
+ .probe = pat9125_probe,
+ .address_list = normal_i2c,
+ .id_table = pat9125_id,
+};
+
+module_i2c_driver(pat9125_driver);
+
+MODULE_AUTHOR("Alexandre Mergnat <amergnat@baylibre.com>");
+MODULE_DESCRIPTION("Optical Tracking sensor");
+MODULE_LICENSE("GPL");
--
2.17.1
^ permalink raw reply related
* [PATCH v4 2/3] dt-bindings: iio: position: Add docs pat9125
From: Alexandre Mergnat @ 2019-07-13 8:04 UTC (permalink / raw)
To: robh+dt, mark.rutland, jic23
Cc: linux-kernel, linux-iio, baylibre-upstreaming, dmitry.torokhov,
linux-input, devicetree, Alexandre Mergnat
In-Reply-To: <20190713080455.17513-1-amergnat@baylibre.com>
Add documentation for the optical tracker PAT9125 and
"position" directory for chip which can provides position data.
Signed-off-by: Alexandre Mergnat <amergnat@baylibre.com>
---
.../bindings/iio/position/pat9125.txt | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
create mode 100644 Documentation/devicetree/bindings/iio/position/pat9125.txt
diff --git a/Documentation/devicetree/bindings/iio/position/pat9125.txt b/Documentation/devicetree/bindings/iio/position/pat9125.txt
new file mode 100644
index 000000000000..4028aeef9b42
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/position/pat9125.txt
@@ -0,0 +1,18 @@
+PixArt Imaging PAT9125 Optical Tracking Miniature Chip device driver
+
+Required properties:
+ - compatible: must be "pixart,pat9125"
+ - reg: i2c address where to find the device
+ - interrupts: the sole interrupt generated by the device
+
+ Refer to interrupt-controller/interrupts.txt for generic
+ interrupt client node bindings.
+
+Example:
+
+pat9125@75 {
+ compatible = "pixart,pat9125";
+ reg = <0x75>;
+ interrupt-parent = <&gpio3>;
+ interrupts = <12 IRQ_TYPE_EDGE_FALLING>;
+};
--
2.17.1
^ permalink raw reply related
* [PATCH v4 1/3] dt-bindings: Add pixart vendor
From: Alexandre Mergnat @ 2019-07-13 8:04 UTC (permalink / raw)
To: robh+dt, mark.rutland, jic23
Cc: linux-kernel, linux-iio, baylibre-upstreaming, dmitry.torokhov,
linux-input, devicetree, Alexandre Mergnat
In-Reply-To: <20190713080455.17513-1-amergnat@baylibre.com>
PixArt Imaging Inc. is expertized in CMOS image sensors (CIS),
capacitive touch controllers and related imaging application development.
Signed-off-by: Alexandre Mergnat <amergnat@baylibre.com>
---
Documentation/devicetree/bindings/vendor-prefixes.yaml | 2 ++
1 file changed, 2 insertions(+)
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml
index 18b79c4cf7d5..120529f40c7c 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.yaml
+++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml
@@ -705,6 +705,8 @@ patternProperties:
description: Pine64
"^pineriver,.*":
description: Shenzhen PineRiver Designs Co., Ltd.
+ "^pixart,.*":
+ description: PixArt Imaging Inc.
"^pixcir,.*":
description: PIXCIR MICROELECTRONICS Co., Ltd
"^plantower,.*":
--
2.17.1
^ permalink raw reply related
* [PATCH v4 0/3] Add PAT9125 optical tracker driver
From: Alexandre Mergnat @ 2019-07-13 8:04 UTC (permalink / raw)
To: robh+dt, mark.rutland, jic23
Cc: linux-kernel, linux-iio, baylibre-upstreaming, dmitry.torokhov,
linux-input, devicetree, Alexandre Mergnat
PixArt Imaging PAT9125 is a miniature low power optical navigation chip
using LASER light source enabling digital surface tracking.
This device driver use IIO API to provide punctual and/or buffered data.
The data is a relative position from where start the device on X and Y
axis, depend on CPI (Counts Per Inch) resolution setting chosen.
The device support CPI configuration through IIO interface.
This patchset :
- Update vendor prefix
- Add the bindings for this device
- Add the device driver
- Add directory for optical tracker devices
Change since v3:
- Replace delta value by relative position
- Improve write protected reg function by removing print log and obvious
returns
- Handle error in postenable buffer function
Change since v2:
- Fix typo
- Add constructor webpage and datasheet in commit message
- Use BIT() macro for define bit mask
- Remove shift from IIO channel spec structure
- Replace IIO_LE by IIO_CPU from IIO channel spec structure
- Replace memcpy() by cast (s32)
- Rename "pat9125_trig_try_reen" to "pat9125_trig_try_reenable"
- Add carriage return (\n) at the end of each "dev_err" function
- Remove "iio_trigger_unregister" in case of "iio_trigger_register" fail,
register function already manage it
- Remove log which print device name in case of successful initialization
- Fix enabled IRQ flag warning during nested IRQ thread
- Improve retry algo now based on status register
- Remove "ts", "motion_detected" and "buffer_mode" from pat9125_data
structure
- Rename all "ot" directories to "position"
- Polling sample through IIO_CHAN_INFO_RAW now return position value
(relative to the position at initialization time) instead of delta
position
- Clean iio_buffer_setup_ops structure by removing NULL pointer.
- Use devm_iio_ function for all init functions and then delete
"pat9125_remove"
- Move device_register at the end of probe function
- Replace MODULE_PARM_DESC by IIO_SCALE to set axis resolution (CPI)
Change since v1:
- Fix typo
- Rename some defines / variables
- Remove I2C client from driver structure
- Change type of delta_x and delta_y from s16 to s32 to simplify signed
operations
- Add module parameter for axis resolution
- Replace "IIO_MOD_X_AND_Y" by "IIO_MOD_X" and "IIO_MOD_Y"
- Add sign extension macro
- Improve read value algorithm to avoid data loss
- Implement a trigger handler function which can work with any IIO
trigger, independently of it own GPIO IRQ, to match with IIO
requirement/behaviour
- Replace iio push event function by iio trigger poll in GPIO IRQ handler
- Use triggered_buffer helpers to replace kfifo use, setup buffer,
implement enable/disable setup buffer operations, IIO trigger
allocation and re-enable operations
- Remove useless "goto"
- Change GPIO IRQ handler from planified thread to IRQ thread
- Change GPIO IRQ trigger from low level and one shot to falling edge
- Add device unregister and buffer cleanup to driver remove function
Alexandre Mergnat (3):
dt-bindings: Add pixart vendor
dt-bindings: iio: position: Add docs pat9125
iio: Add PAT9125 optical tracker sensor
.../bindings/iio/position/pat9125.txt | 18 +
.../devicetree/bindings/vendor-prefixes.yaml | 2 +
drivers/iio/Kconfig | 1 +
drivers/iio/Makefile | 1 +
drivers/iio/position/Kconfig | 18 +
drivers/iio/position/Makefile | 6 +
drivers/iio/position/pat9125.c | 506 ++++++++++++++++++
7 files changed, 552 insertions(+)
create mode 100644 Documentation/devicetree/bindings/iio/position/pat9125.txt
create mode 100644 drivers/iio/position/Kconfig
create mode 100644 drivers/iio/position/Makefile
create mode 100644 drivers/iio/position/pat9125.c
--
2.17.1
^ permalink raw reply
* Fwd: [PATCH v4 0/3] Add PAT9125 optical tracker driver
From: Alexandre Mergnat @ 2019-07-13 7:57 UTC (permalink / raw)
Cc: devicetree
In-Reply-To: <15B09F895BF9AE09.30352@groups.io>
PixArt Imaging PAT9125 is a miniature low power optical navigation chip
using LASER light source enabling digital surface tracking.
This device driver use IIO API to provide punctual and/or buffered data.
The data is a relative position from where start the device on X and Y
axis, depend on CPI (Counts Per Inch) resolution setting chosen.
The device support CPI configuration through IIO interface.
This patchset :
- Update vendor prefix
- Add the bindings for this device
- Add the device driver
- Add directory for optical tracker devices
Change since v3:
- Replace delta value by relative position
- Improve write protected reg function by removing print log and obvious
returns
- Handle error in postenable buffer function
Change since v2:
- Fix typo
- Add constructor webpage and datasheet in commit message
- Use BIT() macro for define bit mask
- Remove shift from IIO channel spec structure
- Replace IIO_LE by IIO_CPU from IIO channel spec structure
- Replace memcpy() by cast (s32)
- Rename "pat9125_trig_try_reen" to "pat9125_trig_try_reenable"
- Add carriage return (\n) at the end of each "dev_err" function
- Remove "iio_trigger_unregister" in case of "iio_trigger_register" fail,
register function already manage it
- Remove log which print device name in case of successful initialization
- Fix enabled IRQ flag warning during nested IRQ thread
- Improve retry algo now based on status register
- Remove "ts", "motion_detected" and "buffer_mode" from pat9125_data
structure
- Rename all "ot" directories to "position"
- Polling sample through IIO_CHAN_INFO_RAW now return position value
(relative to the position at initialization time) instead of delta
position
- Clean iio_buffer_setup_ops structure by removing NULL pointer.
- Use devm_iio_ function for all init functions and then delete
"pat9125_remove"
- Move device_register at the end of probe function
- Replace MODULE_PARM_DESC by IIO_SCALE to set axis resolution (CPI)
Change since v1:
- Fix typo
- Rename some defines / variables
- Remove I2C client from driver structure
- Change type of delta_x and delta_y from s16 to s32 to simplify signed
operations
- Add module parameter for axis resolution
- Replace "IIO_MOD_X_AND_Y" by "IIO_MOD_X" and "IIO_MOD_Y"
- Add sign extension macro
- Improve read value algorithm to avoid data loss
- Implement a trigger handler function which can work with any IIO
trigger, independently of it own GPIO IRQ, to match with IIO
requirement/behaviour
- Replace iio push event function by iio trigger poll in GPIO IRQ handler
- Use triggered_buffer helpers to replace kfifo use, setup buffer,
implement enable/disable setup buffer operations, IIO trigger
allocation and re-enable operations
- Remove useless "goto"
- Change GPIO IRQ handler from planified thread to IRQ thread
- Change GPIO IRQ trigger from low level and one shot to falling edge
- Add device unregister and buffer cleanup to driver remove function
Alexandre Mergnat (3):
dt-bindings: Add pixart vendor
dt-bindings: iio: position: Add docs pat9125
iio: Add PAT9125 optical tracker sensor
.../bindings/iio/position/pat9125.txt | 18 +
.../devicetree/bindings/vendor-prefixes.yaml | 2 +
drivers/iio/Kconfig | 1 +
drivers/iio/Makefile | 1 +
drivers/iio/position/Kconfig | 18 +
drivers/iio/position/Makefile | 6 +
drivers/iio/position/pat9125.c | 506 ++++++++++++++++++
7 files changed, 552 insertions(+)
create mode 100644 Documentation/devicetree/bindings/iio/position/pat9125.txt
create mode 100644 drivers/iio/position/Kconfig
create mode 100644 drivers/iio/position/Makefile
create mode 100644 drivers/iio/position/pat9125.c
--
2.17.1
-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#161): https://groups.io/g/baylibre-upstreaming/message/161
Mute This Topic: https://groups.io/mt/32440226/1769967
Group Owner: baylibre-upstreaming+owner@groups.io
Unsubscribe: https://groups.io/g/baylibre-upstreaming/unsub
[amergnat@baylibre.com]
-=-=-=-=-=-=-=-=-=-=-=-
^ permalink raw reply
* Re: [PATCH V13 12/12] PCI: tegra: Add Tegra194 PCIe support
From: Vidya Sagar @ 2019-07-13 7:04 UTC (permalink / raw)
To: Lorenzo Pieralisi
Cc: mark.rutland, devicetree, mperttunen, mmaddireddy, linux-pci,
catalin.marinas, will.deacon, linux-kernel, kthota, kishon,
linux-tegra, robh+dt, thierry.reding, gustavo.pimentel,
jingoohan1, bhelgaas, digetx, jonathanh, linux-arm-kernel,
sagar.tv
In-Reply-To: <20190712160754.GA24285@e121166-lin.cambridge.arm.com>
On 7/12/2019 9:37 PM, Lorenzo Pieralisi wrote:
> On Fri, Jul 12, 2019 at 09:02:49PM +0530, Vidya Sagar wrote:
>
> [...]
>
>>>> +static irqreturn_t tegra_pcie_irq_handler(int irq, void *arg)
>>>> +{
>>>> + struct tegra_pcie_dw *pcie = arg;
>>>> +
>>>> + if (pcie->mode == DW_PCIE_RC_TYPE)
>>>> + return tegra_pcie_rp_irq_handler(pcie);
>>>
>>> What's the point of registering the handler if mode != DW_PCIE_RC_TYPE ?
>> Currently this driver supports only root port mode but we have a plan
>> to add support for endpoint mode (as Tegra194 as dual mode
>> controllers) also in future and when that happens, we'll have a
>> corresponding tegra_pcie_ep_irq_handler() to take care of ep specific
>> interrupts.
>
> Sure, that's why you should add tegra_pcie_dw->mode when it is needed,
> not in this patch.
Ok.
>
> [...]
>
>>>> +static int tegra_pcie_dw_host_init(struct pcie_port *pp)
>>>> +{
>>>> + struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
>>>> + struct tegra_pcie_dw *pcie = to_tegra_pcie(pci);
>>>> + u32 val, tmp, offset, speed;
>>>> + unsigned int count;
>>>> + u16 val_w;
>>>> +
>>>> +core_init:
>>>
>>> I think it would be cleaner to include all registers programming
>>> within a function and we remove this label (and goto) below.
>> Some background: As per spec r4.0 v1.0, downstream ports that support
>> 16.0 GT/s must support Scaled Flow Control (sec 3.4.2) and Tegra194's
>> downstream ports being 16.0 GT/s capable, enable scaled flow control
>> by having Data Link Feature (sec 7.7.4) enabled by default. There is
>> one endpoint (ASMedia USB3.0 controller) that doesn't link up with
>> root port because of this (i.e. DLF being enabled). The way we are
>> detecting this situation is to check for partial linkup i.e. one of
>> application logic registers (i.e. from "appl" region) says link is up
>> but the same is not reflected in configuration space of root port.
>> Recommendation from our hardware team in this situation is to disable
>> DLF in root port and try link up with endpoint again. To achieve
>> this, we put the core through reset cycle, disable DLF and proceed
>> with configuring all other registers and check for link up.
>>
>> Initially in Patch-1, I didn't have goto statement but a recursion
>> with depth-1 (as the above situation occurs only once). It was
>> reviewed @ http://patchwork.ozlabs.org/patch/1065707/ and Thierry said
>> it would be simpler to use a goto instead of calling the same function
>> again. So, I modified the code accordingly. Please do let me know if
>> you strongly feel we should call tegra_pcie_dw_host_init() instead of
>> goto here. I'll change it.
>
> I did not say we should call tegra_pcie_dw_host_init(), sorry for
> not being clear. What I asked is factoring out registers programming
> in a function and call it where core_init: label is and call it
> again if DLF enablement causes link up to fail.
Ok.
>
> [...]
>
>>>> +static int tegra_pcie_bpmp_set_ctrl_state(struct tegra_pcie_dw *pcie,
>>>> + bool enable)
>>>> +{
>>>> + struct mrq_uphy_response resp;
>>>> + struct tegra_bpmp_message msg;
>>>> + struct mrq_uphy_request req;
>>>> + int err;
>>>> +
>>>> + if (pcie->cid == 5)
>>>> + return 0;
>>>
>>> What's wrong with cid == 5 ? Explain please.
>> Controller with ID=5 doesn't need any programming to enable it which is
>> done here through calling firmware API.
>>
>>>
>>>> + memset(&req, 0, sizeof(req));
>>>> + memset(&resp, 0, sizeof(resp));
>>>> +
>>>> + req.cmd = CMD_UPHY_PCIE_CONTROLLER_STATE;
>>>> + req.controller_state.pcie_controller = pcie->cid;
>>>> + req.controller_state.enable = enable;
>>>> +
>>>> + memset(&msg, 0, sizeof(msg));
>>>> + msg.mrq = MRQ_UPHY;
>>>> + msg.tx.data = &req;
>>>> + msg.tx.size = sizeof(req);
>>>> + msg.rx.data = &resp;
>>>> + msg.rx.size = sizeof(resp);
>>>> +
>>>> + if (irqs_disabled())
>>>
>>> Can you explain to me what this check is meant to achieve please ?
>> Firmware interface provides different APIs to be called when there are
>> no interrupts enabled in the system (noirq context) and otherwise
>> hence checking that situation here and calling appropriate API.
>
> That's what I am questioning. Being called from {suspend/resume}_noirq()
> callbacks (if that's the code path this check caters for) does not mean
> irqs_disabled() == true.
Agree.
Actually, I got a hint of having this check from the following.
Both tegra_bpmp_transfer_atomic() and tegra_bpmp_transfer() are indirectly
called by APIs registered with .master_xfer() and .master_xfer_atomic() hooks of
struct i2c_algorithm and the decision to call which one of these is made using the
following check in i2c-core.h file.
static inline bool i2c_in_atomic_xfer_mode(void)
{
return system_state > SYSTEM_RUNNING && irqs_disabled();
}
I think I should use this condition as is IIUC.
Please let me know if there are any concerns with this.
>
> Actually, if tegra_bpmp_transfer() requires IRQs to be enabled you may
> even end up in a situation where that blocking call does not wake up
> because the IRQ in question was disabled in the NOIRQ suspend/resume
> phase.
>
> [...]
>
>>>> +static int tegra_pcie_dw_probe(struct platform_device *pdev)
>>>> +{
>>>> + const struct tegra_pcie_soc *data;
>>>> + struct device *dev = &pdev->dev;
>>>> + struct resource *atu_dma_res;
>>>> + struct tegra_pcie_dw *pcie;
>>>> + struct resource *dbi_res;
>>>> + struct pcie_port *pp;
>>>> + struct dw_pcie *pci;
>>>> + struct phy **phys;
>>>> + char *name;
>>>> + int ret;
>>>> + u32 i;
>>>> +
>>>> + pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL);
>>>> + if (!pcie)
>>>> + return -ENOMEM;
>>>> +
>>>> + pci = &pcie->pci;
>>>> + pci->dev = &pdev->dev;
>>>> + pci->ops = &tegra_dw_pcie_ops;
>>>> + pp = &pci->pp;
>>>> + pcie->dev = &pdev->dev;
>>>> +
>>>> + data = (struct tegra_pcie_soc *)of_device_get_match_data(dev);
>>>> + if (!data)
>>>> + return -EINVAL;
>>>> + pcie->mode = (enum dw_pcie_device_mode)data->mode;
>>>> +
>>>> + ret = tegra_pcie_dw_parse_dt(pcie);
>>>> + if (ret < 0) {
>>>> + dev_err(dev, "Failed to parse device tree: %d\n", ret);
>>>> + return ret;
>>>> + }
>>>> +
>>>> + pcie->pex_ctl_supply = devm_regulator_get(dev, "vddio-pex-ctl");
>>>> + if (IS_ERR(pcie->pex_ctl_supply)) {
>>>> + dev_err(dev, "Failed to get regulator: %ld\n",
>>>> + PTR_ERR(pcie->pex_ctl_supply));
>>>> + return PTR_ERR(pcie->pex_ctl_supply);
>>>> + }
>>>> +
>>>> + pcie->core_clk = devm_clk_get(dev, "core");
>>>> + if (IS_ERR(pcie->core_clk)) {
>>>> + dev_err(dev, "Failed to get core clock: %ld\n",
>>>> + PTR_ERR(pcie->core_clk));
>>>> + return PTR_ERR(pcie->core_clk);
>>>> + }
>>>> +
>>>> + pcie->appl_res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
>>>> + "appl");
>>>> + if (!pcie->appl_res) {
>>>> + dev_err(dev, "Failed to find \"appl\" region\n");
>>>> + return PTR_ERR(pcie->appl_res);
>>>> + }
>>>> + pcie->appl_base = devm_ioremap_resource(dev, pcie->appl_res);
>>>> + if (IS_ERR(pcie->appl_base))
>>>> + return PTR_ERR(pcie->appl_base);
>>>> +
>>>> + pcie->core_apb_rst = devm_reset_control_get(dev, "apb");
>>>> + if (IS_ERR(pcie->core_apb_rst)) {
>>>> + dev_err(dev, "Failed to get APB reset: %ld\n",
>>>> + PTR_ERR(pcie->core_apb_rst));
>>>> + return PTR_ERR(pcie->core_apb_rst);
>>>> + }
>>>> +
>>>> + phys = devm_kcalloc(dev, pcie->phy_count, sizeof(*phys), GFP_KERNEL);
>>>> + if (!phys)
>>>> + return PTR_ERR(phys);
>>>> +
>>>> + for (i = 0; i < pcie->phy_count; i++) {
>>>> + name = kasprintf(GFP_KERNEL, "p2u-%u", i);
>>>> + if (!name) {
>>>> + dev_err(dev, "Failed to create P2U string\n");
>>>> + return -ENOMEM;
>>>> + }
>>>> + phys[i] = devm_phy_get(dev, name);
>>>> + kfree(name);
>>>> + if (IS_ERR(phys[i])) {
>>>> + ret = PTR_ERR(phys[i]);
>>>> + dev_err(dev, "Failed to get PHY: %d\n", ret);
>>>> + return ret;
>>>> + }
>>>> + }
>>>> +
>>>> + pcie->phys = phys;
>>>> +
>>>> + dbi_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dbi");
>>>> + if (!dbi_res) {
>>>> + dev_err(dev, "Failed to find \"dbi\" region\n");
>>>> + return PTR_ERR(dbi_res);
>>>> + }
>>>> + pcie->dbi_res = dbi_res;
>>>> +
>>>> + pci->dbi_base = devm_ioremap_resource(dev, dbi_res);
>>>> + if (IS_ERR(pci->dbi_base))
>>>> + return PTR_ERR(pci->dbi_base);
>>>> +
>>>> + /* Tegra HW locates DBI2 at a fixed offset from DBI */
>>>> + pci->dbi_base2 = pci->dbi_base + 0x1000;
>>>> +
>>>> + atu_dma_res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
>>>> + "atu_dma");
>>>> + if (!atu_dma_res) {
>>>> + dev_err(dev, "Failed to find \"atu_dma\" region\n");
>>>> + return PTR_ERR(atu_dma_res);
>>>> + }
>>>> + pcie->atu_dma_res = atu_dma_res;
>>>> + pci->atu_base = devm_ioremap_resource(dev, atu_dma_res);
>>>> + if (IS_ERR(pci->atu_base))
>>>> + return PTR_ERR(pci->atu_base);
>>>> +
>>>> + pcie->core_rst = devm_reset_control_get(dev, "core");
>>>> + if (IS_ERR(pcie->core_rst)) {
>>>> + dev_err(dev, "Failed to get core reset: %ld\n",
>>>> + PTR_ERR(pcie->core_rst));
>>>> + return PTR_ERR(pcie->core_rst);
>>>> + }
>>>> +
>>>> + pp->irq = platform_get_irq_byname(pdev, "intr");
>>>> + if (!pp->irq) {
>>>> + dev_err(dev, "Failed to get \"intr\" interrupt\n");
>>>> + return -ENODEV;
>>>> + }
>>>> +
>>>> + ret = devm_request_irq(dev, pp->irq, tegra_pcie_irq_handler,
>>>> + IRQF_SHARED, "tegra-pcie-intr", pcie);
>>>> + if (ret) {
>>>> + dev_err(dev, "Failed to request IRQ %d: %d\n", pp->irq, ret);
>>>> + return ret;
>>>> + }
>>>> +
>>>> + pcie->bpmp = tegra_bpmp_get(dev);
>>>> + if (IS_ERR(pcie->bpmp))
>>>> + return PTR_ERR(pcie->bpmp);
>>>> +
>>>> + platform_set_drvdata(pdev, pcie);
>>>> +
>>>> + if (pcie->mode == DW_PCIE_RC_TYPE) {
>>>> + ret = tegra_pcie_config_rp(pcie);
>>>> + if (ret && ret != -ENOMEDIUM)
>>>> + goto fail;
>>>> + else
>>>> + return 0;
>>>
>>> So if the link is not up we still go ahead and make probe
>>> succeed. What for ?
>> We may need root port to be available to support hot-plugging of
>> endpoint devices, so, we don't fail the probe.
>
> We need it or we don't. If you do support hotplugging of endpoint
> devices point me at the code, otherwise link up failure means
> failure to probe.
Currently hotplugging of endpoint is not supported, but it is one of the use cases that
we may add support for in future.
But, why should we fail probe if link up doesn't happen? As such, nothing went wrong in
terms of root port initialization right?
I checked other DWC based implementations and following are not failing the probe
pci-dra7xx.c, pcie-armada8k.c, pcie-artpec6.c, pcie-histb.c, pcie-kirin.c, pcie-spear13xx.c,
pci-exynos.c, pci-imx6.c, pci-keystone.c, pci-layerscape.c
Although following do fail the probe if link is not up.
pcie-qcom.c, pcie-uniphier.c, pci-meson.c
So, to me, it looks more like a choice we can make whether to fail the probe or not and in this
case we are choosing not to fail.
>
>>>> + }
>>>> +
>>>> +fail:
>>>> + tegra_bpmp_put(pcie->bpmp);
>>>> + return ret;
>>>> +}
>>>> +
>>>> +static int tegra_pcie_dw_remove(struct platform_device *pdev)
>>>> +{
>>>> + struct tegra_pcie_dw *pcie = platform_get_drvdata(pdev);
>>>> +
>>>> + if (pcie->mode != DW_PCIE_RC_TYPE)
>>>> + return 0;
>>>> +
>>>> + if (!pcie->link_state)
>>>> + return 0;
>>>> +
>>>> + debugfs_remove_recursive(pcie->debugfs);
>>>> + tegra_pcie_deinit_controller(pcie);
>>>> + pm_runtime_put_sync(pcie->dev);
>>>> + pm_runtime_disable(pcie->dev);
>>>> + tegra_bpmp_put(pcie->bpmp);
>>>> +
>>>> + return 0;
>>>> +}
>>>> +
>>>> +static int tegra_pcie_dw_suspend_late(struct device *dev)
>>>> +{
>>>> + struct tegra_pcie_dw *pcie = dev_get_drvdata(dev);
>>>> + u32 val;
>>>> +
>>>> + if (!pcie->link_state)
>>>> + return 0;
>>>> +
>>>> + /* Enable HW_HOT_RST mode */
>>>> + val = appl_readl(pcie, APPL_CTRL);
>>>> + val &= ~(APPL_CTRL_HW_HOT_RST_MODE_MASK <<
>>>> + APPL_CTRL_HW_HOT_RST_MODE_SHIFT);
>>>> + val |= APPL_CTRL_HW_HOT_RST_EN;
>>>> + appl_writel(pcie, val, APPL_CTRL);
>>>> +
>>>> + return 0;
>>>> +}
>>>> +
>>>> +static int tegra_pcie_dw_suspend_noirq(struct device *dev)
>>>> +{
>>>> + struct tegra_pcie_dw *pcie = dev_get_drvdata(dev);
>>>> +
>>>> + if (!pcie->link_state)
>>>> + return 0;
>>>> +
>>>> + /* Save MSI interrupt vector */
>>>> + pcie->msi_ctrl_int = dw_pcie_readl_dbi(&pcie->pci,
>>>> + PORT_LOGIC_MSI_CTRL_INT_0_EN);
>>>> + tegra_pcie_downstream_dev_to_D0(pcie);
>>>
>>> I think this requires some comments. AFAIU this is allowed by
>>> the PCI specs (PCI Express Base 4.0 r1.0 September 29-2017,
>>> 5.2 Link State Power Management). However, I would like to
>>> understand how this plays with the D state the devices are left
>>> in upon system suspend.
>>>
>>> "As the following example illustrates, it is also possible to remove
>>> power without first placing all Functions into D3Hot".
>>>
>>> I assume that's what happens on this platform to allow L2 entry but
>>> again, this needs clarification.
>> Yes. It is true that in the case of Tegra194, it brings devices back
>> to D0 before putting link to L2 state.
>
> Comment it, extensively, so that anyone reading the code understands
> why it is done so and what happens to devices then.
I added comment in tegra_pcie_deinit_controller() where this API is called
but I think I should move the comment inside tegra_pcie_downstream_dev_to_D0()
API and also add more info to it.
I'll take care of it in the next patch.
>
> Lorenzo
>
^ permalink raw reply
* Re: [PATCH V5 11/18] clk: tegra210: Add support for Tegra210 clocks
From: Sowjanya Komatineni @ 2019-07-13 5:54 UTC (permalink / raw)
To: Dmitry Osipenko, thierry.reding, jonathanh, tglx, jason,
marc.zyngier, linus.walleij, stefan, mark.rutland
Cc: pdeschrijver, pgaikwad, sboyd, linux-clk, linux-gpio, jckuo,
josephl, talho, linux-tegra, linux-kernel, mperttunen, spatra,
robh+dt, devicetree
In-Reply-To: <a5e1a6df-dff7-9e0c-9551-f78103a5462f@gmail.com>
On 6/29/19 8:10 AM, Dmitry Osipenko wrote:
> 28.06.2019 5:12, Sowjanya Komatineni пишет:
>> This patch adds system suspend and resume support for Tegra210
>> clocks.
>>
>> All the CAR controller settings are lost on suspend when core power
>> goes off.
>>
>> This patch has implementation for saving and restoring all the PLLs
>> and clocks context during system suspend and resume to have the
>> clocks back to same state for normal operation.
>>
>> Acked-by: Thierry Reding <treding@nvidia.com>
>> Signed-off-by: Sowjanya Komatineni <skomatineni@nvidia.com>
>> ---
>> drivers/clk/tegra/clk-tegra210.c | 115 ++++++++++++++++++++++++++++++++++++++-
>> drivers/clk/tegra/clk.c | 14 +++++
>> drivers/clk/tegra/clk.h | 1 +
>> 3 files changed, 127 insertions(+), 3 deletions(-)
>>
>> diff --git a/drivers/clk/tegra/clk-tegra210.c b/drivers/clk/tegra/clk-tegra210.c
>> index 1c08c53482a5..1b839544e086 100644
>> --- a/drivers/clk/tegra/clk-tegra210.c
>> +++ b/drivers/clk/tegra/clk-tegra210.c
>> @@ -9,10 +9,12 @@
>> #include <linux/clkdev.h>
>> #include <linux/of.h>
>> #include <linux/of_address.h>
>> +#include <linux/of_platform.h>
>> #include <linux/delay.h>
>> #include <linux/export.h>
>> #include <linux/mutex.h>
>> #include <linux/clk/tegra.h>
>> +#include <linux/syscore_ops.h>
>> #include <dt-bindings/clock/tegra210-car.h>
>> #include <dt-bindings/reset/tegra210-car.h>
>> #include <linux/iopoll.h>
>> @@ -20,6 +22,7 @@
>> #include <soc/tegra/pmc.h>
>>
>> #include "clk.h"
>> +#include "clk-dfll.h"
>> #include "clk-id.h"
>>
>> /*
>> @@ -225,6 +228,7 @@
>>
>> #define CLK_RST_CONTROLLER_RST_DEV_Y_SET 0x2a8
>> #define CLK_RST_CONTROLLER_RST_DEV_Y_CLR 0x2ac
>> +#define CPU_SOFTRST_CTRL 0x380
>>
>> #define LVL2_CLK_GATE_OVRA 0xf8
>> #define LVL2_CLK_GATE_OVRC 0x3a0
>> @@ -2820,6 +2824,7 @@ static int tegra210_enable_pllu(void)
>> struct tegra_clk_pll_freq_table *fentry;
>> struct tegra_clk_pll pllu;
>> u32 reg;
>> + int ret;
>>
>> for (fentry = pll_u_freq_table; fentry->input_rate; fentry++) {
>> if (fentry->input_rate == pll_ref_freq)
>> @@ -2847,10 +2852,10 @@ static int tegra210_enable_pllu(void)
>> fence_udelay(1, clk_base);
>> reg |= PLL_ENABLE;
>> writel(reg, clk_base + PLLU_BASE);
>> + fence_udelay(1, clk_base);
>>
>> - readl_relaxed_poll_timeout_atomic(clk_base + PLLU_BASE, reg,
>> - reg & PLL_BASE_LOCK, 2, 1000);
>> - if (!(reg & PLL_BASE_LOCK)) {
>> + ret = tegra210_wait_for_mask(&pllu, PLLU_BASE, PLL_BASE_LOCK);
>> + if (ret) {
>> pr_err("Timed out waiting for PLL_U to lock\n");
>> return -ETIMEDOUT;
>> }
>> @@ -3283,6 +3288,103 @@ static void tegra210_disable_cpu_clock(u32 cpu)
>> }
>>
>> #ifdef CONFIG_PM_SLEEP
>> +static u32 cpu_softrst_ctx[3];
>> +static struct platform_device *dfll_pdev;
>> +#define car_readl(_base, _off) readl_relaxed(clk_base + (_base) + ((_off) * 4))
>> +#define car_writel(_val, _base, _off) \
>> + writel_relaxed(_val, clk_base + (_base) + ((_off) * 4))
>> +
>> +static int tegra210_clk_suspend(void)
>> +{
>> + unsigned int i;
>> + struct device_node *node;
>> +
>> + tegra_cclkg_burst_policy_save_context();
>> +
>> + if (!dfll_pdev) {
>> + node = of_find_compatible_node(NULL, NULL,
>> + "nvidia,tegra210-dfll");
>> + if (node)
>> + dfll_pdev = of_find_device_by_node(node);
>> +
>> + of_node_put(node);
>> + if (!dfll_pdev)
>> + pr_err("dfll node not found. no suspend for dfll\n");
>> + }
>> +
>> + if (dfll_pdev)
>> + tegra_dfll_suspend(dfll_pdev);
>> +
>> + /* Enable PLLP_OUT_CPU after dfll suspend */
>> + tegra_clk_set_pllp_out_cpu(true);
>> +
>> + tegra_sclk_cclklp_burst_policy_save_context();
>> +
>> + clk_save_context();
>> +
>> + for (i = 0; i < ARRAY_SIZE(cpu_softrst_ctx); i++)
>> + cpu_softrst_ctx[i] = car_readl(CPU_SOFTRST_CTRL, i);
>> +
>> + return 0;
>> +}
>> +
>> +static void tegra210_clk_resume(void)
>> +{
>> + unsigned int i;
>> + struct clk_hw *parent;
>> + struct clk *clk;
>> +
>> + /*
>> + * clk_restore_context restores clocks as per the clock tree.
>> + *
>> + * dfllCPU_out is first in the clock tree to get restored and it
>> + * involves programming DFLL controller along with restoring CPUG
>> + * clock burst policy.
>> + *
>> + * DFLL programming needs dfll_ref and dfll_soc peripheral clocks
>> + * to be restores which are part ofthe peripheral clocks.
>> + * So, peripheral clocks restore should happen prior to dfll clock
>> + * restore.
>> + */
>> +
>> + tegra_clk_osc_resume(clk_base);
>> + for (i = 0; i < ARRAY_SIZE(cpu_softrst_ctx); i++)
>> + car_writel(cpu_softrst_ctx[i], CPU_SOFTRST_CTRL, i);
>> +
>> + /* restore all plls and peripheral clocks */
>> + tegra210_init_pllu();
>> + clk_restore_context();
>> +
>> + fence_udelay(5, clk_base);
>> +
>> + /* resume SCLK and CPULP clocks */
>> + tegra_sclk_cpulp_burst_policy_restore_context();
>> +
>> + /*
>> + * restore CPUG clocks:
>> + * - enable DFLL in open loop mode
>> + * - switch CPUG to DFLL clock source
>> + * - close DFLL loop
>> + * - sync PLLX state
>> + */
>> + if (dfll_pdev)
>> + tegra_dfll_resume(dfll_pdev, false);
>> +
>> + tegra_cclkg_burst_policy_restore_context();
>> + fence_udelay(2, clk_base);
>> +
>> + if (dfll_pdev)
>> + tegra_dfll_resume(dfll_pdev, true);
>> +
>> + parent = clk_hw_get_parent(__clk_get_hw(clks[TEGRA210_CLK_CCLK_G]));
>> + clk = clks[TEGRA210_CLK_PLL_X];
>> + if (parent != __clk_get_hw(clk))
>> + tegra_clk_sync_state_pll(__clk_get_hw(clk));
>> +
>> + /* Disable PLL_OUT_CPU after DFLL resume */
>> + tegra_clk_set_pllp_out_cpu(false);
>> +}
>> +
>> static void tegra210_cpu_clock_suspend(void)
>> {
>> /* switch coresite to clk_m, save off original source */
>> @@ -3298,6 +3400,11 @@ static void tegra210_cpu_clock_resume(void)
>> }
>> #endif
>>
>> +static struct syscore_ops tegra_clk_syscore_ops = {
>> + .suspend = tegra210_clk_suspend,
>> + .resume = tegra210_clk_resume,
>> +};
>> +
>> static struct tegra_cpu_car_ops tegra210_cpu_car_ops = {
>> .wait_for_reset = tegra210_wait_cpu_in_reset,
>> .disable_clock = tegra210_disable_cpu_clock,
>> @@ -3583,5 +3690,7 @@ static void __init tegra210_clock_init(struct device_node *np)
>> tegra210_mbist_clk_init();
>>
>> tegra_cpu_car_ops = &tegra210_cpu_car_ops;
>> +
>> + register_syscore_ops(&tegra_clk_syscore_ops);
>> }
> Is it really worthwhile to use syscore_ops for suspend/resume given that drivers for
> won't resume before the CLK driver anyway? Are there any other options for CLK
> suspend/resume?
>
> I'm also not sure whether PM runtime API could be used at all in the context of
> syscore_ops ..
>
> Secondly, what about to use generic clk_save_context() / clk_restore_context()
> helpers for the suspend-resume? It looks to me that some other essential (and proper)
> platform driver (soc/tegra/? PMC?) should suspend-resume the clocks using the generic
> CLK Framework API.
Clock resume should happen very early to restore peripheral and cpu
clocks very early than peripheral drivers resume happens.
this patch series uses clk_save_context and clk_restore_context for
corresponding divider, pll, pllout.. save and restore context.
But as there is dependency on dfll resume and cpu and pllx clocks
restore, couldnt use clk_save_context and clk_restore_context for dfll.
So implemented recommended dfll resume sequence in main Tegra210 clock
driver along with invoking clk_save_context/clk_restore_context where
all other clocks save/restore happens as per clock tree traversal.
^ permalink raw reply
* Re: [PATCH V5 02/18] pinctrl: tegra: Add suspend and resume support
From: Sowjanya Komatineni @ 2019-07-13 5:48 UTC (permalink / raw)
To: Dmitry Osipenko, thierry.reding, jonathanh, tglx, jason,
marc.zyngier, linus.walleij, stefan, mark.rutland
Cc: pdeschrijver, pgaikwad, sboyd, linux-clk, linux-gpio, jckuo,
josephl, talho, linux-tegra, linux-kernel, mperttunen, spatra,
robh+dt, devicetree
In-Reply-To: <a262cbb3-845c-3ad1-16cc-375a24b9f7e9@gmail.com>
On 6/29/19 8:46 AM, Dmitry Osipenko wrote:
> 28.06.2019 5:12, Sowjanya Komatineni пишет:
>> This patch adds support for Tegra pinctrl driver suspend and resume.
>>
>> During suspend, context of all pinctrl registers are stored and
>> on resume they are all restored to have all the pinmux and pad
>> configuration for normal operation.
>>
>> Acked-by: Thierry Reding <treding@nvidia.com>
>> Signed-off-by: Sowjanya Komatineni <skomatineni@nvidia.com>
>> ---
>> drivers/pinctrl/tegra/pinctrl-tegra.c | 52 ++++++++++++++++++++++++++++++++
>> drivers/pinctrl/tegra/pinctrl-tegra.h | 3 ++
>> drivers/pinctrl/tegra/pinctrl-tegra210.c | 1 +
>> 3 files changed, 56 insertions(+)
>>
>> diff --git a/drivers/pinctrl/tegra/pinctrl-tegra.c b/drivers/pinctrl/tegra/pinctrl-tegra.c
>> index 34596b246578..e7c0a1011cba 100644
>> --- a/drivers/pinctrl/tegra/pinctrl-tegra.c
>> +++ b/drivers/pinctrl/tegra/pinctrl-tegra.c
>> @@ -621,6 +621,43 @@ static void tegra_pinctrl_clear_parked_bits(struct tegra_pmx *pmx)
>> }
>> }
>>
>> +static int tegra_pinctrl_suspend(struct device *dev)
>> +{
>> + struct tegra_pmx *pmx = dev_get_drvdata(dev);
>> + u32 *backup_regs = pmx->backup_regs;
>> + u32 *regs;
>> + unsigned int i, j;
>> +
>> + for (i = 0; i < pmx->nbanks; i++) {
>> + regs = pmx->regs[i];
>> + for (j = 0; j < pmx->reg_bank_size[i] / 4; j++)
>> + *backup_regs++ = readl(regs++);
>> + }
>> +
>> + return pinctrl_force_sleep(pmx->pctl);
>> +}
>> +
>> +static int tegra_pinctrl_resume(struct device *dev)
>> +{
>> + struct tegra_pmx *pmx = dev_get_drvdata(dev);
>> + u32 *backup_regs = pmx->backup_regs;
>> + u32 *regs;
>> + unsigned int i, j;
>> +
>> + for (i = 0; i < pmx->nbanks; i++) {
>> + regs = pmx->regs[i];
>> + for (j = 0; j < pmx->reg_bank_size[i] / 4; j++)
>> + writel(*backup_regs++, regs++);
>> + }
>> +
>> + return 0;
>> +}
>> +
>> +const struct dev_pm_ops tegra_pinctrl_pm = {
>> + .suspend = &tegra_pinctrl_suspend,
>> + .resume = &tegra_pinctrl_resume
>> +};
> Hm, so this are the generic platform-driver suspend-resume OPS here, which is very
> nice! But.. shouldn't pinctrl be resumed before the CLK driver (which is syscore_ops
> in this version of the series)? .. Given that "clock" function may need to be
> selected for some of the pins.
selection of clock functions on some Tegra pins through corresponding
pinmux (like extperiph clks) can happen after clock driver resume as
well where clock source is restored to state during suspend before
selecting clock function on that pin.
^ permalink raw reply
* [PATCH v4 8/8] ARM: dts: sun8i: s3: add devicetree for Lichee zero plus w/ S3
From: Icenowy Zheng @ 2019-07-13 3:46 UTC (permalink / raw)
To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Linus Walleij
Cc: devicetree, linux-arm-kernel, linux-kernel, linux-clk, linux-gpio,
linux-sunxi, Icenowy Zheng
In-Reply-To: <20190713034634.44585-1-icenowy@aosc.io>
Lichee zero plus is a core board made by Sipeed, which includes on-board
TF slot or SMT SD NAND, and optional SPI NOR or eMMC, a UART debug
header, a microUSB slot and a gold finger connector for expansion. It
can use either Sochip S3 or Allwinner S3L SoC.
Add the basic device tree for the core board, w/o optional onboard
storage, and with S3 SoC.
Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
---
No changes in v4.
Changes in v3:
- Drop common regulator DTSI usage and added vcc3v3 regulator.
arch/arm/boot/dts/Makefile | 1 +
.../boot/dts/sun8i-s3-lichee-zero-plus.dts | 8 ++++
.../dts/sun8i-s3-s3l-lichee-zero-plus.dtsi | 46 +++++++++++++++++++
3 files changed, 55 insertions(+)
create mode 100644 arch/arm/boot/dts/sun8i-s3-lichee-zero-plus.dts
create mode 100644 arch/arm/boot/dts/sun8i-s3-s3l-lichee-zero-plus.dtsi
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index 9159fa2cea90..e320460a952b 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -1114,6 +1114,7 @@ dtb-$(CONFIG_MACH_SUN8I) += \
sun8i-r16-nintendo-super-nes-classic.dtb \
sun8i-r16-parrot.dtb \
sun8i-r40-bananapi-m2-ultra.dtb \
+ sun8i-s3-lichee-zero-plus.dtb \
sun8i-t3-cqa3t-bv3.dtb \
sun8i-v3s-licheepi-zero.dtb \
sun8i-v3s-licheepi-zero-dock.dtb \
diff --git a/arch/arm/boot/dts/sun8i-s3-lichee-zero-plus.dts b/arch/arm/boot/dts/sun8i-s3-lichee-zero-plus.dts
new file mode 100644
index 000000000000..7d2f6b145190
--- /dev/null
+++ b/arch/arm/boot/dts/sun8i-s3-lichee-zero-plus.dts
@@ -0,0 +1,8 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (C) 2019 Icenowy Zheng <icenowy@aosc.io>
+ */
+
+/dts-v1/;
+#include "sun8i-s3.dtsi"
+#include "sun8i-s3-s3l-lichee-zero-plus.dtsi"
diff --git a/arch/arm/boot/dts/sun8i-s3-s3l-lichee-zero-plus.dtsi b/arch/arm/boot/dts/sun8i-s3-s3l-lichee-zero-plus.dtsi
new file mode 100644
index 000000000000..2677d319fb29
--- /dev/null
+++ b/arch/arm/boot/dts/sun8i-s3-s3l-lichee-zero-plus.dtsi
@@ -0,0 +1,46 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (C) 2019 Icenowy Zheng <icenowy@aosc.io>
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+ aliases {
+ serial0 = &uart0;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+
+ reg_vcc3v3: vcc3v3 {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc3v3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+};
+
+&mmc0 {
+ broken-cd;
+ bus-width = <4>;
+ vmmc-supply = <®_vcc3v3>;
+ status = "okay";
+};
+
+&uart0 {
+ pinctrl-0 = <&uart0_pb_pins>;
+ pinctrl-names = "default";
+ status = "okay";
+};
+
+&usb_otg {
+ dr_mode = "otg";
+ status = "okay";
+};
+
+&usbphy {
+ usb0_id_det-gpios = <&pio 5 6 GPIO_ACTIVE_HIGH>;
+ status = "okay";
+};
--
2.21.0
^ permalink raw reply related
* [PATCH v4 7/8] dt-bindings: arm: sunxi: add binding for Lichee Zero Plus core board
From: Icenowy Zheng @ 2019-07-13 3:46 UTC (permalink / raw)
To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Linus Walleij
Cc: devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-clk-u79uwXL29TY76Z2rM5mHXA,
linux-gpio-u79uwXL29TY76Z2rM5mHXA,
linux-sunxi-/JYPxA39Uh5TLH3MbocFFw, Icenowy Zheng
In-Reply-To: <20190713034634.44585-1-icenowy-h8G6r0blFSE@public.gmane.org>
The Lichee Zero Plus is a core board made by Sipeed, with a microUSB
connector on it, TF slot or WSON8 SD chip, optional eMMC or SPI Flash.
It has a gold finger connector for expansion, and UART is available from
reserved pins w/ 2.54mm pitch. The board can use either SoChip S3 or
Allwinner V3L SoCs.
Add the device tree binding of the basic version of the core board --
w/o eMMC or SPI Flash, w/ TF slot or WSON8 SD, and use S3 SoC.
Signed-off-by: Icenowy Zheng <icenowy-h8G6r0blFSE@public.gmane.org>
---
No changes since v3.
Patch introduced in v2.
Documentation/devicetree/bindings/arm/sunxi.yaml | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/Documentation/devicetree/bindings/arm/sunxi.yaml b/Documentation/devicetree/bindings/arm/sunxi.yaml
index 000a00d12d6a..48c126a7a848 100644
--- a/Documentation/devicetree/bindings/arm/sunxi.yaml
+++ b/Documentation/devicetree/bindings/arm/sunxi.yaml
@@ -353,6 +353,11 @@ properties:
- const: licheepi,licheepi-zero
- const: allwinner,sun8i-v3s
+ - description: Lichee Zero Plus (with S3, without eMMC/SPI Flash)
+ items:
+ - const: sipeed,lichee-zero-plus
+ - const: allwinner,sun8i-s3
+
- description: Linksprite PCDuino
items:
- const: linksprite,a10-pcduino
--
2.21.0
^ permalink raw reply related
* [PATCH v4 6/8] ARM: sunxi: dts: s3/s3l/v3: add DTSI files for S3/S3L/V3 SoCs
From: Icenowy Zheng @ 2019-07-13 3:46 UTC (permalink / raw)
To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Linus Walleij
Cc: devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-clk-u79uwXL29TY76Z2rM5mHXA,
linux-gpio-u79uwXL29TY76Z2rM5mHXA,
linux-sunxi-/JYPxA39Uh5TLH3MbocFFw, Icenowy Zheng
In-Reply-To: <20190713034634.44585-1-icenowy-h8G6r0blFSE@public.gmane.org>
The Allwinner S3/S3L/V3 SoCs all share the same die with the V3s SoC,
but with more GPIO wired out of the package.
Add DTSI files for these SoCs. The DTSI file for V3 just replaces the
pinctrl compatible string, and the S3/S3L DTSI files just include the V3
DTSI file.
Signed-off-by: Icenowy Zheng <icenowy-h8G6r0blFSE@public.gmane.org>
---
No changes since v2.
arch/arm/boot/dts/sun8i-s3.dtsi | 6 ++++++
arch/arm/boot/dts/sun8i-s3l.dtsi | 6 ++++++
arch/arm/boot/dts/sun8i-v3.dtsi | 14 ++++++++++++++
3 files changed, 26 insertions(+)
create mode 100644 arch/arm/boot/dts/sun8i-s3.dtsi
create mode 100644 arch/arm/boot/dts/sun8i-s3l.dtsi
create mode 100644 arch/arm/boot/dts/sun8i-v3.dtsi
diff --git a/arch/arm/boot/dts/sun8i-s3.dtsi b/arch/arm/boot/dts/sun8i-s3.dtsi
new file mode 100644
index 000000000000..0f41a25ecb30
--- /dev/null
+++ b/arch/arm/boot/dts/sun8i-s3.dtsi
@@ -0,0 +1,6 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (C) 2019 Icenowy Zheng <icenowy-h8G6r0blFSE@public.gmane.org>
+ */
+
+#include "sun8i-v3.dtsi"
diff --git a/arch/arm/boot/dts/sun8i-s3l.dtsi b/arch/arm/boot/dts/sun8i-s3l.dtsi
new file mode 100644
index 000000000000..0f41a25ecb30
--- /dev/null
+++ b/arch/arm/boot/dts/sun8i-s3l.dtsi
@@ -0,0 +1,6 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (C) 2019 Icenowy Zheng <icenowy-h8G6r0blFSE@public.gmane.org>
+ */
+
+#include "sun8i-v3.dtsi"
diff --git a/arch/arm/boot/dts/sun8i-v3.dtsi b/arch/arm/boot/dts/sun8i-v3.dtsi
new file mode 100644
index 000000000000..6ae8645ade50
--- /dev/null
+++ b/arch/arm/boot/dts/sun8i-v3.dtsi
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (C) 2019 Icenowy Zheng <icenowy-h8G6r0blFSE@public.gmane.org>
+ */
+
+#include "sun8i-v3s.dtsi"
+
+&ccu {
+ compatible = "allwinner,sun8i-v3-ccu";
+};
+
+&pio {
+ compatible = "allwinner,sun8i-v3-pinctrl";
+};
--
2.21.0
^ permalink raw reply related
* [PATCH v4 5/8] clk: sunxi-ng: v3s: add Allwinner V3 support
From: Icenowy Zheng @ 2019-07-13 3:46 UTC (permalink / raw)
To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Linus Walleij
Cc: devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-clk-u79uwXL29TY76Z2rM5mHXA,
linux-gpio-u79uwXL29TY76Z2rM5mHXA,
linux-sunxi-/JYPxA39Uh5TLH3MbocFFw, Icenowy Zheng
In-Reply-To: <20190713034634.44585-1-icenowy-h8G6r0blFSE@public.gmane.org>
Allwinner V3 has the same main die with V3s, but with more pins wired.
There's a I2S bus on V3 that is not available on V3s.
Add the V3-only peripheral's clocks and reset to the V3s CCU driver,
bound to a new V3 compatible string. The driver name is not changed
because it's part of the device tree binding (the header file name).
Signed-off-by: Icenowy Zheng <icenowy-h8G6r0blFSE@public.gmane.org>
---
Changes in v4:
- Add the missing MMC2 clock slices.
No changes in v3/v2.
drivers/clk/sunxi-ng/ccu-sun8i-v3s.c | 228 +++++++++++++++++++++-
drivers/clk/sunxi-ng/ccu-sun8i-v3s.h | 2 +-
include/dt-bindings/clock/sun8i-v3s-ccu.h | 4 +
include/dt-bindings/reset/sun8i-v3s-ccu.h | 3 +
4 files changed, 234 insertions(+), 3 deletions(-)
diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-v3s.c b/drivers/clk/sunxi-ng/ccu-sun8i-v3s.c
index 9c88015d4419..32854dec3753 100644
--- a/drivers/clk/sunxi-ng/ccu-sun8i-v3s.c
+++ b/drivers/clk/sunxi-ng/ccu-sun8i-v3s.c
@@ -235,6 +235,8 @@ static SUNXI_CCU_GATE(bus_codec_clk, "bus-codec", "apb1",
0x068, BIT(0), 0);
static SUNXI_CCU_GATE(bus_pio_clk, "bus-pio", "apb1",
0x068, BIT(5), 0);
+static SUNXI_CCU_GATE(bus_i2s0_clk, "bus-i2s0", "apb1",
+ 0x068, BIT(12), 0);
static SUNXI_CCU_GATE(bus_i2c0_clk, "bus-i2c0", "apb2",
0x06c, BIT(0), 0);
@@ -306,6 +308,11 @@ static SUNXI_CCU_MP_WITH_MUX_GATE(spi0_clk, "spi0", mod0_default_parents, 0x0a0,
BIT(31), /* gate */
0);
+static const char * const i2s_parents[] = { "pll-audio-8x", "pll-audio-4x",
+ "pll-audio-2x", "pll-audio" };
+static SUNXI_CCU_MUX_WITH_GATE(i2s0_clk, "i2s0", i2s_parents,
+ 0x0b0, 16, 2, BIT(31), CLK_SET_RATE_PARENT);
+
static SUNXI_CCU_GATE(usb_phy0_clk, "usb-phy0", "osc24M",
0x0cc, BIT(8), 0);
static SUNXI_CCU_GATE(usb_ohci0_clk, "usb-ohci0", "osc24M",
@@ -443,6 +450,80 @@ static const struct clk_hw *clk_parent_pll_audio[] = {
&pll_audio_base_clk.common.hw
};
+static struct ccu_common *sun8i_v3_ccu_clks[] = {
+ &pll_cpu_clk.common,
+ &pll_audio_base_clk.common,
+ &pll_video_clk.common,
+ &pll_ve_clk.common,
+ &pll_ddr0_clk.common,
+ &pll_periph0_clk.common,
+ &pll_isp_clk.common,
+ &pll_periph1_clk.common,
+ &pll_ddr1_clk.common,
+ &cpu_clk.common,
+ &axi_clk.common,
+ &ahb1_clk.common,
+ &apb1_clk.common,
+ &apb2_clk.common,
+ &ahb2_clk.common,
+ &bus_ce_clk.common,
+ &bus_dma_clk.common,
+ &bus_mmc0_clk.common,
+ &bus_mmc1_clk.common,
+ &bus_mmc2_clk.common,
+ &bus_dram_clk.common,
+ &bus_emac_clk.common,
+ &bus_hstimer_clk.common,
+ &bus_spi0_clk.common,
+ &bus_otg_clk.common,
+ &bus_ehci0_clk.common,
+ &bus_ohci0_clk.common,
+ &bus_ve_clk.common,
+ &bus_tcon0_clk.common,
+ &bus_csi_clk.common,
+ &bus_de_clk.common,
+ &bus_codec_clk.common,
+ &bus_pio_clk.common,
+ &bus_i2s0_clk.common,
+ &bus_i2c0_clk.common,
+ &bus_i2c1_clk.common,
+ &bus_uart0_clk.common,
+ &bus_uart1_clk.common,
+ &bus_uart2_clk.common,
+ &bus_ephy_clk.common,
+ &bus_dbg_clk.common,
+ &mmc0_clk.common,
+ &mmc0_sample_clk.common,
+ &mmc0_output_clk.common,
+ &mmc1_clk.common,
+ &mmc1_sample_clk.common,
+ &mmc1_output_clk.common,
+ &mmc2_clk.common,
+ &mmc2_sample_clk.common,
+ &mmc2_output_clk.common,
+ &ce_clk.common,
+ &spi0_clk.common,
+ &i2s0_clk.common,
+ &usb_phy0_clk.common,
+ &usb_ohci0_clk.common,
+ &dram_clk.common,
+ &dram_ve_clk.common,
+ &dram_csi_clk.common,
+ &dram_ohci_clk.common,
+ &dram_ehci_clk.common,
+ &de_clk.common,
+ &tcon_clk.common,
+ &csi_misc_clk.common,
+ &csi0_mclk_clk.common,
+ &csi1_sclk_clk.common,
+ &csi1_mclk_clk.common,
+ &ve_clk.common,
+ &ac_dig_clk.common,
+ &avs_clk.common,
+ &mbus_clk.common,
+ &mipi_csi_clk.common,
+};
+
/* We hardcode the divider to 4 for now */
static CLK_FIXED_FACTOR_HWS(pll_audio_clk, "pll-audio",
clk_parent_pll_audio,
@@ -540,6 +621,88 @@ static struct clk_hw_onecell_data sun8i_v3s_hw_clks = {
.num = CLK_NUMBER,
};
+static struct clk_hw_onecell_data sun8i_v3_hw_clks = {
+ .hws = {
+ [CLK_PLL_CPU] = &pll_cpu_clk.common.hw,
+ [CLK_PLL_AUDIO_BASE] = &pll_audio_base_clk.common.hw,
+ [CLK_PLL_AUDIO] = &pll_audio_clk.hw,
+ [CLK_PLL_AUDIO_2X] = &pll_audio_2x_clk.hw,
+ [CLK_PLL_AUDIO_4X] = &pll_audio_4x_clk.hw,
+ [CLK_PLL_AUDIO_8X] = &pll_audio_8x_clk.hw,
+ [CLK_PLL_VIDEO] = &pll_video_clk.common.hw,
+ [CLK_PLL_VE] = &pll_ve_clk.common.hw,
+ [CLK_PLL_DDR0] = &pll_ddr0_clk.common.hw,
+ [CLK_PLL_PERIPH0] = &pll_periph0_clk.common.hw,
+ [CLK_PLL_PERIPH0_2X] = &pll_periph0_2x_clk.hw,
+ [CLK_PLL_ISP] = &pll_isp_clk.common.hw,
+ [CLK_PLL_PERIPH1] = &pll_periph1_clk.common.hw,
+ [CLK_PLL_DDR1] = &pll_ddr1_clk.common.hw,
+ [CLK_CPU] = &cpu_clk.common.hw,
+ [CLK_AXI] = &axi_clk.common.hw,
+ [CLK_AHB1] = &ahb1_clk.common.hw,
+ [CLK_APB1] = &apb1_clk.common.hw,
+ [CLK_APB2] = &apb2_clk.common.hw,
+ [CLK_AHB2] = &ahb2_clk.common.hw,
+ [CLK_BUS_CE] = &bus_ce_clk.common.hw,
+ [CLK_BUS_DMA] = &bus_dma_clk.common.hw,
+ [CLK_BUS_MMC0] = &bus_mmc0_clk.common.hw,
+ [CLK_BUS_MMC1] = &bus_mmc1_clk.common.hw,
+ [CLK_BUS_MMC2] = &bus_mmc2_clk.common.hw,
+ [CLK_BUS_DRAM] = &bus_dram_clk.common.hw,
+ [CLK_BUS_EMAC] = &bus_emac_clk.common.hw,
+ [CLK_BUS_HSTIMER] = &bus_hstimer_clk.common.hw,
+ [CLK_BUS_SPI0] = &bus_spi0_clk.common.hw,
+ [CLK_BUS_OTG] = &bus_otg_clk.common.hw,
+ [CLK_BUS_EHCI0] = &bus_ehci0_clk.common.hw,
+ [CLK_BUS_OHCI0] = &bus_ohci0_clk.common.hw,
+ [CLK_BUS_VE] = &bus_ve_clk.common.hw,
+ [CLK_BUS_TCON0] = &bus_tcon0_clk.common.hw,
+ [CLK_BUS_CSI] = &bus_csi_clk.common.hw,
+ [CLK_BUS_DE] = &bus_de_clk.common.hw,
+ [CLK_BUS_CODEC] = &bus_codec_clk.common.hw,
+ [CLK_BUS_PIO] = &bus_pio_clk.common.hw,
+ [CLK_BUS_I2S0] = &bus_i2s0_clk.common.hw,
+ [CLK_BUS_I2C0] = &bus_i2c0_clk.common.hw,
+ [CLK_BUS_I2C1] = &bus_i2c1_clk.common.hw,
+ [CLK_BUS_UART0] = &bus_uart0_clk.common.hw,
+ [CLK_BUS_UART1] = &bus_uart1_clk.common.hw,
+ [CLK_BUS_UART2] = &bus_uart2_clk.common.hw,
+ [CLK_BUS_EPHY] = &bus_ephy_clk.common.hw,
+ [CLK_BUS_DBG] = &bus_dbg_clk.common.hw,
+ [CLK_MMC0] = &mmc0_clk.common.hw,
+ [CLK_MMC0_SAMPLE] = &mmc0_sample_clk.common.hw,
+ [CLK_MMC0_OUTPUT] = &mmc0_output_clk.common.hw,
+ [CLK_MMC1] = &mmc1_clk.common.hw,
+ [CLK_MMC1_SAMPLE] = &mmc1_sample_clk.common.hw,
+ [CLK_MMC1_OUTPUT] = &mmc1_output_clk.common.hw,
+ [CLK_MMC2] = &mmc1_clk.common.hw,
+ [CLK_MMC2_SAMPLE] = &mmc1_sample_clk.common.hw,
+ [CLK_MMC2_OUTPUT] = &mmc1_output_clk.common.hw,
+ [CLK_CE] = &ce_clk.common.hw,
+ [CLK_SPI0] = &spi0_clk.common.hw,
+ [CLK_I2S0] = &i2s0_clk.common.hw,
+ [CLK_USB_PHY0] = &usb_phy0_clk.common.hw,
+ [CLK_USB_OHCI0] = &usb_ohci0_clk.common.hw,
+ [CLK_DRAM] = &dram_clk.common.hw,
+ [CLK_DRAM_VE] = &dram_ve_clk.common.hw,
+ [CLK_DRAM_CSI] = &dram_csi_clk.common.hw,
+ [CLK_DRAM_EHCI] = &dram_ehci_clk.common.hw,
+ [CLK_DRAM_OHCI] = &dram_ohci_clk.common.hw,
+ [CLK_DE] = &de_clk.common.hw,
+ [CLK_TCON0] = &tcon_clk.common.hw,
+ [CLK_CSI_MISC] = &csi_misc_clk.common.hw,
+ [CLK_CSI0_MCLK] = &csi0_mclk_clk.common.hw,
+ [CLK_CSI1_SCLK] = &csi1_sclk_clk.common.hw,
+ [CLK_CSI1_MCLK] = &csi1_mclk_clk.common.hw,
+ [CLK_VE] = &ve_clk.common.hw,
+ [CLK_AC_DIG] = &ac_dig_clk.common.hw,
+ [CLK_AVS] = &avs_clk.common.hw,
+ [CLK_MBUS] = &mbus_clk.common.hw,
+ [CLK_MIPI_CSI] = &mipi_csi_clk.common.hw,
+ },
+ .num = CLK_NUMBER,
+};
+
static struct ccu_reset_map sun8i_v3s_ccu_resets[] = {
[RST_USB_PHY0] = { 0x0cc, BIT(0) },
@@ -575,6 +738,42 @@ static struct ccu_reset_map sun8i_v3s_ccu_resets[] = {
[RST_BUS_UART2] = { 0x2d8, BIT(18) },
};
+static struct ccu_reset_map sun8i_v3_ccu_resets[] = {
+ [RST_USB_PHY0] = { 0x0cc, BIT(0) },
+
+ [RST_MBUS] = { 0x0fc, BIT(31) },
+
+ [RST_BUS_CE] = { 0x2c0, BIT(5) },
+ [RST_BUS_DMA] = { 0x2c0, BIT(6) },
+ [RST_BUS_MMC0] = { 0x2c0, BIT(8) },
+ [RST_BUS_MMC1] = { 0x2c0, BIT(9) },
+ [RST_BUS_MMC2] = { 0x2c0, BIT(10) },
+ [RST_BUS_DRAM] = { 0x2c0, BIT(14) },
+ [RST_BUS_EMAC] = { 0x2c0, BIT(17) },
+ [RST_BUS_HSTIMER] = { 0x2c0, BIT(19) },
+ [RST_BUS_SPI0] = { 0x2c0, BIT(20) },
+ [RST_BUS_OTG] = { 0x2c0, BIT(24) },
+ [RST_BUS_EHCI0] = { 0x2c0, BIT(26) },
+ [RST_BUS_OHCI0] = { 0x2c0, BIT(29) },
+
+ [RST_BUS_VE] = { 0x2c4, BIT(0) },
+ [RST_BUS_TCON0] = { 0x2c4, BIT(4) },
+ [RST_BUS_CSI] = { 0x2c4, BIT(8) },
+ [RST_BUS_DE] = { 0x2c4, BIT(12) },
+ [RST_BUS_DBG] = { 0x2c4, BIT(31) },
+
+ [RST_BUS_EPHY] = { 0x2c8, BIT(2) },
+
+ [RST_BUS_CODEC] = { 0x2d0, BIT(0) },
+ [RST_BUS_I2S0] = { 0x2d0, BIT(12) },
+
+ [RST_BUS_I2C0] = { 0x2d8, BIT(0) },
+ [RST_BUS_I2C1] = { 0x2d8, BIT(1) },
+ [RST_BUS_UART0] = { 0x2d8, BIT(16) },
+ [RST_BUS_UART1] = { 0x2d8, BIT(17) },
+ [RST_BUS_UART2] = { 0x2d8, BIT(18) },
+};
+
static const struct sunxi_ccu_desc sun8i_v3s_ccu_desc = {
.ccu_clks = sun8i_v3s_ccu_clks,
.num_ccu_clks = ARRAY_SIZE(sun8i_v3s_ccu_clks),
@@ -585,7 +784,18 @@ static const struct sunxi_ccu_desc sun8i_v3s_ccu_desc = {
.num_resets = ARRAY_SIZE(sun8i_v3s_ccu_resets),
};
-static void __init sun8i_v3s_ccu_setup(struct device_node *node)
+static const struct sunxi_ccu_desc sun8i_v3_ccu_desc = {
+ .ccu_clks = sun8i_v3_ccu_clks,
+ .num_ccu_clks = ARRAY_SIZE(sun8i_v3_ccu_clks),
+
+ .hw_clks = &sun8i_v3_hw_clks,
+
+ .resets = sun8i_v3_ccu_resets,
+ .num_resets = ARRAY_SIZE(sun8i_v3_ccu_resets),
+};
+
+static void __init sun8i_v3_v3s_ccu_init(struct device_node *node,
+ const struct sunxi_ccu_desc *ccu_desc)
{
void __iomem *reg;
u32 val;
@@ -601,7 +811,21 @@ static void __init sun8i_v3s_ccu_setup(struct device_node *node)
val &= ~GENMASK(19, 16);
writel(val | (3 << 16), reg + SUN8I_V3S_PLL_AUDIO_REG);
- sunxi_ccu_probe(node, reg, &sun8i_v3s_ccu_desc);
+ sunxi_ccu_probe(node, reg, ccu_desc);
+}
+
+static void __init sun8i_v3s_ccu_setup(struct device_node *node)
+{
+ sun8i_v3_v3s_ccu_init(node, &sun8i_v3s_ccu_desc);
+}
+
+static void __init sun8i_v3_ccu_setup(struct device_node *node)
+{
+ sun8i_v3_v3s_ccu_init(node, &sun8i_v3_ccu_desc);
}
+
CLK_OF_DECLARE(sun8i_v3s_ccu, "allwinner,sun8i-v3s-ccu",
sun8i_v3s_ccu_setup);
+
+CLK_OF_DECLARE(sun8i_v3_ccu, "allwinner,sun8i-v3-ccu",
+ sun8i_v3_ccu_setup);
diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-v3s.h b/drivers/clk/sunxi-ng/ccu-sun8i-v3s.h
index 10af324bd6b1..b0160d305a67 100644
--- a/drivers/clk/sunxi-ng/ccu-sun8i-v3s.h
+++ b/drivers/clk/sunxi-ng/ccu-sun8i-v3s.h
@@ -51,6 +51,6 @@
#define CLK_PLL_DDR1 74
-#define CLK_NUMBER (CLK_PLL_DDR1 + 1)
+#define CLK_NUMBER (CLK_I2S0 + 1)
#endif /* _CCU_SUN8I_H3_H_ */
diff --git a/include/dt-bindings/clock/sun8i-v3s-ccu.h b/include/dt-bindings/clock/sun8i-v3s-ccu.h
index c0d5d5599c87..014ac6123d17 100644
--- a/include/dt-bindings/clock/sun8i-v3s-ccu.h
+++ b/include/dt-bindings/clock/sun8i-v3s-ccu.h
@@ -104,4 +104,8 @@
#define CLK_MIPI_CSI 73
+/* Clocks not available on V3s */
+#define CLK_BUS_I2S0 75
+#define CLK_I2S0 76
+
#endif /* _DT_BINDINGS_CLK_SUN8I_V3S_H_ */
diff --git a/include/dt-bindings/reset/sun8i-v3s-ccu.h b/include/dt-bindings/reset/sun8i-v3s-ccu.h
index b58ef21a2e18..b6790173afd6 100644
--- a/include/dt-bindings/reset/sun8i-v3s-ccu.h
+++ b/include/dt-bindings/reset/sun8i-v3s-ccu.h
@@ -75,4 +75,7 @@
#define RST_BUS_UART1 50
#define RST_BUS_UART2 51
+/* Reset lines not available on V3s */
+#define RST_BUS_I2S0 52
+
#endif /* _DT_BINDINGS_RST_SUN8I_H3_H_ */
--
2.21.0
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox