Skip to content

Commit c3643a6

Browse files
committed
arm64: rockchip: rk3576: add more patches to support photonicat2
1 parent 8c71479 commit c3643a6

12 files changed

+2201
-0
lines changed
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2+
From: HackingGate <[email protected]>
3+
Date: Tue, 7 Oct 2025 02:45:09 +0900
4+
Subject: [PATCH] gpio: rockchip: set input direction when request irq
5+
6+
Set input direction when requesting IRQ to ensure proper GPIO
7+
configuration for interrupt handling.
8+
9+
Signed-off-by: Ye Zhang <[email protected]>
10+
Reviewed-by: Andy Shevchenko <[email protected]>
11+
Reviewed-by: Sebastian Reichel <[email protected]>
12+
---
13+
drivers/gpio/gpio-rockchip.c | 5 ++++-
14+
1 file changed, 4 insertions(+), 1 deletion(-)
15+
16+
diff --git a/drivers/gpio/gpio-rockchip.c b/drivers/gpio/gpio-rockchip.c
17+
index bcfc323a8315..8c07896fbc0f 100644
18+
--- a/drivers/gpio/gpio-rockchip.c
19+
+++ b/drivers/gpio/gpio-rockchip.c
20+
@@ -478,8 +478,11 @@ static int rockchip_irq_reqres(struct irq_data *d)
21+
{
22+
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
23+
struct rockchip_pin_bank *bank = gc->private;
24+
+ irq_hw_number_t hwirq = irqd_to_hwirq(d);
25+
26+
- return gpiochip_reqres_irq(&bank->gpio_chip, d->hwirq);
27+
+ rockchip_gpio_direction_input(&bank->gpio_chip, hwirq);
28+
+
29+
+ return gpiochip_reqres_irq(&bank->gpio_chip, hwirq);
30+
}
31+
32+
static void rockchip_irq_relres(struct irq_data *d)
33+
--
34+
2.47.3
35+
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2+
From: HackingGate <[email protected]>
3+
Date: Tue, 7 Oct 2025 02:45:42 +0900
4+
Subject: [PATCH] mmc: dw_mmc-rockchip: add v2 tuning support
5+
6+
Add support for v2 tuning mechanism in Rockchip DW MMC controller
7+
to improve MMC performance and reliability.
8+
9+
Signed-off-by: Shawn Lin <[email protected]>
10+
---
11+
drivers/mmc/host/dw_mmc-rockchip.c | 64 ++++++++++++++++++++++++++++++
12+
1 file changed, 64 insertions(+)
13+
14+
diff --git a/drivers/mmc/host/dw_mmc-rockchip.c b/drivers/mmc/host/dw_mmc-rockchip.c
15+
index baa23b517731..2ca4e5d2b63c 100644
16+
--- a/drivers/mmc/host/dw_mmc-rockchip.c
17+
+++ b/drivers/mmc/host/dw_mmc-rockchip.c
18+
@@ -35,6 +35,8 @@ struct dw_mci_rockchip_priv_data {
19+
int default_sample_phase;
20+
int num_phases;
21+
bool internal_phase;
22+
+ int last_degree;
23+
+ bool use_v2_tuning;
24+
};
25+
26+
/*
27+
@@ -279,6 +281,58 @@ static void dw_mci_rk3288_set_ios(struct dw_mci *host, struct mmc_ios *ios)
28+
#define TUNING_ITERATION_TO_PHASE(i, num_phases) \
29+
(DIV_ROUND_UP((i) * 360, num_phases))
30+
31+
+static int dw_mci_v2_execute_tuning(struct dw_mci_slot *slot, u32 opcode)
32+
+{
33+
+ struct dw_mci *host = slot->host;
34+
+ struct dw_mci_rockchip_priv_data *priv = host->priv;
35+
+ struct mmc_host *mmc = slot->mmc;
36+
+ u32 degrees[4] = {0, 90, 180, 270}, degree;
37+
+ int i;
38+
+ static bool inherit = true;
39+
+
40+
+ if (inherit) {
41+
+ inherit = false;
42+
+ i = clk_get_phase(priv->sample_clk) / 90;
43+
+ degree = degrees[i];
44+
+ goto done;
45+
+ }
46+
+
47+
+ /*
48+
+ * v2 only support 4 degrees in theory.
49+
+ * First we inherit sample phases from firmware, which should
50+
+ * be able work fine, at least in the first place.
51+
+ * If retune is needed, we search forward to pick the last
52+
+ * one phase from degree list and loop around until we get one.
53+
+ * It's impossible all 4 fixed phase won't be able to work.
54+
+ */
55+
+ for (i = 0; i < ARRAY_SIZE(degrees); i++) {
56+
+ degree = degrees[i] + priv->last_degree + 90;
57+
+ degree = degree % 360;
58+
+ clk_set_phase(priv->sample_clk, degree);
59+
+ if (mmc_send_tuning(mmc, opcode, NULL)) {
60+
+ /*
61+
+ * Tuning error, the phase is a bad phase,
62+
+ * then try using the calculated best phase.
63+
+ */
64+
+ dev_info(host->dev, "V2 tuned phase to %d error, try the best phase\n", degree);
65+
+ degree = (degree + 180) % 360;
66+
+ clk_set_phase(priv->sample_clk, degree);
67+
+ if (!mmc_send_tuning(mmc, opcode, NULL))
68+
+ break;
69+
+ }
70+
+ }
71+
+
72+
+ if (i == ARRAY_SIZE(degrees)) {
73+
+ dev_warn(host->dev, "V2 All phases bad!");
74+
+ return -EIO;
75+
+ }
76+
+
77+
+done:
78+
+ dev_info(host->dev, "V2 Successfully tuned phase to %d\n", degree);
79+
+ priv->last_degree = degree;
80+
+ return 0;
81+
+}
82+
+
83+
static int dw_mci_rk3288_execute_tuning(struct dw_mci_slot *slot, u32 opcode)
84+
{
85+
struct dw_mci *host = slot->host;
86+
@@ -303,6 +357,12 @@ static int dw_mci_rk3288_execute_tuning(struct dw_mci_slot *slot, u32 opcode)
87+
return -EIO;
88+
}
89+
90+
+ if (priv->use_v2_tuning) {
91+
+ if (!dw_mci_v2_execute_tuning(slot, opcode))
92+
+ return 0;
93+
+ /* Otherwise we continue using fine tuning */
94+
+ }
95+
+
96+
ranges = kmalloc_array(priv->num_phases / 2 + 1,
97+
sizeof(*ranges), GFP_KERNEL);
98+
if (!ranges)
99+
@@ -431,6 +491,7 @@ static int dw_mci_common_parse_dt(struct dw_mci *host)
100+
101+
static int dw_mci_rk3288_parse_dt(struct dw_mci *host)
102+
{
103+
+ struct device_node *np = host->dev->of_node;
104+
struct dw_mci_rockchip_priv_data *priv;
105+
int err;
106+
107+
@@ -440,6 +501,9 @@ static int dw_mci_rk3288_parse_dt(struct dw_mci *host)
108+
109+
priv = host->priv;
110+
111+
+ if (of_property_read_bool(np, "rockchip,use-v2-tuning"))
112+
+ priv->use_v2_tuning = true;
113+
+
114+
priv->drv_clk = devm_clk_get(host->dev, "ciu-drive");
115+
if (IS_ERR(priv->drv_clk))
116+
dev_dbg(host->dev, "ciu-drive not available\n");
117+
--
118+
2.47.3
119+
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2+
From: Finley Xiao <[email protected]>
3+
Date: Wed, 12 Oct 2022 19:25:38 +0800
4+
Subject: [PATCH] pmdomain: rockchip: Add always on configuration for power
5+
domain
6+
7+
This adds support for the always_on flag in the rockchip_domain_info
8+
structure, allowing certain power domains to be kept always on.
9+
10+
Signed-off-by: Finley Xiao <[email protected]>
11+
---
12+
drivers/pmdomain/rockchip/pm-domains.c | 32 ++++++++++++++++++++++++++
13+
1 file changed, 32 insertions(+)
14+
15+
diff --git a/drivers/pmdomain/rockchip/pm-domains.c b/drivers/pmdomain/rockchip/pm-domains.c
16+
index 1955c6d453e4..f8d587fc3af8 100644
17+
--- a/drivers/pmdomain/rockchip/pm-domains.c
18+
+++ b/drivers/pmdomain/rockchip/pm-domains.c
19+
@@ -55,6 +55,7 @@ struct rockchip_domain_info {
20+
int clk_ungate_mask;
21+
int mem_status_mask;
22+
int repair_status_mask;
23+
+ bool always_on;
24+
u32 pwr_offset;
25+
u32 mem_offset;
26+
u32 req_offset;
27+
@@ -750,6 +752,26 @@ static void rockchip_pd_detach_dev(struct generic_pm_domain *genpd,
28+
pm_clk_destroy(dev);
29+
}
30+
31+
+static int rockchip_pd_add_alwasy_on_flag(struct rockchip_pm_domain *pd)
32+
+{
33+
+ int error;
34+
+
35+
+ if (pd->genpd.flags & GENPD_FLAG_ALWAYS_ON)
36+
+ return 0;
37+
+ pd->genpd.flags |= GENPD_FLAG_ALWAYS_ON;
38+
+ if (!rockchip_pmu_domain_is_on(pd)) {
39+
+ error = rockchip_pd_power(pd, true);
40+
+ if (error) {
41+
+ dev_err(pd->pmu->dev,
42+
+ "failed to power on domain '%s': %d\n",
43+
+ pd->genpd.name, error);
44+
+ return error;
45+
+ }
46+
+ }
47+
+
48+
+ return 0;
49+
+}
50+
+
51+
static int rockchip_pm_add_one_domain(struct rockchip_pmu *pmu,
52+
struct device_node *node)
53+
{
54+
@@ -868,6 +890,11 @@ static int rockchip_pm_add_one_domain(struct rockchip_pmu *pmu,
55+
pd->genpd.flags = GENPD_FLAG_PM_CLK | GENPD_FLAG_NO_STAY_ON;
56+
if (pd_info->active_wakeup)
57+
pd->genpd.flags |= GENPD_FLAG_ACTIVE_WAKEUP;
58+
+ if (pd_info->always_on) {
59+
+ error = rockchip_pd_add_alwasy_on_flag(pd);
60+
+ if (error)
61+
+ goto err_unprepare_clocks;
62+
+ }
63+
pm_genpd_init(&pd->genpd, NULL,
64+
!rockchip_pmu_domain_is_on(pd) ||
65+
(pd->info->mem_status_mask && !rockchip_pmu_domain_is_mem_on(pd)));
66+
--
67+
2.49.0
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2+
From: HackingGate <[email protected]>
3+
Date: Wed, 8 Oct 2025 00:23:40 +0900
4+
Subject: [PATCH] feat: add FIELD_PREP_HI16_WE macros for hardware register
5+
write-enable masks
6+
7+
---
8+
include/linux/bitfield.h | 47 ++++++++++++++++++++++++++++++++++++++++
9+
1 file changed, 47 insertions(+)
10+
11+
diff --git a/include/linux/bitfield.h b/include/linux/bitfield.h
12+
index 5355f8f806a9..8ee7723007d9 100644
13+
--- a/include/linux/bitfield.h
14+
+++ b/include/linux/bitfield.h
15+
@@ -8,6 +8,7 @@
16+
#define _LINUX_BITFIELD_H
17+
18+
#include <linux/build_bug.h>
19+
+#include <linux/limits.h>
20+
#include <linux/typecheck.h>
21+
#include <asm/byteorder.h>
22+
23+
@@ -142,6 +143,52 @@
24+
(((typeof(_mask))(_val) << __bf_shf(_mask)) & (_mask)) \
25+
)
26+
27+
+/**
28+
+ * FIELD_PREP_HI16_WE() - prepare a bitfield element with a write-enable mask
29+
+ * @_mask: shifted mask defining the field's length and position
30+
+ * @_val: value to put in the field
31+
+ *
32+
+ * FIELD_PREP_HI16_WE() masks and shifts up the value, as well as bitwise ORs
33+
+ * the result with the mask shifted up by 16.
34+
+ *
35+
+ * This is useful for a common design of hardware registers where the upper
36+
+ * 16-bit half of a 32-bit register is used as a write-enable mask. In such a
37+
+ * register, a bit in the lower half is only updated if the corresponding bit
38+
+ * in the upper half is high.
39+
+ */
40+
+#define FIELD_PREP_HI16_WE(_mask, _val) \
41+
+ ({ \
42+
+ __BF_FIELD_CHECK(_mask, ((u16) 0U), _val, \
43+
+ "FIELD_PREP_HI16_WE: "); \
44+
+ (((typeof(_mask))(_val) << __bf_shf(_mask)) & (_mask)) | \
45+
+ ((_mask) << 16); \
46+
+ })
47+
+
48+
+/**
49+
+* FIELD_PREP_HI16_WE_CONST() - prepare a constant bitfield element with a
50+
+* write-enable mask
51+
+* @_mask: shifted mask defining the field's length and position
52+
+* @_val: value to put in the field
53+
+*
54+
+* FIELD_PREP_HI16_WE_CONST() masks and shifts up the value, as well as bitwise
55+
+* ORs the result with the mask shifted up by 16.
56+
+*
57+
+* This is useful for a common design of hardware registers where the upper
58+
+* 16-bit half of a 32-bit register is used as a write-enable mask. In such a
59+
+* register, a bit in the lower half is only updated if the corresponding bit
60+
+* in the upper half is high.
61+
+*
62+
+* Unlike FIELD_PREP_HI16_WE(), this is a constant expression and can therefore
63+
+* be used in initializers. Error checking is less comfortable for this
64+
+* version, and non-constant masks cannot be used.
65+
+*/
66+
+#define FIELD_PREP_HI16_WE_CONST(_mask, _val) \
67+
+ ( \
68+
+ FIELD_PREP_CONST(_mask, _val) | \
69+
+ (BUILD_BUG_ON_ZERO(const_true((u64) (_mask) > U16_MAX)) + \
70+
+ ((_mask) << 16)) \
71+
+ )
72+
+
73+
/**
74+
* FIELD_GET() - extract a bitfield element
75+
* @_mask: shifted mask defining the field's length and position
76+
--
77+
2.47.3
78+

0 commit comments

Comments
 (0)