* Re: [PATCH] iio: industrialio-core: look for aliases to request device index
From: Dominique Martinet @ 2024-04-01 8:18 UTC (permalink / raw)
To: Jonathan Cameron
Cc: Jonathan Cameron, David Lechner, Krzysztof Kozlowski,
Syunya Ohshio, Guido Günther, Lars-Peter Clausen,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, linux-iio,
devicetree, linux-kernel
In-Reply-To: <20240331152042.394b4289@jic23-huawei>
Jonathan Cameron wrote on Sun, Mar 31, 2024 at 03:20:42PM +0100:
> Hi, got back to this finally...
Thank you for taking the time to express your thoughts!
> So the problems compared to other 'alias' users is that IIO is a bit more
> complex than for example LEDs. A single DT node/compatible (or equivalent) can
> result in a 1+ IIO devices and 1+ triggers.
Right. I'm no longer really arguing for it at this point, but for
comparison in the patch I sent, the alias sets the start of the idr for
the device index, so if you have a driver that creates two IIO devices
you could just "reserve" two for this DT node and assuming the order
within this node is constant you'd still get constant numbering, so I
think it still somewhat holds up here.
For triggers though the numbers are separate and it wouldn't make sense
to use the same alias, if we wanted a coherent design with this we'd
need to add a second alias (such as iio_trigger = ..), but that makes
much less sense to me given they're also likely to be dynamically
instancied via configfs from what I've seen; I wouldn't want to do this
kind of mapping, so I agree with you.
> So I've messed around a bit and can think of various possible options to make
> this simpler.
> 1) Use a tmpfs mount and link from that.
> Now we 'could' put an alias directory somewhere under /sys/bus/iio/ that
> is a mount point created via sysfs_create_mount_point() - I abused the
> /sys/kernel/debug directory to test this (unmounted debugfs and mounted
> a tmpfs). That would provide somewhere in sysfs that allows suitable
> links. However, this is unusual so likely to be controversial.
Agreed that's probably not something we want to put our hands into.
> 2) Alternatively the relevant platform could create one of these somewhere
> outside of sysfs and use udev rules to create the links.
I'm not sure I understood this one, something akin to the udev rules
I've showed that made links to the /sys iio device in /dev?
"relevant platform" here would be vendors?
> 3) Stick to the oddity of doing it under /dev/
> 4) Access the things in the first place via more stable paths?
> /sys/bus/i2c/devices/i2c-0/0-0008/iio\:device?/ etc
> Relying on the alias support for i2c bus numbering to make that stable should work
> and if you are sure there will only be one entry (most devices) that matches
> the wild card, should be easy enough to use in scripts.
>
> My personal preference is this last option. Basically if you want stable paths
> don't use /sys/bus/iio/devices/ to get them.
Hmm, I wouldn't call that path stable given the '?' portion can change,
but at least that certainly is a single glob away so it's definitely
simpler than checking every labels all the time.
My second nitpick with this is that while these paths are stable for a
given kernel version, but we've had some paths changes over many years
(not sure if it was 3.14 or 4.9 but one of these perhaps didn't have
/sys/devices/platform yet? and things got moved there at some point with
some subtle name changes, breaking a couple of scripts).
OTOH /sys/bus/iio/devices feels less likely to change, but I guess this
is something that'd come up on tests when preparing a new kernel anyway,
so this is probably acceptable; I'm just thinking out loud.
With that said I can't think of anything that'd work everywhere either,
so I guess we can stick to the status-quo and I'll rediscuss what we
want to do with coworkers.
Thanks,
--
Dominique
^ permalink raw reply
* [PATCH v3] dt-bindings: mfd: twl: Convert trivial subdevices to json-schema
From: Andreas Kemnade @ 2024-04-01 8:18 UTC (permalink / raw)
To: dmitry.torokhov, robh, krzysztof.kozlowski+dt, conor+dt, lee,
alexandre.belloni, wim, linux, andreas, linux-input, devicetree,
linux-kernel, linux-rtc, linux-watchdog, sre
Convert subdevices with just an interrupt and compatbile to
json-schema and wire up already converted subdevices.
RTC is available in all variants, so allow it unconditionally.
GPADC binding for TWL603X uses two different compatibles, so
specify just the compatible and do not include it.
Signed-off-by: Andreas Kemnade <andreas@kemnade.info>
Acked-by: Guenter Roeck <linux@roeck-us.net>
---
Changes in v3:
- added Ack
(apparantly many recipients did not receive the V2 patch,
so there is a need for a resend)
Changes in v2:
- style cleanup
- absolute paths
- unevalutedProperties instead of additionalProperties
due to not accepting things in if: clauses without it
.../bindings/input/twl4030-pwrbutton.txt | 21 ------
.../devicetree/bindings/mfd/ti,twl.yaml | 72 ++++++++++++++++++-
.../devicetree/bindings/rtc/twl-rtc.txt | 11 ---
.../bindings/watchdog/twl4030-wdt.txt | 10 ---
4 files changed, 71 insertions(+), 43 deletions(-)
delete mode 100644 Documentation/devicetree/bindings/input/twl4030-pwrbutton.txt
delete mode 100644 Documentation/devicetree/bindings/rtc/twl-rtc.txt
delete mode 100644 Documentation/devicetree/bindings/watchdog/twl4030-wdt.txt
diff --git a/Documentation/devicetree/bindings/input/twl4030-pwrbutton.txt b/Documentation/devicetree/bindings/input/twl4030-pwrbutton.txt
deleted file mode 100644
index 6c201a2ba8acf..0000000000000
--- a/Documentation/devicetree/bindings/input/twl4030-pwrbutton.txt
+++ /dev/null
@@ -1,21 +0,0 @@
-Texas Instruments TWL family (twl4030) pwrbutton module
-
-This module is part of the TWL4030. For more details about the whole
-chip see Documentation/devicetree/bindings/mfd/ti,twl.yaml.
-
-This module provides a simple power button event via an Interrupt.
-
-Required properties:
-- compatible: should be one of the following
- - "ti,twl4030-pwrbutton": For controllers compatible with twl4030
-- interrupts: should be one of the following
- - <8>: For controllers compatible with twl4030
-
-Example:
-
-&twl {
- twl_pwrbutton: pwrbutton {
- compatible = "ti,twl4030-pwrbutton";
- interrupts = <8>;
- };
-};
diff --git a/Documentation/devicetree/bindings/mfd/ti,twl.yaml b/Documentation/devicetree/bindings/mfd/ti,twl.yaml
index 52ed228fb1e7e..c2357fecb56cc 100644
--- a/Documentation/devicetree/bindings/mfd/ti,twl.yaml
+++ b/Documentation/devicetree/bindings/mfd/ti,twl.yaml
@@ -15,6 +15,67 @@ description: |
USB transceiver or Audio amplifier.
These chips are connected to an i2c bus.
+allOf:
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: ti,twl4030
+ then:
+ properties:
+ madc:
+ type: object
+ $ref: /schemas/iio/adc/ti,twl4030-madc.yaml
+ unevaluatedProperties: false
+
+ bci:
+ type: object
+ $ref: /schemas/power/supply/twl4030-charger.yaml
+ unevaluatedProperties: false
+
+ pwrbutton:
+ type: object
+ additionalProperties: false
+ properties:
+ compatible:
+ const: ti,twl4030-pwrbutton
+ interrupts:
+ items:
+ - items:
+ const: 8
+
+ watchdog:
+ type: object
+ additionalProperties: false
+ properties:
+ compatible:
+ const: ti,twl4030-wdt
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: ti,twl6030
+ then:
+ properties:
+ gpadc:
+ type: object
+ properties:
+ compatible:
+ const: ti,twl6030-gpadc
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: ti,twl6032
+ then:
+ properties:
+ gpadc:
+ type: object
+ properties:
+ compatible:
+ const: ti,twl6032-gpadc
+
properties:
compatible:
description:
@@ -42,7 +103,16 @@ properties:
"#clock-cells":
const: 1
-additionalProperties: false
+ rtc:
+ type: object
+ additionalProperties: false
+ properties:
+ compatible:
+ const: ti,twl4030-rtc
+ interrupts:
+ maxItems: 1
+
+unevaluatedProperties: false
required:
- compatible
diff --git a/Documentation/devicetree/bindings/rtc/twl-rtc.txt b/Documentation/devicetree/bindings/rtc/twl-rtc.txt
deleted file mode 100644
index 8f9a94f2f8969..0000000000000
--- a/Documentation/devicetree/bindings/rtc/twl-rtc.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-* Texas Instruments TWL4030/6030 RTC
-
-Required properties:
-- compatible : Should be "ti,twl4030-rtc"
-- interrupts : Should be the interrupt number.
-
-Example:
- rtc {
- compatible = "ti,twl4030-rtc";
- interrupts = <11>;
- };
diff --git a/Documentation/devicetree/bindings/watchdog/twl4030-wdt.txt b/Documentation/devicetree/bindings/watchdog/twl4030-wdt.txt
deleted file mode 100644
index 80a37193c0b86..0000000000000
--- a/Documentation/devicetree/bindings/watchdog/twl4030-wdt.txt
+++ /dev/null
@@ -1,10 +0,0 @@
-Device tree bindings for twl4030-wdt driver (TWL4030 watchdog)
-
-Required properties:
- compatible = "ti,twl4030-wdt";
-
-Example:
-
-watchdog {
- compatible = "ti,twl4030-wdt";
-};
--
2.39.2
^ permalink raw reply related
* [PATCH v2 0/8] Add Loongson-2k0500 and Loongson-2k2000 clock support
From: Binbin Zhou @ 2024-04-01 8:23 UTC (permalink / raw)
To: Binbin Zhou, Huacai Chen, Michael Turquette, Stephen Boyd,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Yinbo Zhu
Cc: Huacai Chen, loongson-kernel, linux-clk, devicetree, Xuerui Wang,
loongarch, Binbin Zhou
Hi all:
As we know, the Loongson-2K family of SoCs (ls2k0500/ls2k1000/ls2k2000)
have a similar clock structure, and I support them to be configured with
different parameters (e.g., register offsets, etc.).
To make it easier to add support for different SoCs, I refactored the
original driver to make the whole driver as understandable as possible.
Briefly, I have divided all clocks into three categories according to
their properties and their parent clocks: Independent PLLs, clocks based
on frequency scales, and clock dividers.
Thanks.
----
V2:
patch(1/8):
- Drop LOONGSON2_CLK_END, for it is not a binding.
patch(1/8)(3/8)(5/8):
- Add Acked-by tag from Conor, Thanks.
Link to V1:
https://lore.kernel.org/all/cover.1710926402.git.zhoubinbin@loongson.cn/
Binbin Zhou (8):
dt-bindings: clock: add Loongson-2K expand clock index
clk: clk-loongson2: Refactor driver for adding new platforms
dt-bindings: clock: loongson2: add Loongson-2K0500 compatible
clk: clk-loongson2: Add Loongson-2K0500 clock support
dt-bindings: clock: loongson2: add Loongson-2K2000 compatible
clk: clk-loongson2: Add Loongson-2K2000 clock support
LoongArch: dts: Add clock support to Loongson-2K0500
LoongArch: dts: Add clock support to Loongson-2K2000
.../bindings/clock/loongson,ls2k-clk.yaml | 4 +-
.../boot/dts/loongson-2k0500-ref.dts | 4 +
arch/loongarch/boot/dts/loongson-2k0500.dtsi | 57 +-
.../boot/dts/loongson-2k2000-ref.dts | 4 +
arch/loongarch/boot/dts/loongson-2k2000.dtsi | 19 +-
drivers/clk/clk-loongson2.c | 549 ++++++++++--------
include/dt-bindings/clock/loongson,ls2k-clk.h | 56 +-
7 files changed, 408 insertions(+), 285 deletions(-)
--
2.43.0
^ permalink raw reply
* [PATCH v2 2/8] clk: clk-loongson2: Refactor driver for adding new platforms
From: Binbin Zhou @ 2024-04-01 8:23 UTC (permalink / raw)
To: Binbin Zhou, Huacai Chen, Michael Turquette, Stephen Boyd,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Yinbo Zhu
Cc: Huacai Chen, loongson-kernel, linux-clk, devicetree, Xuerui Wang,
loongarch, Binbin Zhou
In-Reply-To: <cover.1711504700.git.zhoubinbin@loongson.cn>
The driver only supported loongson-2K1000 at first, but the clock
structure of loongson-2K0500 and loongson-2K2000 are actually similar,
and I tried to refactor the whole driver to adjust to the addition of
the new platform.
Briefly, I have divided all clocks into three categories according to
their properties and their parent clocks: Independent PLLs, clocks based
on frequency scales, and clock dividers.
Signed-off-by: Binbin Zhou <zhoubinbin@loongson.cn>
---
drivers/clk/clk-loongson2.c | 459 ++++++++++++++++--------------------
1 file changed, 199 insertions(+), 260 deletions(-)
diff --git a/drivers/clk/clk-loongson2.c b/drivers/clk/clk-loongson2.c
index bacdcbb287ac..ff2ade6a471a 100644
--- a/drivers/clk/clk-loongson2.c
+++ b/drivers/clk/clk-loongson2.c
@@ -6,6 +6,7 @@
#include <linux/err.h>
#include <linux/init.h>
+#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/slab.h>
#include <linux/module.h>
@@ -13,317 +14,254 @@
#include <linux/io-64-nonatomic-lo-hi.h>
#include <dt-bindings/clock/loongson,ls2k-clk.h>
-#define LOONGSON2_PLL_MULT_SHIFT 32
-#define LOONGSON2_PLL_MULT_WIDTH 10
-#define LOONGSON2_PLL_DIV_SHIFT 26
-#define LOONGSON2_PLL_DIV_WIDTH 6
-#define LOONGSON2_APB_FREQSCALE_SHIFT 20
-#define LOONGSON2_APB_FREQSCALE_WIDTH 3
-#define LOONGSON2_USB_FREQSCALE_SHIFT 16
-#define LOONGSON2_USB_FREQSCALE_WIDTH 3
-#define LOONGSON2_SATA_FREQSCALE_SHIFT 12
-#define LOONGSON2_SATA_FREQSCALE_WIDTH 3
-#define LOONGSON2_BOOT_FREQSCALE_SHIFT 8
-#define LOONGSON2_BOOT_FREQSCALE_WIDTH 3
-
-static void __iomem *loongson2_pll_base;
-
static const struct clk_parent_data pdata[] = {
- { .fw_name = "ref_100m",},
+ { .fw_name = "ref_100m", },
};
-static struct clk_hw *loongson2_clk_register(struct device *dev,
- const char *name,
- const char *parent_name,
- const struct clk_ops *ops,
- unsigned long flags)
-{
- int ret;
- struct clk_hw *hw;
- struct clk_init_data init = { };
-
- hw = devm_kzalloc(dev, sizeof(*hw), GFP_KERNEL);
- if (!hw)
- return ERR_PTR(-ENOMEM);
-
- init.name = name;
- init.ops = ops;
- init.flags = flags;
- init.num_parents = 1;
-
- if (!parent_name)
- init.parent_data = pdata;
- else
- init.parent_names = &parent_name;
-
- hw->init = &init;
-
- ret = devm_clk_hw_register(dev, hw);
- if (ret)
- hw = ERR_PTR(ret);
-
- return hw;
-}
-
-static unsigned long loongson2_calc_pll_rate(int offset, unsigned long rate)
-{
- u64 val;
- u32 mult, div;
-
- val = readq(loongson2_pll_base + offset);
-
- mult = (val >> LOONGSON2_PLL_MULT_SHIFT) &
- clk_div_mask(LOONGSON2_PLL_MULT_WIDTH);
- div = (val >> LOONGSON2_PLL_DIV_SHIFT) &
- clk_div_mask(LOONGSON2_PLL_DIV_WIDTH);
-
- return div_u64((u64)rate * mult, div);
-}
-
-static unsigned long loongson2_node_recalc_rate(struct clk_hw *hw,
- unsigned long parent_rate)
-{
- return loongson2_calc_pll_rate(0x0, parent_rate);
-}
-
-static const struct clk_ops loongson2_node_clk_ops = {
- .recalc_rate = loongson2_node_recalc_rate,
+enum loongson2_clk_type {
+ CLK_TYPE_PLL,
+ CLK_TYPE_SCALE,
+ CLK_TYPE_DIVIDER,
+ CLK_TYPE_NONE,
};
-static unsigned long loongson2_ddr_recalc_rate(struct clk_hw *hw,
- unsigned long parent_rate)
-{
- return loongson2_calc_pll_rate(0x10, parent_rate);
-}
+struct loongson2_clk_provider {
+ void __iomem *base;
+ struct device *dev;
+ struct clk_hw_onecell_data clk_data;
+ spinlock_t clk_lock; /* protect access to DIV registers */
+};
-static const struct clk_ops loongson2_ddr_clk_ops = {
- .recalc_rate = loongson2_ddr_recalc_rate,
+struct loongson2_clk_data {
+ struct clk_hw hw;
+ void __iomem *reg;
+ u8 div_shift;
+ u8 div_width;
+ u8 mult_shift;
+ u8 mult_width;
};
-static unsigned long loongson2_dc_recalc_rate(struct clk_hw *hw,
- unsigned long parent_rate)
-{
- return loongson2_calc_pll_rate(0x20, parent_rate);
-}
+struct loongson2_clk_board_info {
+ u8 id;
+ enum loongson2_clk_type type;
+ const char *name;
+ const char *parent_name;
+ u8 reg_offset;
+ u8 div_shift;
+ u8 div_width;
+ u8 mult_shift;
+ u8 mult_width;
+};
-static const struct clk_ops loongson2_dc_clk_ops = {
- .recalc_rate = loongson2_dc_recalc_rate,
+#define CLK_DIV(_id, _name, _pname, _offset, _dshift, _dwidth) \
+ { \
+ .id = _id, \
+ .type = CLK_TYPE_DIVIDER, \
+ .name = _name, \
+ .parent_name = _pname, \
+ .reg_offset = _offset, \
+ .div_shift = _dshift, \
+ .div_width = _dwidth, \
+ }
+
+#define CLK_PLL(_id, _name, _offset, _mshift, _mwidth, \
+ _dshift, _dwidth) \
+ { \
+ .id = _id, \
+ .type = CLK_TYPE_PLL, \
+ .name = _name, \
+ .parent_name = NULL, \
+ .reg_offset = _offset, \
+ .mult_shift = _mshift, \
+ .mult_width = _mwidth, \
+ .div_shift = _dshift, \
+ .div_width = _dwidth, \
+ }
+
+#define CLK_SCALE(_id, _name, _pname, _offset, \
+ _dshift, _dwidth) \
+ { \
+ .id = _id, \
+ .type = CLK_TYPE_SCALE, \
+ .name = _name, \
+ .parent_name = _pname, \
+ .reg_offset = _offset, \
+ .div_shift = _dshift, \
+ .div_width = _dwidth, \
+ }
+
+static const struct loongson2_clk_board_info ls2k1000_clks[] = {
+ CLK_PLL(LOONGSON2_NODE_PLL, "pll_node", 0, 32, 10, 26, 6),
+ CLK_PLL(LOONGSON2_DDR_PLL, "pll_ddr", 0x10, 32, 10, 26, 6),
+ CLK_PLL(LOONGSON2_DC_PLL, "pll_dc", 0x20, 32, 10, 26, 6),
+ CLK_PLL(LOONGSON2_PIX0_PLL, "pll_pix0", 0x30, 32, 10, 26, 6),
+ CLK_PLL(LOONGSON2_PIX1_PLL, "pll_pix1", 0x40, 32, 10, 26, 6),
+ CLK_DIV(LOONGSON2_NODE_CLK, "clk_node", "pll_node", 0x8, 0, 6),
+ CLK_DIV(LOONGSON2_DDR_CLK, "clk_ddr", "pll_ddr", 0x18, 0, 6),
+ CLK_DIV(LOONGSON2_GPU_CLK, "clk_gpu", "pll_ddr", 0x18, 22, 6),
+ /*
+ * The hda clk divisor in the upper 32bits and the clk-prodiver
+ * layer code doesn't support 64bit io operation thus a conversion
+ * is required that subtract shift by 32 and add 4byte to the hda
+ * address
+ */
+ CLK_DIV(LOONGSON2_HDA_CLK, "clk_hda", "pll_ddr", 0x22, 12, 7),
+ CLK_DIV(LOONGSON2_DC_CLK, "clk_dc", "pll_dc", 0x28, 0, 6),
+ CLK_DIV(LOONGSON2_GMAC_CLK, "clk_gmac", "pll_dc", 0x28, 22, 6),
+ CLK_DIV(LOONGSON2_PIX0_CLK, "clk_pix0", "pll_pix0", 0x38, 0, 6),
+ CLK_DIV(LOONGSON2_PIX1_CLK, "clk_pix1", "pll_pix1", 0x38, 0, 6),
+ CLK_SCALE(LOONGSON2_BOOT_CLK, "clk_boot", NULL, 0x50, 8, 3),
+ CLK_SCALE(LOONGSON2_SATA_CLK, "clk_sata", "clk_gmac", 0x50, 12, 3),
+ CLK_SCALE(LOONGSON2_USB_CLK, "clk_usb", "clk_gmac", 0x50, 16, 3),
+ CLK_SCALE(LOONGSON2_APB_CLK, "clk_apb", "clk_gmac", 0x50, 20, 3),
+ { /* Sentinel */ },
};
-static unsigned long loongson2_pix0_recalc_rate(struct clk_hw *hw,
- unsigned long parent_rate)
+static inline struct loongson2_clk_data *to_loongson2_clk(struct clk_hw *hw)
{
- return loongson2_calc_pll_rate(0x30, parent_rate);
+ return container_of(hw, struct loongson2_clk_data, hw);
}
-static const struct clk_ops loongson2_pix0_clk_ops = {
- .recalc_rate = loongson2_pix0_recalc_rate,
-};
-
-static unsigned long loongson2_pix1_recalc_rate(struct clk_hw *hw,
- unsigned long parent_rate)
+static inline unsigned long loongson2_rate_part(u64 val, u8 shift, u8 width)
{
- return loongson2_calc_pll_rate(0x40, parent_rate);
+ return (val & GENMASK(shift + width - 1, shift)) >> shift;
}
-static const struct clk_ops loongson2_pix1_clk_ops = {
- .recalc_rate = loongson2_pix1_recalc_rate,
-};
-
-static unsigned long loongson2_calc_rate(unsigned long rate,
- int shift, int width)
+static unsigned long loongson2_pll_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
{
- u64 val;
- u32 mult;
-
- val = readq(loongson2_pll_base + 0x50);
+ u64 val, mult, div;
+ struct loongson2_clk_data *clk = to_loongson2_clk(hw);
- mult = (val >> shift) & clk_div_mask(width);
+ val = readq(clk->reg);
+ mult = loongson2_rate_part(val, clk->mult_shift, clk->mult_width);
+ div = loongson2_rate_part(val, clk->div_shift, clk->div_width);
- return div_u64((u64)rate * (mult + 1), 8);
-}
-
-static unsigned long loongson2_boot_recalc_rate(struct clk_hw *hw,
- unsigned long parent_rate)
-{
- return loongson2_calc_rate(parent_rate,
- LOONGSON2_BOOT_FREQSCALE_SHIFT,
- LOONGSON2_BOOT_FREQSCALE_WIDTH);
+ return div_u64((u64)parent_rate * mult, div);
}
-static const struct clk_ops loongson2_boot_clk_ops = {
- .recalc_rate = loongson2_boot_recalc_rate,
+static const struct clk_ops loongson2_pll_recalc_ops = {
+ .recalc_rate = loongson2_pll_recalc_rate,
};
-static unsigned long loongson2_apb_recalc_rate(struct clk_hw *hw,
- unsigned long parent_rate)
+static unsigned long loongson2_freqscale_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
{
- return loongson2_calc_rate(parent_rate,
- LOONGSON2_APB_FREQSCALE_SHIFT,
- LOONGSON2_APB_FREQSCALE_WIDTH);
-}
+ u64 val, mult;
+ struct loongson2_clk_data *clk = to_loongson2_clk(hw);
-static const struct clk_ops loongson2_apb_clk_ops = {
- .recalc_rate = loongson2_apb_recalc_rate,
-};
+ val = readq(clk->reg);
+ mult = loongson2_rate_part(val, clk->div_shift, clk->div_width) + 1;
-static unsigned long loongson2_usb_recalc_rate(struct clk_hw *hw,
- unsigned long parent_rate)
-{
- return loongson2_calc_rate(parent_rate,
- LOONGSON2_USB_FREQSCALE_SHIFT,
- LOONGSON2_USB_FREQSCALE_WIDTH);
+ return div_u64((u64)parent_rate * mult, 8);
}
-static const struct clk_ops loongson2_usb_clk_ops = {
- .recalc_rate = loongson2_usb_recalc_rate,
+static const struct clk_ops loongson2_freqscale_recalc_ops = {
+ .recalc_rate = loongson2_freqscale_recalc_rate,
};
-static unsigned long loongson2_sata_recalc_rate(struct clk_hw *hw,
- unsigned long parent_rate)
+static struct clk_hw *loongson2_clk_register(struct loongson2_clk_provider *clp,
+ const struct loongson2_clk_board_info *cld,
+ const struct clk_ops *ops)
{
- return loongson2_calc_rate(parent_rate,
- LOONGSON2_SATA_FREQSCALE_SHIFT,
- LOONGSON2_SATA_FREQSCALE_WIDTH);
-}
+ int ret;
+ struct clk_hw *hw;
+ struct loongson2_clk_data *clk;
+ struct clk_init_data init = { };
-static const struct clk_ops loongson2_sata_clk_ops = {
- .recalc_rate = loongson2_sata_recalc_rate,
-};
+ clk = devm_kzalloc(clp->dev, sizeof(*clk), GFP_KERNEL);
+ if (!clk)
+ return ERR_PTR(-ENOMEM);
-static inline int loongson2_check_clk_hws(struct clk_hw *clks[], unsigned int count)
-{
- unsigned int i;
+ init.name = cld->name;
+ init.ops = ops;
+ init.flags = 0;
+ init.num_parents = 1;
- for (i = 0; i < count; i++)
- if (IS_ERR(clks[i])) {
- pr_err("Loongson2 clk %u: register failed with %ld\n",
- i, PTR_ERR(clks[i]));
- return PTR_ERR(clks[i]);
- }
+ if (!cld->parent_name)
+ init.parent_data = pdata;
+ else
+ init.parent_names = &cld->parent_name;
+
+ clk->reg = clp->base + cld->reg_offset;
+ clk->div_shift = cld->div_shift;
+ clk->div_width = cld->div_width;
+ clk->mult_shift = cld->mult_shift;
+ clk->mult_width = cld->mult_width;
+ clk->hw.init = &init;
- return 0;
+ hw = &clk->hw;
+ ret = devm_clk_hw_register(clp->dev, hw);
+ if (ret)
+ clk = ERR_PTR(ret);
+
+ return hw;
}
static int loongson2_clk_probe(struct platform_device *pdev)
{
- int ret;
- struct clk_hw **hws;
- struct clk_hw_onecell_data *clk_hw_data;
- spinlock_t loongson2_clk_lock;
+ int i, clks_num = 0;
+ struct clk_hw *hw;
struct device *dev = &pdev->dev;
+ struct loongson2_clk_provider *clp;
+ const struct loongson2_clk_board_info *p, *data;
- loongson2_pll_base = devm_platform_ioremap_resource(pdev, 0);
- if (IS_ERR(loongson2_pll_base))
- return PTR_ERR(loongson2_pll_base);
-
- clk_hw_data = devm_kzalloc(dev, struct_size(clk_hw_data, hws, LOONGSON2_CLK_END),
- GFP_KERNEL);
- if (WARN_ON(!clk_hw_data))
- return -ENOMEM;
-
- clk_hw_data->num = LOONGSON2_CLK_END;
- hws = clk_hw_data->hws;
-
- hws[LOONGSON2_NODE_PLL] = loongson2_clk_register(dev, "node_pll",
- NULL,
- &loongson2_node_clk_ops, 0);
-
- hws[LOONGSON2_DDR_PLL] = loongson2_clk_register(dev, "ddr_pll",
- NULL,
- &loongson2_ddr_clk_ops, 0);
+ data = device_get_match_data(dev);
+ if (!data)
+ return -EINVAL;
- hws[LOONGSON2_DC_PLL] = loongson2_clk_register(dev, "dc_pll",
- NULL,
- &loongson2_dc_clk_ops, 0);
+ for (p = data; p->name; p++)
+ clks_num++;
- hws[LOONGSON2_PIX0_PLL] = loongson2_clk_register(dev, "pix0_pll",
- NULL,
- &loongson2_pix0_clk_ops, 0);
-
- hws[LOONGSON2_PIX1_PLL] = loongson2_clk_register(dev, "pix1_pll",
- NULL,
- &loongson2_pix1_clk_ops, 0);
+ clp = devm_kzalloc(dev, struct_size(clp, clk_data.hws, clks_num),
+ GFP_KERNEL);
+ if (!clp)
+ return -ENOMEM;
- hws[LOONGSON2_BOOT_CLK] = loongson2_clk_register(dev, "boot",
- NULL,
- &loongson2_boot_clk_ops, 0);
+ clp->base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(clp->base))
+ return PTR_ERR(clp->base);
+
+ spin_lock_init(&clp->clk_lock);
+ clp->clk_data.num = clks_num + 1;
+ clp->dev = dev;
+
+ for (i = 0; i < clks_num; i++) {
+ p = &data[i];
+ switch (p->type) {
+ case CLK_TYPE_PLL:
+ hw = loongson2_clk_register(clp, p,
+ &loongson2_pll_recalc_ops);
+ break;
+ case CLK_TYPE_SCALE:
+ hw = loongson2_clk_register(clp, p,
+ &loongson2_freqscale_recalc_ops);
+ break;
+ case CLK_TYPE_DIVIDER:
+ hw = devm_clk_hw_register_divider(dev, p->name,
+ p->parent_name, 0,
+ clp->base + p->reg_offset,
+ p->div_shift, p->div_width,
+ CLK_DIVIDER_ONE_BASED,
+ &clp->clk_lock);
+ break;
+ default:
+ return dev_err_probe(dev, -EINVAL, "Invalid clk type\n");
+ }
- hws[LOONGSON2_NODE_CLK] = devm_clk_hw_register_divider(dev, "node",
- "node_pll", 0,
- loongson2_pll_base + 0x8, 0,
- 6, CLK_DIVIDER_ONE_BASED,
- &loongson2_clk_lock);
+ if (IS_ERR(hw))
+ return dev_err_probe(dev, PTR_ERR(hw),
+ "Register clk: %s, type: %u failed!\n",
+ p->name, p->type);
- /*
- * The hda clk divisor in the upper 32bits and the clk-prodiver
- * layer code doesn't support 64bit io operation thus a conversion
- * is required that subtract shift by 32 and add 4byte to the hda
- * address
- */
- hws[LOONGSON2_HDA_CLK] = devm_clk_hw_register_divider(dev, "hda",
- "ddr_pll", 0,
- loongson2_pll_base + 0x22, 12,
- 7, CLK_DIVIDER_ONE_BASED,
- &loongson2_clk_lock);
-
- hws[LOONGSON2_GPU_CLK] = devm_clk_hw_register_divider(dev, "gpu",
- "ddr_pll", 0,
- loongson2_pll_base + 0x18, 22,
- 6, CLK_DIVIDER_ONE_BASED,
- &loongson2_clk_lock);
-
- hws[LOONGSON2_DDR_CLK] = devm_clk_hw_register_divider(dev, "ddr",
- "ddr_pll", 0,
- loongson2_pll_base + 0x18, 0,
- 6, CLK_DIVIDER_ONE_BASED,
- &loongson2_clk_lock);
-
- hws[LOONGSON2_GMAC_CLK] = devm_clk_hw_register_divider(dev, "gmac",
- "dc_pll", 0,
- loongson2_pll_base + 0x28, 22,
- 6, CLK_DIVIDER_ONE_BASED,
- &loongson2_clk_lock);
-
- hws[LOONGSON2_DC_CLK] = devm_clk_hw_register_divider(dev, "dc",
- "dc_pll", 0,
- loongson2_pll_base + 0x28, 0,
- 6, CLK_DIVIDER_ONE_BASED,
- &loongson2_clk_lock);
-
- hws[LOONGSON2_APB_CLK] = loongson2_clk_register(dev, "apb",
- "gmac",
- &loongson2_apb_clk_ops, 0);
-
- hws[LOONGSON2_USB_CLK] = loongson2_clk_register(dev, "usb",
- "gmac",
- &loongson2_usb_clk_ops, 0);
-
- hws[LOONGSON2_SATA_CLK] = loongson2_clk_register(dev, "sata",
- "gmac",
- &loongson2_sata_clk_ops, 0);
-
- hws[LOONGSON2_PIX0_CLK] = clk_hw_register_divider(NULL, "pix0",
- "pix0_pll", 0,
- loongson2_pll_base + 0x38, 0, 6,
- CLK_DIVIDER_ONE_BASED,
- &loongson2_clk_lock);
-
- hws[LOONGSON2_PIX1_CLK] = clk_hw_register_divider(NULL, "pix1",
- "pix1_pll", 0,
- loongson2_pll_base + 0x48, 0, 6,
- CLK_DIVIDER_ONE_BASED,
- &loongson2_clk_lock);
-
- ret = loongson2_check_clk_hws(hws, LOONGSON2_CLK_END);
- if (ret)
- return ret;
+ clp->clk_data.hws[p->id] = hw;
+ }
- return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, clk_hw_data);
+ return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, &clp->clk_data);
}
static const struct of_device_id loongson2_clk_match_table[] = {
- { .compatible = "loongson,ls2k-clk" },
+ { .compatible = "loongson,ls2k-clk", .data = &ls2k1000_clks },
{ }
};
MODULE_DEVICE_TABLE(of, loongson2_clk_match_table);
@@ -338,4 +276,5 @@ static struct platform_driver loongson2_clk_driver = {
module_platform_driver(loongson2_clk_driver);
MODULE_DESCRIPTION("Loongson2 clock driver");
+MODULE_AUTHOR("Loongson Technology Corporation Limited");
MODULE_LICENSE("GPL");
--
2.43.0
^ permalink raw reply related
* [PATCH v2 1/8] dt-bindings: clock: add Loongson-2K expand clock index
From: Binbin Zhou @ 2024-04-01 8:23 UTC (permalink / raw)
To: Binbin Zhou, Huacai Chen, Michael Turquette, Stephen Boyd,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Yinbo Zhu
Cc: Huacai Chen, loongson-kernel, linux-clk, devicetree, Xuerui Wang,
loongarch, Binbin Zhou, Conor Dooley
In-Reply-To: <cover.1711504700.git.zhoubinbin@loongson.cn>
In the new Loongson-2K family of SoCs, more clock indexes are needed,
such as clock gates.
The patch adds these clock indexes
Signed-off-by: Binbin Zhou <zhoubinbin@loongson.cn>
Acked-by: Conor Dooley <conor.dooley@microchip.com>
---
include/dt-bindings/clock/loongson,ls2k-clk.h | 56 ++++++++++++-------
1 file changed, 37 insertions(+), 19 deletions(-)
diff --git a/include/dt-bindings/clock/loongson,ls2k-clk.h b/include/dt-bindings/clock/loongson,ls2k-clk.h
index 3bc4dfc193c2..4e6811eca8c6 100644
--- a/include/dt-bindings/clock/loongson,ls2k-clk.h
+++ b/include/dt-bindings/clock/loongson,ls2k-clk.h
@@ -7,24 +7,42 @@
#ifndef __DT_BINDINGS_CLOCK_LOONGSON2_H
#define __DT_BINDINGS_CLOCK_LOONGSON2_H
-#define LOONGSON2_REF_100M 0
-#define LOONGSON2_NODE_PLL 1
-#define LOONGSON2_DDR_PLL 2
-#define LOONGSON2_DC_PLL 3
-#define LOONGSON2_PIX0_PLL 4
-#define LOONGSON2_PIX1_PLL 5
-#define LOONGSON2_NODE_CLK 6
-#define LOONGSON2_HDA_CLK 7
-#define LOONGSON2_GPU_CLK 8
-#define LOONGSON2_DDR_CLK 9
-#define LOONGSON2_GMAC_CLK 10
-#define LOONGSON2_DC_CLK 11
-#define LOONGSON2_APB_CLK 12
-#define LOONGSON2_USB_CLK 13
-#define LOONGSON2_SATA_CLK 14
-#define LOONGSON2_PIX0_CLK 15
-#define LOONGSON2_PIX1_CLK 16
-#define LOONGSON2_BOOT_CLK 17
-#define LOONGSON2_CLK_END 18
+#define LOONGSON2_REF_100M 0
+#define LOONGSON2_NODE_PLL 1
+#define LOONGSON2_DDR_PLL 2
+#define LOONGSON2_DC_PLL 3
+#define LOONGSON2_PIX0_PLL 4
+#define LOONGSON2_PIX1_PLL 5
+#define LOONGSON2_NODE_CLK 6
+#define LOONGSON2_HDA_CLK 7
+#define LOONGSON2_GPU_CLK 8
+#define LOONGSON2_DDR_CLK 9
+#define LOONGSON2_GMAC_CLK 10
+#define LOONGSON2_DC_CLK 11
+#define LOONGSON2_APB_CLK 12
+#define LOONGSON2_USB_CLK 13
+#define LOONGSON2_SATA_CLK 14
+#define LOONGSON2_PIX0_CLK 15
+#define LOONGSON2_PIX1_CLK 16
+#define LOONGSON2_BOOT_CLK 17
+
+/* Loongson-2K2000 */
+#define LOONGSON2_OUT0_GATE 18
+#define LOONGSON2_GMAC_GATE 19
+#define LOONGSON2_RIO_GATE 20
+#define LOONGSON2_DC_GATE 21
+#define LOONGSON2_GPU_GATE 22
+#define LOONGSON2_DDR_GATE 23
+#define LOONGSON2_HDA_GATE 24
+#define LOONGSON2_NODE_GATE 25
+#define LOONGSON2_EMMC_GATE 26
+#define LOONGSON2_PIX0_GATE 27
+#define LOONGSON2_PIX1_GATE 28
+#define LOONGSON2_OUT0_CLK 29
+#define LOONGSON2_RIO_CLK 30
+#define LOONGSON2_EMMC_CLK 31
+#define LOONGSON2_DES_CLK 32
+#define LOONGSON2_I2S_CLK 33
+#define LOONGSON2_MISC_CLK 34
#endif
--
2.43.0
^ permalink raw reply related
* [PATCH v2 3/8] dt-bindings: clock: loongson2: add Loongson-2K0500 compatible
From: Binbin Zhou @ 2024-04-01 8:23 UTC (permalink / raw)
To: Binbin Zhou, Huacai Chen, Michael Turquette, Stephen Boyd,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Yinbo Zhu
Cc: Huacai Chen, loongson-kernel, linux-clk, devicetree, Xuerui Wang,
loongarch, Binbin Zhou, Conor Dooley
In-Reply-To: <cover.1711504700.git.zhoubinbin@loongson.cn>
Add the devicetree compatible for Loongson-2K0500 clocks.
Signed-off-by: Binbin Zhou <zhoubinbin@loongson.cn>
Acked-by: Conor Dooley <conor.dooley@microchip.com>
---
Documentation/devicetree/bindings/clock/loongson,ls2k-clk.yaml | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/Documentation/devicetree/bindings/clock/loongson,ls2k-clk.yaml b/Documentation/devicetree/bindings/clock/loongson,ls2k-clk.yaml
index 63a59015987e..83baee40e200 100644
--- a/Documentation/devicetree/bindings/clock/loongson,ls2k-clk.yaml
+++ b/Documentation/devicetree/bindings/clock/loongson,ls2k-clk.yaml
@@ -16,7 +16,8 @@ description: |
properties:
compatible:
enum:
- - loongson,ls2k-clk
+ - loongson,ls2k0500-clk
+ - loongson,ls2k-clk # This is for Loongson-2K1000
reg:
maxItems: 1
--
2.43.0
^ permalink raw reply related
* [PATCH v2 4/8] clk: clk-loongson2: Add Loongson-2K0500 clock support
From: Binbin Zhou @ 2024-04-01 8:24 UTC (permalink / raw)
To: Binbin Zhou, Huacai Chen, Michael Turquette, Stephen Boyd,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Yinbo Zhu
Cc: Huacai Chen, loongson-kernel, linux-clk, devicetree, Xuerui Wang,
loongarch, Binbin Zhou
In-Reply-To: <cover.1711504700.git.zhoubinbin@loongson.cn>
The Loongson-2K0500 and Loongson-2K1000 clock is similar, we add its
support by different configurations.
Signed-off-by: Binbin Zhou <zhoubinbin@loongson.cn>
---
drivers/clk/clk-loongson2.c | 22 ++++++++++++++++++++++
1 file changed, 22 insertions(+)
diff --git a/drivers/clk/clk-loongson2.c b/drivers/clk/clk-loongson2.c
index ff2ade6a471a..b5dd9d028826 100644
--- a/drivers/clk/clk-loongson2.c
+++ b/drivers/clk/clk-loongson2.c
@@ -90,6 +90,27 @@ struct loongson2_clk_board_info {
.div_width = _dwidth, \
}
+static const struct loongson2_clk_board_info ls2k0500_clks[] = {
+ CLK_PLL(LOONGSON2_NODE_PLL, "pll_node", 0, 16, 8, 8, 6),
+ CLK_PLL(LOONGSON2_DDR_PLL, "pll_ddr", 0x8, 16, 8, 8, 6),
+ CLK_PLL(LOONGSON2_DC_PLL, "pll_soc", 0x10, 16, 8, 8, 6),
+ CLK_PLL(LOONGSON2_PIX0_PLL, "pll_pix0", 0x18, 16, 8, 8, 6),
+ CLK_PLL(LOONGSON2_PIX1_PLL, "pll_pix1", 0x20, 16, 8, 8, 6),
+ CLK_DIV(LOONGSON2_NODE_CLK, "clk_node", "pll_node", 0, 24, 6),
+ CLK_DIV(LOONGSON2_DDR_CLK, "clk_ddr", "pll_ddr", 0x8, 24, 6),
+ CLK_DIV(LOONGSON2_HDA_CLK, "clk_hda", "pll_ddr", 0xc, 8, 6),
+ CLK_DIV(LOONGSON2_GPU_CLK, "clk_gpu", "pll_soc", 0x10, 24, 6),
+ CLK_DIV(LOONGSON2_DC_CLK, "clk_sb", "pll_soc", 0x14, 0, 6),
+ CLK_DIV(LOONGSON2_GMAC_CLK, "clk_gmac", "pll_soc", 0x14, 8, 6),
+ CLK_DIV(LOONGSON2_PIX0_CLK, "clk_pix0", "pll_pix0", 0x18, 24, 6),
+ CLK_DIV(LOONGSON2_PIX1_CLK, "clk_pix1", "pll_pix1", 0x20, 24, 6),
+ CLK_SCALE(LOONGSON2_BOOT_CLK, "clk_boot", "clk_sb", 0x28, 8, 3),
+ CLK_SCALE(LOONGSON2_SATA_CLK, "clk_sata", "clk_sb", 0x28, 12, 3),
+ CLK_SCALE(LOONGSON2_USB_CLK, "clk_usb", "clk_sb", 0x28, 16, 3),
+ CLK_SCALE(LOONGSON2_APB_CLK, "clk_apb", "clk_sb", 0x28, 20, 3),
+ { /* Sentinel */ },
+};
+
static const struct loongson2_clk_board_info ls2k1000_clks[] = {
CLK_PLL(LOONGSON2_NODE_PLL, "pll_node", 0, 32, 10, 26, 6),
CLK_PLL(LOONGSON2_DDR_PLL, "pll_ddr", 0x10, 32, 10, 26, 6),
@@ -261,6 +282,7 @@ static int loongson2_clk_probe(struct platform_device *pdev)
}
static const struct of_device_id loongson2_clk_match_table[] = {
+ { .compatible = "loongson,ls2k0500-clk", .data = &ls2k0500_clks },
{ .compatible = "loongson,ls2k-clk", .data = &ls2k1000_clks },
{ }
};
--
2.43.0
^ permalink raw reply related
* [PATCH v2 5/8] dt-bindings: clock: loongson2: add Loongson-2K2000 compatible
From: Binbin Zhou @ 2024-04-01 8:24 UTC (permalink / raw)
To: Binbin Zhou, Huacai Chen, Michael Turquette, Stephen Boyd,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Yinbo Zhu
Cc: Huacai Chen, loongson-kernel, linux-clk, devicetree, Xuerui Wang,
loongarch, Binbin Zhou, Conor Dooley
In-Reply-To: <cover.1711504700.git.zhoubinbin@loongson.cn>
Add the devicetree compatible for Loongson-2K2000 clocks.
Signed-off-by: Binbin Zhou <zhoubinbin@loongson.cn>
Acked-by: Conor Dooley <conor.dooley@microchip.com>
---
Documentation/devicetree/bindings/clock/loongson,ls2k-clk.yaml | 1 +
1 file changed, 1 insertion(+)
diff --git a/Documentation/devicetree/bindings/clock/loongson,ls2k-clk.yaml b/Documentation/devicetree/bindings/clock/loongson,ls2k-clk.yaml
index 83baee40e200..4f79cdb417ab 100644
--- a/Documentation/devicetree/bindings/clock/loongson,ls2k-clk.yaml
+++ b/Documentation/devicetree/bindings/clock/loongson,ls2k-clk.yaml
@@ -18,6 +18,7 @@ properties:
enum:
- loongson,ls2k0500-clk
- loongson,ls2k-clk # This is for Loongson-2K1000
+ - loongson,ls2k2000-clk
reg:
maxItems: 1
--
2.43.0
^ permalink raw reply related
* [PATCH v2 6/8] clk: clk-loongson2: Add Loongson-2K2000 clock support
From: Binbin Zhou @ 2024-04-01 8:24 UTC (permalink / raw)
To: Binbin Zhou, Huacai Chen, Michael Turquette, Stephen Boyd,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Yinbo Zhu
Cc: Huacai Chen, loongson-kernel, linux-clk, devicetree, Xuerui Wang,
loongarch, Binbin Zhou
In-Reply-To: <cover.1711504700.git.zhoubinbin@loongson.cn>
The Loongson-2K2000 and Loongson-2K1000 clock is similar, we add its
support by different configurations.
Signed-off-by: Binbin Zhou <zhoubinbin@loongson.cn>
---
drivers/clk/clk-loongson2.c | 72 +++++++++++++++++++++++++++++++++++++
1 file changed, 72 insertions(+)
diff --git a/drivers/clk/clk-loongson2.c b/drivers/clk/clk-loongson2.c
index b5dd9d028826..0d82aeeadb45 100644
--- a/drivers/clk/clk-loongson2.c
+++ b/drivers/clk/clk-loongson2.c
@@ -22,6 +22,8 @@ enum loongson2_clk_type {
CLK_TYPE_PLL,
CLK_TYPE_SCALE,
CLK_TYPE_DIVIDER,
+ CLK_TYPE_GATE,
+ CLK_TYPE_FIXED,
CLK_TYPE_NONE,
};
@@ -46,11 +48,13 @@ struct loongson2_clk_board_info {
enum loongson2_clk_type type;
const char *name;
const char *parent_name;
+ unsigned long fixed_rate;
u8 reg_offset;
u8 div_shift;
u8 div_width;
u8 mult_shift;
u8 mult_width;
+ u8 bit_idx;
};
#define CLK_DIV(_id, _name, _pname, _offset, _dshift, _dwidth) \
@@ -90,6 +94,25 @@ struct loongson2_clk_board_info {
.div_width = _dwidth, \
}
+#define CLK_GATE(_id, _name, _pname, _offset, _bidx) \
+ { \
+ .id = _id, \
+ .type = CLK_TYPE_GATE, \
+ .name = _name, \
+ .parent_name = _pname, \
+ .reg_offset = _offset, \
+ .bit_idx = _bidx, \
+ }
+
+#define CLK_FIXED(_id, _name, _pname, _rate) \
+ { \
+ .id = _id, \
+ .type = CLK_TYPE_FIXED, \
+ .name = _name, \
+ .parent_name = _pname, \
+ .fixed_rate = _rate, \
+ }
+
static const struct loongson2_clk_board_info ls2k0500_clks[] = {
CLK_PLL(LOONGSON2_NODE_PLL, "pll_node", 0, 16, 8, 8, 6),
CLK_PLL(LOONGSON2_DDR_PLL, "pll_ddr", 0x8, 16, 8, 8, 6),
@@ -138,6 +161,44 @@ static const struct loongson2_clk_board_info ls2k1000_clks[] = {
{ /* Sentinel */ },
};
+static const struct loongson2_clk_board_info ls2k2000_clks[] = {
+ CLK_PLL(LOONGSON2_DC_PLL, "pll_0", 0, 21, 9, 32, 6),
+ CLK_PLL(LOONGSON2_DDR_PLL, "pll_1", 0x10, 21, 9, 32, 6),
+ CLK_PLL(LOONGSON2_NODE_PLL, "pll_2", 0x20, 21, 9, 32, 6),
+ CLK_PLL(LOONGSON2_PIX0_PLL, "pll_pix0", 0x30, 21, 9, 32, 6),
+ CLK_PLL(LOONGSON2_PIX1_PLL, "pll_pix1", 0x40, 21, 9, 32, 6),
+ CLK_GATE(LOONGSON2_OUT0_GATE, "out0_gate", "pll_0", 0, 40),
+ CLK_GATE(LOONGSON2_GMAC_GATE, "gmac_gate", "pll_0", 0, 41),
+ CLK_GATE(LOONGSON2_RIO_GATE, "rio_gate", "pll_0", 0, 42),
+ CLK_GATE(LOONGSON2_DC_GATE, "dc_gate", "pll_1", 0x10, 40),
+ CLK_GATE(LOONGSON2_DDR_GATE, "ddr_gate", "pll_1", 0x10, 41),
+ CLK_GATE(LOONGSON2_GPU_GATE, "gpu_gate", "pll_1", 0x10, 42),
+ CLK_GATE(LOONGSON2_HDA_GATE, "hda_gate", "pll_2", 0x20, 40),
+ CLK_GATE(LOONGSON2_NODE_GATE, "node_gate", "pll_2", 0x20, 41),
+ CLK_GATE(LOONGSON2_EMMC_GATE, "emmc_gate", "pll_2", 0x20, 42),
+ CLK_GATE(LOONGSON2_PIX0_GATE, "pix0_gate", "pll_pix0", 0x30, 40),
+ CLK_GATE(LOONGSON2_PIX1_GATE, "pix1_gate", "pll_pix1", 0x40, 40),
+ CLK_DIV(LOONGSON2_OUT0_CLK, "clk_out0", "out0_gate", 0, 0, 6),
+ CLK_DIV(LOONGSON2_GMAC_CLK, "clk_gmac", "gmac_gate", 0, 7, 6),
+ CLK_DIV(LOONGSON2_RIO_CLK, "clk_rio", "rio_gate", 0, 14, 6),
+ CLK_DIV(LOONGSON2_DC_CLK, "clk_dc", "dc_gate", 0x10, 0, 6),
+ CLK_DIV(LOONGSON2_GPU_CLK, "clk_gpu", "gpu_gate", 0x10, 7, 6),
+ CLK_DIV(LOONGSON2_DDR_CLK, "clk_ddr", "ddr_gate", 0x10, 14, 6),
+ CLK_DIV(LOONGSON2_HDA_CLK, "clk_hda", "hda_gate", 0x20, 0, 6),
+ CLK_DIV(LOONGSON2_NODE_CLK, "clk_node", "node_gate", 0x20, 7, 6),
+ CLK_DIV(LOONGSON2_EMMC_CLK, "clk_emmc", "emmc_gate", 0x20, 14, 6),
+ CLK_DIV(LOONGSON2_PIX0_CLK, "clk_pix0", "pll_pix0", 0x30, 0, 6),
+ CLK_DIV(LOONGSON2_PIX1_CLK, "clk_pix1", "pll_pix1", 0x40, 0, 6),
+ CLK_SCALE(LOONGSON2_SATA_CLK, "clk_sata", "clk_out0", 0x50, 12, 3),
+ CLK_SCALE(LOONGSON2_USB_CLK, "clk_usb", "clk_out0", 0x50, 16, 3),
+ CLK_SCALE(LOONGSON2_APB_CLK, "clk_apb", "clk_node", 0x50, 20, 3),
+ CLK_SCALE(LOONGSON2_BOOT_CLK, "clk_boot", NULL, 0x50, 23, 3),
+ CLK_SCALE(LOONGSON2_DES_CLK, "clk_des", "clk_node", 0x50, 40, 3),
+ CLK_SCALE(LOONGSON2_I2S_CLK, "clk_i2s", "clk_node", 0x50, 44, 3),
+ CLK_FIXED(LOONGSON2_MISC_CLK, "clk_misc", NULL, 50000000),
+ { /* Sentinel */ },
+};
+
static inline struct loongson2_clk_data *to_loongson2_clk(struct clk_hw *hw)
{
return container_of(hw, struct loongson2_clk_data, hw);
@@ -266,6 +327,16 @@ static int loongson2_clk_probe(struct platform_device *pdev)
CLK_DIVIDER_ONE_BASED,
&clp->clk_lock);
break;
+ case CLK_TYPE_GATE:
+ hw = devm_clk_hw_register_gate(dev, p->name, p->parent_name, 0,
+ clp->base + p->reg_offset,
+ p->bit_idx, 0,
+ &clp->clk_lock);
+ break;
+ case CLK_TYPE_FIXED:
+ hw = clk_hw_register_fixed_rate_parent_data(dev, p->name, pdata,
+ 0, p->fixed_rate);
+ break;
default:
return dev_err_probe(dev, -EINVAL, "Invalid clk type\n");
}
@@ -284,6 +355,7 @@ static int loongson2_clk_probe(struct platform_device *pdev)
static const struct of_device_id loongson2_clk_match_table[] = {
{ .compatible = "loongson,ls2k0500-clk", .data = &ls2k0500_clks },
{ .compatible = "loongson,ls2k-clk", .data = &ls2k1000_clks },
+ { .compatible = "loongson,ls2k2000-clk", .data = &ls2k2000_clks },
{ }
};
MODULE_DEVICE_TABLE(of, loongson2_clk_match_table);
--
2.43.0
^ permalink raw reply related
* [PATCH v2 7/8] LoongArch: dts: Add clock support to Loongson-2K0500
From: Binbin Zhou @ 2024-04-01 8:24 UTC (permalink / raw)
To: Binbin Zhou, Huacai Chen, Michael Turquette, Stephen Boyd,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Yinbo Zhu
Cc: Huacai Chen, loongson-kernel, linux-clk, devicetree, Xuerui Wang,
loongarch, Binbin Zhou
In-Reply-To: <cover.1711504700.git.zhoubinbin@loongson.cn>
The module is supported, enable it.
Also, add the dma node associated with it.
Signed-off-by: Binbin Zhou <zhoubinbin@loongson.cn>
---
.../boot/dts/loongson-2k0500-ref.dts | 4 ++
arch/loongarch/boot/dts/loongson-2k0500.dtsi | 57 ++++++++++++++++++-
2 files changed, 58 insertions(+), 3 deletions(-)
diff --git a/arch/loongarch/boot/dts/loongson-2k0500-ref.dts b/arch/loongarch/boot/dts/loongson-2k0500-ref.dts
index 8aefb0c12672..62dad6297e82 100644
--- a/arch/loongarch/boot/dts/loongson-2k0500-ref.dts
+++ b/arch/loongarch/boot/dts/loongson-2k0500-ref.dts
@@ -41,6 +41,10 @@ linux,cma {
};
};
+&clk {
+ status = "okay";
+};
+
&gmac0 {
status = "okay";
diff --git a/arch/loongarch/boot/dts/loongson-2k0500.dtsi b/arch/loongarch/boot/dts/loongson-2k0500.dtsi
index 444779c21034..413b83366367 100644
--- a/arch/loongarch/boot/dts/loongson-2k0500.dtsi
+++ b/arch/loongarch/boot/dts/loongson-2k0500.dtsi
@@ -6,6 +6,7 @@
/dts-v1/;
#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/clock/loongson,ls2k-clk.h>
/ {
#address-cells = <2>;
@@ -19,14 +20,15 @@ cpu0: cpu@0 {
compatible = "loongson,la264";
device_type = "cpu";
reg = <0x0>;
- clocks = <&cpu_clk>;
+ clocks = <&clk LOONGSON2_NODE_CLK>;
};
};
- cpu_clk: cpu-clk {
+ ref_100m: clock-ref-100m {
compatible = "fixed-clock";
#clock-cells = <0>;
- clock-frequency = <500000000>;
+ clock-frequency = <100000000>;
+ clock-output-names = "ref_100m";
};
cpuintc: interrupt-controller {
@@ -52,6 +54,55 @@ isa@16400000 {
ranges = <1 0x0 0x0 0x16400000 0x4000>;
};
+ clk: clock-controller@1fe10400 {
+ compatible = "loongson,ls2k0500-clk";
+ reg = <0x0 0x1fe10400 0x0 0x2c>;
+ #clock-cells = <1>;
+ clocks = <&ref_100m>;
+ clock-names = "ref_100m";
+ status = "disabled";
+ };
+
+ dma-controller@1fe10c00 {
+ compatible = "loongson,ls2k0500-apbdma", "loongson,ls2k1000-apbdma";
+ reg = <0 0x1fe10c00 0 0x8>;
+ interrupt-parent = <&eiointc>;
+ interrupts = <67>;
+ clocks = <&clk LOONGSON2_APB_CLK>;
+ #dma-cells = <1>;
+ status = "disabled";
+ };
+
+ dma-controller@1fe10c10 {
+ compatible = "loongson,ls2k0500-apbdma", "loongson,ls2k1000-apbdma";
+ reg = <0 0x1fe10c10 0 0x8>;
+ interrupt-parent = <&eiointc>;
+ interrupts = <68>;
+ clocks = <&clk LOONGSON2_APB_CLK>;
+ #dma-cells = <1>;
+ status = "disabled";
+ };
+
+ dma-controller@1fe10c20 {
+ compatible = "loongson,ls2k0500-apbdma", "loongson,ls2k1000-apbdma";
+ reg = <0 0x1fe10c20 0 0x8>;
+ interrupt-parent = <&eiointc>;
+ interrupts = <69>;
+ clocks = <&clk LOONGSON2_APB_CLK>;
+ #dma-cells = <1>;
+ status = "disabled";
+ };
+
+ dma-controller@1fe10c30 {
+ compatible = "loongson,ls2k0500-apbdma", "loongson,ls2k1000-apbdma";
+ reg = <0 0x1fe10c30 0 0x8>;
+ interrupt-parent = <&eiointc>;
+ interrupts = <70>;
+ clocks = <&clk LOONGSON2_APB_CLK>;
+ #dma-cells = <1>;
+ status = "disabled";
+ };
+
liointc0: interrupt-controller@1fe11400 {
compatible = "loongson,liointc-2.0";
reg = <0x0 0x1fe11400 0x0 0x40>,
--
2.43.0
^ permalink raw reply related
* [PATCH v2 8/8] LoongArch: dts: Add clock support to Loongson-2K2000
From: Binbin Zhou @ 2024-04-01 8:24 UTC (permalink / raw)
To: Binbin Zhou, Huacai Chen, Michael Turquette, Stephen Boyd,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Yinbo Zhu
Cc: Huacai Chen, loongson-kernel, linux-clk, devicetree, Xuerui Wang,
loongarch, Binbin Zhou
In-Reply-To: <cover.1711504700.git.zhoubinbin@loongson.cn>
The module is supported, enable it.
Signed-off-by: Binbin Zhou <zhoubinbin@loongson.cn>
---
.../boot/dts/loongson-2k2000-ref.dts | 4 ++++
arch/loongarch/boot/dts/loongson-2k2000.dtsi | 19 +++++++++++++++----
2 files changed, 19 insertions(+), 4 deletions(-)
diff --git a/arch/loongarch/boot/dts/loongson-2k2000-ref.dts b/arch/loongarch/boot/dts/loongson-2k2000-ref.dts
index dca91caf895e..a7af345b30ea 100644
--- a/arch/loongarch/boot/dts/loongson-2k2000-ref.dts
+++ b/arch/loongarch/boot/dts/loongson-2k2000-ref.dts
@@ -39,6 +39,10 @@ linux,cma {
};
};
+&clk {
+ status = "okay";
+};
+
&sata {
status = "okay";
};
diff --git a/arch/loongarch/boot/dts/loongson-2k2000.dtsi b/arch/loongarch/boot/dts/loongson-2k2000.dtsi
index a231949b5f55..605efaba7292 100644
--- a/arch/loongarch/boot/dts/loongson-2k2000.dtsi
+++ b/arch/loongarch/boot/dts/loongson-2k2000.dtsi
@@ -6,6 +6,7 @@
/dts-v1/;
#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/clock/loongson,ls2k-clk.h>
/ {
#address-cells = <2>;
@@ -19,21 +20,22 @@ cpu0: cpu@1 {
compatible = "loongson,la364";
device_type = "cpu";
reg = <0x0>;
- clocks = <&cpu_clk>;
+ clocks = <&clk LOONGSON2_NODE_CLK>;
};
cpu1: cpu@2 {
compatible = "loongson,la364";
device_type = "cpu";
reg = <0x1>;
- clocks = <&cpu_clk>;
+ clocks = <&clk LOONGSON2_NODE_CLK>;
};
};
- cpu_clk: cpu-clk {
+ ref_100m: clock-ref-100m {
compatible = "fixed-clock";
#clock-cells = <0>;
- clock-frequency = <1400000000>;
+ clock-frequency = <100000000>;
+ clock-output-names = "ref_100m";
};
cpuintc: interrupt-controller {
@@ -51,6 +53,15 @@ bus@10000000 {
#address-cells = <2>;
#size-cells = <2>;
+ clk: clock-controller@10010480 {
+ compatible = "loongson,ls2k2000-clk";
+ reg = <0x0 0x10010480 0x0 0x100>;
+ #clock-cells = <1>;
+ clocks = <&ref_100m>;
+ clock-names = "ref_100m";
+ status = "disabled";
+ };
+
pmc: power-management@100d0000 {
compatible = "loongson,ls2k2000-pmc", "loongson,ls2k0500-pmc", "syscon";
reg = <0x0 0x100d0000 0x0 0x58>;
--
2.43.0
^ permalink raw reply related
* [PATCH v8 2/3] dt-bindings: input: qcom,pm8xxx-vib: add new SPMI vibrator module
From: Fenglin Wu via B4 Relay @ 2024-04-01 8:38 UTC (permalink / raw)
To: kernel, Andy Gross, Bjorn Andersson, Konrad Dybcio,
Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski,
Dmitry Baryshkov
Cc: linux-arm-msm, linux-input, linux-kernel, devicetree, Fenglin Wu,
Krzysztof Kozlowski
In-Reply-To: <20240401-pm8xxx-vibrator-new-design-v8-0-6f2b8b03b4c7@quicinc.com>
From: Fenglin Wu <quic_fenglinw@quicinc.com>
Add compatible strings to support vibrator module inside PMI632,
PMI7250B, PM7325B, PM7550BA.
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Signed-off-by: Fenglin Wu <quic_fenglinw@quicinc.com>
---
.../devicetree/bindings/input/qcom,pm8xxx-vib.yaml | 16 ++++++++++++----
1 file changed, 12 insertions(+), 4 deletions(-)
diff --git a/Documentation/devicetree/bindings/input/qcom,pm8xxx-vib.yaml b/Documentation/devicetree/bindings/input/qcom,pm8xxx-vib.yaml
index c8832cd0d7da..2025d6a5423e 100644
--- a/Documentation/devicetree/bindings/input/qcom,pm8xxx-vib.yaml
+++ b/Documentation/devicetree/bindings/input/qcom,pm8xxx-vib.yaml
@@ -11,10 +11,18 @@ maintainers:
properties:
compatible:
- enum:
- - qcom,pm8058-vib
- - qcom,pm8916-vib
- - qcom,pm8921-vib
+ oneOf:
+ - enum:
+ - qcom,pm8058-vib
+ - qcom,pm8916-vib
+ - qcom,pm8921-vib
+ - qcom,pmi632-vib
+ - items:
+ - enum:
+ - qcom,pm7250b-vib
+ - qcom,pm7325b-vib
+ - qcom,pm7550ba-vib
+ - const: qcom,pmi632-vib
reg:
maxItems: 1
--
2.25.1
^ permalink raw reply related
* [PATCH v8 1/3] input: pm8xxx-vibrator: refactor to support new SPMI vibrator
From: Fenglin Wu via B4 Relay @ 2024-04-01 8:38 UTC (permalink / raw)
To: kernel, Andy Gross, Bjorn Andersson, Konrad Dybcio,
Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski,
Dmitry Baryshkov
Cc: linux-arm-msm, linux-input, linux-kernel, devicetree, Fenglin Wu
In-Reply-To: <20240401-pm8xxx-vibrator-new-design-v8-0-6f2b8b03b4c7@quicinc.com>
From: Fenglin Wu <quic_fenglinw@quicinc.com>
Currently, vibrator control register addresses are hard coded,
including the base address and offsets, it's not flexible to
support new SPMI vibrator module which is usually included in
different PMICs with different base address. Refactor it by using
the base address defined in devicetree.
Signed-off-by: Fenglin Wu <quic_fenglinw@quicinc.com>
---
drivers/input/misc/pm8xxx-vibrator.c | 40 ++++++++++++++++++++++++------------
1 file changed, 27 insertions(+), 13 deletions(-)
diff --git a/drivers/input/misc/pm8xxx-vibrator.c b/drivers/input/misc/pm8xxx-vibrator.c
index 04cb87efd799..3b6a2e949f30 100644
--- a/drivers/input/misc/pm8xxx-vibrator.c
+++ b/drivers/input/misc/pm8xxx-vibrator.c
@@ -19,26 +19,26 @@
#define MAX_FF_SPEED 0xff
struct pm8xxx_regs {
- unsigned int enable_addr;
+ unsigned int enable_offset;
unsigned int enable_mask;
- unsigned int drv_addr;
+ unsigned int drv_offset;
unsigned int drv_mask;
unsigned int drv_shift;
unsigned int drv_en_manual_mask;
};
static const struct pm8xxx_regs pm8058_regs = {
- .drv_addr = 0x4A,
+ .drv_offset = 0x4A,
.drv_mask = 0xf8,
.drv_shift = 3,
.drv_en_manual_mask = 0xfc,
};
static struct pm8xxx_regs pm8916_regs = {
- .enable_addr = 0xc046,
+ .enable_offset = 0x46,
.enable_mask = BIT(7),
- .drv_addr = 0xc041,
+ .drv_offset = 0x41,
.drv_mask = 0x1F,
.drv_shift = 0,
.drv_en_manual_mask = 0,
@@ -50,6 +50,8 @@ static struct pm8xxx_regs pm8916_regs = {
* @work: work structure to set the vibration parameters
* @regmap: regmap for register read/write
* @regs: registers' info
+ * @enable_addr: vibrator enable register
+ * @drv_addr: vibrator drive strength register
* @speed: speed of vibration set from userland
* @active: state of vibrator
* @level: level of vibration to set in the chip
@@ -60,6 +62,8 @@ struct pm8xxx_vib {
struct work_struct work;
struct regmap *regmap;
const struct pm8xxx_regs *regs;
+ unsigned int enable_addr;
+ unsigned int drv_addr;
int speed;
int level;
bool active;
@@ -82,14 +86,14 @@ static int pm8xxx_vib_set(struct pm8xxx_vib *vib, bool on)
else
val &= ~regs->drv_mask;
- rc = regmap_write(vib->regmap, regs->drv_addr, val);
+ rc = regmap_write(vib->regmap, vib->drv_addr, val);
if (rc < 0)
return rc;
vib->reg_vib_drv = val;
if (regs->enable_mask)
- rc = regmap_update_bits(vib->regmap, regs->enable_addr,
+ rc = regmap_update_bits(vib->regmap, vib->enable_addr,
regs->enable_mask, on ? ~0 : 0);
return rc;
@@ -102,11 +106,10 @@ static int pm8xxx_vib_set(struct pm8xxx_vib *vib, bool on)
static void pm8xxx_work_handler(struct work_struct *work)
{
struct pm8xxx_vib *vib = container_of(work, struct pm8xxx_vib, work);
- const struct pm8xxx_regs *regs = vib->regs;
- int rc;
unsigned int val;
+ int rc;
- rc = regmap_read(vib->regmap, regs->drv_addr, &val);
+ rc = regmap_read(vib->regmap, vib->drv_addr, &val);
if (rc < 0)
return;
@@ -169,7 +172,7 @@ static int pm8xxx_vib_probe(struct platform_device *pdev)
struct pm8xxx_vib *vib;
struct input_dev *input_dev;
int error;
- unsigned int val;
+ unsigned int val, reg_base = 0;
const struct pm8xxx_regs *regs;
vib = devm_kzalloc(&pdev->dev, sizeof(*vib), GFP_KERNEL);
@@ -189,13 +192,24 @@ static int pm8xxx_vib_probe(struct platform_device *pdev)
regs = of_device_get_match_data(&pdev->dev);
+ if (regs->enable_offset != 0) {
+ error = fwnode_property_read_u32(pdev->dev.fwnode, "reg", ®_base);
+ if (error < 0) {
+ dev_err(&pdev->dev, "Failed to read reg address, rc=%d\n", error);
+ return error;
+ }
+ }
+
+ vib->enable_addr = reg_base + regs->enable_offset;
+ vib->drv_addr = reg_base + regs->drv_offset;
+
/* operate in manual mode */
- error = regmap_read(vib->regmap, regs->drv_addr, &val);
+ error = regmap_read(vib->regmap, vib->drv_addr, &val);
if (error < 0)
return error;
val &= regs->drv_en_manual_mask;
- error = regmap_write(vib->regmap, regs->drv_addr, val);
+ error = regmap_write(vib->regmap, vib->drv_addr, val);
if (error < 0)
return error;
--
2.25.1
^ permalink raw reply related
* [PATCH v8 3/3] input: pm8xxx-vibrator: add new SPMI vibrator support
From: Fenglin Wu via B4 Relay @ 2024-04-01 8:38 UTC (permalink / raw)
To: kernel, Andy Gross, Bjorn Andersson, Konrad Dybcio,
Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski,
Dmitry Baryshkov
Cc: linux-arm-msm, linux-input, linux-kernel, devicetree, Fenglin Wu
In-Reply-To: <20240401-pm8xxx-vibrator-new-design-v8-0-6f2b8b03b4c7@quicinc.com>
From: Fenglin Wu <quic_fenglinw@quicinc.com>
Add support for a new SPMI vibrator module which is very similar
to the vibrator module inside PM8916 but has a finer drive voltage
step and different output voltage range, its drive level control
is expanded across 2 registers. The vibrator module can be found
in following Qualcomm PMICs: PMI632, PM7250B, PM7325B, PM7550BA.
Signed-off-by: Fenglin Wu <quic_fenglinw@quicinc.com>
---
drivers/input/misc/pm8xxx-vibrator.c | 49 +++++++++++++++++++++++++++++-------
1 file changed, 40 insertions(+), 9 deletions(-)
diff --git a/drivers/input/misc/pm8xxx-vibrator.c b/drivers/input/misc/pm8xxx-vibrator.c
index 3b6a2e949f30..59548cd9331c 100644
--- a/drivers/input/misc/pm8xxx-vibrator.c
+++ b/drivers/input/misc/pm8xxx-vibrator.c
@@ -12,9 +12,9 @@
#include <linux/regmap.h>
#include <linux/slab.h>
-#define VIB_MAX_LEVEL_mV (3100)
-#define VIB_MIN_LEVEL_mV (1200)
-#define VIB_MAX_LEVELS (VIB_MAX_LEVEL_mV - VIB_MIN_LEVEL_mV)
+#define VIB_MAX_LEVEL_mV(vib) (vib->drv2_addr ? (3544) : (3100))
+#define VIB_MIN_LEVEL_mV(vib) (vib->drv2_addr ? (1504) : (1200))
+#define VIB_MAX_LEVELS(vib) (VIB_MAX_LEVEL_mV(vib) - VIB_MIN_LEVEL_mV(vib))
#define MAX_FF_SPEED 0xff
@@ -25,6 +25,9 @@ struct pm8xxx_regs {
unsigned int drv_offset;
unsigned int drv_mask;
unsigned int drv_shift;
+ unsigned int drv2_offset;
+ unsigned int drv2_mask;
+ unsigned int drv2_shift;
unsigned int drv_en_manual_mask;
};
@@ -44,6 +47,18 @@ static struct pm8xxx_regs pm8916_regs = {
.drv_en_manual_mask = 0,
};
+static struct pm8xxx_regs pmi632_regs = {
+ .enable_offset = 0x46,
+ .enable_mask = BIT(7),
+ .drv_offset = 0x40,
+ .drv_mask = 0xFF,
+ .drv_shift = 0,
+ .drv2_offset = 0x41,
+ .drv2_mask = 0x0F,
+ .drv2_shift = 8,
+ .drv_en_manual_mask = 0,
+};
+
/**
* struct pm8xxx_vib - structure to hold vibrator data
* @vib_input_dev: input device supporting force feedback
@@ -52,6 +67,7 @@ static struct pm8xxx_regs pm8916_regs = {
* @regs: registers' info
* @enable_addr: vibrator enable register
* @drv_addr: vibrator drive strength register
+ * @drv2_addr: vibrator drive strength upper byte register
* @speed: speed of vibration set from userland
* @active: state of vibrator
* @level: level of vibration to set in the chip
@@ -64,6 +80,7 @@ struct pm8xxx_vib {
const struct pm8xxx_regs *regs;
unsigned int enable_addr;
unsigned int drv_addr;
+ unsigned int drv2_addr;
int speed;
int level;
bool active;
@@ -92,6 +109,16 @@ static int pm8xxx_vib_set(struct pm8xxx_vib *vib, bool on)
vib->reg_vib_drv = val;
+ if (regs->drv2_mask) {
+ if (on)
+ val = (vib->level << regs->drv2_shift) & regs->drv2_mask;
+ else
+ val = 0;
+ rc = regmap_write(vib->regmap, vib->drv2_addr, val);
+ if (rc < 0)
+ return rc;
+ }
+
if (regs->enable_mask)
rc = regmap_update_bits(vib->regmap, vib->enable_addr,
regs->enable_mask, on ? ~0 : 0);
@@ -114,19 +141,22 @@ static void pm8xxx_work_handler(struct work_struct *work)
return;
/*
- * pmic vibrator supports voltage ranges from 1.2 to 3.1V, so
+ * pmic vibrator supports voltage ranges from MIN_LEVEL to MAX_LEVEL, so
* scale the level to fit into these ranges.
*/
if (vib->speed) {
vib->active = true;
- vib->level = ((VIB_MAX_LEVELS * vib->speed) / MAX_FF_SPEED) +
- VIB_MIN_LEVEL_mV;
- vib->level /= 100;
+ vib->level = ((VIB_MAX_LEVELS(vib) * vib->speed) / MAX_FF_SPEED) +
+ VIB_MIN_LEVEL_mV(vib);
} else {
vib->active = false;
- vib->level = VIB_MIN_LEVEL_mV / 100;
+ vib->level = VIB_MIN_LEVEL_mV(vib);
+
}
+ if (!vib->drv2_addr)
+ vib->level /= 100;
+
pm8xxx_vib_set(vib, vib->active);
}
@@ -202,7 +232,7 @@ static int pm8xxx_vib_probe(struct platform_device *pdev)
vib->enable_addr = reg_base + regs->enable_offset;
vib->drv_addr = reg_base + regs->drv_offset;
-
+ vib->drv2_addr = reg_base + regs->drv2_offset;
/* operate in manual mode */
error = regmap_read(vib->regmap, vib->drv_addr, &val);
if (error < 0)
@@ -256,6 +286,7 @@ static const struct of_device_id pm8xxx_vib_id_table[] = {
{ .compatible = "qcom,pm8058-vib", .data = &pm8058_regs },
{ .compatible = "qcom,pm8921-vib", .data = &pm8058_regs },
{ .compatible = "qcom,pm8916-vib", .data = &pm8916_regs },
+ { .compatible = "qcom,pmi632-vib", .data = &pmi632_regs },
{ }
};
MODULE_DEVICE_TABLE(of, pm8xxx_vib_id_table);
--
2.25.1
^ permalink raw reply related
* [PATCH v8 0/3] Add support for vibrator in multiple PMICs
From: Fenglin Wu via B4 Relay @ 2024-04-01 8:38 UTC (permalink / raw)
To: kernel, Andy Gross, Bjorn Andersson, Konrad Dybcio,
Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski,
Dmitry Baryshkov
Cc: linux-arm-msm, linux-input, linux-kernel, devicetree, Fenglin Wu,
Krzysztof Kozlowski
Add SW support for the vibrator module inside PMI632, PM7250B, PM7325B, PM7550BA.
It is very similar to the vibrator module inside PM8916 which is supported in
pm8xxx-vib driver but just the drive amplitude is controlled with 2 registers,
and the register base offset in each PMIC is different.
Changes in v8:
1. Remove hw_type, and still keep the register info in match data
2. Update to use register offset in pm8xxx_regs, and the base address
defined in DT for SPMI vibrator will be added in register access
3. Update voltage output range for SPMI vibrator which has 2 bytes drive
registers
Changes in v7:
1. Fix a typo: SSBL_VIB_DRV_REG --> SSBI_VIB_DRV_REG
2. Move the hw_type switch case in pm8xxx_vib_set() to the refactoring
change.
Changes in v6:
1. Add "qcom,pmi632-vib" as a standalone compatible string.
Changes in v5:
1. Drop "qcom,spmi-vib-gen2" generic compatible string as requested
and use device specific compatible strings only.
Changes in v4:
1. Update to use the combination of the HW type and register offset
as the constant match data, the register base address defined in
'reg' property will be added when accessing SPMI registers using
regmap APIs.
2. Remove 'qcom,spmi-vib-gen1' generic compatible string.
Changes in v3:
1. Refactor the driver to support different type of the vibrators with
better flexibility by introducing the HW type with corresponding
register fields definitions.
2. Add 'qcom,spmi-vib-gen1' and 'qcom,spmi-vib-gen2' compatible
strings, and add PMI632, PM7250B, PM7325B, PM7550BA as compatbile as
spmi-vib-gen2.
Changes in v2:
Remove the "pm7550ba-vib" compatible string as it's compatible with pm7325b.
Signed-off-by: Fenglin Wu <quic_fenglinw@quicinc.com>
---
Fenglin Wu (3):
input: pm8xxx-vibrator: refactor to support new SPMI vibrator
dt-bindings: input: qcom,pm8xxx-vib: add new SPMI vibrator module
input: pm8xxx-vibrator: add new SPMI vibrator support
.../devicetree/bindings/input/qcom,pm8xxx-vib.yaml | 16 +++-
drivers/input/misc/pm8xxx-vibrator.c | 87 ++++++++++++++++------
2 files changed, 78 insertions(+), 25 deletions(-)
---
base-commit: 650cda2ce25f08e8fae391b3ba6be27e7296c6a5
change-id: 20240328-pm8xxx-vibrator-new-design-e5811ad59e8a
Best regards,
--
Fenglin Wu <quic_fenglinw@quicinc.com>
^ permalink raw reply
* [PATCH v1] Revise duty cycle for SMB9 and SMB10
From: Delphine CC Chiu @ 2024-04-01 9:05 UTC (permalink / raw)
To: patrick, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Joel Stanley, Andrew Jeffery
Cc: Delphine CC Chiu, devicetree, linux-arm-kernel, linux-aspeed,
linux-kernel
ARM: dts: aspeed: yosemite4:
Revise duty cycle for SMB9 and SMB10 to 40:60
To meet 400kHz-i2c clock low time spec (> 1.3 us).
Signed-off-by: Delphine CC Chiu <Delphine_CC_Chiu@Wiwynn.com>
---
arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-yosemite4.dts | 2 ++
1 file changed, 2 insertions(+)
diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-yosemite4.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-yosemite4.dts
index 64075cc41d92..b3a2aa8f53a5 100644
--- a/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-yosemite4.dts
+++ b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-yosemite4.dts
@@ -257,6 +257,7 @@ power-sensor@40 {
&i2c8 {
status = "okay";
bus-frequency = <400000>;
+ i2c-clk-high-min-percent = <40>;
i2c-mux@70 {
compatible = "nxp,pca9544";
idle-state = <0>;
@@ -268,6 +269,7 @@ i2c-mux@70 {
&i2c9 {
status = "okay";
bus-frequency = <400000>;
+ i2c-clk-high-min-percent = <40>;
i2c-mux@71 {
compatible = "nxp,pca9544";
idle-state = <0>;
--
2.25.1
^ permalink raw reply related
* Re: [PATCH v7 2/2] dmaengine: Loongson1: Add Loongson-1 APB DMA driver
From: Huacai Chen @ 2024-04-01 9:05 UTC (permalink / raw)
To: Keguang Zhang
Cc: Vinod Koul, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
linux-mips, dmaengine, devicetree, linux-kernel
In-Reply-To: <CAJhJPsXutxdZkhjWdc-JuJOaC_6+6zsDjbYT1Bg6Yuk8AQX1ug@mail.gmail.com>
On Mon, Apr 1, 2024 at 10:45 AM Keguang Zhang <keguang.zhang@gmail.com> wrote:
>
> Hi Huacai,
>
> On Sat, Mar 30, 2024 at 9:59 PM Huacai Chen <chenhuacai@kernel.org> wrote:
> >
> > Hi, Keguang,
> >
> > On Fri, Mar 29, 2024 at 7:28 PM Keguang Zhang via B4 Relay
> > <devnull+keguang.zhang.gmail.com@kernel.org> wrote:
> > >
> > > From: Keguang Zhang <keguang.zhang@gmail.com>
> > >
> > > This patch adds APB DMA driver for Loongson-1 SoCs.
> > >
> > > Signed-off-by: Keguang Zhang <keguang.zhang@gmail.com>
> > > ---
> > > Changes in v7:
> > > - Change the comptible to 'loongson,ls1*-apbdma'
> > > - Update Kconfig and Makefile accordingly
> > > - Rename the file to loongson1-apb-dma.c to keep the consistency
> > >
> > > Changes in v6:
> > > - Implement .device_prep_dma_cyclic for Loongson1 audio driver,
> > > - as well as .device_pause and .device_resume.
> > > - Set the limitation LS1X_DMA_MAX_DESC and put all descriptors
> > > - into one page to save memory
> > > - Move dma_pool_zalloc() into ls1x_dma_alloc_desc()
> > > - Drop dma_slave_config structure
> > > - Use .remove_new instead of .remove
> > > - Use KBUILD_MODNAME for the driver name
> > > - Improve the debug information
> > >
> > > Changes in v5:
> > > - Add DT support
> > > - Use DT data instead of platform data
> > > - Use chan_id of struct dma_chan instead of own id
> > > - Use of_dma_xlate_by_chan_id() instead of ls1x_dma_filter()
> > > - Update the author information to my official name
> > >
> > > Changes in v4:
> > > - Use dma_slave_map to find the proper channel.
> > > - Explicitly call devm_request_irq() and tasklet_kill().
> > > - Fix namespace issue.
> > > - Some minor fixes and cleanups.
> > >
> > > Changes in v3:
> > > - Rename ls1x_dma_filter_fn to ls1x_dma_filter.
> > >
> > > Changes in v2:
> > > - Change the config from 'DMA_LOONGSON1' to 'LOONGSON1_DMA',
> > > - and rearrange it in alphabetical order in Kconfig and Makefile.
> > > - Fix comment style.
> > > ---
> > > drivers/dma/Kconfig | 9 +
> > > drivers/dma/Makefile | 1 +
> > > drivers/dma/loongson1-apb-dma.c | 665 ++++++++++++++++++++++++++++++++++++++++
> > > 3 files changed, 675 insertions(+)
> > >
> > > diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
> > > index 002a5ec80620..f7b06c4cdf3f 100644
> > > --- a/drivers/dma/Kconfig
> > > +++ b/drivers/dma/Kconfig
> > > @@ -369,6 +369,15 @@ config K3_DMA
> > > Support the DMA engine for Hisilicon K3 platform
> > > devices.
> > >
> > > +config LOONGSON1_APB_DMA
> > > + tristate "Loongson1 APB DMA support"
> > > + depends on MACH_LOONGSON32 || COMPILE_TEST
> > > + select DMA_ENGINE
> > > + select DMA_VIRTUAL_CHANNELS
> > > + help
> > > + This selects support for the APB DMA controller in Loongson1 SoCs,
> > > + which is required by Loongson1 NAND and audio support.
> > Why not rename to LS1X_APB_DMA and put it just before LS2X_APB_DMA
> > (and also the driver file name)?
> >
> So far all Kconfig entries of Loongson-1 drivers are named with the
> keyword "LOONGSON1".
> The same is true for these file names.
> Therefore, I need to keep the consistency.
But I see LS1X_IRQ in drivers/irqchip/Kconfig
Huacai
>
>
> > Huacai
> >
> > > +
> > > config LPC18XX_DMAMUX
> > > bool "NXP LPC18xx/43xx DMA MUX for PL080"
> > > depends on ARCH_LPC18XX || COMPILE_TEST
> > > diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile
> > > index dfd40d14e408..b26f6677978a 100644
> > > --- a/drivers/dma/Makefile
> > > +++ b/drivers/dma/Makefile
> > > @@ -47,6 +47,7 @@ obj-$(CONFIG_INTEL_IDMA64) += idma64.o
> > > obj-$(CONFIG_INTEL_IOATDMA) += ioat/
> > > obj-y += idxd/
> > > obj-$(CONFIG_K3_DMA) += k3dma.o
> > > +obj-$(CONFIG_LOONGSON1_APB_DMA) += loongson1-apb-dma.o
> > > obj-$(CONFIG_LPC18XX_DMAMUX) += lpc18xx-dmamux.o
> > > obj-$(CONFIG_LS2X_APB_DMA) += ls2x-apb-dma.o
> > > obj-$(CONFIG_MILBEAUT_HDMAC) += milbeaut-hdmac.o
> > > diff --git a/drivers/dma/loongson1-apb-dma.c b/drivers/dma/loongson1-apb-dma.c
> > > new file mode 100644
> > > index 000000000000..d474a2601e6e
> > > --- /dev/null
> > > +++ b/drivers/dma/loongson1-apb-dma.c
> > > @@ -0,0 +1,665 @@
> > > +// SPDX-License-Identifier: GPL-2.0-or-later
> > > +/*
> > > + * Driver for Loongson-1 APB DMA Controller
> > > + *
> > > + * Copyright (C) 2015-2024 Keguang Zhang <keguang.zhang@gmail.com>
> > > + */
> > > +
> > > +#include <linux/dmapool.h>
> > > +#include <linux/dma-mapping.h>
> > > +#include <linux/init.h>
> > > +#include <linux/interrupt.h>
> > > +#include <linux/iopoll.h>
> > > +#include <linux/module.h>
> > > +#include <linux/of.h>
> > > +#include <linux/of_dma.h>
> > > +#include <linux/platform_device.h>
> > > +#include <linux/slab.h>
> > > +
> > > +#include "dmaengine.h"
> > > +#include "virt-dma.h"
> > > +
> > > +/* Loongson-1 DMA Control Register */
> > > +#define DMA_CTRL 0x0
> > > +
> > > +/* DMA Control Register Bits */
> > > +#define DMA_STOP BIT(4)
> > > +#define DMA_START BIT(3)
> > > +#define DMA_ASK_VALID BIT(2)
> > > +
> > > +#define DMA_ADDR_MASK GENMASK(31, 6)
> > > +
> > > +/* DMA Next Field Bits */
> > > +#define DMA_NEXT_VALID BIT(0)
> > > +
> > > +/* DMA Command Field Bits */
> > > +#define DMA_RAM2DEV BIT(12)
> > > +#define DMA_INT BIT(1)
> > > +#define DMA_INT_MASK BIT(0)
> > > +
> > > +#define LS1X_DMA_MAX_CHANNELS 3
> > > +
> > > +/* Size of allocations for hardware descriptors */
> > > +#define LS1X_DMA_DESCS_SIZE PAGE_SIZE
> > > +#define LS1X_DMA_MAX_DESC \
> > > + (LS1X_DMA_DESCS_SIZE / sizeof(struct ls1x_dma_hwdesc))
> > > +
> > > +struct ls1x_dma_hwdesc {
> > > + u32 next; /* next descriptor address */
> > > + u32 saddr; /* memory DMA address */
> > > + u32 daddr; /* device DMA address */
> > > + u32 length;
> > > + u32 stride;
> > > + u32 cycles;
> > > + u32 cmd;
> > > + u32 stats;
> > > +};
> > > +
> > > +struct ls1x_dma_desc {
> > > + struct virt_dma_desc vdesc;
> > > + enum dma_transfer_direction dir;
> > > + enum dma_transaction_type type;
> > > + unsigned int bus_width;
> > > +
> > > + unsigned int nr_descs; /* number of descriptors */
> > > +
> > > + struct ls1x_dma_hwdesc *hwdesc;
> > > + dma_addr_t hwdesc_phys;
> > > +};
> > > +
> > > +struct ls1x_dma_chan {
> > > + struct virt_dma_chan vchan;
> > > + struct dma_pool *desc_pool;
> > > + phys_addr_t src_addr;
> > > + phys_addr_t dst_addr;
> > > + enum dma_slave_buswidth src_addr_width;
> > > + enum dma_slave_buswidth dst_addr_width;
> > > +
> > > + void __iomem *reg_base;
> > > + int irq;
> > > +
> > > + struct ls1x_dma_desc *desc;
> > > +
> > > + struct ls1x_dma_hwdesc *curr_hwdesc;
> > > + dma_addr_t curr_hwdesc_phys;
> > > +};
> > > +
> > > +struct ls1x_dma {
> > > + struct dma_device ddev;
> > > + void __iomem *reg_base;
> > > +
> > > + unsigned int nr_chans;
> > > + struct ls1x_dma_chan chan[];
> > > +};
> > > +
> > > +#define to_ls1x_dma_chan(dchan) \
> > > + container_of(dchan, struct ls1x_dma_chan, vchan.chan)
> > > +
> > > +#define to_ls1x_dma_desc(vd) \
> > > + container_of(vd, struct ls1x_dma_desc, vdesc)
> > > +
> > > +/* macros for registers read/write */
> > > +#define chan_readl(chan, off) \
> > > + readl((chan)->reg_base + (off))
> > > +
> > > +#define chan_writel(chan, off, val) \
> > > + writel((val), (chan)->reg_base + (off))
> > > +
> > > +static inline struct device *chan2dev(struct dma_chan *chan)
> > > +{
> > > + return &chan->dev->device;
> > > +}
> > > +
> > > +static inline int ls1x_dma_query(struct ls1x_dma_chan *chan,
> > > + dma_addr_t *hwdesc_phys)
> > > +{
> > > + struct dma_chan *dchan = &chan->vchan.chan;
> > > + int val, ret;
> > > +
> > > + val = *hwdesc_phys & DMA_ADDR_MASK;
> > > + val |= DMA_ASK_VALID;
> > > + val |= dchan->chan_id;
> > > + chan_writel(chan, DMA_CTRL, val);
> > > + ret = readl_poll_timeout_atomic(chan->reg_base + DMA_CTRL, val,
> > > + !(val & DMA_ASK_VALID), 0, 3000);
> > > + if (ret)
> > > + dev_err(chan2dev(dchan), "failed to query DMA\n");
> > > +
> > > + return ret;
> > > +}
> > > +
> > > +static inline int ls1x_dma_start(struct ls1x_dma_chan *chan,
> > > + dma_addr_t *hwdesc_phys)
> > > +{
> > > + struct dma_chan *dchan = &chan->vchan.chan;
> > > + int val, ret;
> > > +
> > > + dev_dbg(chan2dev(dchan), "cookie=%d, starting hwdesc=%x\n",
> > > + dchan->cookie, *hwdesc_phys);
> > > +
> > > + val = *hwdesc_phys & DMA_ADDR_MASK;
> > > + val |= DMA_START;
> > > + val |= dchan->chan_id;
> > > + chan_writel(chan, DMA_CTRL, val);
> > > + ret = readl_poll_timeout(chan->reg_base + DMA_CTRL, val,
> > > + !(val & DMA_START), 0, 3000);
> > > + if (ret)
> > > + dev_err(chan2dev(dchan), "failed to start DMA\n");
> > > +
> > > + return ret;
> > > +}
> > > +
> > > +static inline void ls1x_dma_stop(struct ls1x_dma_chan *chan)
> > > +{
> > > + chan_writel(chan, DMA_CTRL, chan_readl(chan, DMA_CTRL) | DMA_STOP);
> > > +}
> > > +
> > > +static void ls1x_dma_free_chan_resources(struct dma_chan *dchan)
> > > +{
> > > + struct ls1x_dma_chan *chan = to_ls1x_dma_chan(dchan);
> > > +
> > > + dma_free_coherent(chan2dev(dchan), sizeof(struct ls1x_dma_hwdesc),
> > > + chan->curr_hwdesc, chan->curr_hwdesc_phys);
> > > + vchan_free_chan_resources(&chan->vchan);
> > > + dma_pool_destroy(chan->desc_pool);
> > > + chan->desc_pool = NULL;
> > > +}
> > > +
> > > +static int ls1x_dma_alloc_chan_resources(struct dma_chan *dchan)
> > > +{
> > > + struct ls1x_dma_chan *chan = to_ls1x_dma_chan(dchan);
> > > +
> > > + chan->desc_pool = dma_pool_create(dma_chan_name(dchan),
> > > + chan2dev(dchan),
> > > + sizeof(struct ls1x_dma_hwdesc),
> > > + __alignof__(struct ls1x_dma_hwdesc),
> > > + 0);
> > > + if (!chan->desc_pool)
> > > + return -ENOMEM;
> > > +
> > > + /* allocate memory for querying current HW descriptor */
> > > + dma_set_coherent_mask(chan2dev(dchan), DMA_BIT_MASK(32));
> > > + chan->curr_hwdesc = dma_alloc_coherent(chan2dev(dchan),
> > > + sizeof(struct ls1x_dma_hwdesc),
> > > + &chan->curr_hwdesc_phys,
> > > + GFP_KERNEL);
> > > + if (!chan->curr_hwdesc)
> > > + return -ENOMEM;
> > > +
> > > + return 0;
> > > +}
> > > +
> > > +static void ls1x_dma_free_desc(struct virt_dma_desc *vdesc)
> > > +{
> > > + struct ls1x_dma_desc *desc = to_ls1x_dma_desc(vdesc);
> > > + struct ls1x_dma_chan *chan = to_ls1x_dma_chan(vdesc->tx.chan);
> > > +
> > > + dma_pool_free(chan->desc_pool, desc->hwdesc, desc->hwdesc_phys);
> > > + chan->desc = NULL;
> > > + kfree(desc);
> > > +}
> > > +
> > > +static struct ls1x_dma_desc *
> > > +ls1x_dma_alloc_desc(struct dma_chan *dchan, int sg_len,
> > > + enum dma_transfer_direction direction,
> > > + enum dma_transaction_type type)
> > > +{
> > > + struct ls1x_dma_chan *chan = to_ls1x_dma_chan(dchan);
> > > + struct ls1x_dma_desc *desc;
> > > +
> > > + if (sg_len > LS1X_DMA_MAX_DESC) {
> > > + dev_err(chan2dev(dchan), "sg_len %u exceeds limit %lu",
> > > + sg_len, LS1X_DMA_MAX_DESC);
> > > + return NULL;
> > > + }
> > > +
> > > + desc = kzalloc(sizeof(*desc), GFP_NOWAIT);
> > > + if (!desc)
> > > + return NULL;
> > > +
> > > + /* allocate HW descriptors */
> > > + desc->hwdesc = dma_pool_zalloc(chan->desc_pool, GFP_NOWAIT,
> > > + &desc->hwdesc_phys);
> > > + if (!desc->hwdesc) {
> > > + dev_err(chan2dev(dchan), "failed to alloc HW descriptors\n");
> > > + ls1x_dma_free_desc(&desc->vdesc);
> > > + return NULL;
> > > + }
> > > +
> > > + desc->dir = direction;
> > > + desc->type = type;
> > > + desc->nr_descs = sg_len;
> > > +
> > > + return desc;
> > > +}
> > > +
> > > +static int ls1x_dma_setup_hwdescs(struct dma_chan *dchan,
> > > + struct ls1x_dma_desc *desc,
> > > + struct scatterlist *sgl, unsigned int sg_len)
> > > +{
> > > + struct ls1x_dma_chan *chan = to_ls1x_dma_chan(dchan);
> > > + dma_addr_t next_hwdesc_phys = desc->hwdesc_phys;
> > > +
> > > + struct scatterlist *sg;
> > > + unsigned int dev_addr, cmd, i;
> > > +
> > > + switch (desc->dir) {
> > > + case DMA_MEM_TO_DEV:
> > > + dev_addr = chan->dst_addr;
> > > + desc->bus_width = chan->dst_addr_width;
> > > + cmd = DMA_RAM2DEV | DMA_INT;
> > > + break;
> > > + case DMA_DEV_TO_MEM:
> > > + dev_addr = chan->src_addr;
> > > + desc->bus_width = chan->src_addr_width;
> > > + cmd = DMA_INT;
> > > + break;
> > > + default:
> > > + dev_err(chan2dev(dchan), "unsupported DMA direction: %s\n",
> > > + dmaengine_get_direction_text(desc->dir));
> > > + return -EINVAL;
> > > + }
> > > +
> > > + /* setup HW descriptors */
> > > + for_each_sg(sgl, sg, sg_len, i) {
> > > + dma_addr_t buf_addr = sg_dma_address(sg);
> > > + size_t buf_len = sg_dma_len(sg);
> > > + struct ls1x_dma_hwdesc *hwdesc = &desc->hwdesc[i];
> > > +
> > > + if (!is_dma_copy_aligned(dchan->device, buf_addr, 0, buf_len)) {
> > > + dev_err(chan2dev(dchan), "buffer is not aligned!\n");
> > > + return -EINVAL;
> > > + }
> > > +
> > > + hwdesc->saddr = buf_addr;
> > > + hwdesc->daddr = dev_addr;
> > > + hwdesc->length = buf_len / desc->bus_width;
> > > + hwdesc->stride = 0;
> > > + hwdesc->cycles = 1;
> > > + hwdesc->cmd = cmd;
> > > +
> > > + if (i) {
> > > + next_hwdesc_phys += sizeof(*hwdesc);
> > > + desc->hwdesc[i - 1].next = next_hwdesc_phys
> > > + | DMA_NEXT_VALID;
> > > + }
> > > + }
> > > +
> > > + if (desc->type == DMA_CYCLIC)
> > > + desc->hwdesc[i - 1].next = desc->hwdesc_phys | DMA_NEXT_VALID;
> > > +
> > > + for_each_sg(sgl, sg, sg_len, i) {
> > > + struct ls1x_dma_hwdesc *hwdesc = &desc->hwdesc[i];
> > > +
> > > + print_hex_dump_debug("HW DESC: ", DUMP_PREFIX_OFFSET, 16, 4,
> > > + hwdesc, sizeof(*hwdesc), false);
> > > + }
> > > +
> > > + return 0;
> > > +}
> > > +
> > > +static struct dma_async_tx_descriptor *
> > > +ls1x_dma_prep_slave_sg(struct dma_chan *dchan,
> > > + struct scatterlist *sgl, unsigned int sg_len,
> > > + enum dma_transfer_direction direction,
> > > + unsigned long flags, void *context)
> > > +{
> > > + struct ls1x_dma_chan *chan = to_ls1x_dma_chan(dchan);
> > > + struct ls1x_dma_desc *desc;
> > > +
> > > + dev_dbg(chan2dev(dchan), "sg_len=%u flags=0x%lx dir=%s\n",
> > > + sg_len, flags, dmaengine_get_direction_text(direction));
> > > +
> > > + desc = ls1x_dma_alloc_desc(dchan, sg_len, direction, DMA_SLAVE);
> > > + if (!desc)
> > > + return NULL;
> > > +
> > > + if (ls1x_dma_setup_hwdescs(dchan, desc, sgl, sg_len)) {
> > > + ls1x_dma_free_desc(&desc->vdesc);
> > > + return NULL;
> > > + }
> > > +
> > > + return vchan_tx_prep(&chan->vchan, &desc->vdesc, flags);
> > > +}
> > > +
> > > +static struct dma_async_tx_descriptor *
> > > +ls1x_dma_prep_dma_cyclic(struct dma_chan *dchan,
> > > + dma_addr_t buf_addr, size_t buf_len, size_t period_len,
> > > + enum dma_transfer_direction direction,
> > > + unsigned long flags)
> > > +{
> > > + struct ls1x_dma_chan *chan = to_ls1x_dma_chan(dchan);
> > > + struct ls1x_dma_desc *desc;
> > > + struct scatterlist *sgl;
> > > + unsigned int sg_len;
> > > + unsigned int i;
> > > +
> > > + dev_dbg(chan2dev(dchan),
> > > + "buf_len=%d period_len=%zu flags=0x%lx dir=%s\n", buf_len,
> > > + period_len, flags, dmaengine_get_direction_text(direction));
> > > +
> > > + sg_len = buf_len / period_len;
> > > + desc = ls1x_dma_alloc_desc(dchan, sg_len, direction, DMA_CYCLIC);
> > > + if (!desc)
> > > + return NULL;
> > > +
> > > + /* allocate the scatterlist */
> > > + sgl = kmalloc_array(sg_len, sizeof(*sgl), GFP_NOWAIT);
> > > + if (!sgl)
> > > + return NULL;
> > > +
> > > + sg_init_table(sgl, sg_len);
> > > + for (i = 0; i < sg_len; ++i) {
> > > + sg_set_page(&sgl[i], pfn_to_page(PFN_DOWN(buf_addr)),
> > > + period_len, offset_in_page(buf_addr));
> > > + sg_dma_address(&sgl[i]) = buf_addr;
> > > + sg_dma_len(&sgl[i]) = period_len;
> > > + buf_addr += period_len;
> > > + }
> > > +
> > > + if (ls1x_dma_setup_hwdescs(dchan, desc, sgl, sg_len)) {
> > > + ls1x_dma_free_desc(&desc->vdesc);
> > > + return NULL;
> > > + }
> > > +
> > > + kfree(sgl);
> > > +
> > > + return vchan_tx_prep(&chan->vchan, &desc->vdesc, flags);
> > > +}
> > > +
> > > +static int ls1x_dma_slave_config(struct dma_chan *dchan,
> > > + struct dma_slave_config *config)
> > > +{
> > > + struct ls1x_dma_chan *chan = to_ls1x_dma_chan(dchan);
> > > +
> > > + chan->src_addr = config->src_addr;
> > > + chan->src_addr_width = config->src_addr_width;
> > > + chan->dst_addr = config->dst_addr;
> > > + chan->dst_addr_width = config->dst_addr_width;
> > > +
> > > + return 0;
> > > +}
> > > +
> > > +static int ls1x_dma_pause(struct dma_chan *dchan)
> > > +{
> > > + struct ls1x_dma_chan *chan = to_ls1x_dma_chan(dchan);
> > > + unsigned long flags;
> > > + int ret;
> > > +
> > > + spin_lock_irqsave(&chan->vchan.lock, flags);
> > > + ret = ls1x_dma_query(chan, &chan->curr_hwdesc_phys);
> > > + if (!ret)
> > > + ls1x_dma_stop(chan);
> > > + spin_unlock_irqrestore(&chan->vchan.lock, flags);
> > > +
> > > + return ret;
> > > +}
> > > +
> > > +static int ls1x_dma_resume(struct dma_chan *dchan)
> > > +{
> > > + struct ls1x_dma_chan *chan = to_ls1x_dma_chan(dchan);
> > > + unsigned long flags;
> > > + int ret;
> > > +
> > > + spin_lock_irqsave(&chan->vchan.lock, flags);
> > > + ret = ls1x_dma_start(chan, &chan->curr_hwdesc_phys);
> > > + spin_unlock_irqrestore(&chan->vchan.lock, flags);
> > > +
> > > + return ret;
> > > +}
> > > +
> > > +static int ls1x_dma_terminate_all(struct dma_chan *dchan)
> > > +{
> > > + struct ls1x_dma_chan *chan = to_ls1x_dma_chan(dchan);
> > > + unsigned long flags;
> > > + LIST_HEAD(head);
> > > +
> > > + spin_lock_irqsave(&chan->vchan.lock, flags);
> > > + ls1x_dma_stop(chan);
> > > + vchan_get_all_descriptors(&chan->vchan, &head);
> > > + spin_unlock_irqrestore(&chan->vchan.lock, flags);
> > > +
> > > + vchan_dma_desc_free_list(&chan->vchan, &head);
> > > +
> > > + return 0;
> > > +}
> > > +
> > > +static enum dma_status ls1x_dma_tx_status(struct dma_chan *dchan,
> > > + dma_cookie_t cookie,
> > > + struct dma_tx_state *state)
> > > +{
> > > + struct ls1x_dma_chan *chan = to_ls1x_dma_chan(dchan);
> > > + struct virt_dma_desc *vdesc;
> > > + enum dma_status status;
> > > + size_t bytes = 0;
> > > + unsigned long flags;
> > > +
> > > + status = dma_cookie_status(dchan, cookie, state);
> > > + if (status == DMA_COMPLETE)
> > > + return status;
> > > +
> > > + spin_lock_irqsave(&chan->vchan.lock, flags);
> > > + vdesc = vchan_find_desc(&chan->vchan, cookie);
> > > + if (chan->desc && cookie == chan->desc->vdesc.tx.cookie) {
> > > + struct ls1x_dma_desc *desc = chan->desc;
> > > + int i;
> > > +
> > > + if (ls1x_dma_query(chan, &chan->curr_hwdesc_phys))
> > > + return status;
> > > +
> > > + /* locate the current HW descriptor */
> > > + for (i = 0; i < desc->nr_descs; i++)
> > > + if (desc->hwdesc[i].next == chan->curr_hwdesc->next)
> > > + break;
> > > +
> > > + /* count the residues */
> > > + for (; i < desc->nr_descs; i++)
> > > + bytes += desc->hwdesc[i].length * desc->bus_width;
> > > +
> > > + dma_set_residue(state, bytes);
> > > + }
> > > + spin_unlock_irqrestore(&chan->vchan.lock, flags);
> > > +
> > > + return status;
> > > +}
> > > +
> > > +static void ls1x_dma_issue_pending(struct dma_chan *dchan)
> > > +{
> > > + struct ls1x_dma_chan *chan = to_ls1x_dma_chan(dchan);
> > > + struct virt_dma_desc *vdesc;
> > > + unsigned long flags;
> > > +
> > > + spin_lock_irqsave(&chan->vchan.lock, flags);
> > > + if (vchan_issue_pending(&chan->vchan) && !chan->desc) {
> > > + vdesc = vchan_next_desc(&chan->vchan);
> > > + if (!vdesc) {
> > > + chan->desc = NULL;
> > > + return;
> > > + }
> > > + chan->desc = to_ls1x_dma_desc(vdesc);
> > > + ls1x_dma_start(chan, &chan->desc->hwdesc_phys);
> > > + }
> > > + spin_unlock_irqrestore(&chan->vchan.lock, flags);
> > > +}
> > > +
> > > +static irqreturn_t ls1x_dma_irq_handler(int irq, void *data)
> > > +{
> > > + struct ls1x_dma_chan *chan = data;
> > > + struct ls1x_dma_desc *desc = chan->desc;
> > > + struct dma_chan *dchan = &chan->vchan.chan;
> > > +
> > > + if (!desc) {
> > > + dev_warn(chan2dev(dchan),
> > > + "IRQ %d with no active descriptor on channel %d\n",
> > > + irq, dchan->chan_id);
> > > + return IRQ_NONE;
> > > + }
> > > +
> > > + dev_dbg(chan2dev(dchan), "DMA IRQ %d on channel %d\n", irq,
> > > + dchan->chan_id);
> > > +
> > > + spin_lock(&chan->vchan.lock);
> > > +
> > > + if (desc->type == DMA_CYCLIC) {
> > > + vchan_cyclic_callback(&desc->vdesc);
> > > + } else {
> > > + list_del(&desc->vdesc.node);
> > > + vchan_cookie_complete(&desc->vdesc);
> > > + chan->desc = NULL;
> > > + }
> > > +
> > > + spin_unlock(&chan->vchan.lock);
> > > + return IRQ_HANDLED;
> > > +}
> > > +
> > > +static int ls1x_dma_chan_probe(struct platform_device *pdev,
> > > + struct ls1x_dma *dma, int chan_id)
> > > +{
> > > + struct device *dev = &pdev->dev;
> > > + struct ls1x_dma_chan *chan = &dma->chan[chan_id];
> > > + char pdev_irqname[4];
> > > + char *irqname;
> > > + int ret;
> > > +
> > > + sprintf(pdev_irqname, "ch%u", chan_id);
> > > + chan->irq = platform_get_irq_byname(pdev, pdev_irqname);
> > > + if (chan->irq < 0)
> > > + return -ENODEV;
> > > +
> > > + irqname = devm_kasprintf(dev, GFP_KERNEL, "%s:%s",
> > > + dev_name(dev), pdev_irqname);
> > > + if (!irqname)
> > > + return -ENOMEM;
> > > +
> > > + ret = devm_request_irq(dev, chan->irq, ls1x_dma_irq_handler,
> > > + IRQF_SHARED, irqname, chan);
> > > + if (ret)
> > > + return dev_err_probe(dev, ret,
> > > + "failed to request IRQ %u!\n", chan->irq);
> > > +
> > > + chan->reg_base = dma->reg_base;
> > > + chan->vchan.desc_free = ls1x_dma_free_desc;
> > > + vchan_init(&chan->vchan, &dma->ddev);
> > > + dev_info(dev, "%s (irq %d) initialized\n", pdev_irqname, chan->irq);
> > > +
> > > + return 0;
> > > +}
> > > +
> > > +static void ls1x_dma_chan_remove(struct ls1x_dma *dma, int chan_id)
> > > +{
> > > + struct device *dev = dma->ddev.dev;
> > > + struct ls1x_dma_chan *chan = &dma->chan[chan_id];
> > > +
> > > + devm_free_irq(dev, chan->irq, chan);
> > > + list_del(&chan->vchan.chan.device_node);
> > > + tasklet_kill(&chan->vchan.task);
> > > +}
> > > +
> > > +static int ls1x_dma_probe(struct platform_device *pdev)
> > > +{
> > > + struct device *dev = &pdev->dev;
> > > + struct dma_device *ddev;
> > > + struct ls1x_dma *dma;
> > > + int nr_chans, ret, i;
> > > +
> > > + nr_chans = platform_irq_count(pdev);
> > > + if (nr_chans <= 0)
> > > + return nr_chans;
> > > + if (nr_chans > LS1X_DMA_MAX_CHANNELS)
> > > + return dev_err_probe(dev, -EINVAL,
> > > + "nr_chans=%d exceeds the maximum\n",
> > > + nr_chans);
> > > +
> > > + dma = devm_kzalloc(dev, struct_size(dma, chan, nr_chans), GFP_KERNEL);
> > > + if (!dma)
> > > + return -ENOMEM;
> > > +
> > > + /* initialize DMA device */
> > > + dma->reg_base = devm_platform_ioremap_resource(pdev, 0);
> > > + if (IS_ERR(dma->reg_base))
> > > + return PTR_ERR(dma->reg_base);
> > > +
> > > + ddev = &dma->ddev;
> > > + ddev->dev = dev;
> > > + ddev->copy_align = DMAENGINE_ALIGN_4_BYTES;
> > > + ddev->src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
> > > + BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) | BIT(DMA_SLAVE_BUSWIDTH_4_BYTES);
> > > + ddev->dst_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
> > > + BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) | BIT(DMA_SLAVE_BUSWIDTH_4_BYTES);
> > > + ddev->directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV);
> > > + ddev->max_sg_burst = LS1X_DMA_MAX_DESC;
> > > + ddev->residue_granularity = DMA_RESIDUE_GRANULARITY_SEGMENT;
> > > + ddev->device_alloc_chan_resources = ls1x_dma_alloc_chan_resources;
> > > + ddev->device_free_chan_resources = ls1x_dma_free_chan_resources;
> > > + ddev->device_prep_slave_sg = ls1x_dma_prep_slave_sg;
> > > + ddev->device_prep_dma_cyclic = ls1x_dma_prep_dma_cyclic;
> > > + ddev->device_config = ls1x_dma_slave_config;
> > > + ddev->device_pause = ls1x_dma_pause;
> > > + ddev->device_resume = ls1x_dma_resume;
> > > + ddev->device_terminate_all = ls1x_dma_terminate_all;
> > > + ddev->device_tx_status = ls1x_dma_tx_status;
> > > + ddev->device_issue_pending = ls1x_dma_issue_pending;
> > > +
> > > + dma_cap_set(DMA_SLAVE, ddev->cap_mask);
> > > + INIT_LIST_HEAD(&ddev->channels);
> > > +
> > > + /* initialize DMA channels */
> > > + for (i = 0; i < nr_chans; i++) {
> > > + ret = ls1x_dma_chan_probe(pdev, dma, i);
> > > + if (ret)
> > > + return ret;
> > > + }
> > > + dma->nr_chans = nr_chans;
> > > +
> > > + ret = dmaenginem_async_device_register(ddev);
> > > + if (ret) {
> > > + dev_err(dev, "failed to register DMA device! %d\n", ret);
> > > + return ret;
> > > + }
> > > +
> > > + ret =
> > > + of_dma_controller_register(dev->of_node, of_dma_xlate_by_chan_id,
> > > + ddev);
> > > + if (ret) {
> > > + dev_err(dev, "failed to register DMA controller! %d\n", ret);
> > > + return ret;
> > > + }
> > > +
> > > + platform_set_drvdata(pdev, dma);
> > > + dev_info(dev, "Loongson1 DMA driver registered\n");
> > > +
> > > + return 0;
> > > +}
> > > +
> > > +static void ls1x_dma_remove(struct platform_device *pdev)
> > > +{
> > > + struct ls1x_dma *dma = platform_get_drvdata(pdev);
> > > + int i;
> > > +
> > > + of_dma_controller_free(pdev->dev.of_node);
> > > +
> > > + for (i = 0; i < dma->nr_chans; i++)
> > > + ls1x_dma_chan_remove(dma, i);
> > > +}
> > > +
> > > +static const struct of_device_id ls1x_dma_match[] = {
> > > + { .compatible = "loongson,ls1b-apbdma" },
> > > + { .compatible = "loongson,ls1c-apbdma" },
> > > + { /* sentinel */ }
> > > +};
> > > +MODULE_DEVICE_TABLE(of, ls1x_dma_match);
> > > +
> > > +static struct platform_driver ls1x_dma_driver = {
> > > + .probe = ls1x_dma_probe,
> > > + .remove_new = ls1x_dma_remove,
> > > + .driver = {
> > > + .name = KBUILD_MODNAME,
> > > + .of_match_table = ls1x_dma_match,
> > > + },
> > > +};
> > > +
> > > +module_platform_driver(ls1x_dma_driver);
> > > +
> > > +MODULE_AUTHOR("Keguang Zhang <keguang.zhang@gmail.com>");
> > > +MODULE_DESCRIPTION("Loongson-1 APB DMA Controller driver");
> > > +MODULE_LICENSE("GPL");
> > >
> > > --
> > > 2.40.1
> > >
> > >
>
>
>
> --
> Best regards,
>
> Keguang Zhang
>
^ permalink raw reply
* [PATCH v6 RESEND 0/4] arm64: qcom: add AIM300 AIoT board support
From: Tengfei Fan @ 2024-04-01 9:38 UTC (permalink / raw)
To: andersson, konrad.dybcio, robh, krzysztof.kozlowski+dt, conor+dt
Cc: keescook, tony.luck, gpiccoli, linux-arm-msm, devicetree,
linux-kernel, linux-hardening, kernel, Tengfei Fan
Add AIM300 AIoT support along with usb, ufs, regulators, serial, PCIe,
and PMIC functions.
AIM300 Series is a highly optimized family of modules designed to
support AIoT applications. It integrates QCS8550 SoC, UFS and PMIC
chip etc.
Here is a diagram of AIM300 AIoT Carrie Board and SoM
+--------------------------------------------------+
| AIM300 AIOT Carrie Board |
| |
| +-----------------+ |
|power----->| Fixed regulator |---------+ |
| +-----------------+ | |
| | |
| v VPH_PWR |
| +----------------------------------------------+ |
| | AIM300 SOM | | |
| | |VPH_PWR | |
| | v | |
| | +-------+ +--------+ +------+ | |
| | | UFS | | QCS8550| |PMIC | | |
| | +-------+ +--------+ +------+ | |
| | | |
| +----------------------------------------------+ |
| |
| +----+ +------+ |
| |USB | | UART | |
| +----+ +------+ |
+--------------------------------------------------+
The following functions have been verified:
- uart
- usb
- ufs
- PCIe
- PMIC
- display
- adsp
- cdsp
- tlmm
Documentation for qcs8550[1] and sm8550[2]
[1] https://docs.qualcomm.com/bundle/publicresource/87-61717-1_REV_A_Qualcomm_QCS8550_QCM8550_Processors_Product_Brief.pdf
[2] https://www.qualcomm.com/content/dam/qcomm-martech/dm-assets/documents/Snapdragon-8-Gen-2-Product-Brief.pdf
Signed-off-by: Tengfei Fan <quic_tengfan@quicinc.com>
---
v5 -> v6:
- move qcs8550 board info bebind sm8550 boards info in qcom.yaml
v4 -> v5:
- "2023-2024" instead of "2023~2024" for License
- update patch commit message to previous comments and with an updated
board diagram
- use qcs8550.dtsi instead of qcm8550.dtsi
- remove the reserved memory regions which will be handled by
bootloader
- remove pm8550_flash, pm8550_pwm nodes, Type-C USB/DP function node,
remoteproc_mpss function node, audio sound DTS node, new patch will
be updated after respective team's end to end full verification
- address comments to vph_pwr, move vph_pwr node and related
references to qcs8550-aim300-aiot.dts
- use "regulator-vph-pwr" instead of "vph_pwr_regulator"
- add pcie0I AND pcie1 support together
- the following patches were applied, so remove these patches from new
patch series:
- https://lore.kernel.org/linux-arm-msm/20240119100621.11788-3-quic_tengfan@quicinc.com
- https://lore.kernel.org/linux-arm-msm/20240119100621.11788-4-quic_tengfan@quicinc.com
- verified with dtb check, and result is expected, because those
warnings are not introduced by current patch series.
DTC_CHK arch/arm64/boot/dts/qcom/qcs8550-aim300-aiot.dtb
arch/arm64/boot/dts/qcom/sm8550.dtsi:3015.27-3070.6: Warning
(avoid_unnecessary_addr_size): /soc@0/display-subsystem@ae00000/dsi@ae96000: unnecessary
#address-cells/#size-cells without "ranges" or child "reg" property
arch/arm64/boot/dts/qcom/qcs8550-aim300-aiot.dtb:
opp-table: opp-75000000:opp-hz:0: [75000000, 0, 0, 75000000, 0, 0, 0, 0] is too long
from schema $id: http://devicetree.org/schemas/opp/opp-v2.yaml#
arch/arm64/boot/dts/qcom/qcs8550-aim300-aiot.dtb:
opp-table: opp-150000000:opp-hz:0: [150000000, 0, 0, 150000000, 0, 0, 0, 0] is too long
from schema $id: http://devicetree.org/schemas/opp/opp-v2.yaml#
arch/arm64/boot/dts/qcom/qcs8550-aim300-aiot.dtb:
opp-table: opp-300000000:opp-hz:0: [300000000, 0, 0, 300000000, 0, 0, 0, 0] is too long
from schema $id: http://devicetree.org/schemas/opp/opp-v2.yaml#
arch/arm64/boot/dts/qcom/qcs8550-aim300-aiot.dtb:
opp-table: Unevaluated properties are not allowed ('opp-150000000', 'opp-300000000', 'opp-75000000' were unexpected)
from schema $id: http://devicetree.org/schemas/opp/opp-v2.yaml#
v3 -> v4:
- use qcm8550.dtsi instead of qcs8550.dtsi, qcs8550 is a QCS version
of qcm8550, another board with qcm8550 will be added later
- add AIM300 AIoT board string in qcom.yaml file
- add sm8550 and qcm8550 fallback compatible
- add qcm8550 SoC id
- add reserved memory map codes in qcm8550.dtsi
- pm8010 and pmr73d are splited into carrier board DTS file. Because
the regulators which in pm8550, pm8550ve and pm8550vs are present
on the SoM. The regulators which in pm8010 and pmr73d are present
on the carrier board.
- stay VPH_PWR at qcs8550-aim300.dtsi file
VPH_PWR is obtained by vonverting 12v voltage into 3.7 voltage
with a 3.7v buck. VPH_PWR is power supply for regulators in AIM300
SOM. VPH_PWR regulator is defined in AIM300 SOM dtsi file.
v2 -> v3:
- introduce qcs8550.dtsi
- separate fix dtc W=1 warning patch to another patch series
v1 -> v2:
- merge the splited dts patches into one patch
- update dts file name from qcom8550-aim300.dts to qcs8550-aim300 dts
- drop PCIe1 dts node due to it is not enabled
- update display node name for drop sde characters
previous discussion here:
[1] v5: https://lore.kernel.org/linux-arm-msm/20240301134113.14423-1-quic_tengfan@quicinc.com
[2] v4: https://lore.kernel.org/linux-arm-msm/20240119100621.11788-1-quic_tengfan@quicinc.com
[3] v3: https://lore.kernel.org/linux-arm-msm/20231219005007.11644-1-quic_tengfan@quicinc.com
[4] v2: https://lore.kernel.org/linux-arm-msm/20231207092801.7506-1-quic_tengfan@quicinc.com
[5] v1: https://lore.kernel.org/linux-arm-msm/20231117101817.4401-1-quic_tengfan@quicinc.com
Tengfei Fan (4):
dt-bindings: arm: qcom: Document QCS8550 SoC and the AIM300 AIoT board
arm64: dts: qcom: qcs8550: introduce qcs8550 dtsi
arm64: dts: qcom: add base AIM300 dtsi
arm64: dts: qcom: aim300: add AIM300 AIoT
.../devicetree/bindings/arm/qcom.yaml | 8 +
arch/arm64/boot/dts/qcom/Makefile | 1 +
.../boot/dts/qcom/qcs8550-aim300-aiot.dts | 384 ++++++++++++++++++
arch/arm64/boot/dts/qcom/qcs8550-aim300.dtsi | 345 ++++++++++++++++
arch/arm64/boot/dts/qcom/qcs8550.dtsi | 169 ++++++++
5 files changed, 907 insertions(+)
create mode 100644 arch/arm64/boot/dts/qcom/qcs8550-aim300-aiot.dts
create mode 100644 arch/arm64/boot/dts/qcom/qcs8550-aim300.dtsi
create mode 100644 arch/arm64/boot/dts/qcom/qcs8550.dtsi
base-commit: a6bd6c9333397f5a0e2667d4d82fef8c970108f2
--
2.25.1
^ permalink raw reply
* [PATCH v6 RESEND 1/4] dt-bindings: arm: qcom: Document QCS8550 SoC and the AIM300 AIoT board
From: Tengfei Fan @ 2024-04-01 9:38 UTC (permalink / raw)
To: andersson, konrad.dybcio, robh, krzysztof.kozlowski+dt, conor+dt
Cc: keescook, tony.luck, gpiccoli, linux-arm-msm, devicetree,
linux-kernel, linux-hardening, kernel, Tengfei Fan,
Krzysztof Kozlowski
In-Reply-To: <20240401093843.2591147-1-quic_tengfan@quicinc.com>
Document QCS8550 SoC and the AIM300 AIoT board bindings.
QCS8550 is derived from SM8550. The difference between SM8550 and
QCS8550 is QCS8550 doesn't have modem RF system. QCS8550 is mainly used
in IoT scenarios.
AIM300 Series is a highly optimized family of modules designed to
support AIoT applications. It integrates QCS8550 SoC, UFS and PMIC chip
etc.
AIM stands for Artificial Intelligence Module. AIoT stands for AI IoT.
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Signed-off-by: Tengfei Fan <quic_tengfan@quicinc.com>
---
Documentation/devicetree/bindings/arm/qcom.yaml | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/Documentation/devicetree/bindings/arm/qcom.yaml b/Documentation/devicetree/bindings/arm/qcom.yaml
index 66beaac60e1d..8115088a6076 100644
--- a/Documentation/devicetree/bindings/arm/qcom.yaml
+++ b/Documentation/devicetree/bindings/arm/qcom.yaml
@@ -42,6 +42,7 @@ description: |
msm8996
msm8998
qcs404
+ qcs8550
qcm2290
qcm6490
qdu1000
@@ -1005,6 +1006,13 @@ properties:
- qcom,sm8550-qrd
- const: qcom,sm8550
+ - items:
+ - enum:
+ - qcom,qcs8550-aim300-aiot
+ - const: qcom,qcs8550-aim300
+ - const: qcom,qcs8550
+ - const: qcom,sm8550
+
- items:
- enum:
- qcom,sm8650-mtp
--
2.25.1
^ permalink raw reply related
* [PATCH v6 RESEND 2/4] arm64: dts: qcom: qcs8550: introduce qcs8550 dtsi
From: Tengfei Fan @ 2024-04-01 9:38 UTC (permalink / raw)
To: andersson, konrad.dybcio, robh, krzysztof.kozlowski+dt, conor+dt
Cc: keescook, tony.luck, gpiccoli, linux-arm-msm, devicetree,
linux-kernel, linux-hardening, kernel, Tengfei Fan
In-Reply-To: <20240401093843.2591147-1-quic_tengfan@quicinc.com>
QCS8550 is derived from SM8550. The differnece between SM8550 and
QCS8550 is QCS8550 doesn't have modem RF system. QCS8550 is mainly used
in IoT scenarios.
QCS8550 firmware has different memory map with SM8550 firmware. The
memory map will be runtime added through bootloader.
There are 3 types of reserved memory regions here:
1. Firmware related regions which aren't shared with kernel.
The device tree source in kernel doesn't need to have node to indicate
the firmware related reserved information. OS bootloader conveys the
information by update device tree in runtime.
This will be described as: UEFI saves the physical address of the
UEFI System Table to dts file's chosen node. Kernel read this table and
add reserved memory regions to efi config table. Current reserved memory
region may have reserved region which was not yet used, release note of
the firmware have such kind of information.
2. Firmware related memory regions which are shared with Kernel
Each region has a specific node with specific label name for later
phandle reference from other driver dt node.
3. PIL regions.
PIL regions will be reserved and then assigned to subsystem firmware
later.
Here is a reserved memory map for this platform:
0x100000000 +------------------+
| |
| Firmware Related |
| |
0xd4d00000 +------------------+
| |
| Kernel Available |
| |
0xa7000000 +------------------+
| |
| PIL Region |
| |
0x8a800000 +------------------+
| |
| Firmware Related |
| |
0x80000000 +------------------+
Note that:
0xa7000000..0xA8000000 is used by bootloader, when kernel boot up,
it is available for kernel usage. This region is not suggested to be
used by kernel features like ramoops, suspend resume etc.
Signed-off-by: Tengfei Fan <quic_tengfan@quicinc.com>
---
arch/arm64/boot/dts/qcom/qcs8550.dtsi | 169 ++++++++++++++++++++++++++
1 file changed, 169 insertions(+)
create mode 100644 arch/arm64/boot/dts/qcom/qcs8550.dtsi
diff --git a/arch/arm64/boot/dts/qcom/qcs8550.dtsi b/arch/arm64/boot/dts/qcom/qcs8550.dtsi
new file mode 100644
index 000000000000..a3ebf3d4e16d
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/qcs8550.dtsi
@@ -0,0 +1,169 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2023-2024, Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#include "sm8550.dtsi"
+
+/delete-node/ &reserved_memory;
+
+/ {
+ reserved_memory: reserved-memory {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+
+ /* These are 3 types of reserved memory regions here:
+ * 1. Firmware related regions which aren't shared with kernel.
+ * The device tree source in kernel doesn't need to have node to
+ * indicate the firmware related reserved information. OS bootloader
+ * conveys the information by update device tree in runtime.
+ * This will be described as: UEFI saves the physical address of
+ * the UEFI System Table to dts file's chosen node. Kernel read this
+ * table and add reserved memory regions to efi config table. Current
+ * reserved memory region may have reserved region which was not yet
+ * used, release note of the firmware have such kind of information.
+ * 2. Firmware related memory regions which are shared with Kernel.
+ * Each region has a specific node with specific label name for
+ * later phandle reference from other driver dt node.
+ * 3. PIL regions.
+ * PIL regions will be reserved and then assigned to subsystem
+ * firmware later.
+ * Here is a reserved memory map for this platform:
+ * 0x100000000 +------------------+
+ * | |
+ * | Firmware Related |
+ * | |
+ * 0xd4d00000 +------------------+
+ * | |
+ * | Kernel Available |
+ * | |
+ * 0xa7000000 +------------------+
+ * | |
+ * | PIL Region |
+ * | |
+ * 0x8a800000 +------------------+
+ * | |
+ * | Firmware Related |
+ * | |
+ * 0x80000000 +------------------+
+ * Note that:
+ * 0xa7000000..0xA8000000 is used by bootloader, when kernel boot up,
+ * it is available for kernel usage. This region is not suggested to
+ * be used by kernel features like ramoops, suspend resume etc.
+ */
+
+ /*
+ * Firmware related regions, bootlader will possible reserve parts of
+ * region from 0x80000000..0x8a800000.
+ */
+ aop_image_mem: aop-image-region@81c00000 {
+ reg = <0x0 0x81c00000 0x0 0x60000>;
+ no-map;
+ };
+
+ aop_cmd_db_mem: aop-cmd-db-region@81c60000 {
+ compatible = "qcom,cmd-db";
+ reg = <0x0 0x81c60000 0x0 0x20000>;
+ no-map;
+ };
+
+ aop_config_mem: aop-config-region@81c80000 {
+ no-map;
+ reg = <0x0 0x81c80000 0x0 0x20000>;
+ };
+
+ smem_mem: smem-region@81d00000 {
+ compatible = "qcom,smem";
+ reg = <0x0 0x81d00000 0x0 0x200000>;
+ hwlocks = <&tcsr_mutex 3>;
+ no-map;
+ };
+
+ adsp_mhi_mem: adsp-mhi-region@81f00000 {
+ reg = <0x0 0x81f00000 0x0 0x20000>;
+ no-map;
+ };
+
+ /* PIL region */
+ mpss_mem: mpss-region@8a800000 {
+ reg = <0x0 0x8a800000 0x0 0x10800000>;
+ no-map;
+ };
+
+ q6_mpss_dtb_mem: q6-mpss-dtb-region@9b000000 {
+ reg = <0x0 0x9b000000 0x0 0x80000>;
+ no-map;
+ };
+
+ ipa_fw_mem: ipa-fw-region@9b080000 {
+ reg = <0x0 0x9b080000 0x0 0x10000>;
+ no-map;
+ };
+
+ ipa_gsi_mem: ipa-gsi-region@9b090000 {
+ reg = <0x0 0x9b090000 0x0 0xa000>;
+ no-map;
+ };
+
+ gpu_micro_code_mem: gpu-micro-code-region@9b09a000 {
+ reg = <0x0 0x9b09a000 0x0 0x2000>;
+ no-map;
+ };
+
+ spss_region_mem: spss-region@9b100000 {
+ reg = <0x0 0x9b100000 0x0 0x180000>;
+ no-map;
+ };
+
+ spu_secure_shared_memory_mem: spu-secure-shared-memory-region@9b280000 {
+ reg = <0x0 0x9b280000 0x0 0x80000>;
+ no-map;
+ };
+
+ camera_mem: camera-region@9b300000 {
+ reg = <0x0 0x9b300000 0x0 0x800000>;
+ no-map;
+ };
+
+ video_mem: video-region@9bb00000 {
+ reg = <0x0 0x9bb00000 0x0 0x700000>;
+ no-map;
+ };
+
+ cvp_mem: cvp-region@9c200000 {
+ reg = <0x0 0x9c200000 0x0 0x700000>;
+ no-map;
+ };
+
+ cdsp_mem: cdsp-region@9c900000 {
+ reg = <0x0 0x9c900000 0x0 0x2000000>;
+ no-map;
+ };
+
+ q6_cdsp_dtb_mem: q6-cdsp-dtb-region@9e900000 {
+ reg = <0x0 0x9e900000 0x0 0x80000>;
+ no-map;
+ };
+
+ q6_adsp_dtb_mem: q6-adsp-dtb-region@9e980000 {
+ reg = <0x0 0x9e980000 0x0 0x80000>;
+ no-map;
+ };
+
+ adspslpi_mem: adspslpi-region@9ea00000 {
+ reg = <0x0 0x9ea00000 0x0 0x4080000>;
+ no-map;
+ };
+
+ /*
+ * Firmware related regions, bootlader will possible reserve parts of
+ * region from 0xd8000000..0x100000000.
+ */
+ mpss_dsm_mem: mpss_dsm_region@d4d00000 {
+ reg = <0x0 0xd4d00000 0x0 0x3300000>;
+ no-map;
+ };
+ };
+};
--
2.25.1
^ permalink raw reply related
* [PATCH v6 RESEND 3/4] arm64: dts: qcom: add base AIM300 dtsi
From: Tengfei Fan @ 2024-04-01 9:38 UTC (permalink / raw)
To: andersson, konrad.dybcio, robh, krzysztof.kozlowski+dt, conor+dt
Cc: keescook, tony.luck, gpiccoli, linux-arm-msm, devicetree,
linux-kernel, linux-hardening, kernel, Tengfei Fan, Fenglin Wu
In-Reply-To: <20240401093843.2591147-1-quic_tengfan@quicinc.com>
AIM300 Series is a highly optimized family of modules designed to
support AIoT applications. It integrates QCS8550 SoC, UFS and PMIC
chip etc.
Here is a diagram of AIM300 SoM:
+----------------------------------------+
|AIM300 SoM |
| |
| +-----+ |
| |--->| UFS | |
| | +-----+ |
| | |
| | |
3.7v | +-----------------+ | +---------+ |
---------->| PMIC |----->| QCS8550 | |
| +-----------------+ +---------+ |
| | |
| | |
| | +-----+ |
| |--->| ... | |
| +-----+ |
| |
+----------------------------------------+
Co-developed-by: Fenglin Wu <quic_fenglinw@quicinc.com>
Signed-off-by: Fenglin Wu <quic_fenglinw@quicinc.com>
Signed-off-by: Tengfei Fan <quic_tengfan@quicinc.com>
---
arch/arm64/boot/dts/qcom/qcs8550-aim300.dtsi | 345 +++++++++++++++++++
1 file changed, 345 insertions(+)
create mode 100644 arch/arm64/boot/dts/qcom/qcs8550-aim300.dtsi
diff --git a/arch/arm64/boot/dts/qcom/qcs8550-aim300.dtsi b/arch/arm64/boot/dts/qcom/qcs8550-aim300.dtsi
new file mode 100644
index 000000000000..43dde67df136
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/qcs8550-aim300.dtsi
@@ -0,0 +1,345 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2023-2024, Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#include <dt-bindings/regulator/qcom,rpmh-regulator.h>
+#include "qcs8550.dtsi"
+#include "pm8550.dtsi"
+#include "pm8550b.dtsi"
+#define PMK8550VE_SID 5
+#include "pm8550ve.dtsi"
+#include "pm8550vs.dtsi"
+#include "pmk8550.dtsi"
+
+&apps_rsc {
+ regulators-0 {
+ compatible = "qcom,pm8550-rpmh-regulators";
+ qcom,pmic-id = "b";
+
+ vdd-l1-l4-l10-supply = <&vreg_s6g_1p86>;
+ vdd-l2-l13-l14-supply = <&vreg_bob1>;
+ vdd-l3-supply = <&vreg_s4g_1p25>;
+ vdd-l5-l16-supply = <&vreg_bob1>;
+ vdd-l6-l7-supply = <&vreg_bob1>;
+ vdd-l8-l9-supply = <&vreg_bob1>;
+ vdd-l11-supply = <&vreg_s4g_1p25>;
+ vdd-l12-supply = <&vreg_s6g_1p86>;
+ vdd-l15-supply = <&vreg_s6g_1p86>;
+ vdd-l17-supply = <&vreg_bob2>;
+
+ vreg_bob1: bob1 {
+ regulator-name = "vreg_bob1";
+ regulator-min-microvolt = <3296000>;
+ regulator-max-microvolt = <3960000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_bob2: bob2 {
+ regulator-name = "vreg_bob2";
+ regulator-min-microvolt = <2720000>;
+ regulator-max-microvolt = <3960000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l1b_1p8: ldo1 {
+ regulator-name = "vreg_l1b_1p8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l2b_3p0: ldo2 {
+ regulator-name = "vreg_l2b_3p0";
+ regulator-min-microvolt = <3008000>;
+ regulator-max-microvolt = <3008000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l5b_3p1: ldo5 {
+ regulator-name = "vreg_l5b_3p1";
+ regulator-min-microvolt = <3104000>;
+ regulator-max-microvolt = <3104000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l6b_1p8: ldo6 {
+ regulator-name = "vreg_l6b_1p8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3008000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l7b_1p8: ldo7 {
+ regulator-name = "vreg_l7b_1p8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3008000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l8b_1p8: ldo8 {
+ regulator-name = "vreg_l8b_1p8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3008000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l9b_2p9: ldo9 {
+ regulator-name = "vreg_l9b_2p9";
+ regulator-min-microvolt = <2960000>;
+ regulator-max-microvolt = <3008000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l11b_1p2: ldo11 {
+ regulator-name = "vreg_l11b_1p2";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1504000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l12b_1p8: ldo12 {
+ regulator-name = "vreg_l12b_1p8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l13b_3p0: ldo13 {
+ regulator-name = "vreg_l13b_3p0";
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l14b_3p2: ldo14 {
+ regulator-name = "vreg_l14b_3p2";
+ regulator-min-microvolt = <3200000>;
+ regulator-max-microvolt = <3200000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l15b_1p8: ldo15 {
+ regulator-name = "vreg_l15b_1p8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l16b_2p8: ldo16 {
+ regulator-name = "vreg_l16b_2p8";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l17b_2p5: ldo17 {
+ regulator-name = "vreg_l17b_2p5";
+ regulator-min-microvolt = <2504000>;
+ regulator-max-microvolt = <2504000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+ };
+
+ regulators-1 {
+ compatible = "qcom,pm8550vs-rpmh-regulators";
+ qcom,pmic-id = "c";
+
+ vdd-l1-supply = <&vreg_s4g_1p25>;
+ vdd-l2-supply = <&vreg_s4e_0p95>;
+ vdd-l3-supply = <&vreg_s4e_0p95>;
+
+ vreg_l3c_0p9: ldo3 {
+ regulator-name = "vreg_l3c_0p9";
+ regulator-min-microvolt = <880000>;
+ regulator-max-microvolt = <912000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+ };
+
+ regulators-2 {
+ compatible = "qcom,pm8550vs-rpmh-regulators";
+ qcom,pmic-id = "d";
+
+ vdd-l1-supply = <&vreg_s4e_0p95>;
+ vdd-l2-supply = <&vreg_s4e_0p95>;
+ vdd-l3-supply = <&vreg_s4e_0p95>;
+
+ vreg_l1d_0p88: ldo1 {
+ regulator-name = "vreg_l1d_0p88";
+ regulator-min-microvolt = <880000>;
+ regulator-max-microvolt = <920000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+ };
+
+ regulators-3 {
+ compatible = "qcom,pm8550vs-rpmh-regulators";
+ qcom,pmic-id = "e";
+
+ vdd-l1-supply = <&vreg_s4e_0p95>;
+ vdd-l2-supply = <&vreg_s4e_0p95>;
+ vdd-l3-supply = <&vreg_s4g_1p25>;
+
+ vreg_s4e_0p95: smps4 {
+ regulator-name = "vreg_s4e_0p95";
+ regulator-min-microvolt = <904000>;
+ regulator-max-microvolt = <984000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_s5e_1p08: smps5 {
+ regulator-name = "vreg_s5e_1p08";
+ regulator-min-microvolt = <1010000>;
+ regulator-max-microvolt = <1120000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l1e_0p88: ldo1 {
+ regulator-name = "vreg_l1e_0p88";
+ regulator-min-microvolt = <880000>;
+ regulator-max-microvolt = <912000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l2e_0p9: ldo2 {
+ regulator-name = "vreg_l2e_0p9";
+ regulator-min-microvolt = <870000>;
+ regulator-max-microvolt = <970000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l3e_1p2: ldo3 {
+ regulator-name = "vreg_l3e_1p2";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+ };
+
+ regulators-4 {
+ compatible = "qcom,pm8550ve-rpmh-regulators";
+ qcom,pmic-id = "f";
+
+ vdd-l1-supply = <&vreg_s4e_0p95>;
+ vdd-l2-supply = <&vreg_s4e_0p95>;
+ vdd-l3-supply = <&vreg_s4e_0p95>;
+
+ vreg_s4f_0p5: smps4 {
+ regulator-name = "vreg_s4f_0p5";
+ regulator-min-microvolt = <300000>;
+ regulator-max-microvolt = <700000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l1f_0p9: ldo1 {
+ regulator-name = "vreg_l1f_0p9";
+ regulator-min-microvolt = <880000>;
+ regulator-max-microvolt = <912000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l2f_0p88: ldo2 {
+ regulator-name = "vreg_l2f_0p88";
+ regulator-min-microvolt = <880000>;
+ regulator-max-microvolt = <912000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l3f_0p88: ldo3 {
+ regulator-name = "vreg_l3f_0p88";
+ regulator-min-microvolt = <880000>;
+ regulator-max-microvolt = <912000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+ };
+
+ regulators-5 {
+ compatible = "qcom,pm8550vs-rpmh-regulators";
+ qcom,pmic-id = "g";
+ vdd-l1-supply = <&vreg_s4g_1p25>;
+ vdd-l2-supply = <&vreg_s4g_1p25>;
+ vdd-l3-supply = <&vreg_s4g_1p25>;
+
+ vreg_s1g_1p25: smps1 {
+ regulator-name = "vreg_s1g_1p25";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1300000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_s2g_0p85: smps2 {
+ regulator-name = "vreg_s2g_0p85";
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <1036000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_s3g_0p8: smps3 {
+ regulator-name = "vreg_s3g_0p8";
+ regulator-min-microvolt = <300000>;
+ regulator-max-microvolt = <1004000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_s4g_1p25: smps4 {
+ regulator-name = "vreg_s4g_1p25";
+ regulator-min-microvolt = <1256000>;
+ regulator-max-microvolt = <1408000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_s5g_0p85: smps5 {
+ regulator-name = "vreg_s5g_0p85";
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <1004000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_s6g_1p86: smps6 {
+ regulator-name = "vreg_s6g_1p86";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2000000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l1g_1p2: ldo1 {
+ regulator-name = "vreg_l1g_1p2";
+ regulator-min-microvolt = <1128000>;
+ regulator-max-microvolt = <1272000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l2g_1p2: ldo2 {
+ regulator-name = "vreg_l2g_1p2";
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l3g_1p2: ldo3 {
+ regulator-name = "vreg_l3g_1p2";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+ };
+};
+
+&ufs_mem_hc {
+ reset-gpios = <&tlmm 210 GPIO_ACTIVE_LOW>;
+ vcc-supply = <&vreg_l17b_2p5>;
+ vcc-max-microamp = <1300000>;
+ vccq-supply = <&vreg_l1g_1p2>;
+ vccq-max-microamp = <1200000>;
+ vdd-hba-supply = <&vreg_l3g_1p2>;
+
+ status = "okay";
+};
+
+&ufs_mem_phy {
+ vdda-phy-supply = <&vreg_l1d_0p88>;
+ vdda-pll-supply = <&vreg_l3e_1p2>;
+
+ status = "okay";
+};
--
2.25.1
^ permalink raw reply related
* [PATCH v6 RESEND 4/4] arm64: dts: qcom: aim300: add AIM300 AIoT
From: Tengfei Fan @ 2024-04-01 9:38 UTC (permalink / raw)
To: andersson, konrad.dybcio, robh, krzysztof.kozlowski+dt, conor+dt
Cc: keescook, tony.luck, gpiccoli, linux-arm-msm, devicetree,
linux-kernel, linux-hardening, kernel, Tengfei Fan, Qiang Yu,
Ziyue Zhang
In-Reply-To: <20240401093843.2591147-1-quic_tengfan@quicinc.com>
Add AIM300 AIoT Carrier board DTS support, including usb, UART, PCIe,
I2C functions support.
Here is a diagram of AIM300 AIoT Carrie Board and SoM
+--------------------------------------------------+
| AIM300 AIOT Carrie Board |
| |
| +-----------------+ |
|power----->| Fixed regulator |---------+ |
| +-----------------+ | |
| | |
| v VPH_PWR |
| +----------------------------------------------+ |
| | AIM300 SOM | | |
| | |VPH_PWR | |
| | v | |
| | +-------+ +--------+ +------+ | |
| | | UFS | | QCS8550| |PMIC | | |
| | +-------+ +--------+ +------+ | |
| | | |
| +----------------------------------------------+ |
| |
| +----+ +------+ |
| |USB | | UART | |
| +----+ +------+ |
+--------------------------------------------------+
Co-developed-by: Qiang Yu <quic_qianyu@quicinc.com>
Signed-off-by: Qiang Yu <quic_qianyu@quicinc.com>
Co-developed-by: Ziyue Zhang <quic_ziyuzhan@quicinc.com>
Signed-off-by: Ziyue Zhang <quic_ziyuzhan@quicinc.com>
Signed-off-by: Tengfei Fan <quic_tengfan@quicinc.com>
---
arch/arm64/boot/dts/qcom/Makefile | 1 +
.../boot/dts/qcom/qcs8550-aim300-aiot.dts | 384 ++++++++++++++++++
2 files changed, 385 insertions(+)
create mode 100644 arch/arm64/boot/dts/qcom/qcs8550-aim300-aiot.dts
diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile
index 7d40ec5e7d21..02d9bc3bfce7 100644
--- a/arch/arm64/boot/dts/qcom/Makefile
+++ b/arch/arm64/boot/dts/qcom/Makefile
@@ -96,6 +96,7 @@ dtb-$(CONFIG_ARCH_QCOM) += qcm6490-idp.dtb
dtb-$(CONFIG_ARCH_QCOM) += qcs404-evb-1000.dtb
dtb-$(CONFIG_ARCH_QCOM) += qcs404-evb-4000.dtb
dtb-$(CONFIG_ARCH_QCOM) += qcs6490-rb3gen2.dtb
+dtb-$(CONFIG_ARCH_QCOM) += qcs8550-aim300-aiot.dtb
dtb-$(CONFIG_ARCH_QCOM) += qdu1000-idp.dtb
dtb-$(CONFIG_ARCH_QCOM) += qrb2210-rb1.dtb
dtb-$(CONFIG_ARCH_QCOM) += qrb4210-rb2.dtb
diff --git a/arch/arm64/boot/dts/qcom/qcs8550-aim300-aiot.dts b/arch/arm64/boot/dts/qcom/qcs8550-aim300-aiot.dts
new file mode 100644
index 000000000000..8188766c3d84
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/qcs8550-aim300-aiot.dts
@@ -0,0 +1,384 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2023-2024, Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/leds/common.h>
+#include "qcs8550-aim300.dtsi"
+#include "pm8010.dtsi"
+#include "pmr735d_a.dtsi"
+#include "pmr735d_b.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. QCS8550 AIM300 AIOT";
+ compatible = "qcom,qcs8550-aim300-aiot", "qcom,qcs8550-aim300", "qcom,qcs8550",
+ "qcom,sm8550";
+
+ aliases {
+ serial0 = &uart7;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+
+ pinctrl-0 = <&volume_up_n>;
+ pinctrl-names = "default";
+
+ key-volume-up {
+ label = "Volume Up";
+ debounce-interval = <15>;
+ gpios = <&pm8550_gpios 6 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_VOLUMEUP>;
+ linux,can-disable;
+ wakeup-source;
+ };
+ };
+
+ pmic-glink {
+ compatible = "qcom,sm8550-pmic-glink", "qcom,pmic-glink";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ orientation-gpios = <&tlmm 11 GPIO_ACTIVE_HIGH>;
+
+ connector@0 {
+ compatible = "usb-c-connector";
+ reg = <0>;
+ power-role = "dual";
+ data-role = "dual";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ pmic_glink_hs_in: endpoint {
+ remote-endpoint = <&usb_1_dwc3_hs>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+
+ pmic_glink_ss_in: endpoint {
+ remote-endpoint = <&redriver_ss_out>;
+ };
+ };
+
+ port@2 {
+ reg = <2>;
+
+ pmic_glink_sbu: endpoint {
+ remote-endpoint = <&fsa4480_sbu_mux>;
+ };
+ };
+ };
+ };
+ };
+
+ vph_pwr: regulator-vph-pwr {
+ compatible = "regulator-fixed";
+ regulator-name = "vph_pwr";
+ regulator-min-microvolt = <3700000>;
+ regulator-max-microvolt = <3700000>;
+
+ regulator-always-on;
+ regulator-boot-on;
+ };
+};
+
+&apps_rsc {
+ regulators-0 {
+ vdd-bob1-supply = <&vph_pwr>;
+ vdd-bob2-supply = <&vph_pwr>;
+ };
+
+ regulators-3 {
+ vdd-s4-supply = <&vph_pwr>;
+ vdd-s5-supply = <&vph_pwr>;
+ };
+
+ regulators-4 {
+ vdd-s4-supply = <&vph_pwr>;
+ };
+
+ regulators-5 {
+ vdd-s1-supply = <&vph_pwr>;
+ vdd-s2-supply = <&vph_pwr>;
+ vdd-s3-supply = <&vph_pwr>;
+ vdd-s4-supply = <&vph_pwr>;
+ vdd-s5-supply = <&vph_pwr>;
+ vdd-s6-supply = <&vph_pwr>;
+ };
+};
+
+&i2c_hub_2 {
+ status = "okay";
+
+ typec-mux@42 {
+ compatible = "fcs,fsa4480";
+ reg = <0x42>;
+
+ vcc-supply = <&vreg_bob1>;
+
+ mode-switch;
+ orientation-switch;
+
+ port {
+ fsa4480_sbu_mux: endpoint {
+ remote-endpoint = <&pmic_glink_sbu>;
+ };
+ };
+ };
+
+ typec-retimer@1c {
+ compatible = "onnn,nb7vpq904m";
+ reg = <0x1c>;
+
+ vcc-supply = <&vreg_l15b_1p8>;
+
+ orientation-switch;
+ retimer-switch;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ redriver_ss_out: endpoint {
+ remote-endpoint = <&pmic_glink_ss_in>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+
+ redriver_ss_in: endpoint {
+ data-lanes = <3 2 1 0>;
+ remote-endpoint = <&usb_dp_qmpphy_out>;
+ };
+ };
+ };
+ };
+};
+
+&mdss_dsi0 {
+ vdda-supply = <&vreg_l3e_1p2>;
+ status = "okay";
+
+ panel@0 {
+ compatible = "visionox,vtdr6130";
+ reg = <0>;
+
+ pinctrl-0 = <&dsi_active>, <&te_active>;
+ pinctrl-1 = <&dsi_suspend>, <&te_suspend>;
+ pinctrl-names = "default", "sleep";
+
+ reset-gpios = <&tlmm 133 GPIO_ACTIVE_LOW>;
+
+ vci-supply = <&vreg_l13b_3p0>;
+ vdd-supply = <&vreg_l11b_1p2>;
+ vddio-supply = <&vreg_l12b_1p8>;
+
+ port {
+ panel0_in: endpoint {
+ remote-endpoint = <&mdss_dsi0_out>;
+ };
+ };
+ };
+};
+
+&mdss_dsi0_out {
+ remote-endpoint = <&panel0_in>;
+ data-lanes = <0 1 2 3>;
+};
+
+&mdss_dsi0_phy {
+ vdds-supply = <&vreg_l1e_0p88>;
+ status = "okay";
+};
+
+&pcie0 {
+ perst-gpios = <&tlmm 94 GPIO_ACTIVE_LOW>;
+ wake-gpios = <&tlmm 96 GPIO_ACTIVE_HIGH>;
+
+ pinctrl-0 = <&pcie0_default_state>;
+ pinctrl-names = "default";
+
+ status = "okay";
+};
+
+&pcie0_phy {
+ vdda-phy-supply = <&vreg_l1e_0p88>;
+ vdda-pll-supply = <&vreg_l3e_1p2>;
+
+ status = "okay";
+};
+
+&pcie_1_phy_aux_clk {
+ clock-frequency = <1000>;
+};
+
+&pcie1 {
+ perst-gpios = <&tlmm 97 GPIO_ACTIVE_LOW>;
+ wake-gpios = <&tlmm 99 GPIO_ACTIVE_HIGH>;
+
+ pinctrl-0 = <&pcie1_default_state>;
+ pinctrl-names = "default";
+
+ status = "okay";
+};
+
+&pcie1_phy {
+ vdda-phy-supply = <&vreg_l3c_0p9>;
+ vdda-pll-supply = <&vreg_l3e_1p2>;
+ vdda-qref-supply = <&vreg_l1e_0p88>;
+
+ status = "okay";
+};
+
+&pm8550_gpios {
+ volume_up_n: volume-up-n-state {
+ pins = "gpio6";
+ function = "normal";
+ power-source = <1>;
+ bias-pull-up;
+ input-enable;
+ };
+};
+
+&pm8550b_eusb2_repeater {
+ vdd18-supply = <&vreg_l15b_1p8>;
+ vdd3-supply = <&vreg_l5b_3p1>;
+};
+
+
+&pon_pwrkey {
+ status = "okay";
+};
+
+&pon_resin {
+ linux,code = <KEY_VOLUMEDOWN>;
+
+ status = "okay";
+};
+
+&qupv3_id_0 {
+ status = "okay";
+};
+
+&remoteproc_adsp {
+ firmware-name = "qcom/qcs8550/adsp.mbn",
+ "qcom/qcs8550/adsp_dtbs.elf";
+ status = "okay";
+};
+
+&remoteproc_cdsp {
+ firmware-name = "qcom/qcs8550/cdsp.mbn",
+ "qcom/qcs8550/cdsp_dtbs.elf";
+ status = "okay";
+};
+
+&sleep_clk {
+ clock-frequency = <32000>;
+};
+
+&swr1 {
+ status = "okay";
+};
+
+&swr2 {
+ status = "okay";
+};
+
+&tlmm {
+ gpio-reserved-ranges = <32 8>;
+
+ dsi_active: dsi-active-state {
+ pins = "gpio133";
+ function = "gpio";
+ drive-strength = <8>;
+ bias-disable;
+ };
+
+ dsi_suspend: dsi-suspend-state {
+ pins = "gpio133";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-pull-down;
+ };
+
+ te_active: te-active-state {
+ pins = "gpio86";
+ function = "mdp_vsync";
+ drive-strength = <2>;
+ bias-pull-down;
+ };
+
+ te_suspend: te-suspend-state {
+ pins = "gpio86";
+ function = "mdp_vsync";
+ drive-strength = <2>;
+ bias-pull-down;
+ };
+};
+
+&uart7 {
+ status = "okay";
+};
+
+&usb_1 {
+ status = "okay";
+};
+
+&usb_1_dwc3 {
+ dr_mode = "otg";
+ usb-role-switch;
+};
+
+&usb_1_dwc3_hs {
+ remote-endpoint = <&pmic_glink_hs_in>;
+};
+
+&usb_1_dwc3_ss {
+ remote-endpoint = <&usb_dp_qmpphy_usb_ss_in>;
+};
+
+&usb_1_hsphy {
+ phys = <&pm8550b_eusb2_repeater>;
+
+ vdd-supply = <&vreg_l1e_0p88>;
+ vdda12-supply = <&vreg_l3e_1p2>;
+
+ status = "okay";
+};
+
+&usb_dp_qmpphy {
+ vdda-phy-supply = <&vreg_l3e_1p2>;
+ vdda-pll-supply = <&vreg_l3f_0p88>;
+
+ orientation-switch;
+
+ status = "okay";
+};
+
+&usb_dp_qmpphy_out {
+ remote-endpoint = <&redriver_ss_in>;
+};
+
+&usb_dp_qmpphy_usb_ss_in {
+ remote-endpoint = <&usb_1_dwc3_ss>;
+};
+
+&xo_board {
+ clock-frequency = <76800000>;
+};
--
2.25.1
^ permalink raw reply related
* Re: [PATCH v2 27/27] kselftest/riscv: kselftest for user mode cfi
From: Muhammad Usama Anjum @ 2024-04-01 9:46 UTC (permalink / raw)
To: Deepak Gupta
Cc: Muhammad Usama Anjum, paul.walmsley, rick.p.edgecombe, broonie,
Szabolcs.Nagy, kito.cheng, keescook, ajones, conor.dooley, cleger,
atishp, alex, bjorn, alexghiti, samuel.holland, palmer, conor,
linux-doc, linux-riscv, linux-kernel, devicetree, linux-mm,
linux-arch, linux-kselftest, corbet, tech-j-ext, palmer, aou,
robh+dt, krzysztof.kozlowski+dt, oleg, akpm, arnd, ebiederm,
Liam.Howlett, vbabka, lstoakes, shuah, brauner, andy.chiu,
jerry.shih, hankuan.chen, greentime.hu, evan, xiao.w.wang,
charlie, apatel, mchitale, dbarboza, sameo, shikemeng, willy,
vincent.chen, guoren, samitolvanen, songshuaishuai, gerg, heiko,
bhe, jeeheng.sia, cyy, maskray, ancientmodern4, mathis.salmen,
cuiyunhui, bgray, mpe, baruch, alx, david, catalin.marinas,
revest, josh, shr, deller, omosnace, ojeda, jhubbard
In-Reply-To: <CAKC1njQ_RU=uHhrna=MFVdjAMjjQNqZWnkjPoJvO7CxtPMeNuQ@mail.gmail.com>
On 3/30/24 1:02 AM, Deepak Gupta wrote:
> On Fri, Mar 29, 2024 at 12:50 PM Muhammad Usama Anjum
> <usama.anjum@collabora.com> wrote:
>>
>> On 3/29/24 9:44 AM, Deepak Gupta wrote:
>>> Adds kselftest for RISC-V control flow integrity implementation for user
>>> mode. There is not a lot going on in kernel for enabling landing pad for
>>> user mode. Thus kselftest simply enables landing pad for the binary and
>>> a signal handler is registered for SIGSEGV. Any control flow violation are
>>> reported as SIGSEGV with si_code = SEGV_CPERR. Test will fail on recieving
>>> any SEGV_CPERR. Shadow stack part has more changes in kernel and thus there
>>> are separate tests for that
>>> - enable and disable
>>> - Exercise `map_shadow_stack` syscall
>>> - `fork` test to make sure COW works for shadow stack pages
>>> - gup tests
>>> As of today kernel uses FOLL_FORCE when access happens to memory via
>>> /proc/<pid>/mem. Not breaking that for shadow stack
>>> - signal test. Make sure signal delivery results in token creation on
>>> shadow stack and consumes (and verifies) token on sigreturn
>>> - shadow stack protection test. attempts to write using regular store
>>> instruction on shadow stack memory must result in access faults
>>>
>>> Signed-off-by: Deepak Gupta <debug@rivosinc.com>
>>> ---
>>> tools/testing/selftests/riscv/Makefile | 2 +-
>>> tools/testing/selftests/riscv/cfi/Makefile | 10 +
>>> .../testing/selftests/riscv/cfi/cfi_rv_test.h | 85 ++++
>>> .../selftests/riscv/cfi/riscv_cfi_test.c | 91 +++++
>>> .../testing/selftests/riscv/cfi/shadowstack.c | 376 ++++++++++++++++++
>>> .../testing/selftests/riscv/cfi/shadowstack.h | 39 ++
>> Please add generated binaries in the .gitignore files.
>
> hmm...
> I don't see binary as part of the patch. Which file are you referring
> to here being binary?
shadowstack would be generated by the build. Create a .gitignore file and
add it there. For example, look at
tools/testing/selftests/riscv/vector/.gitignore to understand.
>
>>
>
--
BR,
Muhammad Usama Anjum
^ permalink raw reply
* Re: [PATCH v5 3/4] dt-bindings: clock: add i.MX95 clock header
From: Krzysztof Kozlowski @ 2024-04-01 9:51 UTC (permalink / raw)
To: Peng Fan, Peng Fan (OSS), Michael Turquette, Stephen Boyd,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Shawn Guo,
Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam, Abel Vesa
Cc: linux-clk@vger.kernel.org, devicetree@vger.kernel.org,
imx@lists.linux.dev, linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org
In-Reply-To: <DU0PR04MB9417AD4C2F5644FAE6D5A762883F2@DU0PR04MB9417.eurprd04.prod.outlook.com>
On 01/04/2024 09:26, Peng Fan wrote:
>> Subject: Re: [PATCH v5 3/4] dt-bindings: clock: add i.MX95 clock header
>>
>> On 24/03/2024 08:52, Peng Fan (OSS) wrote:
>>> From: Peng Fan <peng.fan@nxp.com>
>>>
>>> Add clock header for i.MX95 BLK CTL modules
>>>
>>> Signed-off-by: Peng Fan <peng.fan@nxp.com>
>>> ---
>>> include/dt-bindings/clock/nxp,imx95-clock.h | 32
>> +++++++++++++++++++++++++++++
>>> 1 file changed, 32 insertions(+)
>>>
>>> diff --git a/include/dt-bindings/clock/nxp,imx95-clock.h b/include/dt-
>> bindings/clock/nxp,imx95-clock.h
>>> new file mode 100644
>>> index 000000000000..83fa3ffe78a8
>>> --- /dev/null
>>> +++ b/include/dt-bindings/clock/nxp,imx95-clock.h
>>> @@ -0,0 +1,32 @@
>>> +/* SPDX-License-Identifier: GPL-2.0-only OR MIT */
>>> +/*
>>> + * Copyright 2024 NXP
>>> + */
>>> +
>>> +#ifndef __DT_BINDINGS_CLOCK_IMX95_H
>>> +#define __DT_BINDINGS_CLOCK_IMX95_H
>>> +
>>> +#define IMX95_CLK_VPUBLK_WAVE 0
>>> +#define IMX95_CLK_VPUBLK_JPEG_ENC 1
>>> +#define IMX95_CLK_VPUBLK_JPEG_DEC 2
>>> +#define IMX95_CLK_VPUBLK_END 3
>>
>> No improvements, so again: drop counting.
>
> Could you please give more details on what you think needs
> to be addressed here? I may overlook your comments before,
> but I search v1-v4, not find comments on the headers,
> except the one file name align with binding if 1:1 match.
Drop all defines which count number of clocks.
Best regards,
Krzysztof
^ permalink raw reply
* Re: [RFC PATCH 1/2] spi: dt-bindings: add Siflower Quad SPI controller
From: Krzysztof Kozlowski @ 2024-04-01 9:53 UTC (permalink / raw)
To: Qingfang Deng
Cc: Mark Brown, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Qingfang Deng, linux-spi, devicetree, linux-kernel
In-Reply-To: <CALW65jZoU8ChPg+e-5T4+ZmS2=g8O3wL96mjaRAPbomHJhg4gg@mail.gmail.com>
On 01/04/2024 05:36, Qingfang Deng wrote:
> Hi Krzysztof,
>
> On Sun, Mar 31, 2024 at 1:42 AM Krzysztof Kozlowski
> <krzysztof.kozlowski@linaro.org> wrote:
>> On 29/03/2024 02:51, Qingfang Deng wrote:
>>> Add YAML devicetree bindings for Siflower Quad SPI controller.
>>
>> Describe the hardware. What is this Siflower?
>
> It's a new RISC-V SoC which hasn't been upstreamed yet.
>
>>> +properties:
>>> + compatible:
>>> + const: siflower,qspi
>>
>> Except that this was not tested, aren't you adding it for some SoC? If
>> so, then you miss here SoC part.
>
> I should add the "siflower" prefix to
> Documentation/devicetree/bindings/vendor-prefixes.yaml, right?
Isn't it already there? Then obvious you must, but that was not the
point. Please read writing-bindings document. Compatibles should be SoC
specific, not generic. "qspi" is generic.
Best regards,
Krzysztof
^ permalink raw reply
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