* RE: [PATCH v2 4/6] firmware: arm_scmi: add initial support for i.MX MISC protocol
From: Peng Fan @ 2024-04-07 1:03 UTC (permalink / raw)
To: Marco Felsch, Peng Fan (OSS)
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Shawn Guo,
Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
Sudeep Holla, Cristian Marussi, devicetree@vger.kernel.org,
linux-kernel@vger.kernel.org,
linux-arm-kernel@lists.infradead.org, imx@lists.linux.dev
In-Reply-To: <20240405164414.t3fqhnwudxxt2ozv@pengutronix.de>
> Subject: Re: [PATCH v2 4/6] firmware: arm_scmi: add initial support for i.MX
> MISC protocol
>
> Hi Peng,
>
> On 24-04-05, Peng Fan (OSS) wrote:
> > From: Peng Fan <peng.fan@nxp.com>
> >
> > The i.MX MISC protocol is for misc settings, such as gpio expander
> > wakeup.
>
> Can you elaborate a bit more please?
The gpio expander is under M33(SCMI firmware used core) I2C control,
But the gpio expander supports board function such as PCIE_WAKEUP,
BTN_WAKEUP. So these are managed by MISC protocol.
SAI_CLK_MSEL in WAKEUP BLK CTRL is also managed by MISC Protocol.
And etc...
I will add more info in commit log in next version later, after I get more
reviews on the patchset.
Thanks,
Peng.
>
> Regards,
> Marco
>
>
> >
> > Signed-off-by: Peng Fan <peng.fan@nxp.com>
> > ---
> > drivers/firmware/arm_scmi/Kconfig | 10 ++
> > drivers/firmware/arm_scmi/Makefile | 1 +
> > drivers/firmware/arm_scmi/imx-sm-misc.c | 305
> ++++++++++++++++++++++++++++++++
> > include/linux/scmi_imx_protocol.h | 17 ++
> > 4 files changed, 333 insertions(+)
> >
> > diff --git a/drivers/firmware/arm_scmi/Kconfig
> > b/drivers/firmware/arm_scmi/Kconfig
> > index 56d11c9d9f47..bfeae92f6420 100644
> > --- a/drivers/firmware/arm_scmi/Kconfig
> > +++ b/drivers/firmware/arm_scmi/Kconfig
> > @@ -191,3 +191,13 @@ config IMX_SCMI_BBM_EXT
> > and BUTTON.
> >
> > This driver can also be built as a module.
> > +
> > +config IMX_SCMI_MISC_EXT
> > + tristate "i.MX SCMI MISC EXTENSION"
> > + depends on ARM_SCMI_PROTOCOL || (COMPILE_TEST && OF)
> > + default y if ARCH_MXC
> > + help
> > + This enables i.MX System MISC control logic such as gpio expander
> > + wakeup
> > +
> > + This driver can also be built as a module.
> > diff --git a/drivers/firmware/arm_scmi/Makefile
> > b/drivers/firmware/arm_scmi/Makefile
> > index 327687acf857..a23fde721222 100644
> > --- a/drivers/firmware/arm_scmi/Makefile
> > +++ b/drivers/firmware/arm_scmi/Makefile
> > @@ -12,6 +12,7 @@ scmi-transport-
> $(CONFIG_ARM_SCMI_TRANSPORT_VIRTIO)
> > += virtio.o
> > scmi-transport-$(CONFIG_ARM_SCMI_TRANSPORT_OPTEE) += optee.o
> > scmi-protocols-y = base.o clock.o perf.o power.o reset.o sensors.o
> > system.o voltage.o powercap.o
> > scmi-protocols-$(CONFIG_IMX_SCMI_BBM_EXT) += imx-sm-bbm.o
> > +scmi-protocols-$(CONFIG_IMX_SCMI_MISC_EXT) += imx-sm-misc.o
> > scmi-module-objs := $(scmi-driver-y) $(scmi-protocols-y)
> > $(scmi-transport-y)
> >
> > obj-$(CONFIG_ARM_SCMI_PROTOCOL) += scmi-core.o diff --git
> > a/drivers/firmware/arm_scmi/imx-sm-misc.c
> > b/drivers/firmware/arm_scmi/imx-sm-misc.c
> > new file mode 100644
> > index 000000000000..1b0ec2281518
> > --- /dev/null
> > +++ b/drivers/firmware/arm_scmi/imx-sm-misc.c
> > @@ -0,0 +1,305 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * System control and Management Interface (SCMI) NXP MISC Protocol
> > + *
> > + * Copyright 2024 NXP
> > + */
> > +
> > +#define pr_fmt(fmt) "SCMI Notifications MISC - " fmt
> > +
> > +#include <linux/bits.h>
> > +#include <linux/io.h>
> > +#include <linux/module.h>
> > +#include <linux/of.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/scmi_protocol.h>
> > +#include <linux/scmi_imx_protocol.h>
> > +
> > +#include "protocols.h"
> > +#include "notify.h"
> > +
> > +#define SCMI_PROTOCOL_SUPPORTED_VERSION 0x10000
> > +
> > +enum scmi_imx_misc_protocol_cmd {
> > + SCMI_IMX_MISC_CTRL_SET = 0x3,
> > + SCMI_IMX_MISC_CTRL_GET = 0x4,
> > + SCMI_IMX_MISC_CTRL_NOTIFY = 0x8,
> > +};
> > +
> > +struct scmi_imx_misc_info {
> > + u32 version;
> > + u32 nr_dev_ctrl;
> > + u32 nr_brd_ctrl;
> > + u32 nr_reason;
> > +};
> > +
> > +struct scmi_msg_imx_misc_protocol_attributes {
> > + __le32 attributes;
> > +};
> > +
> > +#define GET_BRD_CTRLS_NR(x) le32_get_bits((x), GENMASK(31,
> 24))
> > +#define GET_REASONS_NR(x) le32_get_bits((x), GENMASK(23, 16))
> > +#define GET_DEV_CTRLS_NR(x) le32_get_bits((x), GENMASK(15, 0))
> > +#define BRD_CTRL_START_ID BIT(15)
> > +
> > +struct scmi_imx_misc_ctrl_set_in {
> > + __le32 id;
> > + __le32 num;
> > + __le32 value[MISC_MAX_VAL];
> > +};
> > +
> > +struct scmi_imx_misc_ctrl_notify_in {
> > + __le32 ctrl_id;
> > + __le32 flags;
> > +};
> > +
> > +struct scmi_imx_misc_ctrl_notify_payld {
> > + __le32 ctrl_id;
> > + __le32 flags;
> > +};
> > +
> > +struct scmi_imx_misc_ctrl_get_out {
> > + __le32 num;
> > + __le32 *val;
> > +};
> > +
> > +static int scmi_imx_misc_attributes_get(const struct scmi_protocol_handle
> *ph,
> > + struct scmi_imx_misc_info *mi)
> > +{
> > + int ret;
> > + struct scmi_xfer *t;
> > + struct scmi_msg_imx_misc_protocol_attributes *attr;
> > +
> > + ret = ph->xops->xfer_get_init(ph, PROTOCOL_ATTRIBUTES, 0,
> > + sizeof(*attr), &t);
> > + if (ret)
> > + return ret;
> > +
> > + attr = t->rx.buf;
> > +
> > + ret = ph->xops->do_xfer(ph, t);
> > + if (!ret) {
> > + mi->nr_dev_ctrl = GET_DEV_CTRLS_NR(attr->attributes);
> > + mi->nr_brd_ctrl = GET_BRD_CTRLS_NR(attr->attributes);
> > + mi->nr_reason = GET_REASONS_NR(attr->attributes);
> > + dev_info(ph->dev, "i.MX MISC NUM DEV CTRL: %d, NUM
> BRD CTRL: %d,NUM Reason: %d\n",
> > + mi->nr_dev_ctrl, mi->nr_brd_ctrl, mi->nr_reason);
> > + }
> > +
> > + ph->xops->xfer_put(ph, t);
> > +
> > + return ret;
> > +}
> > +
> > +static int scmi_imx_misc_ctrl_validate_id(const struct
> scmi_protocol_handle *ph,
> > + u32 ctrl_id)
> > +{
> > + struct scmi_imx_misc_info *mi = ph->get_priv(ph);
> > +
> > + if ((ctrl_id < BRD_CTRL_START_ID) && (ctrl_id > mi->nr_dev_ctrl))
> > + return -EINVAL;
> > + if (ctrl_id >= BRD_CTRL_START_ID + mi->nr_brd_ctrl)
> > + return -EINVAL;
> > +
> > + return 0;
> > +}
> > +
> > +static int scmi_imx_misc_ctrl_notify(const struct scmi_protocol_handle
> *ph,
> > + u32 ctrl_id, u32 flags)
> > +{
> > + struct scmi_imx_misc_ctrl_notify_in *in;
> > + struct scmi_xfer *t;
> > + int ret;
> > +
> > + ret = scmi_imx_misc_ctrl_validate_id(ph, ctrl_id);
> > + if (ret)
> > + return ret;
> > +
> > + ret = ph->xops->xfer_get_init(ph, SCMI_IMX_MISC_CTRL_NOTIFY,
> > + sizeof(*in), 0, &t);
> > + if (ret)
> > + return ret;
> > +
> > + in = t->tx.buf;
> > + in->ctrl_id = cpu_to_le32(ctrl_id);
> > + in->flags = cpu_to_le32(flags);
> > +
> > + ret = ph->xops->do_xfer(ph, t);
> > +
> > + ph->xops->xfer_put(ph, t);
> > +
> > + return ret;
> > +}
> > +
> > +static int
> > +scmi_imx_misc_ctrl_set_notify_enabled(const struct
> scmi_protocol_handle *ph,
> > + u8 evt_id, u32 src_id, bool enable) {
> > + int ret;
> > +
> > + ret = scmi_imx_misc_ctrl_notify(ph, src_id, enable ? evt_id : 0);
> > + if (ret)
> > + dev_err(ph->dev, "FAIL_ENABLED - evt[%X] src[%d] -
> ret:%d\n",
> > + evt_id, src_id, ret);
> > +
> > + return ret;
> > +}
> > +
> > +static int scmi_imx_misc_ctrl_get_num_sources(const struct
> > +scmi_protocol_handle *ph) {
> > + return GENMASK(15, 0);
> > +}
> > +
> > +static void *
> > +scmi_imx_misc_ctrl_fill_custom_report(const struct scmi_protocol_handle
> *ph,
> > + u8 evt_id, ktime_t timestamp,
> > + const void *payld, size_t payld_sz,
> > + void *report, u32 *src_id)
> > +{
> > + const struct scmi_imx_misc_ctrl_notify_payld *p = payld;
> > + struct scmi_imx_misc_ctrl_notify_report *r = report;
> > +
> > + if (sizeof(*p) != payld_sz)
> > + return NULL;
> > +
> > + r->timestamp = timestamp;
> > + r->ctrl_id = p->ctrl_id;
> > + r->flags = p->flags;
> > + *src_id = r->ctrl_id;
> > + dev_dbg(ph->dev, "%s: ctrl_id: %d flags: %d\n", __func__,
> > + r->ctrl_id, r->flags);
> > +
> > + return r;
> > +}
> > +
> > +static const struct scmi_event_ops scmi_imx_misc_event_ops = {
> > + .get_num_sources = scmi_imx_misc_ctrl_get_num_sources,
> > + .set_notify_enabled = scmi_imx_misc_ctrl_set_notify_enabled,
> > + .fill_custom_report = scmi_imx_misc_ctrl_fill_custom_report,
> > +};
> > +
> > +static const struct scmi_event scmi_imx_misc_events[] = {
> > + {
> > + .id = SCMI_EVENT_IMX_MISC_CONTROL_DISABLED,
> > + .max_payld_sz = sizeof(struct
> scmi_imx_misc_ctrl_notify_payld),
> > + .max_report_sz = sizeof(struct
> scmi_imx_misc_ctrl_notify_report),
> > + },
> > + {
> > + .id = SCMI_EVENT_IMX_MISC_CONTROL_FALLING_EDGE,
> > + .max_payld_sz = sizeof(struct
> scmi_imx_misc_ctrl_notify_payld),
> > + .max_report_sz = sizeof(struct
> scmi_imx_misc_ctrl_notify_report),
> > + },
> > + {
> > + .id = SCMI_EVENT_IMX_MISC_CONTROL_RISING_EDGE,
> > + .max_payld_sz = sizeof(struct
> scmi_imx_misc_ctrl_notify_payld),
> > + .max_report_sz = sizeof(struct
> scmi_imx_misc_ctrl_notify_report),
> > + }
> > +};
> > +
> > +static struct scmi_protocol_events scmi_imx_misc_protocol_events = {
> > + .queue_sz = SCMI_PROTO_QUEUE_SZ,
> > + .ops = &scmi_imx_misc_event_ops,
> > + .evts = scmi_imx_misc_events,
> > + .num_events = ARRAY_SIZE(scmi_imx_misc_events), };
> > +
> > +static int scmi_imx_misc_protocol_init(const struct
> > +scmi_protocol_handle *ph) {
> > + struct scmi_imx_misc_info *minfo;
> > + u32 version;
> > + int ret;
> > +
> > + ret = ph->xops->version_get(ph, &version);
> > + if (ret)
> > + return ret;
> > +
> > + dev_info(ph->dev, "NXP SM MISC Version %d.%d\n",
> > + PROTOCOL_REV_MAJOR(version),
> PROTOCOL_REV_MINOR(version));
> > +
> > + minfo = devm_kzalloc(ph->dev, sizeof(*minfo), GFP_KERNEL);
> > + if (!minfo)
> > + return -ENOMEM;
> > +
> > + ret = scmi_imx_misc_attributes_get(ph, minfo);
> > + if (ret)
> > + return ret;
> > +
> > + return ph->set_priv(ph, minfo, version); }
> > +
> > +static int scmi_imx_misc_ctrl_get(const struct scmi_protocol_handle *ph,
> > + u32 ctrl_id, u32 *num, u32 *val) {
> > + struct scmi_imx_misc_ctrl_get_out *out;
> > + struct scmi_xfer *t;
> > + int ret, i;
> > +
> > + ret = scmi_imx_misc_ctrl_validate_id(ph, ctrl_id);
> > + if (ret)
> > + return ret;
> > +
> > + ret = ph->xops->xfer_get_init(ph, SCMI_IMX_MISC_CTRL_GET,
> sizeof(u32),
> > + 0, &t);
> > + if (ret)
> > + return ret;
> > +
> > + put_unaligned_le32(ctrl_id, t->tx.buf);
> > + ret = ph->xops->do_xfer(ph, t);
> > + if (!ret) {
> > + out = t->rx.buf;
> > + *num = le32_to_cpu(out->num);
> > + for (i = 0; i < *num && i < MISC_MAX_VAL; i++)
> > + val[i] = le32_to_cpu(out->val[i]);
> > + }
> > +
> > + ph->xops->xfer_put(ph, t);
> > +
> > + return ret;
> > +}
> > +
> > +static int scmi_imx_misc_ctrl_set(const struct scmi_protocol_handle *ph,
> > + u32 ctrl_id, u32 num, u32 *val) {
> > + struct scmi_imx_misc_ctrl_set_in *in;
> > + struct scmi_xfer *t;
> > + int ret, i;
> > +
> > + ret = scmi_imx_misc_ctrl_validate_id(ph, ctrl_id);
> > + if (ret)
> > + return ret;
> > +
> > + if (num > MISC_MAX_VAL)
> > + return -EINVAL;
> > +
> > + ret = ph->xops->xfer_get_init(ph, SCMI_IMX_MISC_CTRL_SET,
> sizeof(*in),
> > + 0, &t);
> > + if (ret)
> > + return ret;
> > +
> > + in = t->tx.buf;
> > + in->id = cpu_to_le32(ctrl_id);
> > + in->num = cpu_to_le32(num);
> > + for (i = 0; i < num; i++)
> > + in->value[i] = cpu_to_le32(val[i]);
> > +
> > + ret = ph->xops->do_xfer(ph, t);
> > +
> > + ph->xops->xfer_put(ph, t);
> > +
> > + return ret;
> > +}
> > +
> > +static const struct scmi_imx_misc_proto_ops scmi_imx_misc_proto_ops =
> {
> > + .misc_ctrl_set = scmi_imx_misc_ctrl_set,
> > + .misc_ctrl_get = scmi_imx_misc_ctrl_get, };
> > +
> > +static const struct scmi_protocol scmi_imx_misc = {
> > + .id = SCMI_PROTOCOL_IMX_MISC,
> > + .owner = THIS_MODULE,
> > + .instance_init = &scmi_imx_misc_protocol_init,
> > + .ops = &scmi_imx_misc_proto_ops,
> > + .events = &scmi_imx_misc_protocol_events,
> > + .supported_version = SCMI_PROTOCOL_SUPPORTED_VERSION, };
> > +module_scmi_protocol(scmi_imx_misc);
> > diff --git a/include/linux/scmi_imx_protocol.h
> > b/include/linux/scmi_imx_protocol.h
> > index 90ce011a4429..a69bd4a20f0f 100644
> > --- a/include/linux/scmi_imx_protocol.h
> > +++ b/include/linux/scmi_imx_protocol.h
> > @@ -13,8 +13,14 @@
> > #include <linux/notifier.h>
> > #include <linux/types.h>
> >
> > +#define SCMI_PAYLOAD_LEN 100
> > +
> > +#define SCMI_ARRAY(X, Y) ((SCMI_PAYLOAD_LEN - (X)) / sizeof(Y))
> > +#define MISC_MAX_VAL SCMI_ARRAY(8, uint32_t)
> > +
> > enum scmi_nxp_protocol {
> > SCMI_PROTOCOL_IMX_BBM = 0x81,
> > + SCMI_PROTOCOL_IMX_MISC = 0x84,
> > };
> >
> > struct scmi_imx_bbm_proto_ops {
> > @@ -42,4 +48,15 @@ struct scmi_imx_bbm_notif_report {
> > unsigned int rtc_id;
> > unsigned int rtc_evt;
> > };
> > +
> > +struct scmi_imx_misc_ctrl_notify_report {
> > + ktime_t timestamp;
> > + unsigned int ctrl_id;
> > + unsigned int flags;
> > +};
> > +
> > +struct scmi_imx_misc_proto_ops {
> > + int (*misc_ctrl_set)(const struct scmi_protocol_handle *ph, u32 id,
> u32 num, u32 *val);
> > + int (*misc_ctrl_get)(const struct scmi_protocol_handle *ph, u32 id,
> > +u32 *num, u32 *val); };
> > #endif
> >
> > --
> > 2.37.1
> >
> >
> >
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* RE: [PATCH v2 2/6] dt-bindings: firmware: add i.MX SCMI Extension protocol
From: Peng Fan @ 2024-04-07 1:50 UTC (permalink / raw)
To: Krzysztof Kozlowski, Peng Fan (OSS), Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Shawn Guo, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam, Sudeep Holla,
Cristian Marussi
Cc: devicetree@vger.kernel.org, imx@lists.linux.dev,
linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org
In-Reply-To: <DU0PR04MB941719A18C3F749E7D180FD888012@DU0PR04MB9417.eurprd04.prod.outlook.com>
> Subject: RE: [PATCH v2 2/6] dt-bindings: firmware: add i.MX SCMI Extension
> protocol
>
> > Subject: Re: [PATCH v2 2/6] dt-bindings: firmware: add i.MX SCMI
> > Extension protocol
> >
> > On 05/04/2024 14:39, Peng Fan (OSS) wrote:
> > > From: Peng Fan <peng.fan@nxp.com>
> > >
> > > Add i.MX SCMI Extension protocols bindings for:
> > > - Battery Backed Secure Module(BBSM)
> >
> > Which is what?
>
> I should say BBM(BBSM + BBNSM), BBM has RTC and ON/OFF key features,
> but BBM is managed by SCMI firmware and exported to agent by BBM
> protocol. So add bindings for i.MX BBM protocol.
>
> Is this ok?
>
> >
> > > - MISC settings such as General Purpose Registers settings.
> > >
> > > Signed-off-by: Peng Fan <peng.fan@nxp.com>
> > > ---
> > > .../devicetree/bindings/firmware/imx,scmi.yaml | 80
> > ++++++++++++++++++++++
> > > 1 file changed, 80 insertions(+)
> > >
> > > diff --git
> > > a/Documentation/devicetree/bindings/firmware/imx,scmi.yaml
> > > b/Documentation/devicetree/bindings/firmware/imx,scmi.yaml
> > > new file mode 100644
> > > index 000000000000..7ee19a661d83
> > > --- /dev/null
> > > +++ b/Documentation/devicetree/bindings/firmware/imx,scmi.yaml
> > > @@ -0,0 +1,80 @@
> > > +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) # Copyright
> > > +2024 NXP %YAML 1.2
> > > +---
> > > +$id:
> > > +https://eur01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fde
> > > +vi
> > >
> >
> +cetree.org%2Fschemas%2Ffirmware%2Fimx%2Cscmi.yaml%23&data=05%7
> > C02%7Cp
> > >
> >
> +eng.fan%40nxp.com%7C5d16781d3eca425a342508dc562910b7%7C686ea
> > 1d3bc2b4c
> > >
> > +6fa92cd99c5c301635%7C0%7C0%7C638479981570959816%7CUnknown%
> > 7CTWFpbGZsb
> > >
> >
> +3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn
> > 0%3D
> > >
> >
> +%7C0%7C%7C%7C&sdata=mWNwPvu2eyF18MroVOBHb%2Fjeo%2BIHfV5V
> > h%2F9ebdx65MM
> > > +%3D&reserved=0
> > > +$schema:
> > > +https://eur01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fde
> > > +vi
> > > +cetree.org%2Fmeta-
> > schemas%2Fcore.yaml%23&data=05%7C02%7Cpeng.fan%40nx
> > >
> >
> +p.com%7C5d16781d3eca425a342508dc562910b7%7C686ea1d3bc2b4c6fa
> > 92cd99c5c
> > >
> >
> +301635%7C0%7C0%7C638479981570971949%7CUnknown%7CTWFpbGZs
> > b3d8eyJWIjoiM
> > >
> >
> +C4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C0%7
> > C%7C%7
> > >
> >
> +C&sdata=v4XnGG00D4I8j5MJvDUVYMRTm7yRrvz0V3fUyc5KAAA%3D&reser
> > ved=0
> > > +
> > > +title: i.MX System Control and Management Interface(SCMI) Vendor
> > > +Protocols Extension
> > > +
> > > +maintainers:
> > > + - Peng Fan <peng.fan@nxp.com>
> > > +
> > > +allOf:
> > > + - $ref: arm,scmi.yaml#
> >
> > Sorry, but arm,scmi is a final schema. Is your plan to define some
> > common part?
>
> No. I just wanna add vendor extension per SCMI spec.
>
> 0x80-0xFF:
> Reserved for vendor or platform-specific extensions to this interface
>
> Each vendor may have different usage saying id 0x81, so I add i.MX dt-
> schema file.
>
> >
> > > +
> > > +properties:
> > > + protocol@81:
> > > + $ref: 'arm,scmi.yaml#/$defs/protocol-node'
> > > + unevaluatedProperties: false
> > > + description:
> > > + The BBM Protocol is for managing Battery Backed Secure Module
> > (BBSM) RTC
> > > + and the ON/OFF Key
> > > +
> > > + properties:
> > > + reg:
> > > + const: 0x81
> > > +
> > > + required:
> > > + - reg
> > > +
> > > + protocol@84:
> > > + $ref: 'arm,scmi.yaml#/$defs/protocol-node'
> > > + unevaluatedProperties: false
> > > + description:
> > > + The MISC Protocol is for managing SoC Misc settings, such as
> > > + GPR settings
> >
> > Genera register is not a setting... this is a pleonasm. Please be more
> > specific what is the GPR, MISC protocol etc.
>
> The MISC Protocol is for managing SoC Misc settings, such as SAI MCLK/MQS
> in Always On domain BLK CTRL, SAI_CLK_SEL in WAKEUP BLK CTRL, gpio
> expanders which is under control of SCMI firmware.
>
> > > +
> > > + properties:
> > > + reg:
> > > + const: 0x84
> > > +
> > > + wakeup-sources:
> > > + description:
> > > + Each entry consists of 2 integers, represents the source
> > > + and electric signal edge
> >
> > Can you answer questions from reviewers?
>
> Sorry. Is this ok?
> minItems: 1
> maxItems: 32
>
> >
> > > + items:
> > > + items:
> > > + - description: the wakeup source
> > > + - description: the wakeup electric signal edge
> > > + $ref: /schemas/types.yaml#/definitions/uint32-matrix
> > > +
> > > + required:
> > > + - reg
> > > +
> > > +additionalProperties: false
> > > +
> > > +examples:
> > > + - |
> > > + firmware {
> > > + scmi {
> > > + compatible = "arm,scmi";
> >
> > > + mboxes = <&mu2 5 0>, <&mu2 3 0>, <&mu2 3 1>;
> > > + shmem = <&scmi_buf0>, <&scmi_buf1>;
> > > +
> > > + #address-cells = <1>;
> > > + #size-cells = <0>;
> > > +
> > > + protocol@81 {
> > > + reg = <0x81>;
> > > + };
> > > +
> > > + protocol@84 {
> > > + reg = <0x84>;
> > > + wakeup-sources = <0x8000 1
> > > + 0x8001 1
> > > + 0x8002 1
> > > + 0x8003 1
> > > + 0x8004 1>;
> >
> > Nothing improved... If you are going to ignore reviews, then you will
> > only get NAKed.
>
> Sorry, you mean the examples, or the whole dt-schema?
Missed Rob's comment, will use
< > for each entry.
Thanks,
Peng.
>
> Thanks,
> Peng.
> >
> > Best regards,
> > Krzysztof
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH 1/2] media: v4l2-ctrls: Add average qp control
From: ming qian @ 2024-04-07 2:43 UTC (permalink / raw)
To: Nicolas Dufresne, Ming Qian, mchehab, hverkuil-cisco
Cc: shawnguo, robh+dt, s.hauer, kernel, festevam, linux-imx,
xiahong.bao, eagle.zhou, tao.jiang_2, imx, linux-media,
linux-kernel, linux-arm-kernel
In-Reply-To: <5fc25468198cb3a228b91160dcc490600e1197d4.camel@ndufresne.ca>
Hi Nicolas,
On 4/5/24 02:14, Nicolas Dufresne wrote:
> Hi,
>
> Le vendredi 29 mars 2024 à 18:23 +0900, Ming Qian a écrit :
>> Add a control V4L2_CID_MPEG_VIDEO_AVERAGE_QP to report the average qp
>> value of current encoded frame.
>>
>> Signed-off-by: Ming Qian <ming.qian@nxp.com>
>> ---
>> Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst | 4 ++++
>> drivers/media/v4l2-core/v4l2-ctrls-defs.c | 5 +++++
>> include/uapi/linux/v4l2-controls.h | 2 ++
>> 3 files changed, 11 insertions(+)
>>
>> diff --git a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst
>> index 2a165ae063fb..cef20b3f54ca 100644
>> --- a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst
>> +++ b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst
>> @@ -1653,6 +1653,10 @@ enum v4l2_mpeg_video_h264_hierarchical_coding_type -
>> Quantization parameter for a P frame for FWHT. Valid range: from 1
>> to 31.
>>
>> +``V4L2_CID_MPEG_VIDEO_AVERAGE_QP (integer)``
>> + This read-only control returns the average qp value of the currently
>> + encoded frame. Applicable to the H264 and HEVC encoders.
>
> That seems ambiguous at best. What does it mean the "currently encoded frame" ?
> The OUTPUT and CAPTURE queue can be holding multiple frames. For "per frame"
> accurate reporting, I feel like we'd need something like Hans' read-only
> requests proposal [0]. Its basically a mechanism that let you attach request FD
> to capture buffer, so that supported controls can be saved per v4l2-buffer and
> read later on.
>
> https://patches.linaro.org/project/linux-media/patch/20210610113615.785359-12-hverkuil-cisco@xs4all.nl/
>
> If this isn't what you wanted, we'll need a better definition. It might be
> helpful to explain what this is used for.
>
> Nicolas
>
Yes, I want to report the qp value for every frame.
I thought the request FD is only used for stateless decoder, but I want
to add a read-only ctrl for the stateful encoder. So I checked the
defined read-only ctrls, I think it's similar with
V4L2_CID_MPEG_VIDEO_DEC_PTS.
(https://linuxtv.org/downloads/v4l-dvb-apis/userspace-api/v4l/ext-ctrls-codec.html?highlight=v4l2_cid_mpeg_video_dec_pts)
then back to your question about the "currently encoded frame", it's the
last dequeued capture buffer of the encoder, the capture queue can hold
multiple frames, each frame will have a qp value in this case, and this
ctrl only report the qp value of the last dequeued frame, when user has
dequeued an encoded frame from the capture queue, he can get the ctrl
value of V4L2_CID_MPEG_VIDEO_AVERAGE_QP immediately to get the qp value
of the currently dequeued frame. If user doesn't care about this
parameter, he doesn't need to do anything, it's just the same as before.
so I think this ctrl is backward compatible.
Maybe the request FD is a better and more intuitive way to suggest a
one-to-one correspondence between ctrl and frame. I'm just not sure if
it just applies to the stateless decoder. I did find any stateful
decoder or encoder to use them.
If we use the request FD for this stateful encoder, I'm not sure if it
will break the original flow.
best regards,
Ming
>> +
>> .. raw:: latex
>>
>> \normalsize
>> diff --git a/drivers/media/v4l2-core/v4l2-ctrls-defs.c b/drivers/media/v4l2-core/v4l2-ctrls-defs.c
>> index 8696eb1cdd61..88e86e4e539d 100644
>> --- a/drivers/media/v4l2-core/v4l2-ctrls-defs.c
>> +++ b/drivers/media/v4l2-core/v4l2-ctrls-defs.c
>> @@ -972,6 +972,7 @@ const char *v4l2_ctrl_get_name(u32 id)
>> case V4L2_CID_MPEG_VIDEO_USE_LTR_FRAMES: return "Use LTR Frames";
>> case V4L2_CID_FWHT_I_FRAME_QP: return "FWHT I-Frame QP Value";
>> case V4L2_CID_FWHT_P_FRAME_QP: return "FWHT P-Frame QP Value";
>> + case V4L2_CID_MPEG_VIDEO_AVERAGE_QP: return "Average QP value";
>>
>> /* VPX controls */
>> case V4L2_CID_MPEG_VIDEO_VPX_NUM_PARTITIONS: return "VPX Number of Partitions";
>> @@ -1507,6 +1508,10 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
>> *max = 0xffffffffffffLL;
>> *step = 1;
>> break;
>> + case V4L2_CID_MPEG_VIDEO_AVERAGE_QP:
>> + *type = V4L2_CTRL_TYPE_INTEGER;
>> + *flags |= V4L2_CTRL_FLAG_VOLATILE | V4L2_CTRL_FLAG_READ_ONLY;
>> + break;
>> case V4L2_CID_PIXEL_RATE:
>> *type = V4L2_CTRL_TYPE_INTEGER64;
>> *flags |= V4L2_CTRL_FLAG_READ_ONLY;
>> diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h
>> index 99c3f5e99da7..974fd254e573 100644
>> --- a/include/uapi/linux/v4l2-controls.h
>> +++ b/include/uapi/linux/v4l2-controls.h
>> @@ -898,6 +898,8 @@ enum v4l2_mpeg_video_av1_level {
>> V4L2_MPEG_VIDEO_AV1_LEVEL_7_3 = 23
>> };
>>
>> +#define V4L2_CID_MPEG_VIDEO_AVERAGE_QP (V4L2_CID_CODEC_BASE + 657)
>> +
>> /* MPEG-class control IDs specific to the CX2341x driver as defined by V4L2 */
>> #define V4L2_CID_CODEC_CX2341X_BASE (V4L2_CTRL_CLASS_CODEC | 0x1000)
>> #define V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE (V4L2_CID_CODEC_CX2341X_BASE+0)
>
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* RE: [PATCH v8 4/4] pinctrl: Implementation of the generic scmi-pinctrl driver
From: Peng Fan @ 2024-04-07 3:17 UTC (permalink / raw)
To: Peng Fan (OSS), Sudeep Holla, Cristian Marussi, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Linus Walleij, Dan Carpenter
Cc: Andy Shevchenko, linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org, devicetree@vger.kernel.org,
linux-gpio@vger.kernel.org, Oleksii Moisieiev
In-Reply-To: <20240405-pinctrl-scmi-v8-4-5fc8e33871bf@nxp.com>
> Subject: [PATCH v8 4/4] pinctrl: Implementation of the generic scmi-pinctrl
> driver
>
> From: Peng Fan <peng.fan@nxp.com>
>
> scmi-pinctrl driver implements pinctrl driver interface and using SCMI
> protocol to redirect messages from pinctrl subsystem SDK to SCMI platform
> firmware, which does the changes in HW.
Considering pinctrl expects ENOTSUPP, so I would add this in v9.
diff --git a/drivers/pinctrl/pinctrl-scmi.c b/drivers/pinctrl/pinctrl-scmi.c
index 0f55f000a679..accebe3f0706 100644
--- a/drivers/pinctrl/pinctrl-scmi.c
+++ b/drivers/pinctrl/pinctrl-scmi.c
@@ -296,8 +296,12 @@ static int pinctrl_scmi_pinconf_get(struct pinctrl_dev *pctldev,
ret = pinctrl_ops->settings_get_one(pmx->ph, pin, PIN_TYPE, type,
&config_value);
- if (ret)
+ if (ret) {
+ /* Convert SCMI error code to PINCTRL expected error code */
+ if (ret == -EOPNOTSUPP)
+ ret = -ENOTSUPP;
return ret;
+ }
*config = pinconf_to_config_packed(config_type, config_value);
@@ -445,8 +449,12 @@ static int pinctrl_scmi_pinconf_group_get(struct pinctrl_dev *pctldev,
ret = pinctrl_ops->settings_get_one(pmx->ph, group, GROUP_TYPE, type,
&config_value);
- if (ret)
+ if (ret) {
+ /* Convert SCMI error code to PINCTRL expected error code */
+ if (ret == -EOPNOTSUPP)
+ ret = -ENOTSUPP;
return ret;
+ }
*config = pinconf_to_config_packed(config_type, config_value);
I will collect more comments before post v9. Just post out upper diff
to see any disagreements.
Thanks,
Peng.
>
> Co-developed-by: Oleksii Moisieiev <oleksii_moisieiev@epam.com>
> Signed-off-by: Oleksii Moisieiev <oleksii_moisieiev@epam.com>
> Signed-off-by: Peng Fan <peng.fan@nxp.com>
> ---
> MAINTAINERS | 1 +
> drivers/pinctrl/Kconfig | 11 +
> drivers/pinctrl/Makefile | 1 +
> drivers/pinctrl/pinctrl-scmi.c | 564
> +++++++++++++++++++++++++++++++++++++++++
> 4 files changed, 577 insertions(+)
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 4b511a55101c..d8270ac6651a 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -21457,6 +21457,7 @@ F: drivers/cpufreq/sc[mp]i-cpufreq.c
> F: drivers/firmware/arm_scmi/
> F: drivers/firmware/arm_scpi.c
> F: drivers/hwmon/scmi-hwmon.c
> +F: drivers/pinctrl/pinctrl-scmi.c
> F: drivers/pmdomain/arm/
> F: drivers/powercap/arm_scmi_powercap.c
> F: drivers/regulator/scmi-regulator.c
> diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index
> d45657aa986a..4e6f65cf0e76 100644
> --- a/drivers/pinctrl/Kconfig
> +++ b/drivers/pinctrl/Kconfig
> @@ -450,6 +450,17 @@ config PINCTRL_ROCKCHIP
> help
> This support pinctrl and GPIO driver for Rockchip SoCs.
>
> +config PINCTRL_SCMI
> + tristate "Pinctrl driver using SCMI protocol interface"
> + depends on ARM_SCMI_PROTOCOL || COMPILE_TEST
> + select PINMUX
> + select GENERIC_PINCONF
> + help
> + This driver provides support for pinctrl which is controlled
> + by firmware that implements the SCMI interface.
> + It uses SCMI Message Protocol to interact with the
> + firmware providing all the pinctrl controls.
> +
> config PINCTRL_SINGLE
> tristate "One-register-per-pin type device tree based pinctrl driver"
> depends on OF
> diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile index
> 2152539b53d5..cc809669405a 100644
> --- a/drivers/pinctrl/Makefile
> +++ b/drivers/pinctrl/Makefile
> @@ -45,6 +45,7 @@ obj-$(CONFIG_PINCTRL_PIC32) += pinctrl-pic32.o
> obj-$(CONFIG_PINCTRL_PISTACHIO) += pinctrl-pistachio.o
> obj-$(CONFIG_PINCTRL_RK805) += pinctrl-rk805.o
> obj-$(CONFIG_PINCTRL_ROCKCHIP) += pinctrl-rockchip.o
> +obj-$(CONFIG_PINCTRL_SCMI) += pinctrl-scmi.o
> obj-$(CONFIG_PINCTRL_SINGLE) += pinctrl-single.o
> obj-$(CONFIG_PINCTRL_ST) += pinctrl-st.o
> obj-$(CONFIG_PINCTRL_STMFX) += pinctrl-stmfx.o
> diff --git a/drivers/pinctrl/pinctrl-scmi.c b/drivers/pinctrl/pinctrl-scmi.c new
> file mode 100644 index 000000000000..0f55f000a679
> --- /dev/null
> +++ b/drivers/pinctrl/pinctrl-scmi.c
> @@ -0,0 +1,564 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * System Control and Power Interface (SCMI) Protocol based pinctrl
> +driver
> + *
> + * Copyright (C) 2024 EPAM
> + * Copyright 2024 NXP
> + */
> +
> +#include <linux/device.h>
> +#include <linux/dev_printk.h>
> +#include <linux/err.h>
> +#include <linux/module.h>
> +#include <linux/scmi_protocol.h>
> +#include <linux/slab.h>
> +#include <linux/types.h>
> +
> +#include <linux/pinctrl/machine.h>
> +#include <linux/pinctrl/pinconf.h>
> +#include <linux/pinctrl/pinconf-generic.h> #include
> +<linux/pinctrl/pinctrl.h> #include <linux/pinctrl/pinmux.h>
> +
> +#include "pinctrl-utils.h"
> +#include "core.h"
> +#include "pinconf.h"
> +
> +#define DRV_NAME "scmi-pinctrl"
> +
> +/* Define num configs, if not large than 4 use stack, else use kcalloc */
> +#define SCMI_NUM_CONFIGS 4
> +
> +static const struct scmi_pinctrl_proto_ops *pinctrl_ops;
> +
> +struct scmi_pinctrl {
> + struct device *dev;
> + struct scmi_protocol_handle *ph;
> + struct pinctrl_dev *pctldev;
> + struct pinctrl_desc pctl_desc;
> + struct pinfunction *functions;
> + unsigned int nr_functions;
> + struct pinctrl_pin_desc *pins;
> + unsigned int nr_pins;
> +};
> +
> +static int pinctrl_scmi_get_groups_count(struct pinctrl_dev *pctldev) {
> + struct scmi_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
> +
> + return pinctrl_ops->count_get(pmx->ph, GROUP_TYPE); }
> +
> +static const char *pinctrl_scmi_get_group_name(struct pinctrl_dev *pctldev,
> + unsigned int selector)
> +{
> + int ret;
> + const char *name;
> + struct scmi_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
> +
> + ret = pinctrl_ops->name_get(pmx->ph, selector, GROUP_TYPE,
> &name);
> + if (ret) {
> + dev_err(pmx->dev, "get name failed with err %d", ret);
> + return NULL;
> + }
> +
> + return name;
> +}
> +
> +static int pinctrl_scmi_get_group_pins(struct pinctrl_dev *pctldev,
> + unsigned int selector,
> + const unsigned int **pins,
> + unsigned int *num_pins)
> +{
> + struct scmi_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
> +
> + return pinctrl_ops->group_pins_get(pmx->ph, selector, pins,
> num_pins);
> +}
> +
> +static const struct pinctrl_ops pinctrl_scmi_pinctrl_ops = {
> + .get_groups_count = pinctrl_scmi_get_groups_count,
> + .get_group_name = pinctrl_scmi_get_group_name,
> + .get_group_pins = pinctrl_scmi_get_group_pins, #ifdef CONFIG_OF
> + .dt_node_to_map = pinconf_generic_dt_node_to_map_all,
> + .dt_free_map = pinconf_generic_dt_free_map, #endif };
> +
> +static int pinctrl_scmi_get_functions_count(struct pinctrl_dev
> +*pctldev) {
> + struct scmi_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
> +
> + return pinctrl_ops->count_get(pmx->ph, FUNCTION_TYPE); }
> +
> +static const char *pinctrl_scmi_get_function_name(struct pinctrl_dev
> *pctldev,
> + unsigned int selector)
> +{
> + int ret;
> + const char *name;
> + struct scmi_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
> +
> + ret = pinctrl_ops->name_get(pmx->ph, selector, FUNCTION_TYPE,
> &name);
> + if (ret) {
> + dev_err(pmx->dev, "get name failed with err %d", ret);
> + return NULL;
> + }
> +
> + return name;
> +}
> +
> +static int pinctrl_scmi_get_function_groups(struct pinctrl_dev *pctldev,
> + unsigned int selector,
> + const char * const **p_groups,
> + unsigned int * const
> p_num_groups) {
> + struct pinfunction *func;
> + const unsigned int *group_ids;
> + unsigned int num_groups;
> + const char **groups;
> + int ret, i;
> + struct scmi_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
> +
> + if (!p_groups || !p_num_groups)
> + return -EINVAL;
> +
> + if (selector >= pmx->nr_functions)
> + return -EINVAL;
> +
> + func = &pmx->functions[selector];
> + if (func->ngroups)
> + goto done;
> +
> + ret = pinctrl_ops->function_groups_get(pmx->ph, selector,
> &num_groups,
> + &group_ids);
> + if (ret) {
> + dev_err(pmx->dev, "Unable to get function groups, err %d",
> ret);
> + return ret;
> + }
> + if (!num_groups)
> + return -EINVAL;
> +
> + groups = kcalloc(num_groups, sizeof(*groups), GFP_KERNEL);
> + if (!groups)
> + return -ENOMEM;
> +
> + for (i = 0; i < num_groups; i++) {
> + groups[i] = pinctrl_scmi_get_group_name(pctldev,
> group_ids[i]);
> + if (!groups[i]) {
> + ret = -EINVAL;
> + goto err_free;
> + }
> + }
> +
> + func->ngroups = num_groups;
> + func->groups = groups;
> +done:
> + *p_groups = func->groups;
> + *p_num_groups = func->ngroups;
> +
> + return 0;
> +
> +err_free:
> + kfree(groups);
> +
> + return ret;
> +}
> +
> +static int pinctrl_scmi_func_set_mux(struct pinctrl_dev *pctldev,
> + unsigned int selector, unsigned int group)
> {
> + struct scmi_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
> +
> + return pinctrl_ops->mux_set(pmx->ph, selector, group); }
> +
> +static int pinctrl_scmi_request(struct pinctrl_dev *pctldev,
> + unsigned int offset)
> +{
> + struct scmi_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
> +
> + return pinctrl_ops->pin_request(pmx->ph, offset); }
> +
> +static int pinctrl_scmi_free(struct pinctrl_dev *pctldev, unsigned int
> +offset) {
> + struct scmi_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
> +
> + return pinctrl_ops->pin_free(pmx->ph, offset); }
> +
> +static const struct pinmux_ops pinctrl_scmi_pinmux_ops = {
> + .request = pinctrl_scmi_request,
> + .free = pinctrl_scmi_free,
> + .get_functions_count = pinctrl_scmi_get_functions_count,
> + .get_function_name = pinctrl_scmi_get_function_name,
> + .get_function_groups = pinctrl_scmi_get_function_groups,
> + .set_mux = pinctrl_scmi_func_set_mux,
> +};
> +
> +static int pinctrl_scmi_map_pinconf_type(enum pin_config_param param,
> + enum scmi_pinctrl_conf_type
> *type) {
> + u32 arg = param;
> +
> + switch (arg) {
> + case PIN_CONFIG_BIAS_BUS_HOLD:
> + *type = SCMI_PIN_BIAS_BUS_HOLD;
> + break;
> + case PIN_CONFIG_BIAS_DISABLE:
> + *type = SCMI_PIN_BIAS_DISABLE;
> + break;
> + case PIN_CONFIG_BIAS_HIGH_IMPEDANCE:
> + *type = SCMI_PIN_BIAS_HIGH_IMPEDANCE;
> + break;
> + case PIN_CONFIG_BIAS_PULL_DOWN:
> + *type = SCMI_PIN_BIAS_PULL_DOWN;
> + break;
> + case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT:
> + *type = SCMI_PIN_BIAS_PULL_DEFAULT;
> + break;
> + case PIN_CONFIG_BIAS_PULL_UP:
> + *type = SCMI_PIN_BIAS_PULL_UP;
> + break;
> + case PIN_CONFIG_DRIVE_OPEN_DRAIN:
> + *type = SCMI_PIN_DRIVE_OPEN_DRAIN;
> + break;
> + case PIN_CONFIG_DRIVE_OPEN_SOURCE:
> + *type = SCMI_PIN_DRIVE_OPEN_SOURCE;
> + break;
> + case PIN_CONFIG_DRIVE_PUSH_PULL:
> + *type = SCMI_PIN_DRIVE_PUSH_PULL;
> + break;
> + case PIN_CONFIG_DRIVE_STRENGTH:
> + *type = SCMI_PIN_DRIVE_STRENGTH;
> + break;
> + case PIN_CONFIG_DRIVE_STRENGTH_UA:
> + *type = SCMI_PIN_DRIVE_STRENGTH;
> + break;
> + case PIN_CONFIG_INPUT_DEBOUNCE:
> + *type = SCMI_PIN_INPUT_DEBOUNCE;
> + break;
> + case PIN_CONFIG_INPUT_ENABLE:
> + *type = SCMI_PIN_INPUT_MODE;
> + break;
> + case PIN_CONFIG_INPUT_SCHMITT:
> + *type = SCMI_PIN_INPUT_SCHMITT;
> + break;
> + case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
> + *type = SCMI_PIN_INPUT_MODE;
> + break;
> + case PIN_CONFIG_MODE_LOW_POWER:
> + *type = SCMI_PIN_LOW_POWER_MODE;
> + break;
> + case PIN_CONFIG_OUTPUT:
> + *type = SCMI_PIN_OUTPUT_VALUE;
> + break;
> + case PIN_CONFIG_OUTPUT_ENABLE:
> + *type = SCMI_PIN_OUTPUT_MODE;
> + break;
> + case PIN_CONFIG_OUTPUT_IMPEDANCE_OHMS:
> + *type = SCMI_PIN_OUTPUT_VALUE;
> + break;
> + case PIN_CONFIG_POWER_SOURCE:
> + *type = SCMI_PIN_POWER_SOURCE;
> + break;
> + case PIN_CONFIG_SLEW_RATE:
> + *type = SCMI_PIN_SLEW_RATE;
> + break;
> + case SCMI_PIN_OEM_START ... SCMI_PIN_OEM_END:
> + *type = arg;
> + break;
> + default:
> + return -EINVAL;
> + }
> +
> + return 0;
> +}
> +
> +static int pinctrl_scmi_pinconf_get(struct pinctrl_dev *pctldev,
> + unsigned int pin, unsigned long *config) {
> + int ret;
> + struct scmi_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
> + enum pin_config_param config_type;
> + enum scmi_pinctrl_conf_type type;
> + u32 config_value;
> +
> + if (!config)
> + return -EINVAL;
> +
> + config_type = pinconf_to_config_param(*config);
> +
> + ret = pinctrl_scmi_map_pinconf_type(config_type, &type);
> + if (ret)
> + return ret;
> +
> + ret = pinctrl_ops->settings_get_one(pmx->ph, pin, PIN_TYPE, type,
> + &config_value);
> + if (ret)
> + return ret;
> +
> + *config = pinconf_to_config_packed(config_type, config_value);
> +
> + return 0;
> +}
> +
> +static int
> +pinctrl_scmi_alloc_configs(struct pinctrl_dev *pctldev, u32 num_configs,
> + u32 **p_config_value,
> + enum scmi_pinctrl_conf_type **p_config_type) {
> + if (num_configs <= SCMI_NUM_CONFIGS)
> + return 0;
> +
> + *p_config_value = kcalloc(num_configs, sizeof(**p_config_value),
> GFP_KERNEL);
> + if (!*p_config_value)
> + return -ENOMEM;
> +
> + *p_config_type = kcalloc(num_configs, sizeof(**p_config_type),
> GFP_KERNEL);
> + if (!*p_config_type) {
> + kfree(*p_config_value);
> + return -ENOMEM;
> + }
> +
> + return 0;
> +}
> +
> +static void
> +pinctrl_scmi_free_configs(struct pinctrl_dev *pctldev, u32 num_configs,
> + u32 **p_config_value,
> + enum scmi_pinctrl_conf_type **p_config_type) {
> + if (num_configs <= SCMI_NUM_CONFIGS)
> + return;
> +
> + kfree(*p_config_value);
> + kfree(*p_config_type);
> +}
> +
> +static int pinctrl_scmi_pinconf_set(struct pinctrl_dev *pctldev,
> + unsigned int pin,
> + unsigned long *configs,
> + unsigned int num_configs)
> +{
> + int i, ret;
> + struct scmi_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
> + enum scmi_pinctrl_conf_type config_type[SCMI_NUM_CONFIGS];
> + u32 config_value[SCMI_NUM_CONFIGS];
> + enum scmi_pinctrl_conf_type *p_config_type = config_type;
> + u32 *p_config_value = config_value;
> + enum pin_config_param param;
> +
> + if (!configs || !num_configs)
> + return -EINVAL;
> +
> + ret = pinctrl_scmi_alloc_configs(pctldev, num_configs,
> &p_config_type,
> + &p_config_value);
> + if (ret)
> + return ret;
> +
> + for (i = 0; i < num_configs; i++) {
> + param = pinconf_to_config_param(configs[i]);
> + ret = pinctrl_scmi_map_pinconf_type(param,
> &p_config_type[i]);
> + if (ret) {
> + dev_err(pmx->dev, "Error map pinconf_type %d\n",
> ret);
> + goto free_config;
> + }
> + p_config_value[i] = pinconf_to_config_argument(configs[i]);
> + }
> +
> + ret = pinctrl_ops->settings_conf(pmx->ph, pin, PIN_TYPE,
> num_configs,
> + p_config_type, p_config_value);
> + if (ret)
> + dev_err(pmx->dev, "Error parsing config %d\n", ret);
> +
> +free_config:
> + pinctrl_scmi_free_configs(pctldev, num_configs, &p_config_type,
> + &p_config_value);
> + return ret;
> +}
> +
> +static int pinctrl_scmi_pinconf_group_set(struct pinctrl_dev *pctldev,
> + unsigned int group,
> + unsigned long *configs,
> + unsigned int num_configs)
> +{
> + int i, ret;
> + struct scmi_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
> + enum scmi_pinctrl_conf_type config_type[SCMI_NUM_CONFIGS];
> + u32 config_value[SCMI_NUM_CONFIGS];
> + enum scmi_pinctrl_conf_type *p_config_type = config_type;
> + u32 *p_config_value = config_value;
> + enum pin_config_param param;
> +
> + if (!configs || !num_configs)
> + return -EINVAL;
> +
> + ret = pinctrl_scmi_alloc_configs(pctldev, num_configs,
> &p_config_type,
> + &p_config_value);
> + if (ret)
> + return ret;
> +
> + for (i = 0; i < num_configs; i++) {
> + param = pinconf_to_config_param(configs[i]);
> + ret = pinctrl_scmi_map_pinconf_type(param,
> &p_config_type[i]);
> + if (ret) {
> + dev_err(pmx->dev, "Error map pinconf_type %d\n",
> ret);
> + goto free_config;
> + }
> +
> + p_config_value[i] = pinconf_to_config_argument(configs[i]);
> + }
> +
> + ret = pinctrl_ops->settings_conf(pmx->ph, group, GROUP_TYPE,
> + num_configs, p_config_type,
> + p_config_value);
> + if (ret)
> + dev_err(pmx->dev, "Error parsing config %d", ret);
> +
> +free_config:
> + pinctrl_scmi_free_configs(pctldev, num_configs, &p_config_type,
> + &p_config_value);
> + return ret;
> +};
> +
> +static int pinctrl_scmi_pinconf_group_get(struct pinctrl_dev *pctldev,
> + unsigned int group,
> + unsigned long *config)
> +{
> + int ret;
> + struct scmi_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
> + enum pin_config_param config_type;
> + enum scmi_pinctrl_conf_type type;
> + u32 config_value;
> +
> + if (!config)
> + return -EINVAL;
> +
> + config_type = pinconf_to_config_param(*config);
> + ret = pinctrl_scmi_map_pinconf_type(config_type, &type);
> + if (ret) {
> + dev_err(pmx->dev, "Error map pinconf_type %d\n", ret);
> + return ret;
> + }
> +
> + ret = pinctrl_ops->settings_get_one(pmx->ph, group, GROUP_TYPE,
> type,
> + &config_value);
> + if (ret)
> + return ret;
> +
> + *config = pinconf_to_config_packed(config_type, config_value);
> +
> + return 0;
> +}
> +
> +static const struct pinconf_ops pinctrl_scmi_pinconf_ops = {
> + .is_generic = true,
> + .pin_config_get = pinctrl_scmi_pinconf_get,
> + .pin_config_set = pinctrl_scmi_pinconf_set,
> + .pin_config_group_set = pinctrl_scmi_pinconf_group_set,
> + .pin_config_group_get = pinctrl_scmi_pinconf_group_get,
> + .pin_config_config_dbg_show = pinconf_generic_dump_config, };
> +
> +static int pinctrl_scmi_get_pins(struct scmi_pinctrl *pmx,
> + struct pinctrl_desc *desc)
> +{
> + struct pinctrl_pin_desc *pins;
> + unsigned int npins;
> + int ret, i;
> +
> + npins = pinctrl_ops->count_get(pmx->ph, PIN_TYPE);
> + /*
> + * npins will never be zero, the scmi pinctrl driver has bailed out
> + * if npins is zero.
> + */
> + pins = devm_kmalloc_array(pmx->dev, npins, sizeof(*pins),
> GFP_KERNEL);
> + if (!pins)
> + return -ENOMEM;
> +
> + for (i = 0; i < npins; i++) {
> + pins[i].number = i;
> + /*
> + * The memory for name is handled by the scmi firmware
> driver,
> + * no need free here
> + */
> + ret = pinctrl_ops->name_get(pmx->ph, i, PIN_TYPE,
> &pins[i].name);
> + if (ret)
> + return dev_err_probe(pmx->dev, ret,
> + "Can't get name for pin %d", i);
> + }
> +
> + desc->npins = npins;
> + desc->pins = pins;
> + dev_dbg(pmx->dev, "got pins %u", npins);
> +
> + return 0;
> +}
> +
> +static int scmi_pinctrl_probe(struct scmi_device *sdev) {
> + int ret;
> + struct device *dev = &sdev->dev;
> + struct scmi_pinctrl *pmx;
> + const struct scmi_handle *handle;
> + struct scmi_protocol_handle *ph;
> +
> + if (!sdev->handle)
> + return -EINVAL;
> +
> + handle = sdev->handle;
> +
> + pinctrl_ops = handle->devm_protocol_get(sdev,
> SCMI_PROTOCOL_PINCTRL, &ph);
> + if (IS_ERR(pinctrl_ops))
> + return PTR_ERR(pinctrl_ops);
> +
> + pmx = devm_kzalloc(dev, sizeof(*pmx), GFP_KERNEL);
> + if (!pmx)
> + return -ENOMEM;
> +
> + pmx->ph = ph;
> +
> + pmx->dev = dev;
> + pmx->pctl_desc.name = DRV_NAME;
> + pmx->pctl_desc.owner = THIS_MODULE;
> + pmx->pctl_desc.pctlops = &pinctrl_scmi_pinctrl_ops;
> + pmx->pctl_desc.pmxops = &pinctrl_scmi_pinmux_ops;
> + pmx->pctl_desc.confops = &pinctrl_scmi_pinconf_ops;
> +
> + ret = pinctrl_scmi_get_pins(pmx, &pmx->pctl_desc);
> + if (ret)
> + return ret;
> +
> + ret = devm_pinctrl_register_and_init(dev, &pmx->pctl_desc, pmx,
> + &pmx->pctldev);
> + if (ret)
> + return dev_err_probe(dev, ret, "Failed to register pinctrl\n");
> +
> + pmx->nr_functions = pinctrl_scmi_get_functions_count(pmx-
> >pctldev);
> + pmx->functions = devm_kcalloc(dev, pmx->nr_functions,
> + sizeof(*pmx->functions), GFP_KERNEL);
> + if (!pmx->functions)
> + return -ENOMEM;
> +
> + return pinctrl_enable(pmx->pctldev);
> +}
> +
> +static const struct scmi_device_id scmi_id_table[] = {
> + { SCMI_PROTOCOL_PINCTRL, "pinctrl" },
> + { }
> +};
> +MODULE_DEVICE_TABLE(scmi, scmi_id_table);
> +
> +static struct scmi_driver scmi_pinctrl_driver = {
> + .name = DRV_NAME,
> + .probe = scmi_pinctrl_probe,
> + .id_table = scmi_id_table,
> +};
> +module_scmi_driver(scmi_pinctrl_driver);
> +
> +MODULE_AUTHOR("Oleksii Moisieiev <oleksii_moisieiev@epam.com>");
> +MODULE_AUTHOR("Peng Fan <peng.fan@nxp.com>");
> MODULE_DESCRIPTION("ARM
> +SCMI pin controller driver"); MODULE_LICENSE("GPL");
>
> --
> 2.37.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* Re: [RESPIN PATCH] irqchip/gic-v4.1:Fix VSYNC referencing an unmapped VPE
From: Zenghui Yu @ 2024-04-07 3:40 UTC (permalink / raw)
To: Nianyao Tang
Cc: maz, tglx, linux-arm-kernel, linux-kernel, guoyang2, wangwudi
In-Reply-To: <20240406022737.3898763-1-tangnianyao@huawei.com>
On 2024/4/6 10:27, Nianyao Tang wrote:
> As per the GICv4.1 spec (Arm IHI 0069H, 5.3.19):
>
> "A VMAPP with {V, Alloc}=={0, x} is self-synchronizing, This means the
> ITS command queue does not show the command as consumed until all of
> its effects are completed."
>
> Furthermore, VSYNC is allowed to deliver an SError when referencing a
> non existent VPE.
>
> By these definitions, a VMAPP followed by a VSYNC is a bug, as the
> later references a VPE that has been unmapped by the former.
>
> Fix it by eliding the VSYNC in this scenario.
>
> Fixes: 64edfaa9a234 ("irqchip/gic-v4.1: Implement the v4.1 flavour of VMAPP")
>
> Signed-off-by: Nianyao Tang <tangnianyao@huawei.com>
> Reviewed-by: Marc Zyngier <maz@kernel.org>
Reviewed-by: Zenghui Yu <yuzenghui@huawei.com>
Thanks.
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH 1/4] KVM: delete .change_pte MMU notifier callback
From: Anup Patel @ 2024-04-07 4:50 UTC (permalink / raw)
To: Paolo Bonzini
Cc: linux-kernel, kvm, Marc Zyngier, Oliver Upton, Tianrui Zhao,
Bibo Mao, Thomas Bogendoerfer, Nicholas Piggin, Atish Patra,
Sean Christopherson, Andrew Morton, David Hildenbrand,
linux-arm-kernel, kvmarm, loongarch, linux-mips, linuxppc-dev,
kvm-riscv, linux-mm, linux-trace-kernel, linux-perf-users
In-Reply-To: <20240405115815.3226315-2-pbonzini@redhat.com>
On Fri, Apr 5, 2024 at 5:28 PM Paolo Bonzini <pbonzini@redhat.com> wrote:
>
> The .change_pte() MMU notifier callback was intended as an
> optimization. The original point of it was that KSM could tell KVM to flip
> its secondary PTE to a new location without having to first zap it. At
> the time there was also an .invalidate_page() callback; both of them were
> *not* bracketed by calls to mmu_notifier_invalidate_range_{start,end}(),
> and .invalidate_page() also doubled as a fallback implementation of
> .change_pte().
>
> Later on, however, both callbacks were changed to occur within an
> invalidate_range_start/end() block.
>
> In the case of .change_pte(), commit 6bdb913f0a70 ("mm: wrap calls to
> set_pte_at_notify with invalidate_range_start and invalidate_range_end",
> 2012-10-09) did so to remove the fallback from .invalidate_page() to
> .change_pte() and allow sleepable .invalidate_page() hooks.
>
> This however made KVM's usage of the .change_pte() callback completely
> moot, because KVM unmaps the sPTEs during .invalidate_range_start()
> and therefore .change_pte() has no hope of finding a sPTE to change.
> Drop the generic KVM code that dispatches to kvm_set_spte_gfn(), as
> well as all the architecture specific implementations.
>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
For KVM RISC-V:
Acked-by: Anup Patel <anup@brainfault.org>
Regards,
Anup
> ---
> arch/arm64/kvm/mmu.c | 34 -----------------
> arch/loongarch/include/asm/kvm_host.h | 1 -
> arch/loongarch/kvm/mmu.c | 32 ----------------
> arch/mips/kvm/mmu.c | 30 ---------------
> arch/powerpc/include/asm/kvm_ppc.h | 1 -
> arch/powerpc/kvm/book3s.c | 5 ---
> arch/powerpc/kvm/book3s.h | 1 -
> arch/powerpc/kvm/book3s_64_mmu_hv.c | 12 ------
> arch/powerpc/kvm/book3s_hv.c | 1 -
> arch/powerpc/kvm/book3s_pr.c | 7 ----
> arch/powerpc/kvm/e500_mmu_host.c | 6 ---
> arch/riscv/kvm/mmu.c | 20 ----------
> arch/x86/kvm/mmu/mmu.c | 54 +--------------------------
> arch/x86/kvm/mmu/spte.c | 16 --------
> arch/x86/kvm/mmu/spte.h | 2 -
> arch/x86/kvm/mmu/tdp_mmu.c | 46 -----------------------
> arch/x86/kvm/mmu/tdp_mmu.h | 1 -
> include/linux/kvm_host.h | 2 -
> include/trace/events/kvm.h | 15 --------
> virt/kvm/kvm_main.c | 43 ---------------------
> 20 files changed, 2 insertions(+), 327 deletions(-)
>
> diff --git a/arch/arm64/kvm/mmu.c b/arch/arm64/kvm/mmu.c
> index dc04bc767865..ff17849be9f4 100644
> --- a/arch/arm64/kvm/mmu.c
> +++ b/arch/arm64/kvm/mmu.c
> @@ -1768,40 +1768,6 @@ bool kvm_unmap_gfn_range(struct kvm *kvm, struct kvm_gfn_range *range)
> return false;
> }
>
> -bool kvm_set_spte_gfn(struct kvm *kvm, struct kvm_gfn_range *range)
> -{
> - kvm_pfn_t pfn = pte_pfn(range->arg.pte);
> -
> - if (!kvm->arch.mmu.pgt)
> - return false;
> -
> - WARN_ON(range->end - range->start != 1);
> -
> - /*
> - * If the page isn't tagged, defer to user_mem_abort() for sanitising
> - * the MTE tags. The S2 pte should have been unmapped by
> - * mmu_notifier_invalidate_range_end().
> - */
> - if (kvm_has_mte(kvm) && !page_mte_tagged(pfn_to_page(pfn)))
> - return false;
> -
> - /*
> - * We've moved a page around, probably through CoW, so let's treat
> - * it just like a translation fault and the map handler will clean
> - * the cache to the PoC.
> - *
> - * The MMU notifiers will have unmapped a huge PMD before calling
> - * ->change_pte() (which in turn calls kvm_set_spte_gfn()) and
> - * therefore we never need to clear out a huge PMD through this
> - * calling path and a memcache is not required.
> - */
> - kvm_pgtable_stage2_map(kvm->arch.mmu.pgt, range->start << PAGE_SHIFT,
> - PAGE_SIZE, __pfn_to_phys(pfn),
> - KVM_PGTABLE_PROT_R, NULL, 0);
> -
> - return false;
> -}
> -
> bool kvm_age_gfn(struct kvm *kvm, struct kvm_gfn_range *range)
> {
> u64 size = (range->end - range->start) << PAGE_SHIFT;
> diff --git a/arch/loongarch/include/asm/kvm_host.h b/arch/loongarch/include/asm/kvm_host.h
> index 2d62f7b0d377..69305441f40d 100644
> --- a/arch/loongarch/include/asm/kvm_host.h
> +++ b/arch/loongarch/include/asm/kvm_host.h
> @@ -203,7 +203,6 @@ void kvm_flush_tlb_all(void);
> void kvm_flush_tlb_gpa(struct kvm_vcpu *vcpu, unsigned long gpa);
> int kvm_handle_mm_fault(struct kvm_vcpu *vcpu, unsigned long badv, bool write);
>
> -void kvm_set_spte_hva(struct kvm *kvm, unsigned long hva, pte_t pte);
> int kvm_unmap_hva_range(struct kvm *kvm, unsigned long start, unsigned long end, bool blockable);
> int kvm_age_hva(struct kvm *kvm, unsigned long start, unsigned long end);
> int kvm_test_age_hva(struct kvm *kvm, unsigned long hva);
> diff --git a/arch/loongarch/kvm/mmu.c b/arch/loongarch/kvm/mmu.c
> index a556cff35740..98883aa23ab8 100644
> --- a/arch/loongarch/kvm/mmu.c
> +++ b/arch/loongarch/kvm/mmu.c
> @@ -494,38 +494,6 @@ bool kvm_unmap_gfn_range(struct kvm *kvm, struct kvm_gfn_range *range)
> range->end << PAGE_SHIFT, &ctx);
> }
>
> -bool kvm_set_spte_gfn(struct kvm *kvm, struct kvm_gfn_range *range)
> -{
> - unsigned long prot_bits;
> - kvm_pte_t *ptep;
> - kvm_pfn_t pfn = pte_pfn(range->arg.pte);
> - gpa_t gpa = range->start << PAGE_SHIFT;
> -
> - ptep = kvm_populate_gpa(kvm, NULL, gpa, 0);
> - if (!ptep)
> - return false;
> -
> - /* Replacing an absent or old page doesn't need flushes */
> - if (!kvm_pte_present(NULL, ptep) || !kvm_pte_young(*ptep)) {
> - kvm_set_pte(ptep, 0);
> - return false;
> - }
> -
> - /* Fill new pte if write protected or page migrated */
> - prot_bits = _PAGE_PRESENT | __READABLE;
> - prot_bits |= _CACHE_MASK & pte_val(range->arg.pte);
> -
> - /*
> - * Set _PAGE_WRITE or _PAGE_DIRTY iff old and new pte both support
> - * _PAGE_WRITE for map_page_fast if next page write fault
> - * _PAGE_DIRTY since gpa has already recorded as dirty page
> - */
> - prot_bits |= __WRITEABLE & *ptep & pte_val(range->arg.pte);
> - kvm_set_pte(ptep, kvm_pfn_pte(pfn, __pgprot(prot_bits)));
> -
> - return true;
> -}
> -
> bool kvm_age_gfn(struct kvm *kvm, struct kvm_gfn_range *range)
> {
> kvm_ptw_ctx ctx;
> diff --git a/arch/mips/kvm/mmu.c b/arch/mips/kvm/mmu.c
> index 467ee6b95ae1..c17157e700c0 100644
> --- a/arch/mips/kvm/mmu.c
> +++ b/arch/mips/kvm/mmu.c
> @@ -444,36 +444,6 @@ bool kvm_unmap_gfn_range(struct kvm *kvm, struct kvm_gfn_range *range)
> return true;
> }
>
> -bool kvm_set_spte_gfn(struct kvm *kvm, struct kvm_gfn_range *range)
> -{
> - gpa_t gpa = range->start << PAGE_SHIFT;
> - pte_t hva_pte = range->arg.pte;
> - pte_t *gpa_pte = kvm_mips_pte_for_gpa(kvm, NULL, gpa);
> - pte_t old_pte;
> -
> - if (!gpa_pte)
> - return false;
> -
> - /* Mapping may need adjusting depending on memslot flags */
> - old_pte = *gpa_pte;
> - if (range->slot->flags & KVM_MEM_LOG_DIRTY_PAGES && !pte_dirty(old_pte))
> - hva_pte = pte_mkclean(hva_pte);
> - else if (range->slot->flags & KVM_MEM_READONLY)
> - hva_pte = pte_wrprotect(hva_pte);
> -
> - set_pte(gpa_pte, hva_pte);
> -
> - /* Replacing an absent or old page doesn't need flushes */
> - if (!pte_present(old_pte) || !pte_young(old_pte))
> - return false;
> -
> - /* Pages swapped, aged, moved, or cleaned require flushes */
> - return !pte_present(hva_pte) ||
> - !pte_young(hva_pte) ||
> - pte_pfn(old_pte) != pte_pfn(hva_pte) ||
> - (pte_dirty(old_pte) && !pte_dirty(hva_pte));
> -}
> -
> bool kvm_age_gfn(struct kvm *kvm, struct kvm_gfn_range *range)
> {
> return kvm_mips_mkold_gpa_pt(kvm, range->start, range->end);
> diff --git a/arch/powerpc/include/asm/kvm_ppc.h b/arch/powerpc/include/asm/kvm_ppc.h
> index 3281215097cc..ca3829d47ab7 100644
> --- a/arch/powerpc/include/asm/kvm_ppc.h
> +++ b/arch/powerpc/include/asm/kvm_ppc.h
> @@ -287,7 +287,6 @@ struct kvmppc_ops {
> bool (*unmap_gfn_range)(struct kvm *kvm, struct kvm_gfn_range *range);
> bool (*age_gfn)(struct kvm *kvm, struct kvm_gfn_range *range);
> bool (*test_age_gfn)(struct kvm *kvm, struct kvm_gfn_range *range);
> - bool (*set_spte_gfn)(struct kvm *kvm, struct kvm_gfn_range *range);
> void (*free_memslot)(struct kvm_memory_slot *slot);
> int (*init_vm)(struct kvm *kvm);
> void (*destroy_vm)(struct kvm *kvm);
> diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c
> index 8acec144120e..0d0624088e6b 100644
> --- a/arch/powerpc/kvm/book3s.c
> +++ b/arch/powerpc/kvm/book3s.c
> @@ -899,11 +899,6 @@ bool kvm_test_age_gfn(struct kvm *kvm, struct kvm_gfn_range *range)
> return kvm->arch.kvm_ops->test_age_gfn(kvm, range);
> }
>
> -bool kvm_set_spte_gfn(struct kvm *kvm, struct kvm_gfn_range *range)
> -{
> - return kvm->arch.kvm_ops->set_spte_gfn(kvm, range);
> -}
> -
> int kvmppc_core_init_vm(struct kvm *kvm)
> {
>
> diff --git a/arch/powerpc/kvm/book3s.h b/arch/powerpc/kvm/book3s.h
> index 58391b4b32ed..4aa2ab89afbc 100644
> --- a/arch/powerpc/kvm/book3s.h
> +++ b/arch/powerpc/kvm/book3s.h
> @@ -12,7 +12,6 @@ extern void kvmppc_core_flush_memslot_hv(struct kvm *kvm,
> extern bool kvm_unmap_gfn_range_hv(struct kvm *kvm, struct kvm_gfn_range *range);
> extern bool kvm_age_gfn_hv(struct kvm *kvm, struct kvm_gfn_range *range);
> extern bool kvm_test_age_gfn_hv(struct kvm *kvm, struct kvm_gfn_range *range);
> -extern bool kvm_set_spte_gfn_hv(struct kvm *kvm, struct kvm_gfn_range *range);
>
> extern int kvmppc_mmu_init_pr(struct kvm_vcpu *vcpu);
> extern void kvmppc_mmu_destroy_pr(struct kvm_vcpu *vcpu);
> diff --git a/arch/powerpc/kvm/book3s_64_mmu_hv.c b/arch/powerpc/kvm/book3s_64_mmu_hv.c
> index 2b1f0cdd8c18..1b51b1c4713b 100644
> --- a/arch/powerpc/kvm/book3s_64_mmu_hv.c
> +++ b/arch/powerpc/kvm/book3s_64_mmu_hv.c
> @@ -1010,18 +1010,6 @@ bool kvm_test_age_gfn_hv(struct kvm *kvm, struct kvm_gfn_range *range)
> return kvm_test_age_rmapp(kvm, range->slot, range->start);
> }
>
> -bool kvm_set_spte_gfn_hv(struct kvm *kvm, struct kvm_gfn_range *range)
> -{
> - WARN_ON(range->start + 1 != range->end);
> -
> - if (kvm_is_radix(kvm))
> - kvm_unmap_radix(kvm, range->slot, range->start);
> - else
> - kvm_unmap_rmapp(kvm, range->slot, range->start);
> -
> - return false;
> -}
> -
> static int vcpus_running(struct kvm *kvm)
> {
> return atomic_read(&kvm->arch.vcpus_running) != 0;
> diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
> index 8e86eb577eb8..35cb014a0c51 100644
> --- a/arch/powerpc/kvm/book3s_hv.c
> +++ b/arch/powerpc/kvm/book3s_hv.c
> @@ -6364,7 +6364,6 @@ static struct kvmppc_ops kvm_ops_hv = {
> .unmap_gfn_range = kvm_unmap_gfn_range_hv,
> .age_gfn = kvm_age_gfn_hv,
> .test_age_gfn = kvm_test_age_gfn_hv,
> - .set_spte_gfn = kvm_set_spte_gfn_hv,
> .free_memslot = kvmppc_core_free_memslot_hv,
> .init_vm = kvmppc_core_init_vm_hv,
> .destroy_vm = kvmppc_core_destroy_vm_hv,
> diff --git a/arch/powerpc/kvm/book3s_pr.c b/arch/powerpc/kvm/book3s_pr.c
> index 5b92619a05fd..a7d7137ea0c8 100644
> --- a/arch/powerpc/kvm/book3s_pr.c
> +++ b/arch/powerpc/kvm/book3s_pr.c
> @@ -461,12 +461,6 @@ static bool kvm_test_age_gfn_pr(struct kvm *kvm, struct kvm_gfn_range *range)
> return false;
> }
>
> -static bool kvm_set_spte_gfn_pr(struct kvm *kvm, struct kvm_gfn_range *range)
> -{
> - /* The page will get remapped properly on its next fault */
> - return do_kvm_unmap_gfn(kvm, range);
> -}
> -
> /*****************************************/
>
> static void kvmppc_set_msr_pr(struct kvm_vcpu *vcpu, u64 msr)
> @@ -2071,7 +2065,6 @@ static struct kvmppc_ops kvm_ops_pr = {
> .unmap_gfn_range = kvm_unmap_gfn_range_pr,
> .age_gfn = kvm_age_gfn_pr,
> .test_age_gfn = kvm_test_age_gfn_pr,
> - .set_spte_gfn = kvm_set_spte_gfn_pr,
> .free_memslot = kvmppc_core_free_memslot_pr,
> .init_vm = kvmppc_core_init_vm_pr,
> .destroy_vm = kvmppc_core_destroy_vm_pr,
> diff --git a/arch/powerpc/kvm/e500_mmu_host.c b/arch/powerpc/kvm/e500_mmu_host.c
> index ccb8f16ffe41..c664fdec75b1 100644
> --- a/arch/powerpc/kvm/e500_mmu_host.c
> +++ b/arch/powerpc/kvm/e500_mmu_host.c
> @@ -747,12 +747,6 @@ bool kvm_test_age_gfn(struct kvm *kvm, struct kvm_gfn_range *range)
> return false;
> }
>
> -bool kvm_set_spte_gfn(struct kvm *kvm, struct kvm_gfn_range *range)
> -{
> - /* The page will get remapped properly on its next fault */
> - return kvm_e500_mmu_unmap_gfn(kvm, range);
> -}
> -
> /*****************************************/
>
> int e500_mmu_host_init(struct kvmppc_vcpu_e500 *vcpu_e500)
> diff --git a/arch/riscv/kvm/mmu.c b/arch/riscv/kvm/mmu.c
> index a9e2fd7245e1..b63650f9b966 100644
> --- a/arch/riscv/kvm/mmu.c
> +++ b/arch/riscv/kvm/mmu.c
> @@ -550,26 +550,6 @@ bool kvm_unmap_gfn_range(struct kvm *kvm, struct kvm_gfn_range *range)
> return false;
> }
>
> -bool kvm_set_spte_gfn(struct kvm *kvm, struct kvm_gfn_range *range)
> -{
> - int ret;
> - kvm_pfn_t pfn = pte_pfn(range->arg.pte);
> -
> - if (!kvm->arch.pgd)
> - return false;
> -
> - WARN_ON(range->end - range->start != 1);
> -
> - ret = gstage_map_page(kvm, NULL, range->start << PAGE_SHIFT,
> - __pfn_to_phys(pfn), PAGE_SIZE, true, true);
> - if (ret) {
> - kvm_debug("Failed to map G-stage page (error %d)\n", ret);
> - return true;
> - }
> -
> - return false;
> -}
> -
> bool kvm_age_gfn(struct kvm *kvm, struct kvm_gfn_range *range)
> {
> pte_t *ptep;
> diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c
> index 0049d49aa913..87ba2a9da196 100644
> --- a/arch/x86/kvm/mmu/mmu.c
> +++ b/arch/x86/kvm/mmu/mmu.c
> @@ -432,8 +432,8 @@ static u64 __update_clear_spte_slow(u64 *sptep, u64 spte)
> * The idea using the light way get the spte on x86_32 guest is from
> * gup_get_pte (mm/gup.c).
> *
> - * An spte tlb flush may be pending, because kvm_set_pte_rmap
> - * coalesces them and we are running out of the MMU lock. Therefore
> + * An spte tlb flush may be pending, because they are coalesced and
> + * we are running out of the MMU lock. Therefore
> * we need to protect against in-progress updates of the spte.
> *
> * Reading the spte while an update is in progress may get the old value
> @@ -1454,43 +1454,6 @@ static bool kvm_zap_rmap(struct kvm *kvm, struct kvm_rmap_head *rmap_head,
> return __kvm_zap_rmap(kvm, rmap_head, slot);
> }
>
> -static bool kvm_set_pte_rmap(struct kvm *kvm, struct kvm_rmap_head *rmap_head,
> - struct kvm_memory_slot *slot, gfn_t gfn, int level,
> - pte_t pte)
> -{
> - u64 *sptep;
> - struct rmap_iterator iter;
> - bool need_flush = false;
> - u64 new_spte;
> - kvm_pfn_t new_pfn;
> -
> - WARN_ON_ONCE(pte_huge(pte));
> - new_pfn = pte_pfn(pte);
> -
> -restart:
> - for_each_rmap_spte(rmap_head, &iter, sptep) {
> - need_flush = true;
> -
> - if (pte_write(pte)) {
> - kvm_zap_one_rmap_spte(kvm, rmap_head, sptep);
> - goto restart;
> - } else {
> - new_spte = kvm_mmu_changed_pte_notifier_make_spte(
> - *sptep, new_pfn);
> -
> - mmu_spte_clear_track_bits(kvm, sptep);
> - mmu_spte_set(sptep, new_spte);
> - }
> - }
> -
> - if (need_flush && kvm_available_flush_remote_tlbs_range()) {
> - kvm_flush_remote_tlbs_gfn(kvm, gfn, level);
> - return false;
> - }
> -
> - return need_flush;
> -}
> -
> struct slot_rmap_walk_iterator {
> /* input fields. */
> const struct kvm_memory_slot *slot;
> @@ -1596,19 +1559,6 @@ bool kvm_unmap_gfn_range(struct kvm *kvm, struct kvm_gfn_range *range)
> return flush;
> }
>
> -bool kvm_set_spte_gfn(struct kvm *kvm, struct kvm_gfn_range *range)
> -{
> - bool flush = false;
> -
> - if (kvm_memslots_have_rmaps(kvm))
> - flush = kvm_handle_gfn_range(kvm, range, kvm_set_pte_rmap);
> -
> - if (tdp_mmu_enabled)
> - flush |= kvm_tdp_mmu_set_spte_gfn(kvm, range);
> -
> - return flush;
> -}
> -
> static bool kvm_age_rmap(struct kvm *kvm, struct kvm_rmap_head *rmap_head,
> struct kvm_memory_slot *slot, gfn_t gfn, int level,
> pte_t unused)
> diff --git a/arch/x86/kvm/mmu/spte.c b/arch/x86/kvm/mmu/spte.c
> index 318135daf685..283af5b90016 100644
> --- a/arch/x86/kvm/mmu/spte.c
> +++ b/arch/x86/kvm/mmu/spte.c
> @@ -322,22 +322,6 @@ u64 make_nonleaf_spte(u64 *child_pt, bool ad_disabled)
> return spte;
> }
>
> -u64 kvm_mmu_changed_pte_notifier_make_spte(u64 old_spte, kvm_pfn_t new_pfn)
> -{
> - u64 new_spte;
> -
> - new_spte = old_spte & ~SPTE_BASE_ADDR_MASK;
> - new_spte |= (u64)new_pfn << PAGE_SHIFT;
> -
> - new_spte &= ~PT_WRITABLE_MASK;
> - new_spte &= ~shadow_host_writable_mask;
> - new_spte &= ~shadow_mmu_writable_mask;
> -
> - new_spte = mark_spte_for_access_track(new_spte);
> -
> - return new_spte;
> -}
> -
> u64 mark_spte_for_access_track(u64 spte)
> {
> if (spte_ad_enabled(spte))
> diff --git a/arch/x86/kvm/mmu/spte.h b/arch/x86/kvm/mmu/spte.h
> index 1a163aee9ec6..92da4c419171 100644
> --- a/arch/x86/kvm/mmu/spte.h
> +++ b/arch/x86/kvm/mmu/spte.h
> @@ -511,8 +511,6 @@ static inline u64 restore_acc_track_spte(u64 spte)
> return spte;
> }
>
> -u64 kvm_mmu_changed_pte_notifier_make_spte(u64 old_spte, kvm_pfn_t new_pfn);
> -
> void __init kvm_mmu_spte_module_init(void);
> void kvm_mmu_reset_all_pte_masks(void);
>
> diff --git a/arch/x86/kvm/mmu/tdp_mmu.c b/arch/x86/kvm/mmu/tdp_mmu.c
> index 3627744fcab6..fbb86932b766 100644
> --- a/arch/x86/kvm/mmu/tdp_mmu.c
> +++ b/arch/x86/kvm/mmu/tdp_mmu.c
> @@ -1250,52 +1250,6 @@ bool kvm_tdp_mmu_test_age_gfn(struct kvm *kvm, struct kvm_gfn_range *range)
> return kvm_tdp_mmu_handle_gfn(kvm, range, test_age_gfn);
> }
>
> -static bool set_spte_gfn(struct kvm *kvm, struct tdp_iter *iter,
> - struct kvm_gfn_range *range)
> -{
> - u64 new_spte;
> -
> - /* Huge pages aren't expected to be modified without first being zapped. */
> - WARN_ON_ONCE(pte_huge(range->arg.pte) || range->start + 1 != range->end);
> -
> - if (iter->level != PG_LEVEL_4K ||
> - !is_shadow_present_pte(iter->old_spte))
> - return false;
> -
> - /*
> - * Note, when changing a read-only SPTE, it's not strictly necessary to
> - * zero the SPTE before setting the new PFN, but doing so preserves the
> - * invariant that the PFN of a present * leaf SPTE can never change.
> - * See handle_changed_spte().
> - */
> - tdp_mmu_iter_set_spte(kvm, iter, SHADOW_NONPRESENT_VALUE);
> -
> - if (!pte_write(range->arg.pte)) {
> - new_spte = kvm_mmu_changed_pte_notifier_make_spte(iter->old_spte,
> - pte_pfn(range->arg.pte));
> -
> - tdp_mmu_iter_set_spte(kvm, iter, new_spte);
> - }
> -
> - return true;
> -}
> -
> -/*
> - * Handle the changed_pte MMU notifier for the TDP MMU.
> - * data is a pointer to the new pte_t mapping the HVA specified by the MMU
> - * notifier.
> - * Returns non-zero if a flush is needed before releasing the MMU lock.
> - */
> -bool kvm_tdp_mmu_set_spte_gfn(struct kvm *kvm, struct kvm_gfn_range *range)
> -{
> - /*
> - * No need to handle the remote TLB flush under RCU protection, the
> - * target SPTE _must_ be a leaf SPTE, i.e. cannot result in freeing a
> - * shadow page. See the WARN on pfn_changed in handle_changed_spte().
> - */
> - return kvm_tdp_mmu_handle_gfn(kvm, range, set_spte_gfn);
> -}
> -
> /*
> * Remove write access from all SPTEs at or above min_level that map GFNs
> * [start, end). Returns true if an SPTE has been changed and the TLBs need to
> diff --git a/arch/x86/kvm/mmu/tdp_mmu.h b/arch/x86/kvm/mmu/tdp_mmu.h
> index 6e1ea04ca885..58b55e61bd33 100644
> --- a/arch/x86/kvm/mmu/tdp_mmu.h
> +++ b/arch/x86/kvm/mmu/tdp_mmu.h
> @@ -31,7 +31,6 @@ bool kvm_tdp_mmu_unmap_gfn_range(struct kvm *kvm, struct kvm_gfn_range *range,
> bool flush);
> bool kvm_tdp_mmu_age_gfn_range(struct kvm *kvm, struct kvm_gfn_range *range);
> bool kvm_tdp_mmu_test_age_gfn(struct kvm *kvm, struct kvm_gfn_range *range);
> -bool kvm_tdp_mmu_set_spte_gfn(struct kvm *kvm, struct kvm_gfn_range *range);
>
> bool kvm_tdp_mmu_wrprot_slot(struct kvm *kvm,
> const struct kvm_memory_slot *slot, int min_level);
> diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
> index ab439706ea2f..8dea11701ab2 100644
> --- a/include/linux/kvm_host.h
> +++ b/include/linux/kvm_host.h
> @@ -259,7 +259,6 @@ int kvm_async_pf_wakeup_all(struct kvm_vcpu *vcpu);
>
> #ifdef CONFIG_KVM_GENERIC_MMU_NOTIFIER
> union kvm_mmu_notifier_arg {
> - pte_t pte;
> unsigned long attributes;
> };
>
> @@ -273,7 +272,6 @@ struct kvm_gfn_range {
> bool kvm_unmap_gfn_range(struct kvm *kvm, struct kvm_gfn_range *range);
> bool kvm_age_gfn(struct kvm *kvm, struct kvm_gfn_range *range);
> bool kvm_test_age_gfn(struct kvm *kvm, struct kvm_gfn_range *range);
> -bool kvm_set_spte_gfn(struct kvm *kvm, struct kvm_gfn_range *range);
> #endif
>
> enum {
> diff --git a/include/trace/events/kvm.h b/include/trace/events/kvm.h
> index 011fba6b5552..74e40d5d4af4 100644
> --- a/include/trace/events/kvm.h
> +++ b/include/trace/events/kvm.h
> @@ -456,21 +456,6 @@ TRACE_EVENT(kvm_unmap_hva_range,
> __entry->start, __entry->end)
> );
>
> -TRACE_EVENT(kvm_set_spte_hva,
> - TP_PROTO(unsigned long hva),
> - TP_ARGS(hva),
> -
> - TP_STRUCT__entry(
> - __field( unsigned long, hva )
> - ),
> -
> - TP_fast_assign(
> - __entry->hva = hva;
> - ),
> -
> - TP_printk("mmu notifier set pte hva: %#016lx", __entry->hva)
> -);
> -
> TRACE_EVENT(kvm_age_hva,
> TP_PROTO(unsigned long start, unsigned long end),
> TP_ARGS(start, end),
> diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
> index 4eb8afd0b961..2fcd9979752a 100644
> --- a/virt/kvm/kvm_main.c
> +++ b/virt/kvm/kvm_main.c
> @@ -717,48 +717,6 @@ static __always_inline int kvm_handle_hva_range_no_flush(struct mmu_notifier *mn
> return __kvm_handle_hva_range(kvm, &range).ret;
> }
>
> -static bool kvm_change_spte_gfn(struct kvm *kvm, struct kvm_gfn_range *range)
> -{
> - /*
> - * Skipping invalid memslots is correct if and only change_pte() is
> - * surrounded by invalidate_range_{start,end}(), which is currently
> - * guaranteed by the primary MMU. If that ever changes, KVM needs to
> - * unmap the memslot instead of skipping the memslot to ensure that KVM
> - * doesn't hold references to the old PFN.
> - */
> - WARN_ON_ONCE(!READ_ONCE(kvm->mn_active_invalidate_count));
> -
> - if (range->slot->flags & KVM_MEMSLOT_INVALID)
> - return false;
> -
> - return kvm_set_spte_gfn(kvm, range);
> -}
> -
> -static void kvm_mmu_notifier_change_pte(struct mmu_notifier *mn,
> - struct mm_struct *mm,
> - unsigned long address,
> - pte_t pte)
> -{
> - struct kvm *kvm = mmu_notifier_to_kvm(mn);
> - const union kvm_mmu_notifier_arg arg = { .pte = pte };
> -
> - trace_kvm_set_spte_hva(address);
> -
> - /*
> - * .change_pte() must be surrounded by .invalidate_range_{start,end}().
> - * If mmu_invalidate_in_progress is zero, then no in-progress
> - * invalidations, including this one, found a relevant memslot at
> - * start(); rechecking memslots here is unnecessary. Note, a false
> - * positive (count elevated by a different invalidation) is sub-optimal
> - * but functionally ok.
> - */
> - WARN_ON_ONCE(!READ_ONCE(kvm->mn_active_invalidate_count));
> - if (!READ_ONCE(kvm->mmu_invalidate_in_progress))
> - return;
> -
> - kvm_handle_hva_range(mn, address, address + 1, arg, kvm_change_spte_gfn);
> -}
> -
> void kvm_mmu_invalidate_begin(struct kvm *kvm)
> {
> lockdep_assert_held_write(&kvm->mmu_lock);
> @@ -976,7 +934,6 @@ static const struct mmu_notifier_ops kvm_mmu_notifier_ops = {
> .clear_flush_young = kvm_mmu_notifier_clear_flush_young,
> .clear_young = kvm_mmu_notifier_clear_young,
> .test_young = kvm_mmu_notifier_test_young,
> - .change_pte = kvm_mmu_notifier_change_pte,
> .release = kvm_mmu_notifier_release,
> };
>
> --
> 2.43.0
>
>
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [PATCH v1 1/1] arm64: dts: imx93-11x11-evk: add rtc PCF2131 support
From: Joy Zou @ 2024-04-07 5:19 UTC (permalink / raw)
To: ping.bai, robh+dt, krzysztof.kozlowski+dt, conor+dt, shawnguo,
s.hauer
Cc: kernel, festevam, linux-imx, devicetree, imx, linux-arm-kernel,
linux-kernel
In-Reply-To: <20240407051913.1989364-1-joy.zou@nxp.com>
Support rtc PCF2131 on imx93-11x11-evk.
Signed-off-by: Joy Zou <joy.zou@nxp.com>
---
.../boot/dts/freescale/imx93-11x11-evk.dts | 25 +++++++++++++++++++
1 file changed, 25 insertions(+)
diff --git a/arch/arm64/boot/dts/freescale/imx93-11x11-evk.dts b/arch/arm64/boot/dts/freescale/imx93-11x11-evk.dts
index 07e85a30a25f..065fa3390791 100644
--- a/arch/arm64/boot/dts/freescale/imx93-11x11-evk.dts
+++ b/arch/arm64/boot/dts/freescale/imx93-11x11-evk.dts
@@ -281,6 +281,24 @@ ldo5: LDO5 {
};
};
+&lpi2c3 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ clock-frequency = <400000>;
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&pinctrl_lpi2c3>;
+ pinctrl-1 = <&pinctrl_lpi2c3>;
+ status = "okay";
+
+ pcf2131: rtc@53 {
+ compatible = "nxp,pcf2131";
+ reg = <0x53>;
+ interrupt-parent = <&pcal6524>;
+ interrupts = <1 IRQ_TYPE_EDGE_FALLING>;
+ status = "okay";
+ };
+};
+
&iomuxc {
pinctrl_eqos: eqosgrp {
fsl,pins = <
@@ -343,6 +361,13 @@ MX93_PAD_I2C2_SDA__LPI2C2_SDA 0x40000b9e
>;
};
+ pinctrl_lpi2c3: lpi2c3grp {
+ fsl,pins = <
+ MX93_PAD_GPIO_IO28__LPI2C3_SDA 0x40000b9e
+ MX93_PAD_GPIO_IO29__LPI2C3_SCL 0x40000b9e
+ >;
+ };
+
pinctrl_pcal6524: pcal6524grp {
fsl,pins = <
MX93_PAD_CCM_CLKO2__GPIO3_IO27 0x31e
--
2.37.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH v1 0/1] Add rtc PCF2131 support
From: Joy Zou @ 2024-04-07 5:19 UTC (permalink / raw)
To: ping.bai, robh+dt, krzysztof.kozlowski+dt, conor+dt, shawnguo,
s.hauer
Cc: kernel, festevam, linux-imx, devicetree, imx, linux-arm-kernel,
linux-kernel
The patchset supports RTC PCF2131 on board dts.
For the details, please check the patch commit log.
Joy Zou (1):
arm64: dts: imx93-11x11-evk: add rtc PCF2131 support
.../boot/dts/freescale/imx93-11x11-evk.dts | 25 +++++++++++++++++++
1 file changed, 25 insertions(+)
--
2.37.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [PATCH -next] ARM: Add kernel-doc comments to ssp_read_word()
From: Yang Li @ 2024-04-07 6:08 UTC (permalink / raw)
To: linux; +Cc: linux-arm-kernel, linux-kernel, Yang Li
This commit adds kernel-doc style comments with complete parameter
descriptions for the function ssp_read_word().
Signed-off-by: Yang Li <yang.lee@linux.alibaba.com>
---
arch/arm/mach-sa1100/ssp.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/arch/arm/mach-sa1100/ssp.c b/arch/arm/mach-sa1100/ssp.c
index 613fd767afcf..3c97e372bdc4 100644
--- a/arch/arm/mach-sa1100/ssp.c
+++ b/arch/arm/mach-sa1100/ssp.c
@@ -73,6 +73,8 @@ int ssp_write_word(u16 data)
/**
* ssp_read_word - read a word from the SSP port
*
+ * @data: Pointer to the 16-bit buffer where the read data should be stored.
+ *
* Wait for a data word in the SSP receive FIFO, and return the
* received data. Data is LSB justified.
*
--
2.20.1.7.g153144c
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* Re: [PATCH v5 2/4] drm/bridge: add lvds controller support for sam9x7
From: Hari.PrasathGE @ 2024-04-07 6:28 UTC (permalink / raw)
To: Dharma.B, andrzej.hajda, neil.armstrong, rfoss, Laurent.pinchart,
jonas, jernej.skrabec, maarten.lankhorst, mripard, tzimmermann,
airlied, daniel, robh+dt, krzysztof.kozlowski+dt, conor+dt, linux,
Nicolas.Ferre, alexandre.belloni, claudiu.beznea, Manikandan.M,
arnd, geert+renesas, Jason, mpe, gerg, rdunlap, vbabka, dri-devel,
devicetree, linux-kernel, linux-arm-kernel, akpm, deller
In-Reply-To: <20240405043536.274220-3-dharma.b@microchip.com>
On 4/5/24 10:05 AM, Dharma Balasubiramani wrote:
> Add a new LVDS controller driver for sam9x7 which does the following:
> - Prepares and enables the LVDS Peripheral clock
> - Defines its connector type as DRM_MODE_CONNECTOR_LVDS and adds itself
> to the global bridge list.
> - Identifies its output endpoint as panel and adds it to the encoder
> display pipeline
> - Enables the LVDS serializer
Acked-by: Hari Prasath Gujulan Elango <hari.prasathge@microchip.com>
>
> Signed-off-by: Manikandan Muralidharan <manikandan.m@microchip.com>
> Signed-off-by: Dharma Balasubiramani <dharma.b@microchip.com>
> ---
> Changelog
> v4 -> v5
> - Drop the unused variable 'format'.
> - Use DRM wrapper for dev_err() to maintain uniformity.
> - return -ENODEV instead of -EINVAL to maintain consistency with other DRM
> bridge drivers.
> v3 -> v4
> - No changes.
> v2 ->v3
> - Correct Typo error "serializer".
> - Consolidate get() and prepare() functions and use devm_clk_get_prepared().
> - Remove unused variable 'ret' in probe().
> - Use devm_pm_runtime_enable() and drop the mchp_lvds_remove().
> v1 -> v2
> - Drop 'res' variable and combine two lines into one.
> - Handle deferred probe properly, use dev_err_probe().
> - Don't print anything on deferred probe. Dropped print.
> - Remove the MODULE_ALIAS and add MODULE_DEVICE_TABLE().
> - symbol 'mchp_lvds_driver' was not declared. It should be static.
> ---
> drivers/gpu/drm/bridge/Kconfig | 7 +
> drivers/gpu/drm/bridge/Makefile | 1 +
> drivers/gpu/drm/bridge/microchip-lvds.c | 228 ++++++++++++++++++++++++
> 3 files changed, 236 insertions(+)
> create mode 100644 drivers/gpu/drm/bridge/microchip-lvds.c
>
> diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig
> index efd996f6c138..889098e2d65f 100644
> --- a/drivers/gpu/drm/bridge/Kconfig
> +++ b/drivers/gpu/drm/bridge/Kconfig
> @@ -190,6 +190,13 @@ config DRM_MEGACHIPS_STDPXXXX_GE_B850V3_FW
> to DP++. This is used with the i.MX6 imx-ldb
> driver. You are likely to say N here.
>
> +config DRM_MICROCHIP_LVDS_SERIALIZER
> + tristate "Microchip LVDS serializer support"
> + depends on OF
> + depends on DRM_ATMEL_HLCDC
> + help
> + Support for Microchip's LVDS serializer.
> +
> config DRM_NWL_MIPI_DSI
> tristate "Northwest Logic MIPI DSI Host controller"
> depends on DRM
> diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile
> index 017b5832733b..7df87b582dca 100644
> --- a/drivers/gpu/drm/bridge/Makefile
> +++ b/drivers/gpu/drm/bridge/Makefile
> @@ -13,6 +13,7 @@ obj-$(CONFIG_DRM_LONTIUM_LT9611) += lontium-lt9611.o
> obj-$(CONFIG_DRM_LONTIUM_LT9611UXC) += lontium-lt9611uxc.o
> obj-$(CONFIG_DRM_LVDS_CODEC) += lvds-codec.o
> obj-$(CONFIG_DRM_MEGACHIPS_STDPXXXX_GE_B850V3_FW) += megachips-stdpxxxx-ge-b850v3-fw.o
> +obj-$(CONFIG_DRM_MICROCHIP_LVDS_SERIALIZER) += microchip-lvds.o
> obj-$(CONFIG_DRM_NXP_PTN3460) += nxp-ptn3460.o
> obj-$(CONFIG_DRM_PARADE_PS8622) += parade-ps8622.o
> obj-$(CONFIG_DRM_PARADE_PS8640) += parade-ps8640.o
> diff --git a/drivers/gpu/drm/bridge/microchip-lvds.c b/drivers/gpu/drm/bridge/microchip-lvds.c
> new file mode 100644
> index 000000000000..149704f498a6
> --- /dev/null
> +++ b/drivers/gpu/drm/bridge/microchip-lvds.c
> @@ -0,0 +1,228 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (C) 2023 Microchip Technology Inc. and its subsidiaries
> + *
> + * Author: Manikandan Muralidharan <manikandan.m@microchip.com>
> + * Author: Dharma Balasubiramani <dharma.b@microchip.com>
> + *
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/component.h>
> +#include <linux/delay.h>
> +#include <linux/jiffies.h>
> +#include <linux/mfd/syscon.h>
> +#include <linux/of_graph.h>
> +#include <linux/pinctrl/devinfo.h>
> +#include <linux/phy/phy.h>
> +#include <linux/platform_device.h>
> +#include <linux/pm_runtime.h>
> +#include <linux/regmap.h>
> +#include <linux/reset.h>
> +
> +#include <drm/drm_atomic_helper.h>
> +#include <drm/drm_bridge.h>
> +#include <drm/drm_of.h>
> +#include <drm/drm_panel.h>
> +#include <drm/drm_print.h>
> +#include <drm/drm_probe_helper.h>
> +#include <drm/drm_simple_kms_helper.h>
> +
> +#define LVDS_POLL_TIMEOUT_MS 1000
> +
> +/* LVDSC register offsets */
> +#define LVDSC_CR 0x00
> +#define LVDSC_CFGR 0x04
> +#define LVDSC_SR 0x0C
> +#define LVDSC_WPMR 0xE4
> +
> +/* Bitfields in LVDSC_CR (Control Register) */
> +#define LVDSC_CR_SER_EN BIT(0)
> +
> +/* Bitfields in LVDSC_CFGR (Configuration Register) */
> +#define LVDSC_CFGR_PIXSIZE_24BITS 0
> +#define LVDSC_CFGR_DEN_POL_HIGH 0
> +#define LVDSC_CFGR_DC_UNBALANCED 0
> +#define LVDSC_CFGR_MAPPING_JEIDA BIT(6)
> +
> +/*Bitfields in LVDSC_SR */
> +#define LVDSC_SR_CS BIT(0)
> +
> +/* Bitfields in LVDSC_WPMR (Write Protection Mode Register) */
> +#define LVDSC_WPMR_WPKEY_MASK GENMASK(31, 8)
> +#define LVDSC_WPMR_WPKEY_PSSWD 0x4C5644
> +
> +struct mchp_lvds {
> + struct device *dev;
> + void __iomem *regs;
> + struct clk *pclk;
> + struct drm_panel *panel;
> + struct drm_bridge bridge;
> + struct drm_bridge *panel_bridge;
> +};
> +
> +static inline struct mchp_lvds *bridge_to_lvds(struct drm_bridge *bridge)
> +{
> + return container_of(bridge, struct mchp_lvds, bridge);
> +}
> +
> +static inline u32 lvds_readl(struct mchp_lvds *lvds, u32 offset)
> +{
> + return readl_relaxed(lvds->regs + offset);
> +}
> +
> +static inline void lvds_writel(struct mchp_lvds *lvds, u32 offset, u32 val)
> +{
> + writel_relaxed(val, lvds->regs + offset);
> +}
> +
> +static void lvds_serialiser_on(struct mchp_lvds *lvds)
> +{
> + unsigned long timeout = jiffies + msecs_to_jiffies(LVDS_POLL_TIMEOUT_MS);
> +
> + /* The LVDSC registers can only be written if WPEN is cleared */
> + lvds_writel(lvds, LVDSC_WPMR, (LVDSC_WPMR_WPKEY_PSSWD &
> + LVDSC_WPMR_WPKEY_MASK));
> +
> + /* Wait for the status of configuration registers to be changed */
> + while (lvds_readl(lvds, LVDSC_SR) & LVDSC_SR_CS) {
> + if (time_after(jiffies, timeout)) {
> + DRM_DEV_ERROR(lvds->dev, "%s: timeout error\n",
> + __func__);
> + return;
> + }
> + usleep_range(1000, 2000);
> + }
> +
> + /* Configure the LVDSC */
> + lvds_writel(lvds, LVDSC_CFGR, (LVDSC_CFGR_MAPPING_JEIDA |
> + LVDSC_CFGR_DC_UNBALANCED |
> + LVDSC_CFGR_DEN_POL_HIGH |
> + LVDSC_CFGR_PIXSIZE_24BITS));
> +
> + /* Enable the LVDS serializer */
> + lvds_writel(lvds, LVDSC_CR, LVDSC_CR_SER_EN);
> +}
> +
> +static int mchp_lvds_attach(struct drm_bridge *bridge,
> + enum drm_bridge_attach_flags flags)
> +{
> + struct mchp_lvds *lvds = bridge_to_lvds(bridge);
> +
> + bridge->encoder->encoder_type = DRM_MODE_ENCODER_LVDS;
> +
> + return drm_bridge_attach(bridge->encoder, lvds->panel_bridge,
> + bridge, flags);
> +}
> +
> +static void mchp_lvds_enable(struct drm_bridge *bridge)
> +{
> + struct mchp_lvds *lvds = bridge_to_lvds(bridge);
> + int ret;
> +
> + ret = clk_enable(lvds->pclk);
> + if (ret < 0) {
> + DRM_DEV_ERROR(lvds->dev, "failed to enable lvds pclk %d\n", ret);
> + return;
> + }
> +
> + ret = pm_runtime_get_sync(lvds->dev);
> + if (ret < 0) {
> + DRM_DEV_ERROR(lvds->dev, "failed to get pm runtime: %d\n", ret);
> + clk_disable(lvds->pclk);
> + return;
> + }
> +
> + lvds_serialiser_on(lvds);
> +}
> +
> +static void mchp_lvds_disable(struct drm_bridge *bridge)
> +{
> + struct mchp_lvds *lvds = bridge_to_lvds(bridge);
> +
> + pm_runtime_put(lvds->dev);
> + clk_disable(lvds->pclk);
> +}
> +
> +static const struct drm_bridge_funcs mchp_lvds_bridge_funcs = {
> + .attach = mchp_lvds_attach,
> + .enable = mchp_lvds_enable,
> + .disable = mchp_lvds_disable,
> +};
> +
> +static int mchp_lvds_probe(struct platform_device *pdev)
> +{
> + struct device *dev = &pdev->dev;
> + struct mchp_lvds *lvds;
> + struct device_node *port;
> +
> + if (!dev->of_node)
> + return -ENODEV;
> +
> + lvds = devm_kzalloc(&pdev->dev, sizeof(*lvds), GFP_KERNEL);
> + if (!lvds)
> + return -ENOMEM;
> +
> + lvds->dev = dev;
> +
> + lvds->regs = devm_ioremap_resource(lvds->dev,
> + platform_get_resource(pdev, IORESOURCE_MEM, 0));
> + if (IS_ERR(lvds->regs))
> + return PTR_ERR(lvds->regs);
> +
> + lvds->pclk = devm_clk_get_prepared(lvds->dev, "pclk");
> + if (IS_ERR(lvds->pclk))
> + return dev_err_probe(lvds->dev, PTR_ERR(lvds->pclk),
> + "could not get pclk_lvds prepared\n");
> +
> + port = of_graph_get_remote_node(dev->of_node, 1, 0);
> + if (!port) {
> + DRM_DEV_ERROR(dev,
> + "can't find port point, please init lvds panel port!\n");
> + return -ENODEV;
> + }
> +
> + lvds->panel = of_drm_find_panel(port);
> + of_node_put(port);
> +
> + if (IS_ERR(lvds->panel))
> + return -EPROBE_DEFER;
> +
> + lvds->panel_bridge = devm_drm_panel_bridge_add(dev, lvds->panel);
> +
> + if (IS_ERR(lvds->panel_bridge))
> + return PTR_ERR(lvds->panel_bridge);
> +
> + lvds->bridge.of_node = dev->of_node;
> + lvds->bridge.type = DRM_MODE_CONNECTOR_LVDS;
> + lvds->bridge.funcs = &mchp_lvds_bridge_funcs;
> +
> + dev_set_drvdata(dev, lvds);
> + devm_pm_runtime_enable(dev);
> +
> + drm_bridge_add(&lvds->bridge);
> +
> + return 0;
> +}
> +
> +static const struct of_device_id mchp_lvds_dt_ids[] = {
> + {
> + .compatible = "microchip,sam9x75-lvds",
> + },
> + {},
> +};
> +MODULE_DEVICE_TABLE(of, mchp_lvds_dt_ids);
> +
> +static struct platform_driver mchp_lvds_driver = {
> + .probe = mchp_lvds_probe,
> + .driver = {
> + .name = "microchip-lvds",
> + .of_match_table = mchp_lvds_dt_ids,
> + },
> +};
> +module_platform_driver(mchp_lvds_driver);
> +
> +MODULE_AUTHOR("Manikandan Muralidharan <manikandan.m@microchip.com>");
> +MODULE_AUTHOR("Dharma Balasubiramani <dharma.b@microchip.com>");
> +MODULE_DESCRIPTION("Low Voltage Differential Signaling Controller Driver");
> +MODULE_LICENSE("GPL");
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH v2 0/7] arch/mm/fault: accelerate pagefault when badaccess
From: Kefeng Wang @ 2024-04-07 7:49 UTC (permalink / raw)
To: Andrew Morton
Cc: Russell King, Catalin Marinas, Will Deacon, Michael Ellerman,
Nicholas Piggin, Christophe Leroy, Paul Walmsley, Palmer Dabbelt,
Albert Ou, Alexander Gordeev, Gerald Schaefer, Dave Hansen,
Andy Lutomirski, Peter Zijlstra, x86, linux-arm-kernel,
linuxppc-dev, linux-riscv, linux-s390, surenb, linux-mm
In-Reply-To: <20240403134539.fde3a6c594f2d88409be30ed@linux-foundation.org>
On 2024/4/4 4:45, Andrew Morton wrote:
> On Wed, 3 Apr 2024 16:37:58 +0800 Kefeng Wang <wangkefeng.wang@huawei.com> wrote:
>
>> After VMA lock-based page fault handling enabled, if bad access met
>> under per-vma lock, it will fallback to mmap_lock-based handling,
>> so it leads to unnessary mmap lock and vma find again. A test from
>> lmbench shows 34% improve after this changes on arm64,
>>
>> lat_sig -P 1 prot lat_sig 0.29194 -> 0.19198
>>
>> Only build test on other archs except arm64.
>
> Thanks. So we now want a bunch of architectures to runtime test this. Do
> we have a selftest in place which will adequately do this?
I don't find such selftest, and badaccess would lead to coredump, the
performance should not affect most scene, so no selftest is acceptable.
lmbench is easy to use to measure the performance.
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH v2 0/2] Enable JPEG encoding on rk3588
From: Nicolas Dufresne @ 2024-04-07 8:08 UTC (permalink / raw)
To: Link Mauve
Cc: linux-kernel, Ezequiel Garcia, Philipp Zabel,
Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Heiko Stuebner, Joerg Roedel, Will Deacon,
Robin Murphy, Sebastian Reichel, Cristian Ciocaltea, Dragan Simic,
Shreeya Patel, Chris Morgan, Andy Yan, Nicolas Frattaroli,
linux-media, linux-rockchip, devicetree, linux-arm-kernel, iommu
In-Reply-To: <ZhAI6tQZTD7BTosI@desktop>
Le vendredi 05 avril 2024 à 16:21 +0200, Link Mauve a écrit :
> On Thu, Apr 04, 2024 at 01:41:15PM -0400, Nicolas Dufresne wrote:
> > Hi,
>
> Hi,
>
> >
> > Le mercredi 27 mars 2024 à 14:41 +0100, Emmanuel Gil Peyrot a écrit :
> > > Only the JPEG encoder is available for now, although there are patches
> > > for the undocumented VP8 encoder floating around[0].
> >
> > [0] seems like a broken link. The VP8 encoder RFC is for RK3399 (and Hantro H1
> > posted by ST more recently). The TRM says "VEPU121(JPEG encoder only)", which
> > suggest that the H.264 and VP8 encoders usually found on the VEPU121 are
> > removed. As Rockchip have remove the synthesize register while modifying the H1
> > IP, it is difficult to verify. Confusingly the H.264 specific registers are
> > documented in the TRM around VEPU121.
>
> Ah, the link became, and was indeed ST’s series:
> https://patchwork.kernel.org/project/linux-rockchip/list/?series=789885&archive=both
>
> But the TRM part 1 says the VEPU121 supports H.264 encoding (page 367),
> and it’s likely they didn’t remove just VP8 support since the codec
> features are pretty close to H.264’s.
>
> >
> > >
> > > This has been tested on a rock-5b, resulting in four /dev/video*
> > > encoders. The userspace program I’ve been using to test them is
> > > Onix[1], using the jpeg-encoder example, it will pick one of these four
> > > at random (but displays the one it picked):
> > > % ffmpeg -i <input image> -pix_fmt yuvj420p temp.yuv
> > > % jpeg-encoder temp.yuv <width> <height> NV12 <quality> output.jpeg
> >
> > I don't like that we exposing each identical cores a separate video nodes. I
> > think we should aim for 1 device, and then multi-plex and schedule de cores from
> > inside the Linux kernel.
>
> I agree, but this should be handled in the driver not in the device
> tree, and it can be done later.
As the behaviour we want is that these cores becomes a group and get schedule
together, its certainly a good time to slow down and evaluate if that part needs
to be improve in the DT too.
Hantro G1/H1 and VEPU/VDPU121 combos originally shared the same sram region. Its
not clear if any of these cores have this limitation and if this should be
expressed in the DT / driver.
>
> >
> > Not doing this now means we'll never have an optimal hardware usage
> > distribution. Just consider two userspace software wanting to do jpeg encoding.
> > If they both take a guess, they may endup using a single core. Where with proper
> > scheduling in V4L2, the kernel will be able to properly distribute the load. I
> > insist on this, since if we merge you changes it becomes an ABI and we can't
> > change it anymore.
>
> Will it really become ABI just like that? Userspace should always
> discover the video nodes and their capabilities and not hardcode e.g. a
> specific /dev/videoN file for a specific codec. I would argue that this
> series would let userspace do JPEG encoding right away, even if in a
> less optimal way than if the driver would round-robin them through a
> single video node, but that can always be added in a future version.
Might be on the gray side, but there is good chances software written for your
specific board can stop working after te grouping is done.
>
> >
> > I understand that this impose a rework of the mem2mem framework so that we can
> > run multiple jobs, but this will be needed anyway on RK3588, since the rkvdec2,
> > which we don't have a driver yet is also multi-core, but you need to use 2 cores
> > when the resolution is close to 8K.
>
> I think the mediatek JPEG driver already supports that, would it be ok
> to do it the same way?
I don't know for JPEG, the MTK vcoder do support cascading cores. This is
different from concurrent cores. In MTK architecture, for some of the codec,
there is LAT (entropy decoder) and CORE (the reconstruction block) that are
split.
Nicolas
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [PATCH -next 0/2] mm: remove arch's private VM_FAULT_BADMAP/BADACCESS
From: Kefeng Wang @ 2024-04-07 8:12 UTC (permalink / raw)
To: Andrew Morton, Russell King, Catalin Marinas, Will Deacon
Cc: linux-arm-kernel, linux-mm, Kefeng Wang
Directly set SEGV_MAPRR or SEGV_ACCERR for arm/arm64 to remove the last
two arch's private vm_fault reasons.
Based on next-20240405.
Kefeng Wang (2):
arm64: mm: drop VM_FAULT_BADMAP/VM_FAULT_BADACCESS
arm: mm: drop VM_FAULT_BADMAP/VM_FAULT_BADACCESS
arch/arm/mm/fault.c | 28 +++++++++++++---------------
arch/arm64/mm/fault.c | 41 ++++++++++++++++++-----------------------
2 files changed, 31 insertions(+), 38 deletions(-)
--
2.27.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [PATCH 1/2] arm64: mm: drop VM_FAULT_BADMAP/VM_FAULT_BADACCESS
From: Kefeng Wang @ 2024-04-07 8:12 UTC (permalink / raw)
To: Andrew Morton, Russell King, Catalin Marinas, Will Deacon
Cc: linux-arm-kernel, linux-mm, Kefeng Wang
In-Reply-To: <20240407081211.2292362-1-wangkefeng.wang@huawei.com>
If bad map or access, directly set si_code to SEGV_MAPRR or SEGV_ACCERR,
also set fault to 0 and goto error handling, which make us to drop the
arch's special vm fault reason.
Signed-off-by: Kefeng Wang <wangkefeng.wang@huawei.com>
---
arch/arm64/mm/fault.c | 41 ++++++++++++++++++-----------------------
1 file changed, 18 insertions(+), 23 deletions(-)
diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
index 405f9aa831bd..61a2acae0dca 100644
--- a/arch/arm64/mm/fault.c
+++ b/arch/arm64/mm/fault.c
@@ -500,9 +500,6 @@ static bool is_write_abort(unsigned long esr)
return (esr & ESR_ELx_WNR) && !(esr & ESR_ELx_CM);
}
-#define VM_FAULT_BADMAP ((__force vm_fault_t)0x010000)
-#define VM_FAULT_BADACCESS ((__force vm_fault_t)0x020000)
-
static int __kprobes do_page_fault(unsigned long far, unsigned long esr,
struct pt_regs *regs)
{
@@ -513,6 +510,7 @@ static int __kprobes do_page_fault(unsigned long far, unsigned long esr,
unsigned int mm_flags = FAULT_FLAG_DEFAULT;
unsigned long addr = untagged_addr(far);
struct vm_area_struct *vma;
+ int si_code;
if (kprobe_page_fault(regs, esr))
return 0;
@@ -572,9 +570,10 @@ static int __kprobes do_page_fault(unsigned long far, unsigned long esr,
if (!(vma->vm_flags & vm_flags)) {
vma_end_read(vma);
- fault = VM_FAULT_BADACCESS;
+ fault = 0;
+ si_code = SEGV_ACCERR;
count_vm_vma_lock_event(VMA_LOCK_SUCCESS);
- goto done;
+ goto bad_area;
}
fault = handle_mm_fault(vma, addr, mm_flags | FAULT_FLAG_VMA_LOCK, regs);
if (!(fault & (VM_FAULT_RETRY | VM_FAULT_COMPLETED)))
@@ -599,15 +598,18 @@ static int __kprobes do_page_fault(unsigned long far, unsigned long esr,
retry:
vma = lock_mm_and_find_vma(mm, addr, regs);
if (unlikely(!vma)) {
- fault = VM_FAULT_BADMAP;
- goto done;
+ fault = 0;
+ si_code = SEGV_MAPERR;
+ goto bad_area;
}
- if (!(vma->vm_flags & vm_flags))
- fault = VM_FAULT_BADACCESS;
- else
- fault = handle_mm_fault(vma, addr, mm_flags, regs);
+ if (!(vma->vm_flags & vm_flags)) {
+ fault = 0;
+ si_code = SEGV_ACCERR;
+ goto bad_area;
+ }
+ fault = handle_mm_fault(vma, addr, mm_flags, regs);
/* Quick path to respond to signals */
if (fault_signal_pending(fault, regs)) {
if (!user_mode(regs))
@@ -626,13 +628,11 @@ static int __kprobes do_page_fault(unsigned long far, unsigned long esr,
mmap_read_unlock(mm);
done:
- /*
- * Handle the "normal" (no error) case first.
- */
- if (likely(!(fault & (VM_FAULT_ERROR | VM_FAULT_BADMAP |
- VM_FAULT_BADACCESS))))
+ /* Handle the "normal" (no error) case first. */
+ if (likely(!(fault & VM_FAULT_ERROR)))
return 0;
+bad_area:
/*
* If we are in kernel mode at this point, we have no context to
* handle this fault with.
@@ -667,13 +667,8 @@ static int __kprobes do_page_fault(unsigned long far, unsigned long esr,
arm64_force_sig_mceerr(BUS_MCEERR_AR, far, lsb, inf->name);
} else {
- /*
- * Something tried to access memory that isn't in our memory
- * map.
- */
- arm64_force_sig_fault(SIGSEGV,
- fault == VM_FAULT_BADACCESS ? SEGV_ACCERR : SEGV_MAPERR,
- far, inf->name);
+ /* Something tried to access memory that out of memory map */
+ arm64_force_sig_fault(SIGSEGV, si_code, far, inf->name);
}
return 0;
--
2.27.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH 2/2] arm: mm: drop VM_FAULT_BADMAP/VM_FAULT_BADACCESS
From: Kefeng Wang @ 2024-04-07 8:12 UTC (permalink / raw)
To: Andrew Morton, Russell King, Catalin Marinas, Will Deacon
Cc: linux-arm-kernel, linux-mm, Kefeng Wang
In-Reply-To: <20240407081211.2292362-1-wangkefeng.wang@huawei.com>
If bad map or access, directly set si_code to SEGV_MAPRR or SEGV_ACCERR,
also set fault to 0 and goto error handling, which make us to drop the
arch's special vm fault reason.
Signed-off-by: Kefeng Wang <wangkefeng.wang@huawei.com>
---
arch/arm/mm/fault.c | 28 +++++++++++++---------------
1 file changed, 13 insertions(+), 15 deletions(-)
diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c
index 5c4b417e24f9..cab24fb17c4b 100644
--- a/arch/arm/mm/fault.c
+++ b/arch/arm/mm/fault.c
@@ -226,9 +226,6 @@ void do_bad_area(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
}
#ifdef CONFIG_MMU
-#define VM_FAULT_BADMAP ((__force vm_fault_t)0x010000)
-#define VM_FAULT_BADACCESS ((__force vm_fault_t)0x020000)
-
static inline bool is_permission_fault(unsigned int fsr)
{
int fs = fsr_fs(fsr);
@@ -295,7 +292,8 @@ do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
if (!(vma->vm_flags & vm_flags)) {
vma_end_read(vma);
count_vm_vma_lock_event(VMA_LOCK_SUCCESS);
- fault = VM_FAULT_BADACCESS;
+ fault = 0;
+ code = SEGV_ACCERR;
goto bad_area;
}
fault = handle_mm_fault(vma, addr, flags | FAULT_FLAG_VMA_LOCK, regs);
@@ -321,7 +319,8 @@ do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
retry:
vma = lock_mm_and_find_vma(mm, addr, regs);
if (unlikely(!vma)) {
- fault = VM_FAULT_BADMAP;
+ fault = 0;
+ code = SEGV_MAPERR;
goto bad_area;
}
@@ -329,10 +328,13 @@ do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
* ok, we have a good vm_area for this memory access, check the
* permissions on the VMA allow for the fault which occurred.
*/
- if (!(vma->vm_flags & vm_flags))
- fault = VM_FAULT_BADACCESS;
- else
- fault = handle_mm_fault(vma, addr & PAGE_MASK, flags, regs);
+ if (!(vma->vm_flags & vm_flags)) {
+ fault = 0;
+ code = SEGV_ACCERR;
+ goto bad_area;
+ }
+
+ fault = handle_mm_fault(vma, addr & PAGE_MASK, flags, regs);
/* If we need to retry but a fatal signal is pending, handle the
* signal first. We do not need to release the mmap_lock because
@@ -358,10 +360,8 @@ do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
mmap_read_unlock(mm);
done:
- /*
- * Handle the "normal" case first - VM_FAULT_MAJOR
- */
- if (likely(!(fault & (VM_FAULT_ERROR | VM_FAULT_BADMAP | VM_FAULT_BADACCESS))))
+ /* Handle the "normal" case first */
+ if (likely(!(fault & VM_FAULT_ERROR)))
return 0;
bad_area:
@@ -395,8 +395,6 @@ do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
* isn't in our memory map..
*/
sig = SIGSEGV;
- code = fault == VM_FAULT_BADACCESS ?
- SEGV_ACCERR : SEGV_MAPERR;
}
__do_user_fault(addr, fsr, sig, code, regs);
--
2.27.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* Re: [PATCH v3 09/25] media: i2c: imx258: Add support for running on 2 CSI data lanes
From: Kieran Bingham @ 2024-04-07 8:51 UTC (permalink / raw)
To: Luis Garcia, Pavel Machek
Cc: linux-media, dave.stevenson, jacopo.mondi, mchehab, robh,
krzysztof.kozlowski+dt, conor+dt, shawnguo, s.hauer, kernel,
festevam, sakari.ailus, devicetree, imx, linux-arm-kernel,
linux-kernel, phone-devel
In-Reply-To: <803b0bd3-e615-41c1-888e-69b6ecca0b8a@luigi311.com>
Quoting Luis Garcia (2024-04-06 06:25:41)
> On 4/3/24 12:45, Pavel Machek wrote:
> > Hi!
> >
> >> +/*
> >> + * 4208x3120 @ 30 fps needs 1267Mbps/lane, 4 lanes.
> >> + * To avoid further computation of clock settings, adopt the same per
> >> + * lane data rate when using 2 lanes, thus allowing a maximum of 15fps.
> >> + */
> >> +static const struct imx258_reg mipi_1267mbps_19_2mhz_2l[] = {
> >> + { 0x0136, 0x13 },
> >> + { 0x0137, 0x33 },
> >> + { 0x0301, 0x0A },
> >> + { 0x0303, 0x02 },
> >> + { 0x0305, 0x03 },
> >> + { 0x0306, 0x00 },
> >> + { 0x0307, 0xC6 },
> >> + { 0x0309, 0x0A },
> >> + { 0x030B, 0x01 },
> >> + { 0x030D, 0x02 },
> >> + { 0x030E, 0x00 },
> >> + { 0x030F, 0xD8 },
> >> + { 0x0310, 0x00 },
> >> +
> >> + { 0x0114, 0x01 },
> >> + { 0x0820, 0x09 },
> >> + { 0x0821, 0xa6 },
> >> + { 0x0822, 0x66 },
> >> + { 0x0823, 0x66 },
> >> +};
> >> +
> >> +static const struct imx258_reg mipi_1267mbps_19_2mhz_4l[] = {
> >> { 0x0136, 0x13 },
> >> { 0x0137, 0x33 },
> >> { 0x0301, 0x05 },
> >
> > I wish we did not have to copy all the magic values like this.
> >
> > Best regards,
> > Pavel
> >
>
> no kidding, magic values everywhere.... it makes it annoying
> for me to move things around because they all start to look
> similar. Down the line we added in more defined names so its
> not as bad but still its bad lol.
This series converts the defines to names, which is great. It would have
been nicer if the series converted first, but I know the history here
means you have done the register naming on top of existing patches - so
I don't think there's a requirement to change the ordering now.
But I see new drivers coming in with register tables. I hope we can
start to apply more pressure to driver submitters to use higher quality
named register sets in the future, now that we have a greater precendent
of sensor drivers 'doing the right thing'.
Sets of tables like we have are basically a binary blob stored as ascii
and make maintainance far more difficult IMO.
Maybe I should hit send on my comments on the latest GalaxyCore driver
coming in that I hesitated on ...
--
Kieran
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH v2 1/6] dt-bindings: firmware: arm,scmi: set additionalProperties to true
From: Krzysztof Kozlowski @ 2024-04-07 8:55 UTC (permalink / raw)
To: Peng Fan, Peng Fan (OSS), Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Shawn Guo, Sascha Hauer, Pengutronix Kernel Team,
Fabio Estevam, Sudeep Holla, Cristian Marussi
Cc: devicetree@vger.kernel.org, imx@lists.linux.dev,
linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org
In-Reply-To: <DU0PR04MB9417932A6208128FBBB22C4188012@DU0PR04MB9417.eurprd04.prod.outlook.com>
On 07/04/2024 02:37, Peng Fan wrote:
>> Subject: Re: [PATCH v2 1/6] dt-bindings: firmware: arm,scmi: set
>> additionalProperties to true
>>
>> On 05/04/2024 14:39, Peng Fan (OSS) wrote:
>>> From: Peng Fan <peng.fan@nxp.com>
>>>
>>> When adding vendor extension protocols, there is dt-schema warning:
>>> "
>>> imx,scmi.example.dtb: scmi: 'protocol@81', 'protocol@84' do not match
>>> any of the regexes: 'pinctrl-[0-9]+'
>>> "
>>>
>>> Set additionalProperties to true to address the issue.
>>
>> I do not see anything addressed here, except making the binding accepting
>> anything anywhere...
>
> I not wanna add vendor protocols in arm,scmi.yaml, so will introduce
> a new yaml imx.scmi.yaml which add i.MX SCMI protocol extension.
>
> With additionalProperties set to false, I not know how, please suggest.
First of all, you cannot affect negatively existing devices (their
bindings) and your patch does exactly that. This should make you thing
what is the correct approach...
Rob gave you the comment about missing compatible - you still did not
address that.
You need common schema referenced in arm,scmi and your device specific
schema, also using it.
Best regards,
Krzysztof
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH v2 2/6] dt-bindings: firmware: add i.MX SCMI Extension protocol
From: Krzysztof Kozlowski @ 2024-04-07 8:57 UTC (permalink / raw)
To: Peng Fan, Peng Fan (OSS), Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Shawn Guo, Sascha Hauer, Pengutronix Kernel Team,
Fabio Estevam, Sudeep Holla, Cristian Marussi
Cc: devicetree@vger.kernel.org, imx@lists.linux.dev,
linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org
In-Reply-To: <DU0PR04MB941719A18C3F749E7D180FD888012@DU0PR04MB9417.eurprd04.prod.outlook.com>
On 07/04/2024 02:51, Peng Fan wrote:
>> Subject: Re: [PATCH v2 2/6] dt-bindings: firmware: add i.MX SCMI Extension
>> protocol
>>
>> On 05/04/2024 14:39, Peng Fan (OSS) wrote:
>>> From: Peng Fan <peng.fan@nxp.com>
>>>
>>> Add i.MX SCMI Extension protocols bindings for:
>>> - Battery Backed Secure Module(BBSM)
>>
>> Which is what?
>
> I should say BBM(BBSM + BBNSM), BBM has RTC and ON/OFF
> key features, but BBM is managed by SCMI firmware and exported
> to agent by BBM protocol. So add bindings for i.MX BBM protocol.
>
> Is this ok?
No, I still don't know what is BBSM, BBNSM and BBM.
>
>>
>>> - MISC settings such as General Purpose Registers settings.
>>>
>>> Signed-off-by: Peng Fan <peng.fan@nxp.com>
>>> ---
>>> .../devicetree/bindings/firmware/imx,scmi.yaml | 80
>> ++++++++++++++++++++++
>>> 1 file changed, 80 insertions(+)
>>>
>>> diff --git a/Documentation/devicetree/bindings/firmware/imx,scmi.yaml
>>> b/Documentation/devicetree/bindings/firmware/imx,scmi.yaml
>>> new file mode 100644
>>> index 000000000000..7ee19a661d83
>>> --- /dev/null
>>> +++ b/Documentation/devicetree/bindings/firmware/imx,scmi.yaml
>>> @@ -0,0 +1,80 @@
>>> +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) # Copyright 2024
>>> +NXP %YAML 1.2
>>> +---
>>> +$id:
>>> +https://eur01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fdevi
>>>
>> +cetree.org%2Fschemas%2Ffirmware%2Fimx%2Cscmi.yaml%23&data=05%7
>> C02%7Cp
>>>
>> +eng.fan%40nxp.com%7C5d16781d3eca425a342508dc562910b7%7C686ea
>> 1d3bc2b4c
>>>
>> +6fa92cd99c5c301635%7C0%7C0%7C638479981570959816%7CUnknown%
>> 7CTWFpbGZsb
>>>
>> +3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn
>> 0%3D
>>>
>> +%7C0%7C%7C%7C&sdata=mWNwPvu2eyF18MroVOBHb%2Fjeo%2BIHfV5V
>> h%2F9ebdx65MM
>>> +%3D&reserved=0
>>> +$schema:
>>> +https://eur01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fdevi
>>> +cetree.org%2Fmeta-
>> schemas%2Fcore.yaml%23&data=05%7C02%7Cpeng.fan%40nx
>>>
>> +p.com%7C5d16781d3eca425a342508dc562910b7%7C686ea1d3bc2b4c6fa
>> 92cd99c5c
>>>
>> +301635%7C0%7C0%7C638479981570971949%7CUnknown%7CTWFpbGZs
>> b3d8eyJWIjoiM
>>>
>> +C4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C0%7
>> C%7C%7
>>>
>> +C&sdata=v4XnGG00D4I8j5MJvDUVYMRTm7yRrvz0V3fUyc5KAAA%3D&reser
>> ved=0
>>> +
>>> +title: i.MX System Control and Management Interface(SCMI) Vendor
>>> +Protocols Extension
>>> +
>>> +maintainers:
>>> + - Peng Fan <peng.fan@nxp.com>
>>> +
>>> +allOf:
>>> + - $ref: arm,scmi.yaml#
>>
>> Sorry, but arm,scmi is a final schema. Is your plan to define some common
>> part?
>
> No. I just wanna add vendor extension per SCMI spec.
>
> 0x80-0xFF:
> Reserved for vendor or platform-specific extensions to this interface
>
> Each vendor may have different usage saying id 0x81, so I add
> i.MX dt-schema file.
>
>>
>>> +
>>> +properties:
>>> + protocol@81:
>>> + $ref: 'arm,scmi.yaml#/$defs/protocol-node'
>>> + unevaluatedProperties: false
>>> + description:
>>> + The BBM Protocol is for managing Battery Backed Secure Module
>> (BBSM) RTC
>>> + and the ON/OFF Key
>>> +
>>> + properties:
>>> + reg:
>>> + const: 0x81
>>> +
>>> + required:
>>> + - reg
>>> +
>>> + protocol@84:
>>> + $ref: 'arm,scmi.yaml#/$defs/protocol-node'
>>> + unevaluatedProperties: false
>>> + description:
>>> + The MISC Protocol is for managing SoC Misc settings, such as
>>> + GPR settings
>>
>> Genera register is not a setting... this is a pleonasm. Please be more specific
>> what is the GPR, MISC protocol etc.
>
> The MISC Protocol is for managing SoC Misc settings, such as SAI MCLK/MQS in
> Always On domain BLK CTRL, SAI_CLK_SEL in WAKEUP BLK CTRL, gpio
> expanders which is under control of SCMI firmware.
So like a bag for everything which you do not want to call something
specific?
No, be specific...
>
>>> +
>>> + properties:
>>> + reg:
>>> + const: 0x84
>>> +
>>> + wakeup-sources:
>>> + description:
>>> + Each entry consists of 2 integers, represents the source
>>> + and electric signal edge
>>
>> Can you answer questions from reviewers?
>
> Sorry. Is this ok?
> minItems: 1
> maxItems: 32
No. Does it answers Rob's question? I see zero correlation to his question.
Do not ignore emails from reviewers but respond to them.
>
>>
>>> + items:
>>> + items:
>>> + - description: the wakeup source
>>> + - description: the wakeup electric signal edge
>>> + $ref: /schemas/types.yaml#/definitions/uint32-matrix
>>> +
>>> + required:
>>> + - reg
>>> +
>>> +additionalProperties: false
>>> +
>>> +examples:
>>> + - |
>>> + firmware {
>>> + scmi {
>>> + compatible = "arm,scmi";
>>
>>> + mboxes = <&mu2 5 0>, <&mu2 3 0>, <&mu2 3 1>;
>>> + shmem = <&scmi_buf0>, <&scmi_buf1>;
>>> +
>>> + #address-cells = <1>;
>>> + #size-cells = <0>;
>>> +
>>> + protocol@81 {
>>> + reg = <0x81>;
>>> + };
>>> +
>>> + protocol@84 {
>>> + reg = <0x84>;
>>> + wakeup-sources = <0x8000 1
>>> + 0x8001 1
>>> + 0x8002 1
>>> + 0x8003 1
>>> + 0x8004 1>;
>>
>> Nothing improved... If you are going to ignore reviews, then you will only get
>> NAKed.
>
> Sorry, you mean the examples, or the whole dt-schema?
*Read comments and respond to them*. Regardless where they are.
Best regards,
Krzysztof
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH v1 1/1] arm64: dts: imx93-11x11-evk: add rtc PCF2131 support
From: Krzysztof Kozlowski @ 2024-04-07 9:04 UTC (permalink / raw)
To: Joy Zou, ping.bai, robh+dt, krzysztof.kozlowski+dt, conor+dt,
shawnguo, s.hauer
Cc: kernel, festevam, linux-imx, devicetree, imx, linux-arm-kernel,
linux-kernel
In-Reply-To: <20240407051913.1989364-2-joy.zou@nxp.com>
On 07/04/2024 07:19, Joy Zou wrote:
> Support rtc PCF2131 on imx93-11x11-evk.
>
> Signed-off-by: Joy Zou <joy.zou@nxp.com>
> ---
> .../boot/dts/freescale/imx93-11x11-evk.dts | 25 +++++++++++++++++++
> 1 file changed, 25 insertions(+)
>
> diff --git a/arch/arm64/boot/dts/freescale/imx93-11x11-evk.dts b/arch/arm64/boot/dts/freescale/imx93-11x11-evk.dts
> index 07e85a30a25f..065fa3390791 100644
> --- a/arch/arm64/boot/dts/freescale/imx93-11x11-evk.dts
> +++ b/arch/arm64/boot/dts/freescale/imx93-11x11-evk.dts
> @@ -281,6 +281,24 @@ ldo5: LDO5 {
> };
> };
>
> +&lpi2c3 {
> + #address-cells = <1>;
> + #size-cells = <0>;
> + clock-frequency = <400000>;
> + pinctrl-names = "default", "sleep";
> + pinctrl-0 = <&pinctrl_lpi2c3>;
> + pinctrl-1 = <&pinctrl_lpi2c3>;
> + status = "okay";
> +
> + pcf2131: rtc@53 {
> + compatible = "nxp,pcf2131";
> + reg = <0x53>;
> + interrupt-parent = <&pcal6524>;
> + interrupts = <1 IRQ_TYPE_EDGE_FALLING>;
> + status = "okay";
Really, just drop...
Best regards,
Krzysztof
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH v4 4/5] dt-bindings: fsl-imx-sdma: Add I2C peripheral types ID
From: Krzysztof Kozlowski @ 2024-04-07 9:04 UTC (permalink / raw)
To: Frank Li, Vinod Koul, Shawn Guo, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam, NXP Linux Team,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Joy Zou
Cc: dmaengine, linux-arm-kernel, linux-kernel, devicetree, imx
In-Reply-To: <20240329-sdma_upstream-v4-4-daeb3067dea7@nxp.com>
On 29/03/2024 15:34, Frank Li wrote:
> Add peripheral types ID 26 for I2C because sdma firmware (sdma-6q: v3.6,
> sdma-7d: v4.6) support I2C DMA transfer.
>
> Signed-off-by: Frank Li <Frank.Li@nxp.com>
This is a friendly reminder during the review process.
It looks like you received a tag and forgot to add it.
If you do not know the process, here is a short explanation:
Please add Acked-by/Reviewed-by/Tested-by tags when posting new
versions, under or above your Signed-off-by tag. Tag is "received", when
provided in a message replied to you on the mailing list. Tools like b4
can help here. However, there's no need to repost patches *only* to add
the tags. The upstream maintainer will do that for tags received on the
version they apply.
https://elixir.bootlin.com/linux/v6.5-rc3/source/Documentation/process/submitting-patches.rst#L577
If a tag was not added on purpose, please state why and what changed.
Best regards,
Krzysztof
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [PATCH v3 1/2] dt-bindings: arm: qcom: Add Motorola Moto G (2013)
From: Stanislav Jakubek @ 2024-04-07 9:05 UTC (permalink / raw)
To: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
Conor Dooley
Cc: linux-arm-msm, devicetree, linux-arm-kernel, phone-devel,
linux-kernel
Document the Motorola Moto G (2013), which is a smartphone based
on the Qualcomm MSM8226 SoC.
Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Signed-off-by: Stanislav Jakubek <stano.jakubek@gmail.com>
---
Changes in V3:
- no changes
Changes in V2:
- collect Krzysztof's A-b
Documentation/devicetree/bindings/arm/qcom.yaml | 1 +
1 file changed, 1 insertion(+)
diff --git a/Documentation/devicetree/bindings/arm/qcom.yaml b/Documentation/devicetree/bindings/arm/qcom.yaml
index 66beaac60e1d..d2910982ae86 100644
--- a/Documentation/devicetree/bindings/arm/qcom.yaml
+++ b/Documentation/devicetree/bindings/arm/qcom.yaml
@@ -137,6 +137,7 @@ properties:
- microsoft,dempsey
- microsoft,makepeace
- microsoft,moneypenny
+ - motorola,falcon
- samsung,s3ve3g
- const: qcom,msm8226
--
2.34.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH v3 2/2] ARM: dts: qcom: Add support for Motorola Moto G (2013)
From: Stanislav Jakubek @ 2024-04-07 9:05 UTC (permalink / raw)
To: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
Conor Dooley
Cc: linux-arm-msm, devicetree, linux-arm-kernel, phone-devel,
linux-kernel
In-Reply-To: <32c507337ab80c550fb1df08f7014d1e31eb4c32.1712480582.git.stano.jakubek@gmail.com>
Add a device tree for the Motorola Moto G (2013) smartphone based
on the Qualcomm MSM8226 SoC.
Initially supported features:
- Buttons (Volume Down/Up, Power)
- eMMC
- Hall Effect Sensor
- SimpleFB display
- TMP108 temperature sensor
- Vibrator
Note: the dhob and shob reserved-memory regions are seemingly a part of some
Motorola specific (firmware?) mechanism, see [1].
[1] https://github.com/LineageOS/android_kernel_motorola_msm8226/blob/cm-14.1/Documentation/devicetree/bindings/misc/hob_ram.txt
Reviewed-by: Konrad Dybcio <konrad.dybcio@linaro.org>
Signed-off-by: Stanislav Jakubek <stano.jakubek@gmail.com>
---
Changes in V3:
- collect Konrad's R-b
Changes in V2:
- split hob-ram reserved-memory region into dhob and shob
- add a note and a link to downstream documentation with more
information about these regions
arch/arm/boot/dts/qcom/Makefile | 1 +
.../boot/dts/qcom/msm8226-motorola-falcon.dts | 359 ++++++++++++++++++
2 files changed, 360 insertions(+)
create mode 100644 arch/arm/boot/dts/qcom/msm8226-motorola-falcon.dts
diff --git a/arch/arm/boot/dts/qcom/Makefile b/arch/arm/boot/dts/qcom/Makefile
index 6478a39b3be5..3eacbf5c0785 100644
--- a/arch/arm/boot/dts/qcom/Makefile
+++ b/arch/arm/boot/dts/qcom/Makefile
@@ -1,5 +1,6 @@
# SPDX-License-Identifier: GPL-2.0
dtb-$(CONFIG_ARCH_QCOM) += \
+ msm8226-motorola-falcon.dtb \
qcom-apq8016-sbc.dtb \
qcom-apq8026-asus-sparrow.dtb \
qcom-apq8026-huawei-sturgeon.dtb \
diff --git a/arch/arm/boot/dts/qcom/msm8226-motorola-falcon.dts b/arch/arm/boot/dts/qcom/msm8226-motorola-falcon.dts
new file mode 100644
index 000000000000..029e1b1659c9
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/msm8226-motorola-falcon.dts
@@ -0,0 +1,359 @@
+// SPDX-License-Identifier: BSD-3-Clause
+
+/dts-v1/;
+
+#include "qcom-msm8226.dtsi"
+#include "pm8226.dtsi"
+
+/delete-node/ &smem_region;
+
+/ {
+ model = "Motorola Moto G (2013)";
+ compatible = "motorola,falcon", "qcom,msm8226";
+ chassis-type = "handset";
+
+ aliases {
+ mmc0 = &sdhc_1;
+ };
+
+ chosen {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ framebuffer@3200000 {
+ compatible = "simple-framebuffer";
+ reg = <0x03200000 0x800000>;
+ width = <720>;
+ height = <1280>;
+ stride = <(720 * 3)>;
+ format = "r8g8b8";
+ vsp-supply = <®_lcd_pos>;
+ vsn-supply = <®_lcd_neg>;
+ vddio-supply = <&vddio_disp_vreg>;
+ };
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+
+ event-hall-sensor {
+ label = "Hall Effect Sensor";
+ gpios = <&tlmm 51 GPIO_ACTIVE_LOW>;
+ linux,input-type = <EV_SW>;
+ linux,code = <SW_LID>;
+ linux,can-disable;
+ };
+
+ key-volume-up {
+ label = "Volume Up";
+ gpios = <&tlmm 106 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_VOLUMEUP>;
+ debounce-interval = <15>;
+ };
+ };
+
+ vddio_disp_vreg: regulator-vddio-disp {
+ compatible = "regulator-fixed";
+ regulator-name = "vddio_disp";
+ gpio = <&tlmm 34 GPIO_ACTIVE_HIGH>;
+ vin-supply = <&pm8226_l8>;
+ startup-delay-us = <300>;
+ enable-active-high;
+ regulator-boot-on;
+ };
+
+ reserved-memory {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ framebuffer@3200000 {
+ reg = <0x03200000 0x800000>;
+ no-map;
+ };
+
+ dhob@f500000 {
+ reg = <0x0f500000 0x40000>;
+ no-map;
+ };
+
+ shob@f540000 {
+ reg = <0x0f540000 0x2000>;
+ no-map;
+ };
+
+ smem_region: smem@fa00000 {
+ reg = <0x0fa00000 0x100000>;
+ no-map;
+ };
+
+ /* Actually <0x0fa00000 0x500000>, but first 100000 is smem */
+ reserved@fb00000 {
+ reg = <0x0fb00000 0x400000>;
+ no-map;
+ };
+ };
+};
+
+&blsp1_i2c3 {
+ status = "okay";
+
+ regulator@3e {
+ compatible = "ti,tps65132";
+ reg = <0x3e>;
+ pinctrl-0 = <®_lcd_default>;
+ pinctrl-names = "default";
+
+ reg_lcd_pos: outp {
+ regulator-name = "outp";
+ regulator-min-microvolt = <4000000>;
+ regulator-max-microvolt = <6000000>;
+ regulator-active-discharge = <1>;
+ regulator-boot-on;
+ enable-gpios = <&tlmm 31 GPIO_ACTIVE_HIGH>;
+ };
+
+ reg_lcd_neg: outn {
+ regulator-name = "outn";
+ regulator-min-microvolt = <4000000>;
+ regulator-max-microvolt = <6000000>;
+ regulator-active-discharge = <1>;
+ regulator-boot-on;
+ enable-gpios = <&tlmm 33 GPIO_ACTIVE_HIGH>;
+ };
+ };
+
+ temperature-sensor@48 {
+ compatible = "ti,tmp108";
+ reg = <0x48>;
+ interrupts-extended = <&tlmm 13 IRQ_TYPE_LEVEL_LOW>;
+ pinctrl-0 = <&temp_alert_default>;
+ pinctrl-names = "default";
+ #thermal-sensor-cells = <0>;
+ };
+};
+
+&pm8226_resin {
+ linux,code = <KEY_VOLUMEDOWN>;
+ status = "okay";
+};
+
+&pm8226_vib {
+ status = "okay";
+};
+
+&rpm_requests {
+ regulators {
+ compatible = "qcom,rpm-pm8226-regulators";
+
+ pm8226_s3: s3 {
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1300000>;
+ };
+
+ pm8226_s4: s4 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2200000>;
+ };
+
+ pm8226_s5: s5 {
+ regulator-min-microvolt = <1150000>;
+ regulator-max-microvolt = <1150000>;
+ };
+
+ pm8226_l1: l1 {
+ regulator-min-microvolt = <1225000>;
+ regulator-max-microvolt = <1225000>;
+ };
+
+ pm8226_l2: l2 {
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ };
+
+ pm8226_l3: l3 {
+ regulator-min-microvolt = <750000>;
+ regulator-max-microvolt = <1337500>;
+ };
+
+ pm8226_l4: l4 {
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ };
+
+ pm8226_l5: l5 {
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ };
+
+ pm8226_l6: l6 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-allow-set-load;
+ };
+
+ pm8226_l7: l7 {
+ regulator-min-microvolt = <1850000>;
+ regulator-max-microvolt = <1850000>;
+ };
+
+ pm8226_l8: l8 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ pm8226_l9: l9 {
+ regulator-min-microvolt = <2050000>;
+ regulator-max-microvolt = <2050000>;
+ };
+
+ pm8226_l10: l10 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ pm8226_l12: l12 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ pm8226_l14: l14 {
+ regulator-min-microvolt = <2750000>;
+ regulator-max-microvolt = <2750000>;
+ };
+
+ pm8226_l15: l15 {
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ };
+
+ pm8226_l16: l16 {
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3350000>;
+ };
+
+ pm8226_l17: l17 {
+ regulator-min-microvolt = <2950000>;
+ regulator-max-microvolt = <2950000>;
+ };
+
+ pm8226_l18: l18 {
+ regulator-min-microvolt = <2950000>;
+ regulator-max-microvolt = <2950000>;
+ };
+
+ pm8226_l19: l19 {
+ regulator-min-microvolt = <2850000>;
+ regulator-max-microvolt = <2850000>;
+ };
+
+ pm8226_l20: l20 {
+ regulator-min-microvolt = <3075000>;
+ regulator-max-microvolt = <3075000>;
+ };
+
+ pm8226_l21: l21 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2950000>;
+ regulator-allow-set-load;
+ };
+
+ pm8226_l22: l22 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2950000>;
+ };
+
+ pm8226_l23: l23 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2950000>;
+ };
+
+ pm8226_l24: l24 {
+ regulator-min-microvolt = <1300000>;
+ regulator-max-microvolt = <1350000>;
+ };
+
+ pm8226_l25: l25 {
+ regulator-min-microvolt = <1775000>;
+ regulator-max-microvolt = <2125000>;
+ };
+
+ pm8226_l26: l26 {
+ regulator-min-microvolt = <1225000>;
+ regulator-max-microvolt = <1225000>;
+ };
+
+ pm8226_l27: l27 {
+ regulator-min-microvolt = <2050000>;
+ regulator-max-microvolt = <2050000>;
+ };
+
+ pm8226_l28: l28 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3400000>;
+ regulator-boot-on;
+ };
+
+ pm8226_lvs1: lvs1 {
+ regulator-always-on;
+ };
+ };
+};
+
+&sdhc_1 {
+ vmmc-supply = <&pm8226_l17>;
+ vqmmc-supply = <&pm8226_l6>;
+
+ bus-width = <8>;
+ non-removable;
+
+ status = "okay";
+};
+
+&smbb {
+ qcom,fast-charge-safe-current = <2000000>;
+ qcom,fast-charge-current-limit = <1900000>;
+ qcom,fast-charge-safe-voltage = <4400000>;
+ qcom,minimum-input-voltage = <4300000>;
+
+ status = "okay";
+};
+
+&tlmm {
+ reg_lcd_default: reg-lcd-default-state {
+ pins = "gpio31", "gpio33";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ output-high;
+ };
+
+ reg_vddio_disp_default: reg-vddio-disp-default-state {
+ pins = "gpio34";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ output-high;
+ };
+
+ temp_alert_default: temp-alert-default-state {
+ pins = "gpio13";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ output-disable;
+ };
+};
+
+&usb {
+ extcon = <&smbb>;
+ dr_mode = "peripheral";
+ status = "okay";
+};
+
+&usb_hs_phy {
+ extcon = <&smbb>;
+ v1p8-supply = <&pm8226_l10>;
+ v3p3-supply = <&pm8226_l20>;
+};
--
2.34.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* Re: [PATCH v3 2/2] media: i2c: Add GC05A2 image sensor driver
From: Kieran Bingham @ 2024-04-07 9:08 UTC (permalink / raw)
To: Zhi Mao, krzysztof.kozlowski+dt, mchehab, robh+dt, sakari.ailus
Cc: laurent.pinchart, shengnan.wang, yaya.chang,
Project_Global_Chrome_Upstream_Group, yunkec, conor+dt,
matthias.bgg, angelogioacchino.delregno, jacopo.mondi, zhi.mao,
10572168, hverkuil-cisco, heiko, jernej.skrabec, macromorgan,
linus.walleij, hdegoede, tomi.valkeinen, gerald.loacker,
andy.shevchenko, bingbu.cao, dan.scally, linux-media, devicetree,
linux-kernel, linux-arm-kernel, linux-mediatek
In-Reply-To: <20240403033825.9072-3-zhi.mao@mediatek.com>
Hello,
Thanks for helping extending the kernels sensor driver support.
My comments below can likely be taken with a pinch of salt, as they are
mostly around the tabled register values ... but we have many drivers
which are binary blobs of sensor register values and I think it would be
far more beneficial to clean these up where possible...
So the first question is ... Can we ?
Quoting Zhi Mao (2024-04-03 04:38:25)
> Add a V4L2 sub-device driver for Galaxycore GC05A2 image sensor.
>
> Signed-off-by: Zhi Mao <zhi.mao@mediatek.com>
> ---
> drivers/media/i2c/Kconfig | 10 +
> drivers/media/i2c/Makefile | 1 +
> drivers/media/i2c/gc05a2.c | 1383 ++++++++++++++++++++++++++++++++++++
> 3 files changed, 1394 insertions(+)
> create mode 100644 drivers/media/i2c/gc05a2.c
>
> diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig
> index 56f276b920ab..97993bf160f9 100644
> --- a/drivers/media/i2c/Kconfig
> +++ b/drivers/media/i2c/Kconfig
> @@ -70,6 +70,16 @@ config VIDEO_GC0308
> To compile this driver as a module, choose M here: the
> module will be called gc0308.
>
> +config VIDEO_GC05A2
> + tristate "GalaxyCore gc05a2 sensor support"
> + select V4L2_CCI_I2C
> + help
> + This is a Video4Linux2 sensor driver for the GalaxyCore gc05a2
> + camera.
> +
> + To compile this driver as a module, choose M here: the
> + module will be called gc05a2.
> +
> config VIDEO_GC2145
> select V4L2_CCI_I2C
> tristate "GalaxyCore GC2145 sensor support"
> diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile
> index dfbe6448b549..8ed6faf0f854 100644
> --- a/drivers/media/i2c/Makefile
> +++ b/drivers/media/i2c/Makefile
> @@ -38,6 +38,7 @@ obj-$(CONFIG_VIDEO_DW9768) += dw9768.o
> obj-$(CONFIG_VIDEO_DW9807_VCM) += dw9807-vcm.o
> obj-$(CONFIG_VIDEO_ET8EK8) += et8ek8/
> obj-$(CONFIG_VIDEO_GC0308) += gc0308.o
> +obj-$(CONFIG_VIDEO_GC05A2) += gc05a2.o
> obj-$(CONFIG_VIDEO_GC2145) += gc2145.o
> obj-$(CONFIG_VIDEO_HI556) += hi556.o
> obj-$(CONFIG_VIDEO_HI846) += hi846.o
> diff --git a/drivers/media/i2c/gc05a2.c b/drivers/media/i2c/gc05a2.c
> new file mode 100644
> index 000000000000..461d33055a3b
> --- /dev/null
> +++ b/drivers/media/i2c/gc05a2.c
> @@ -0,0 +1,1383 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Driver for GalaxyCore gc05a2 image sensor
> + *
> + * Copyright 2024 MediaTek
> + *
> + * Zhi Mao <zhi.mao@mediatek.com>
> + */
> +#include <linux/array_size.h>
> +#include <linux/bits.h>
> +#include <linux/clk.h>
> +#include <linux/container_of.h>
> +#include <linux/delay.h>
> +#include <linux/device.h>
> +#include <linux/err.h>
> +#include <linux/gpio/consumer.h>
> +#include <linux/math64.h>
> +#include <linux/mod_devicetable.h>
> +#include <linux/pm_runtime.h>
> +#include <linux/property.h>
> +#include <linux/regulator/consumer.h>
> +#include <linux/types.h>
> +#include <linux/units.h>
> +
> +#include <media/v4l2-cci.h>
> +#include <media/v4l2-ctrls.h>
> +#include <media/v4l2-event.h>
> +#include <media/v4l2-fwnode.h>
> +#include <media/v4l2-subdev.h>
> +
> +#define GC05A2_REG_TEST_PATTERN_EN CCI_REG8(0x008c)
> +#define GC05A2_REG_TEST_PATTERN_IDX CCI_REG8(0x008d)
> +#define GC05A2_TEST_PATTERN_EN 0x01
> +
> +#define GC05A2_STREAMING_REG CCI_REG8(0x0100)
> +
> +#define GC05A2_FLIP_REG CCI_REG8(0x0101)
> +#define GC05A2_FLIP_H_MASK BIT(0)
> +#define GC05A2_FLIP_V_MASK BIT(1)
> +
> +#define GC05A2_EXP_REG CCI_REG16(0x0202)
> +#define GC05A2_EXP_MARGIN 16
> +#define GC05A2_EXP_MIN 4
> +#define GC05A2_EXP_STEP 1
> +
> +#define GC05A2_AGAIN_REG CCI_REG16(0x0204)
> +#define GC05A2_AGAIN_MIN 1024
> +#define GC05A2_AGAIN_MAX (1024 * 16)
> +#define GC05A2_AGAIN_STEP 1
> +
> +#define GC05A2_FRAME_LENGTH_REG CCI_REG16(0x0340)
> +#define GC05A2_VTS_MAX 0xffff
> +
> +#define GC05A2_REG_CHIP_ID CCI_REG16(0x03f0)
> +#define GC05A2_CHIP_ID 0x05a2
> +
> +#define GC05A2_NATIVE_WIDTH 2592
> +#define GC05A2_NATIVE_HEIGHT 1944
> +
> +#define GC05A2_DEFAULT_CLK_FREQ (24 * HZ_PER_MHZ)
> +#define GC05A2_MBUS_CODE MEDIA_BUS_FMT_SGRBG10_1X10
> +#define GC05A2_DATA_LANES 2
> +#define GC05A2_RGB_DEPTH 10
> +#define GC05A2_SLEEP_US (2 * USEC_PER_MSEC)
> +
> +static const char *const gc05a2_test_pattern_menu[] = {
> + "No Pattern", "Fade_to_gray_Color Bar", "Color Bar",
> + "PN9", "Horizental_gradient", "Checkboard Pattern",
> + "Slant", "Resolution", "Solid Black",
> + "Solid White",
> +};
> +
> +static const s64 gc05a2_link_freq_menu_items[] = {
> + (448 * HZ_PER_MHZ),
> + (224 * HZ_PER_MHZ),
> +};
> +
> +static const char *const gc05a2_supply_name[] = {
> + "avdd",
> + "dvdd",
> + "dovdd",
> +};
> +
> +struct gc05a2 {
> + struct device *dev;
> + struct v4l2_subdev sd;
> + struct media_pad pad;
> +
> + struct clk *xclk;
> + struct regulator_bulk_data supplies[ARRAY_SIZE(gc05a2_supply_name)];
> + struct gpio_desc *reset_gpio;
> +
> + struct v4l2_ctrl_handler ctrls;
> + struct v4l2_ctrl *pixel_rate;
> + struct v4l2_ctrl *link_freq;
> + struct v4l2_ctrl *exposure;
> + struct v4l2_ctrl *vblank;
> + struct v4l2_ctrl *hblank;
> + struct v4l2_ctrl *hflip;
> + struct v4l2_ctrl *vflip;
> +
> + struct regmap *regmap;
> + unsigned long link_freq_bitmap;
> +
> + /* True if the device has been identified */
> + bool identified;
> + const struct gc05a2_mode *cur_mode;
> +};
> +
> +struct gc05a2_reg_list {
> + u32 num_of_regs;
> + const struct cci_reg_sequence *regs;
> +};
> +
> +static const struct cci_reg_sequence mode_2592x1944[] = {
> + /* system */
> + { CCI_REG8(0x0135), 0x01 },
> +
> + /* pre_setting */
> + { CCI_REG8(0x0084), 0x21 },
> + { CCI_REG8(0x0d05), 0xcc },
> + { CCI_REG8(0x0218), 0x00 },
> + { CCI_REG8(0x005e), 0x48 },
> + { CCI_REG8(0x0d06), 0x01 },
> + { CCI_REG8(0x0007), 0x16 },
> + { CCI_REG8(0x0101), 0x00 },
> +
> + /* analog */
> + { CCI_REG8(0x0342), 0x07 },
> + { CCI_REG8(0x0343), 0x28 },
> + { CCI_REG8(0x0220), 0x07 },
> + { CCI_REG8(0x0221), 0xd0 },
> + { CCI_REG8(0x0202), 0x07 },
> + { CCI_REG8(0x0203), 0x32 },
> + { CCI_REG8(0x0340), 0x07 },
> + { CCI_REG8(0x0341), 0xf0 },
> + { CCI_REG8(0x0219), 0x00 },
> + { CCI_REG8(0x0346), 0x00 },
> + { CCI_REG8(0x0347), 0x04 },
> + { CCI_REG8(0x0d14), 0x00 },
> + { CCI_REG8(0x0d13), 0x05 },
> + { CCI_REG8(0x0d16), 0x05 },
> + { CCI_REG8(0x0d15), 0x1d },
> + { CCI_REG8(0x00c0), 0x0a },
> + { CCI_REG8(0x00c1), 0x30 },
> + { CCI_REG8(0x034a), 0x07 },
> + { CCI_REG8(0x034b), 0xa8 },
> + { CCI_REG8(0x0e0a), 0x00 },
> + { CCI_REG8(0x0e0b), 0x00 },
> + { CCI_REG8(0x0e0e), 0x03 },
> + { CCI_REG8(0x0e0f), 0x00 },
> + { CCI_REG8(0x0e06), 0x0a },
> + { CCI_REG8(0x0e23), 0x15 },
> + { CCI_REG8(0x0e24), 0x15 },
> + { CCI_REG8(0x0e2a), 0x10 },
> + { CCI_REG8(0x0e2b), 0x10 },
> + { CCI_REG8(0x0e17), 0x49 },
> + { CCI_REG8(0x0e1b), 0x1c },
> + { CCI_REG8(0x0e3a), 0x36 },
> + { CCI_REG8(0x0d11), 0x84 },
> + { CCI_REG8(0x0e52), 0x14 },
> + { CCI_REG8(0x000b), 0x10 },
> + { CCI_REG8(0x0008), 0x08 },
> + { CCI_REG8(0x0223), 0x17 },
> + { CCI_REG8(0x0d27), 0x39 },
> + { CCI_REG8(0x0d22), 0x00 },
> + { CCI_REG8(0x03f6), 0x0d },
> + { CCI_REG8(0x0d04), 0x07 },
> + { CCI_REG8(0x03f3), 0x72 },
> + { CCI_REG8(0x03f4), 0xb8 },
> + { CCI_REG8(0x03f5), 0xbc },
> + { CCI_REG8(0x0d02), 0x73 },
> +
> + /* auto load start */
> + { CCI_REG8(0x00cb), 0x00 },
> +
> + /* OUT 2592*1944 */
> + { CCI_REG8(0x0350), 0x01 },
> + { CCI_REG8(0x0353), 0x00 },
> + { CCI_REG8(0x0354), 0x08 },
> + { CCI_REG8(0x034c), 0x0a },
> + { CCI_REG8(0x034d), 0x20 },
Should/Could this be
{ CCI_REG16(0x034c), 2592 }, /* Width */
> + { CCI_REG8(0x021f), 0x14 },
> +
> + /* MIPI */
> + { CCI_REG8(0x0107), 0x05 },
> + { CCI_REG8(0x0117), 0x01 },
> + { CCI_REG8(0x0d81), 0x00 },
> + { CCI_REG8(0x0d84), 0x0c },
> + { CCI_REG8(0x0d85), 0xa8 },
> + { CCI_REG8(0x0d86), 0x06 },
> + { CCI_REG8(0x0d87), 0x55 },
> + { CCI_REG8(0x0db3), 0x06 },
> + { CCI_REG8(0x0db4), 0x08 },
> + { CCI_REG8(0x0db5), 0x1e },
> + { CCI_REG8(0x0db6), 0x02 },
> + { CCI_REG8(0x0db8), 0x12 },
> + { CCI_REG8(0x0db9), 0x0a },
> + { CCI_REG8(0x0d93), 0x06 },
> + { CCI_REG8(0x0d94), 0x09 },
> + { CCI_REG8(0x0d95), 0x0d },
> + { CCI_REG8(0x0d99), 0x0b },
> + { CCI_REG8(0x0084), 0x01 },
> +
> + /* OUT */
> + { CCI_REG8(0x0110), 0x01 },
> +};
> +
> +static const struct cci_reg_sequence mode_1280x720[] = {
> + /* system */
> + { CCI_REG8(0x0135), 0x05 },
In 2592x1944 this is 0x01. Do you have a datasheet? Can you explain why
they are different? Can you add register definitions that have names to
make this more maintainable or extendable in the future?
There's discussion in the recent series improving the IMX258 which makes
me wonder if we should try harder to have sensor drivers with clearer
definitions.
> +
> + /*pre_setting*/
/* pre_setting */ ?
> + { CCI_REG8(0x0084), 0x21 },
> + { CCI_REG8(0x0d05), 0xcc },
> + { CCI_REG8(0x0218), 0x80 },
> + { CCI_REG8(0x005e), 0x49 },
> + { CCI_REG8(0x0d06), 0x81 },
> + { CCI_REG8(0x0007), 0x16 },
> + { CCI_REG8(0x0101), 0x00 },
In 2592x1944, only register 0x0218 differs. Why? What is that? Can it be
broken out to a function that applies the correct configuration at
startuup based on a parameter instead of duplicating this table set?
> +
> + /* analog */
> + { CCI_REG8(0x0342), 0x07 },
> + { CCI_REG8(0x0343), 0x10 },
> + { CCI_REG8(0x0220), 0x07 },
> + { CCI_REG8(0x0221), 0xd0 },
> + { CCI_REG8(0x0202), 0x03 },
> + { CCI_REG8(0x0203), 0x32 },
> + { CCI_REG8(0x0340), 0x04 },
> + { CCI_REG8(0x0341), 0x08 },
> + { CCI_REG8(0x0219), 0x00 },
> + { CCI_REG8(0x0346), 0x01 },
> + { CCI_REG8(0x0347), 0x00 },
> + { CCI_REG8(0x0d14), 0x00 },
> + { CCI_REG8(0x0d13), 0x05 },
> + { CCI_REG8(0x0d16), 0x05 },
> + { CCI_REG8(0x0d15), 0x1d },
> + { CCI_REG8(0x00c0), 0x0a },
> + { CCI_REG8(0x00c1), 0x30 },
> + { CCI_REG8(0x034a), 0x05 },
> + { CCI_REG8(0x034b), 0xb0 },
> + { CCI_REG8(0x0e0a), 0x00 },
> + { CCI_REG8(0x0e0b), 0x00 },
> + { CCI_REG8(0x0e0e), 0x03 },
> + { CCI_REG8(0x0e0f), 0x00 },
> + { CCI_REG8(0x0e06), 0x0a },
> + { CCI_REG8(0x0e23), 0x15 },
> + { CCI_REG8(0x0e24), 0x15 },
> + { CCI_REG8(0x0e2a), 0x10 },
> + { CCI_REG8(0x0e2b), 0x10 },
> + { CCI_REG8(0x0e17), 0x49 },
> + { CCI_REG8(0x0e1b), 0x1c },
> + { CCI_REG8(0x0e3a), 0x36 },
> + { CCI_REG8(0x0d11), 0x84 },
> + { CCI_REG8(0x0e52), 0x14 },
> + { CCI_REG8(0x000b), 0x0e },
> + { CCI_REG8(0x0008), 0x03 },
> + { CCI_REG8(0x0223), 0x16 },
> + { CCI_REG8(0x0d27), 0x39 },
> + { CCI_REG8(0x0d22), 0x00 },
> + { CCI_REG8(0x03f6), 0x0d },
> + { CCI_REG8(0x0d04), 0x07 },
> + { CCI_REG8(0x03f3), 0x72 },
> + { CCI_REG8(0x03f4), 0xb8 },
> + { CCI_REG8(0x03f5), 0xbc },
> + { CCI_REG8(0x0d02), 0x73 },
> +
Are any of those able to be broken out to named register to be more
clear in their intent?
> + /* auto load start */
> + { CCI_REG8(0x00cb), 0xfc },
> +
Why is this auto load start so different to the other modes 'auto load
start'? What do the bits refer to ?
> + /* OUT 1280x720 */
> + { CCI_REG8(0x0350), 0x01 },
> + { CCI_REG8(0x0353), 0x00 },
> + { CCI_REG8(0x0354), 0x0c },
> + { CCI_REG8(0x034c), 0x05 },
> + { CCI_REG8(0x034d), 0x00 },
Should/Could this be
{ CCI_REG16(0x034c), 1280 },
Are there any other register settings that would make more sense to be
in decimal units that match their actual context?
> + { CCI_REG8(0x021f), 0x14 },
I don't see a setting for 720/0x2d0. Do these registers only set the
width?
> +
> + /* MIPI */
> + { CCI_REG8(0x0107), 0x05 },
> + { CCI_REG8(0x0117), 0x01 },
> + { CCI_REG8(0x0d81), 0x00 },
> + { CCI_REG8(0x0d84), 0x06 },
> + { CCI_REG8(0x0d85), 0x40 },
> + { CCI_REG8(0x0d86), 0x03 },
> + { CCI_REG8(0x0d87), 0x21 },
> + { CCI_REG8(0x0db3), 0x03 },
> + { CCI_REG8(0x0db4), 0x04 },
> + { CCI_REG8(0x0db5), 0x0d },
> + { CCI_REG8(0x0db6), 0x01 },
> + { CCI_REG8(0x0db8), 0x04 },
> + { CCI_REG8(0x0db9), 0x06 },
> + { CCI_REG8(0x0d93), 0x03 },
> + { CCI_REG8(0x0d94), 0x04 },
> + { CCI_REG8(0x0d95), 0x05 },
> + { CCI_REG8(0x0d99), 0x06 },
> + { CCI_REG8(0x0084), 0x01 },
> +
> + /* OUT */
Out where? What is out?
> + { CCI_REG8(0x0110), 0x01 },
> +};
> +
> +static const struct cci_reg_sequence mode_table_common[] = {
> + { GC05A2_STREAMING_REG, 0x00 },
> + /* system */
> + { CCI_REG8(0x0315), 0xd4 },
> + { CCI_REG8(0x0d06), 0x01 },
> + { CCI_REG8(0x0a70), 0x80 },
> + { CCI_REG8(0x031a), 0x00 },
> + { CCI_REG8(0x0314), 0x00 },
> + { CCI_REG8(0x0130), 0x08 },
> + { CCI_REG8(0x0132), 0x01 },
> + { CCI_REG8(0x0136), 0x38 },
> + { CCI_REG8(0x0137), 0x03 },
> + { CCI_REG8(0x0134), 0x5b },
> + { CCI_REG8(0x031c), 0xe0 },
> + { CCI_REG8(0x0d82), 0x14 },
> + { CCI_REG8(0x0dd1), 0x56 },
> +
> + /* gate_mode */
> + { CCI_REG8(0x0af4), 0x01 },
> + { CCI_REG8(0x0002), 0x10 },
> + { CCI_REG8(0x00c3), 0x34 },
> +
> + /* auto load start */
The previous 'auto load start' referenced 0x00cb ?
> + { CCI_REG8(0x00c4), 0x00 },
> + { CCI_REG8(0x00c5), 0x01 },
> + { CCI_REG8(0x0af6), 0x00 },
> + { CCI_REG8(0x0ba0), 0x17 },
> + { CCI_REG8(0x0ba1), 0x00 },
> + { CCI_REG8(0x0ba2), 0x00 },
> + { CCI_REG8(0x0ba3), 0x00 },
> + { CCI_REG8(0x0ba4), 0x03 },
> + { CCI_REG8(0x0ba5), 0x00 },
> + { CCI_REG8(0x0ba6), 0x00 },
> + { CCI_REG8(0x0ba7), 0x00 },
> + { CCI_REG8(0x0ba8), 0x40 },
> + { CCI_REG8(0x0ba9), 0x00 },
> + { CCI_REG8(0x0baa), 0x00 },
> + { CCI_REG8(0x0bab), 0x00 },
> + { CCI_REG8(0x0bac), 0x40 },
> + { CCI_REG8(0x0bad), 0x00 },
> + { CCI_REG8(0x0bae), 0x00 },
> + { CCI_REG8(0x0baf), 0x00 },
> + { CCI_REG8(0x0bb0), 0x02 },
> + { CCI_REG8(0x0bb1), 0x00 },
> + { CCI_REG8(0x0bb2), 0x00 },
> + { CCI_REG8(0x0bb3), 0x00 },
> + { CCI_REG8(0x0bb8), 0x02 },
> + { CCI_REG8(0x0bb9), 0x00 },
> + { CCI_REG8(0x0bba), 0x00 },
> + { CCI_REG8(0x0bbb), 0x00 },
> + { CCI_REG8(0x0a70), 0x80 },
> + { CCI_REG8(0x0a71), 0x00 },
> + { CCI_REG8(0x0a72), 0x00 },
> + { CCI_REG8(0x0a66), 0x00 },
> + { CCI_REG8(0x0a67), 0x80 },
> + { CCI_REG8(0x0a4d), 0x4e },
> + { CCI_REG8(0x0a50), 0x00 },
> + { CCI_REG8(0x0a4f), 0x0c },
> + { CCI_REG8(0x0a66), 0x00 },
> + { CCI_REG8(0x00ca), 0x00 },
> + { CCI_REG8(0x00cc), 0x00 },
> + { CCI_REG8(0x00cd), 0x00 },
> + { CCI_REG8(0x0aa1), 0x00 },
> + { CCI_REG8(0x0aa2), 0xe0 },
> + { CCI_REG8(0x0aa3), 0x00 },
> + { CCI_REG8(0x0aa4), 0x40 },
> + { CCI_REG8(0x0a90), 0x03 },
> + { CCI_REG8(0x0a91), 0x0e },
> + { CCI_REG8(0x0a94), 0x80 },
> +
> + /* standby */
> + { CCI_REG8(0x0af6), 0x20 },
> + { CCI_REG8(0x0b00), 0x91 },
> + { CCI_REG8(0x0b01), 0x17 },
> + { CCI_REG8(0x0b02), 0x01 },
> + { CCI_REG8(0x0b03), 0x00 },
> + { CCI_REG8(0x0b04), 0x01 },
> + { CCI_REG8(0x0b05), 0x17 },
> + { CCI_REG8(0x0b06), 0x01 },
> + { CCI_REG8(0x0b07), 0x00 },
> + { CCI_REG8(0x0ae9), 0x01 },
> + { CCI_REG8(0x0aea), 0x02 },
> + { CCI_REG8(0x0ae8), 0x53 },
> + { CCI_REG8(0x0ae8), 0x43 },
> +
> + /* gain_partition */
> + { CCI_REG8(0x0af6), 0x30 },
> + { CCI_REG8(0x0b00), 0x08 },
> + { CCI_REG8(0x0b01), 0x0f },
> + { CCI_REG8(0x0b02), 0x00 },
> + { CCI_REG8(0x0b04), 0x1c },
> + { CCI_REG8(0x0b05), 0x24 },
> + { CCI_REG8(0x0b06), 0x00 },
> + { CCI_REG8(0x0b08), 0x30 },
> + { CCI_REG8(0x0b09), 0x40 },
> + { CCI_REG8(0x0b0a), 0x00 },
> + { CCI_REG8(0x0b0c), 0x0e },
> + { CCI_REG8(0x0b0d), 0x2a },
> + { CCI_REG8(0x0b0e), 0x00 },
> + { CCI_REG8(0x0b10), 0x0e },
> + { CCI_REG8(0x0b11), 0x2b },
> + { CCI_REG8(0x0b12), 0x00 },
> + { CCI_REG8(0x0b14), 0x0e },
> + { CCI_REG8(0x0b15), 0x23 },
> + { CCI_REG8(0x0b16), 0x00 },
> + { CCI_REG8(0x0b18), 0x0e },
> + { CCI_REG8(0x0b19), 0x24 },
> + { CCI_REG8(0x0b1a), 0x00 },
> + { CCI_REG8(0x0b1c), 0x0c },
> + { CCI_REG8(0x0b1d), 0x0c },
> + { CCI_REG8(0x0b1e), 0x00 },
> + { CCI_REG8(0x0b20), 0x03 },
> + { CCI_REG8(0x0b21), 0x03 },
> + { CCI_REG8(0x0b22), 0x00 },
> + { CCI_REG8(0x0b24), 0x0e },
> + { CCI_REG8(0x0b25), 0x0e },
> + { CCI_REG8(0x0b26), 0x00 },
> + { CCI_REG8(0x0b28), 0x03 },
> + { CCI_REG8(0x0b29), 0x03 },
> + { CCI_REG8(0x0b2a), 0x00 },
> + { CCI_REG8(0x0b2c), 0x12 },
> + { CCI_REG8(0x0b2d), 0x12 },
> + { CCI_REG8(0x0b2e), 0x00 },
> + { CCI_REG8(0x0b30), 0x08 },
> + { CCI_REG8(0x0b31), 0x08 },
> + { CCI_REG8(0x0b32), 0x00 },
> + { CCI_REG8(0x0b34), 0x14 },
> + { CCI_REG8(0x0b35), 0x14 },
> + { CCI_REG8(0x0b36), 0x00 },
> + { CCI_REG8(0x0b38), 0x10 },
> + { CCI_REG8(0x0b39), 0x10 },
> + { CCI_REG8(0x0b3a), 0x00 },
> + { CCI_REG8(0x0b3c), 0x16 },
> + { CCI_REG8(0x0b3d), 0x16 },
> + { CCI_REG8(0x0b3e), 0x00 },
> + { CCI_REG8(0x0b40), 0x10 },
> + { CCI_REG8(0x0b41), 0x10 },
> + { CCI_REG8(0x0b42), 0x00 },
> + { CCI_REG8(0x0b44), 0x19 },
> + { CCI_REG8(0x0b45), 0x19 },
> + { CCI_REG8(0x0b46), 0x00 },
> + { CCI_REG8(0x0b48), 0x16 },
> + { CCI_REG8(0x0b49), 0x16 },
> + { CCI_REG8(0x0b4a), 0x00 },
> + { CCI_REG8(0x0b4c), 0x19 },
> + { CCI_REG8(0x0b4d), 0x19 },
> + { CCI_REG8(0x0b4e), 0x00 },
> + { CCI_REG8(0x0b50), 0x16 },
> + { CCI_REG8(0x0b51), 0x16 },
> + { CCI_REG8(0x0b52), 0x00 },
> + { CCI_REG8(0x0b80), 0x01 },
> + { CCI_REG8(0x0b81), 0x00 },
> + { CCI_REG8(0x0b82), 0x00 },
> + { CCI_REG8(0x0b84), 0x00 },
> + { CCI_REG8(0x0b85), 0x00 },
> + { CCI_REG8(0x0b86), 0x00 },
> + { CCI_REG8(0x0b88), 0x01 },
> + { CCI_REG8(0x0b89), 0x6a },
> + { CCI_REG8(0x0b8a), 0x00 },
> + { CCI_REG8(0x0b8c), 0x00 },
> + { CCI_REG8(0x0b8d), 0x01 },
> + { CCI_REG8(0x0b8e), 0x00 },
> + { CCI_REG8(0x0b90), 0x01 },
> + { CCI_REG8(0x0b91), 0xf6 },
> + { CCI_REG8(0x0b92), 0x00 },
> + { CCI_REG8(0x0b94), 0x00 },
> + { CCI_REG8(0x0b95), 0x02 },
> + { CCI_REG8(0x0b96), 0x00 },
> + { CCI_REG8(0x0b98), 0x02 },
> + { CCI_REG8(0x0b99), 0xc4 },
> + { CCI_REG8(0x0b9a), 0x00 },
> + { CCI_REG8(0x0b9c), 0x00 },
> + { CCI_REG8(0x0b9d), 0x03 },
> + { CCI_REG8(0x0b9e), 0x00 },
> + { CCI_REG8(0x0ba0), 0x03 },
> + { CCI_REG8(0x0ba1), 0xd8 },
> + { CCI_REG8(0x0ba2), 0x00 },
> + { CCI_REG8(0x0ba4), 0x00 },
> + { CCI_REG8(0x0ba5), 0x04 },
> + { CCI_REG8(0x0ba6), 0x00 },
> + { CCI_REG8(0x0ba8), 0x05 },
> + { CCI_REG8(0x0ba9), 0x4d },
> + { CCI_REG8(0x0baa), 0x00 },
> + { CCI_REG8(0x0bac), 0x00 },
> + { CCI_REG8(0x0bad), 0x05 },
> + { CCI_REG8(0x0bae), 0x00 },
> + { CCI_REG8(0x0bb0), 0x07 },
> + { CCI_REG8(0x0bb1), 0x3e },
> + { CCI_REG8(0x0bb2), 0x00 },
> + { CCI_REG8(0x0bb4), 0x00 },
> + { CCI_REG8(0x0bb5), 0x06 },
> + { CCI_REG8(0x0bb6), 0x00 },
> + { CCI_REG8(0x0bb8), 0x0a },
> + { CCI_REG8(0x0bb9), 0x1a },
> + { CCI_REG8(0x0bba), 0x00 },
> + { CCI_REG8(0x0bbc), 0x09 },
> + { CCI_REG8(0x0bbd), 0x36 },
> + { CCI_REG8(0x0bbe), 0x00 },
> + { CCI_REG8(0x0bc0), 0x0e },
> + { CCI_REG8(0x0bc1), 0x66 },
> + { CCI_REG8(0x0bc2), 0x00 },
> + { CCI_REG8(0x0bc4), 0x10 },
> + { CCI_REG8(0x0bc5), 0x06 },
> + { CCI_REG8(0x0bc6), 0x00 },
> + { CCI_REG8(0x02c1), 0xe0 },
> + { CCI_REG8(0x0207), 0x04 },
> + { CCI_REG8(0x02c2), 0x10 },
> + { CCI_REG8(0x02c3), 0x74 },
> + { CCI_REG8(0x02c5), 0x09 },
> + { CCI_REG8(0x02c1), 0xe0 },
> + { CCI_REG8(0x0207), 0x04 },
> + { CCI_REG8(0x02c2), 0x10 },
> + { CCI_REG8(0x02c5), 0x09 },
> + { CCI_REG8(0x02c1), 0xe0 },
> + { CCI_REG8(0x0207), 0x04 },
> + { CCI_REG8(0x02c2), 0x10 },
> + { CCI_REG8(0x02c5), 0x09 },
> +
> + /* auto load CH_GAIN */
> + { CCI_REG8(0x0aa1), 0x15 },
> + { CCI_REG8(0x0aa2), 0x50 },
> + { CCI_REG8(0x0aa3), 0x00 },
> + { CCI_REG8(0x0aa4), 0x09 },
> + { CCI_REG8(0x0a90), 0x25 },
> + { CCI_REG8(0x0a91), 0x0e },
> + { CCI_REG8(0x0a94), 0x80 },
> +
> + /* ISP */
> + { CCI_REG8(0x0050), 0x00 },
> + { CCI_REG8(0x0089), 0x83 },
> + { CCI_REG8(0x005a), 0x40 },
> + { CCI_REG8(0x00c3), 0x35 },
> + { CCI_REG8(0x00c4), 0x80 },
> + { CCI_REG8(0x0080), 0x10 },
> + { CCI_REG8(0x0040), 0x12 },
> + { CCI_REG8(0x0053), 0x0a },
> + { CCI_REG8(0x0054), 0x44 },
> + { CCI_REG8(0x0055), 0x32 },
> + { CCI_REG8(0x0058), 0x89 },
> + { CCI_REG8(0x004a), 0x03 },
> + { CCI_REG8(0x0048), 0xf0 },
> + { CCI_REG8(0x0049), 0x0f },
> + { CCI_REG8(0x0041), 0x20 },
> + { CCI_REG8(0x0043), 0x0a },
> + { CCI_REG8(0x009d), 0x08 },
> + { CCI_REG8(0x0236), 0x40 },
> +
> + /* gain */
Is the gain configurable? Is this analogue gain? digital gain? or colour
balanace gains ?
> + { CCI_REG8(0x0204), 0x04 },
> + { CCI_REG8(0x0205), 0x00 },
> + { CCI_REG8(0x02b3), 0x00 },
> + { CCI_REG8(0x02b4), 0x00 },
> + { CCI_REG8(0x009e), 0x01 },
> + { CCI_REG8(0x009f), 0x94 },
> +
> + /* auto load REG */
> + { CCI_REG8(0x0aa1), 0x10 },
> + { CCI_REG8(0x0aa2), 0xf8 },
> + { CCI_REG8(0x0aa3), 0x00 },
> + { CCI_REG8(0x0aa4), 0x1f },
> + { CCI_REG8(0x0a90), 0x11 },
> + { CCI_REG8(0x0a91), 0x0e },
> + { CCI_REG8(0x0a94), 0x80 },
> + { CCI_REG8(0x03fe), 0x00 },
> + { CCI_REG8(0x0a90), 0x00 },
> + { CCI_REG8(0x0a70), 0x00 },
> + { CCI_REG8(0x0a67), 0x00 },
> + { CCI_REG8(0x0af4), 0x29 },
> +
> + /* DPHY */
> + { CCI_REG8(0x0d80), 0x07 },
> + { CCI_REG8(0x0dd3), 0x18 },
> +
> + /* CISCTL_Reset */
> + { CCI_REG8(0x031c), 0x80 },
> + { CCI_REG8(0x03fe), 0x30 },
> + { CCI_REG8(0x0d17), 0x06 },
> + { CCI_REG8(0x03fe), 0x00 },
> + { CCI_REG8(0x0d17), 0x00 },
> + { CCI_REG8(0x031c), 0x93 },
> + { CCI_REG8(0x03fe), 0x00 },
> + { CCI_REG8(0x031c), 0x80 },
> + { CCI_REG8(0x03fe), 0x30 },
> + { CCI_REG8(0x0d17), 0x06 },
> + { CCI_REG8(0x03fe), 0x00 },
> + { CCI_REG8(0x0d17), 0x00 },
> + { CCI_REG8(0x031c), 0x93 },
> +};
> +
> +struct gc05a2_mode {
> + u32 width;
> + u32 height;
> + const struct gc05a2_reg_list reg_list;
> +
> + u32 hts; /* Horizontal timining size */
> + u32 vts_def; /* Default vertical timining size */
> + u32 vts_min; /* Min vertical timining size */
> +};
> +
> +/* Declare modes in order, from biggest to smallest height. */
> +static const struct gc05a2_mode gc05a2_modes[] = {
> + {
> + /* 2592*1944@30fps */
> + .width = GC05A2_NATIVE_WIDTH,
> + .height = GC05A2_NATIVE_HEIGHT,
> + .reg_list = {
> + .num_of_regs = ARRAY_SIZE(mode_2592x1944),
> + .regs = mode_2592x1944,
> + },
> + .hts = 3664,
> + .vts_def = 2032,
> + .vts_min = 2032,
> + },
> + {
> + /* 1280*720@60fps */
> + .width = 1280,
> + .height = 720,
> + .reg_list = {
> + .num_of_regs = ARRAY_SIZE(mode_1280x720),
> + .regs = mode_1280x720,
> + },
> + .hts = 3616,
> + .vts_def = 1032,
> + .vts_min = 1032,
> + },
> +};
> +
> +static inline struct gc05a2 *to_gc05a2(struct v4l2_subdev *sd)
> +{
> + return container_of(sd, struct gc05a2, sd);
> +}
> +
> +static int gc05a2_power_on(struct device *dev)
> +{
> + struct v4l2_subdev *sd = dev_get_drvdata(dev);
> + struct gc05a2 *gc05a2 = to_gc05a2(sd);
> + int ret;
> +
> + ret = regulator_bulk_enable(ARRAY_SIZE(gc05a2_supply_name),
> + gc05a2->supplies);
> + if (ret < 0) {
> + dev_err(gc05a2->dev, "failed to enable regulators: %d\n", ret);
> + return ret;
> + }
> +
> + ret = clk_prepare_enable(gc05a2->xclk);
> + if (ret < 0) {
> + regulator_bulk_disable(ARRAY_SIZE(gc05a2_supply_name),
> + gc05a2->supplies);
> + dev_err(gc05a2->dev, "clk prepare enable failed\n");
> + return ret;
> + }
> +
> + fsleep(GC05A2_SLEEP_US);
> +
> + gpiod_set_value_cansleep(gc05a2->reset_gpio, 0);
> + fsleep(GC05A2_SLEEP_US);
> +
> + return 0;
> +}
> +
> +static int gc05a2_power_off(struct device *dev)
> +{
> + struct v4l2_subdev *sd = dev_get_drvdata(dev);
> + struct gc05a2 *gc05a2 = to_gc05a2(sd);
> +
> + clk_disable_unprepare(gc05a2->xclk);
> + gpiod_set_value_cansleep(gc05a2->reset_gpio, 1);
> + regulator_bulk_disable(ARRAY_SIZE(gc05a2_supply_name),
> + gc05a2->supplies);
> +
> + return 0;
> +}
> +
> +static int gc05a2_enum_mbus_code(struct v4l2_subdev *sd,
> + struct v4l2_subdev_state *sd_state,
> + struct v4l2_subdev_mbus_code_enum *code)
> +{
> + if (code->index > 0)
> + return -EINVAL;
> +
> + code->code = GC05A2_MBUS_CODE;
> +
> + return 0;
> +}
> +
> +static int gc05a2_enum_frame_size(struct v4l2_subdev *subdev,
> + struct v4l2_subdev_state *sd_state,
> + struct v4l2_subdev_frame_size_enum *fse)
> +{
> + if (fse->code != GC05A2_MBUS_CODE)
> + return -EINVAL;
> +
> + if (fse->index >= ARRAY_SIZE(gc05a2_modes))
> + return -EINVAL;
> +
> + fse->min_width = gc05a2_modes[fse->index].width;
> + fse->max_width = gc05a2_modes[fse->index].width;
> + fse->min_height = gc05a2_modes[fse->index].height;
> + fse->max_height = gc05a2_modes[fse->index].height;
> +
> + return 0;
> +}
> +
> +static int gc05a2_update_cur_mode_controls(struct gc05a2 *gc05a2,
> + const struct gc05a2_mode *mode)
> +{
> + s64 exposure_max, h_blank;
> + int ret;
> +
> + ret = __v4l2_ctrl_modify_range(gc05a2->vblank,
> + mode->vts_min - mode->height,
> + GC05A2_VTS_MAX - mode->height, 1,
> + mode->vts_def - mode->height);
> + if (ret) {
> + dev_err(gc05a2->dev, "VB ctrl range update failed\n");
> + return ret;
> + }
> +
> + h_blank = mode->hts - mode->width;
> + ret = __v4l2_ctrl_modify_range(gc05a2->hblank, h_blank, h_blank, 1,
> + h_blank);
> + if (ret) {
> + dev_err(gc05a2->dev, "HB ctrl range update failed\n");
> + return ret;
> + }
> +
> + exposure_max = mode->vts_def - GC05A2_EXP_MARGIN;
> + ret = __v4l2_ctrl_modify_range(gc05a2->exposure, GC05A2_EXP_MIN,
> + exposure_max, GC05A2_EXP_STEP,
> + exposure_max);
> + if (ret) {
> + dev_err(gc05a2->dev, "exposure ctrl range update failed\n");
> + return ret;
> + }
> +
> + return 0;
> +}
> +
> +static void gc05a2_update_pad_format(struct gc05a2 *gc08a3,
> + const struct gc05a2_mode *mode,
> + struct v4l2_mbus_framefmt *fmt)
> +{
> + fmt->width = mode->width;
> + fmt->height = mode->height;
> + fmt->code = GC05A2_MBUS_CODE;
> + fmt->field = V4L2_FIELD_NONE;
> + fmt->colorspace = V4L2_COLORSPACE_RAW;
> + fmt->ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(fmt->colorspace);
> + fmt->quantization = V4L2_QUANTIZATION_FULL_RANGE;
> + fmt->xfer_func = V4L2_XFER_FUNC_NONE;
> +}
> +
> +static int gc05a2_set_format(struct v4l2_subdev *sd,
> + struct v4l2_subdev_state *state,
> + struct v4l2_subdev_format *fmt)
> +{
> + struct gc05a2 *gc05a2 = to_gc05a2(sd);
> + struct v4l2_mbus_framefmt *mbus_fmt;
> + struct v4l2_rect *crop;
> + const struct gc05a2_mode *mode;
> +
> + mode = v4l2_find_nearest_size(gc05a2_modes, ARRAY_SIZE(gc05a2_modes),
> + width, height, fmt->format.width,
> + fmt->format.height);
> +
> + /* update crop info to subdev state */
> + crop = v4l2_subdev_state_get_crop(state, 0);
> + crop->width = mode->width;
> + crop->height = mode->height;
> +
> + /* update fmt info to subdev state */
> + gc05a2_update_pad_format(gc05a2, mode, &fmt->format);
> + mbus_fmt = v4l2_subdev_state_get_format(state, 0);
> + *mbus_fmt = fmt->format;
> +
> + if (fmt->which == V4L2_SUBDEV_FORMAT_TRY)
> + return 0;
> + gc05a2->cur_mode = mode;
> + gc05a2_update_cur_mode_controls(gc05a2, mode);
> +
> + return 0;
> +}
> +
> +static int gc05a2_get_selection(struct v4l2_subdev *sd,
> + struct v4l2_subdev_state *state,
> + struct v4l2_subdev_selection *sel)
> +{
> + switch (sel->target) {
> + case V4L2_SEL_TGT_CROP_DEFAULT:
> + case V4L2_SEL_TGT_CROP:
> + sel->r = *v4l2_subdev_state_get_crop(state, 0);
> + break;
> + case V4L2_SEL_TGT_CROP_BOUNDS:
> + sel->r.top = 0;
> + sel->r.left = 0;
> + sel->r.width = GC05A2_NATIVE_WIDTH;
> + sel->r.height = GC05A2_NATIVE_HEIGHT;
> + break;
> + default:
> + return -EINVAL;
> + }
> +
> + return 0;
> +}
> +
> +static int gc05a2_init_state(struct v4l2_subdev *sd,
> + struct v4l2_subdev_state *state)
> +{
> + struct v4l2_subdev_format fmt = {
> + .which = V4L2_SUBDEV_FORMAT_TRY,
> + .pad = 0,
> + .format = {
> + .code = GC05A2_MBUS_CODE,
> + .width = gc05a2_modes[0].width,
> + .height = gc05a2_modes[0].height,
> + },
> + };
> +
> + gc05a2_set_format(sd, state, &fmt);
> +
> + return 0;
> +}
> +
> +static int gc05a2_set_ctrl_hflip(struct gc05a2 *gc05a2, u32 ctrl_val)
> +{
> + int ret;
> + u64 val;
> +
> + ret = cci_read(gc05a2->regmap, GC05A2_FLIP_REG, &val, NULL);
> + if (ret) {
> + dev_err(gc05a2->dev, "read hflip register failed: %d\n", ret);
> + return ret;
> + }
> +
> + return cci_update_bits(gc05a2->regmap, GC05A2_FLIP_REG,
> + GC05A2_FLIP_H_MASK,
> + ctrl_val ? GC05A2_FLIP_H_MASK : 0, NULL);
> +}
> +
> +static int gc05a2_set_ctrl_vflip(struct gc05a2 *gc05a2, u32 ctrl_val)
> +{
> + int ret;
> + u64 val;
> +
> + ret = cci_read(gc05a2->regmap, GC05A2_FLIP_REG, &val, NULL);
> + if (ret) {
> + dev_err(gc05a2->dev, "read vflip register failed: %d\n", ret);
> + return ret;
> + }
> +
> + return cci_update_bits(gc05a2->regmap, GC05A2_FLIP_REG,
> + GC05A2_FLIP_V_MASK,
> + ctrl_val ? GC05A2_FLIP_V_MASK : 0, NULL);
> +}
> +
> +static int gc05a2_test_pattern(struct gc05a2 *gc05a2, u32 pattern_menu)
> +{
> + u32 pattern;
> + int ret;
> +
> + if (pattern_menu) {
> + switch (pattern_menu) {
> + case 1:
> + case 2:
> + case 3:
> + case 4:
> + case 5:
> + case 6:
> + case 7:
> + pattern = pattern_menu << 4;
> + break;
> +
> + case 8:
> + pattern = 0;
> + break;
> +
> + case 9:
> + pattern = 4;
> + break;
> +
> + default:
> + pattern = 0x00;
> + break;
> + }
This is fairly terse. Can we add comments, or definitions for the types
or such so that the above is easier to interpret?
> +
> + ret = cci_write(gc05a2->regmap, GC05A2_REG_TEST_PATTERN_IDX,
> + pattern, NULL);
> + if (ret)
> + return ret;
> +
> + return cci_write(gc05a2->regmap, GC05A2_REG_TEST_PATTERN_EN,
> + GC05A2_TEST_PATTERN_EN, NULL);
> + } else {
> + return cci_write(gc05a2->regmap, GC05A2_REG_TEST_PATTERN_EN,
> + 0x00, NULL);
> + }
> +}
> +
> +static int gc05a2_set_ctrl(struct v4l2_ctrl *ctrl)
> +{
> + struct gc05a2 *gc05a2 =
> + container_of(ctrl->handler, struct gc05a2, ctrls);
> + int ret = 0;
> + s64 exposure_max;
> + struct v4l2_subdev_state *state;
> + const struct v4l2_mbus_framefmt *format;
> +
> + state = v4l2_subdev_get_locked_active_state(&gc05a2->sd);
> + format = v4l2_subdev_state_get_format(state, 0);
> +
> + if (ctrl->id == V4L2_CID_VBLANK) {
> + /* Update max exposure while meeting expected vblanking */
> + exposure_max = format->height + ctrl->val - GC05A2_EXP_MARGIN;
> + __v4l2_ctrl_modify_range(gc05a2->exposure,
> + gc05a2->exposure->minimum,
> + exposure_max, gc05a2->exposure->step,
> + exposure_max);
> + }
> +
> + /*
> + * Applying V4L2 control value only happens
> + * when power is on for streaming.
> + */
> + if (!pm_runtime_get_if_active(gc05a2->dev))
> + return 0;
> +
> + switch (ctrl->id) {
> + case V4L2_CID_EXPOSURE:
> + ret = cci_write(gc05a2->regmap, GC05A2_EXP_REG,
> + ctrl->val, NULL);
> + break;
> +
> + case V4L2_CID_ANALOGUE_GAIN:
> + ret = cci_write(gc05a2->regmap, GC05A2_AGAIN_REG,
> + ctrl->val, NULL);
> + break;
> +
> + case V4L2_CID_VBLANK:
> + ret = cci_write(gc05a2->regmap, GC05A2_FRAME_LENGTH_REG,
> + gc05a2->cur_mode->height + ctrl->val, NULL);
> + break;
> +
> + case V4L2_CID_HFLIP:
> + ret = gc05a2_set_ctrl_hflip(gc05a2, ctrl->val);
> + break;
> +
> + case V4L2_CID_VFLIP:
> + ret = gc05a2_set_ctrl_vflip(gc05a2, ctrl->val);
> + break;
> +
> + case V4L2_CID_TEST_PATTERN:
> + ret = gc05a2_test_pattern(gc05a2, ctrl->val);
> + break;
> +
> + default:
> + break;
> + }
> +
> + pm_runtime_put(gc05a2->dev);
> +
> + return ret;
> +}
> +
> +static const struct v4l2_ctrl_ops gc05a2_ctrl_ops = {
> + .s_ctrl = gc05a2_set_ctrl,
> +};
> +
> +static int gc05a2_identify_module(struct gc05a2 *gc05a2)
> +{
> + u64 val;
> + int ret;
> +
> + if (gc05a2->identified)
> + return 0;
> +
> + ret = cci_read(gc05a2->regmap, GC05A2_REG_CHIP_ID, &val, NULL);
> + if (ret)
> + return ret;
> +
> + if (val != GC05A2_CHIP_ID) {
> + dev_err(gc05a2->dev, "chip id mismatch: 0x%x!=0x%llx",
> + GC05A2_CHIP_ID, val);
> + return -ENXIO;
> + }
> +
> + gc05a2->identified = true;
> +
> + return 0;
> +}
> +
> +static int gc05a2_start_streaming(struct gc05a2 *gc05a2)
> +{
> + const struct gc05a2_mode *mode;
> + const struct gc05a2_reg_list *reg_list;
> + int ret;
> +
> + ret = pm_runtime_resume_and_get(gc05a2->dev);
> + if (ret < 0)
> + return ret;
> +
> + ret = gc05a2_identify_module(gc05a2);
> + if (ret)
> + goto err_rpm_put;
> +
> + ret = cci_multi_reg_write(gc05a2->regmap,
> + mode_table_common,
> + ARRAY_SIZE(mode_table_common), NULL);
> + if (ret)
> + goto err_rpm_put;
> +
> + mode = gc05a2->cur_mode;
> + reg_list = &mode->reg_list;
> +
> + ret = cci_multi_reg_write(gc05a2->regmap,
> + reg_list->regs, reg_list->num_of_regs, NULL);
> + if (ret < 0)
> + goto err_rpm_put;
> +
> + ret = __v4l2_ctrl_handler_setup(&gc05a2->ctrls);
> + if (ret < 0) {
> + dev_err(gc05a2->dev, "could not sync v4l2 controls\n");
> + goto err_rpm_put;
> + }
> +
> + ret = cci_write(gc05a2->regmap, GC05A2_STREAMING_REG, 1, NULL);
> + if (ret < 0) {
> + dev_err(gc05a2->dev, "write STREAMING_REG failed: %d\n", ret);
> + goto err_rpm_put;
> + }
> +
> + return 0;
> +
> +err_rpm_put:
> + pm_runtime_put(gc05a2->dev);
> + return ret;
> +}
> +
> +static int gc05a2_stop_streaming(struct gc05a2 *gc05a2)
> +{
> + int ret;
> +
> + ret = cci_write(gc05a2->regmap, GC05A2_STREAMING_REG, 0, NULL);
> + if (ret < 0)
> + dev_err(gc05a2->dev, "could not sent stop streaming %d\n", ret);
> +
> + pm_runtime_put(gc05a2->dev);
> + return ret;
> +}
> +
> +static int gc05a2_s_stream(struct v4l2_subdev *subdev, int enable)
> +{
> + struct gc05a2 *gc05a2 = to_gc05a2(subdev);
> + struct v4l2_subdev_state *state;
> + int ret;
> +
> + state = v4l2_subdev_lock_and_get_active_state(subdev);
> +
> + if (enable)
> + ret = gc05a2_start_streaming(gc05a2);
> + else
> + ret = gc05a2_stop_streaming(gc05a2);
> +
> + v4l2_subdev_unlock_state(state);
> +
> + return ret;
> +}
> +
> +static const struct v4l2_subdev_video_ops gc05a2_video_ops = {
> + .s_stream = gc05a2_s_stream,
> +};
> +
> +static const struct v4l2_subdev_pad_ops gc05a2_subdev_pad_ops = {
> + .enum_mbus_code = gc05a2_enum_mbus_code,
> + .enum_frame_size = gc05a2_enum_frame_size,
> + .get_fmt = v4l2_subdev_get_fmt,
> + .set_fmt = gc05a2_set_format,
> + .get_selection = gc05a2_get_selection,
> +};
> +
> +static const struct v4l2_subdev_core_ops gc05a2_core_ops = {
> + .subscribe_event = v4l2_ctrl_subdev_subscribe_event,
> + .unsubscribe_event = v4l2_event_subdev_unsubscribe,
> +};
> +
> +static const struct v4l2_subdev_ops gc05a2_subdev_ops = {
> + .core = &gc05a2_core_ops,
> + .video = &gc05a2_video_ops,
> + .pad = &gc05a2_subdev_pad_ops,
> +};
> +
> +static const struct v4l2_subdev_internal_ops gc05a2_internal_ops = {
> + .init_state = gc05a2_init_state,
> +};
> +
> +static int gc05a2_get_regulators(struct device *dev, struct gc05a2 *gc05a2)
> +{
> + unsigned int i;
> +
> + for (i = 0; i < ARRAY_SIZE(gc05a2_supply_name); i++)
> + gc05a2->supplies[i].supply = gc05a2_supply_name[i];
> +
> + return devm_regulator_bulk_get(dev, ARRAY_SIZE(gc05a2_supply_name),
> + gc05a2->supplies);
> +}
> +
> +static int gc05a2_parse_fwnode(struct gc05a2 *gc05a2)
> +{
> + struct fwnode_handle *endpoint;
> + struct v4l2_fwnode_endpoint bus_cfg = {
> + .bus_type = V4L2_MBUS_CSI2_DPHY,
> + };
> + int ret;
> + struct device *dev = gc05a2->dev;
> +
> + endpoint =
> + fwnode_graph_get_endpoint_by_id(dev_fwnode(dev), 0, 0,
> + FWNODE_GRAPH_ENDPOINT_NEXT);
> + if (!endpoint) {
> + dev_err(dev, "endpoint node not found\n");
> + return -EINVAL;
> + }
> +
> + ret = v4l2_fwnode_endpoint_alloc_parse(endpoint, &bus_cfg);
> + if (ret) {
> + dev_err(dev, "parsing endpoint node failed\n");
> + goto done;
> + }
> +
> + ret = v4l2_link_freq_to_bitmap(dev, bus_cfg.link_frequencies,
> + bus_cfg.nr_of_link_frequencies,
> + gc05a2_link_freq_menu_items,
> + ARRAY_SIZE(gc05a2_link_freq_menu_items),
> + &gc05a2->link_freq_bitmap);
> + if (ret)
> + goto done;
> +
> +done:
> + v4l2_fwnode_endpoint_free(&bus_cfg);
> + fwnode_handle_put(endpoint);
> + return ret;
> +}
> +
> +static u64 gc05a2_to_pixel_rate(u32 f_index)
> +{
> + u64 pixel_rate =
> + gc05a2_link_freq_menu_items[f_index] * 2 * GC05A2_DATA_LANES;
> +
> + return div_u64(pixel_rate, GC05A2_RGB_DEPTH);
> +}
> +
> +static int gc05a2_init_controls(struct gc05a2 *gc05a2)
> +{
> + struct i2c_client *client = v4l2_get_subdevdata(&gc05a2->sd);
> + const struct gc05a2_mode *mode = &gc05a2_modes[0];
> + const struct v4l2_ctrl_ops *ops = &gc05a2_ctrl_ops;
> + struct v4l2_fwnode_device_properties props;
> + struct v4l2_ctrl_handler *ctrl_hdlr;
> + s64 exposure_max, h_blank;
> + int ret;
> +
> + ctrl_hdlr = &gc05a2->ctrls;
> + ret = v4l2_ctrl_handler_init(ctrl_hdlr, 9);
> + if (ret)
> + return ret;
> +
> + gc05a2->hflip = v4l2_ctrl_new_std(ctrl_hdlr, &gc05a2_ctrl_ops,
> + V4L2_CID_HFLIP, 0, 1, 1, 0);
> + gc05a2->vflip = v4l2_ctrl_new_std(ctrl_hdlr, &gc05a2_ctrl_ops,
> + V4L2_CID_VFLIP, 0, 1, 1, 0);
> + v4l2_ctrl_cluster(2, &gc05a2->hflip);
> +
> + gc05a2->link_freq =
> + v4l2_ctrl_new_int_menu(ctrl_hdlr,
> + &gc05a2_ctrl_ops,
> + V4L2_CID_LINK_FREQ,
> + ARRAY_SIZE(gc05a2_link_freq_menu_items) - 1,
> + 0,
> + gc05a2_link_freq_menu_items);
> + if (gc05a2->link_freq)
> + gc05a2->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
> +
> + gc05a2->pixel_rate =
> + v4l2_ctrl_new_std(ctrl_hdlr,
> + &gc05a2_ctrl_ops,
> + V4L2_CID_PIXEL_RATE, 0,
> + gc05a2_to_pixel_rate(0),
> + 1,
> + gc05a2_to_pixel_rate(0));
> +
> + gc05a2->vblank =
> + v4l2_ctrl_new_std(ctrl_hdlr,
> + &gc05a2_ctrl_ops, V4L2_CID_VBLANK,
> + mode->vts_min - mode->height,
> + GC05A2_VTS_MAX - mode->height, 1,
> + mode->vts_def - mode->height);
> +
> + h_blank = mode->hts - mode->width;
> + gc05a2->hblank = v4l2_ctrl_new_std(ctrl_hdlr, &gc05a2_ctrl_ops,
> + V4L2_CID_HBLANK, h_blank, h_blank, 1,
> + h_blank);
> + if (gc05a2->hblank)
> + gc05a2->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
> +
> + v4l2_ctrl_new_std(ctrl_hdlr, &gc05a2_ctrl_ops,
> + V4L2_CID_ANALOGUE_GAIN, GC05A2_AGAIN_MIN,
> + GC05A2_AGAIN_MAX, GC05A2_AGAIN_STEP,
> + GC05A2_AGAIN_MIN);
> +
> + exposure_max = mode->vts_def - GC05A2_EXP_MARGIN;
> + gc05a2->exposure = v4l2_ctrl_new_std(ctrl_hdlr, &gc05a2_ctrl_ops,
> + V4L2_CID_EXPOSURE, GC05A2_EXP_MIN,
> + exposure_max, GC05A2_EXP_STEP,
> + exposure_max);
> +
> + v4l2_ctrl_new_std_menu_items(ctrl_hdlr, &gc05a2_ctrl_ops,
> + V4L2_CID_TEST_PATTERN,
> + ARRAY_SIZE(gc05a2_test_pattern_menu) - 1,
> + 0, 0, gc05a2_test_pattern_menu);
> +
> + /* register properties to fwnode (e.g. rotation, orientation) */
> + ret = v4l2_fwnode_device_parse(&client->dev, &props);
> + if (ret)
> + goto error_ctrls;
> +
> + ret = v4l2_ctrl_new_fwnode_properties(ctrl_hdlr, ops, &props);
> + if (ret)
> + goto error_ctrls;
> +
> + if (ctrl_hdlr->error) {
> + ret = ctrl_hdlr->error;
> + goto error_ctrls;
> + }
> +
> + gc05a2->sd.ctrl_handler = ctrl_hdlr;
> +
> + return 0;
> +
> +error_ctrls:
> + v4l2_ctrl_handler_free(ctrl_hdlr);
> +
> + return ret;
> +}
> +
> +static int gc05a2_probe(struct i2c_client *client)
> +{
> + struct device *dev = &client->dev;
> + struct gc05a2 *gc05a2;
> + int ret;
> +
> + gc05a2 = devm_kzalloc(dev, sizeof(*gc05a2), GFP_KERNEL);
> + if (!gc05a2)
> + return -ENOMEM;
> +
> + gc05a2->dev = dev;
> +
> + ret = gc05a2_parse_fwnode(gc05a2);
> + if (ret)
> + return ret;
> +
> + gc05a2->regmap = devm_cci_regmap_init_i2c(client, 16);
> + if (IS_ERR(gc05a2->regmap))
> + return dev_err_probe(dev, PTR_ERR(gc05a2->regmap),
> + "failed to init CCI\n");
> +
> + gc05a2->xclk = devm_clk_get(dev, NULL);
> + if (IS_ERR(gc05a2->xclk))
> + return dev_err_probe(dev, PTR_ERR(gc05a2->xclk),
> + "failed to get xclk\n");
> +
> + ret = clk_set_rate(gc05a2->xclk, GC05A2_DEFAULT_CLK_FREQ);
> + if (ret)
> + return dev_err_probe(dev, ret,
> + "failed to set xclk frequency\n");
> +
> + ret = gc05a2_get_regulators(dev, gc05a2);
> + if (ret < 0)
> + return dev_err_probe(dev, ret,
> + "failed to get regulators\n");
> +
> + gc05a2->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
> + if (IS_ERR(gc05a2->reset_gpio))
> + return dev_err_probe(dev, PTR_ERR(gc05a2->reset_gpio),
> + "failed to get gpio\n");
> +
> + v4l2_i2c_subdev_init(&gc05a2->sd, client, &gc05a2_subdev_ops);
> + gc05a2->sd.internal_ops = &gc05a2_internal_ops;
> + gc05a2->cur_mode = &gc05a2_modes[0];
> +
> + ret = gc05a2_init_controls(gc05a2);
> + if (ret)
> + return dev_err_probe(dev, ret,
> + "failed to init controls\n");
> +
> + gc05a2->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE |
> + V4L2_SUBDEV_FL_HAS_EVENTS;
> + gc05a2->pad.flags = MEDIA_PAD_FL_SOURCE;
> + gc05a2->sd.dev = &client->dev;
> + gc05a2->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
> +
> + ret = media_entity_pads_init(&gc05a2->sd.entity, 1, &gc05a2->pad);
> + if (ret < 0) {
> + dev_err(dev, "could not register media entity\n");
> + goto err_v4l2_ctrl_handler_free;
> + }
> +
> + gc05a2->sd.state_lock = gc05a2->ctrls.lock;
> + ret = v4l2_subdev_init_finalize(&gc05a2->sd);
> + if (ret < 0) {
> + dev_err(dev, "v4l2 subdev init error: %d\n", ret);
> + goto err_media_entity_cleanup;
> + }
> +
> + pm_runtime_set_active(gc05a2->dev);
> + pm_runtime_enable(gc05a2->dev);
> + pm_runtime_set_autosuspend_delay(gc05a2->dev, 1000);
> + pm_runtime_use_autosuspend(gc05a2->dev);
> + pm_runtime_idle(gc05a2->dev);
> +
> + ret = v4l2_async_register_subdev_sensor(&gc05a2->sd);
> + if (ret < 0) {
> + dev_err(dev, "could not register v4l2 device\n");
> + goto err_rpm;
> + }
> +
> + return 0;
> +
> +err_rpm:
> + pm_runtime_disable(gc05a2->dev);
> + v4l2_subdev_cleanup(&gc05a2->sd);
> +
> +err_media_entity_cleanup:
> + media_entity_cleanup(&gc05a2->sd.entity);
> +
> +err_v4l2_ctrl_handler_free:
> + v4l2_ctrl_handler_free(&gc05a2->ctrls);
> +
> + return ret;
> +}
> +
> +static void gc05a2_remove(struct i2c_client *client)
> +{
> + struct v4l2_subdev *sd = i2c_get_clientdata(client);
> + struct gc05a2 *gc05a2 = to_gc05a2(sd);
> +
> + v4l2_async_unregister_subdev(&gc05a2->sd);
> + v4l2_subdev_cleanup(sd);
> + media_entity_cleanup(&gc05a2->sd.entity);
> + v4l2_ctrl_handler_free(&gc05a2->ctrls);
> +
> + pm_runtime_disable(&client->dev);
> + if (!pm_runtime_status_suspended(&client->dev))
> + gc05a2_power_off(gc05a2->dev);
> + pm_runtime_set_suspended(&client->dev);
> +}
> +
> +static const struct of_device_id gc05a2_of_match[] = {
> + { .compatible = "galaxycore,gc05a2" },
> + {}
> +};
> +MODULE_DEVICE_TABLE(of, gc05a2_of_match);
> +
> +static DEFINE_RUNTIME_DEV_PM_OPS(gc05a2_pm_ops,
> + gc05a2_power_off,
> + gc05a2_power_on,
> + NULL);
> +
> +static struct i2c_driver gc05a2_i2c_driver = {
> + .driver = {
> + .of_match_table = gc05a2_of_match,
> + .pm = pm_ptr(&gc05a2_pm_ops),
> + .name = "gc05a2",
> + },
> + .probe = gc05a2_probe,
> + .remove = gc05a2_remove,
> +};
> +module_i2c_driver(gc05a2_i2c_driver);
> +
> +MODULE_DESCRIPTION("GalaxyCore gc05a2 Camera driver");
> +MODULE_AUTHOR("Zhi Mao <zhi.mao@mediatek.com>");
> +MODULE_LICENSE("GPL");
> --
> 2.25.1
>
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* RE: [EXT] Re: [PATCH v1 1/1] arm64: dts: imx93-11x11-evk: add rtc PCF2131 support
From: Joy Zou @ 2024-04-07 9:09 UTC (permalink / raw)
To: Krzysztof Kozlowski, Jacky Bai, robh+dt@kernel.org,
krzysztof.kozlowski+dt@linaro.org, conor+dt@kernel.org,
shawnguo@kernel.org, s.hauer@pengutronix.de
Cc: kernel@pengutronix.de, festevam@gmail.com, dl-linux-imx,
devicetree@vger.kernel.org, imx@lists.linux.dev,
linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org
In-Reply-To: <f019690a-2397-4bf8-9472-ec38f4b94c1d@linaro.org>
> -----Original Message-----
> From: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
> Sent: 2024年4月7日 17:04
> To: Joy Zou <joy.zou@nxp.com>; Jacky Bai <ping.bai@nxp.com>;
> robh+dt@kernel.org; krzysztof.kozlowski+dt@linaro.org;
> conor+dt@kernel.org; shawnguo@kernel.org; s.hauer@pengutronix.de
> Cc: kernel@pengutronix.de; festevam@gmail.com; dl-linux-imx
> <linux-imx@nxp.com>; devicetree@vger.kernel.org; imx@lists.linux.dev;
> linux-arm-kernel@lists.infradead.org; linux-kernel@vger.kernel.org
> Subject: [EXT] Re: [PATCH v1 1/1] arm64: dts: imx93-11x11-evk: add rtc
> PCF2131 support
> > +&lpi2c3 {
> > + #address-cells = <1>;
> > + #size-cells = <0>;
> > + clock-frequency = <400000>;
> > + pinctrl-names = "default", "sleep";
> > + pinctrl-0 = <&pinctrl_lpi2c3>;
> > + pinctrl-1 = <&pinctrl_lpi2c3>;
> > + status = "okay";
> > +
> > + pcf2131: rtc@53 {
> > + compatible = "nxp,pcf2131";
> > + reg = <0x53>;
> > + interrupt-parent = <&pcal6524>;
> > + interrupts = <1 IRQ_TYPE_EDGE_FALLING>;
> > + status = "okay";
>
> Really, just drop...
Ok, will drop the status in next version.
Thanks for your comment!
BR
Joy Zou
>
>
> Best regards,
> Krzysztof
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [EXT] Re: [PATCH v1 1/1] arm64: dts: imx93-11x11-evk: add rtc PCF2131 support
From: Krzysztof Kozlowski @ 2024-04-07 9:12 UTC (permalink / raw)
To: Joy Zou, Jacky Bai, robh+dt@kernel.org,
krzysztof.kozlowski+dt@linaro.org, conor+dt@kernel.org,
shawnguo@kernel.org, s.hauer@pengutronix.de
Cc: kernel@pengutronix.de, festevam@gmail.com, dl-linux-imx,
devicetree@vger.kernel.org, imx@lists.linux.dev,
linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org
In-Reply-To: <AS4PR04MB9386C629F898A8417AE57506E1012@AS4PR04MB9386.eurprd04.prod.outlook.com>
On 07/04/2024 11:09, Joy Zou wrote:
>
>> -----Original Message-----
>> From: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
>> Sent: 2024年4月7日 17:04
>> To: Joy Zou <joy.zou@nxp.com>; Jacky Bai <ping.bai@nxp.com>;
>> robh+dt@kernel.org; krzysztof.kozlowski+dt@linaro.org;
>> conor+dt@kernel.org; shawnguo@kernel.org; s.hauer@pengutronix.de
>> Cc: kernel@pengutronix.de; festevam@gmail.com; dl-linux-imx
>> <linux-imx@nxp.com>; devicetree@vger.kernel.org; imx@lists.linux.dev;
>> linux-arm-kernel@lists.infradead.org; linux-kernel@vger.kernel.org
>> Subject: [EXT] Re: [PATCH v1 1/1] arm64: dts: imx93-11x11-evk: add rtc
>> PCF2131 support
>>> +&lpi2c3 {
>>> + #address-cells = <1>;
>>> + #size-cells = <0>;
>>> + clock-frequency = <400000>;
>>> + pinctrl-names = "default", "sleep";
>>> + pinctrl-0 = <&pinctrl_lpi2c3>;
>>> + pinctrl-1 = <&pinctrl_lpi2c3>;
>>> + status = "okay";
>>> +
>>> + pcf2131: rtc@53 {
>>> + compatible = "nxp,pcf2131";
>>> + reg = <0x53>;
>>> + interrupt-parent = <&pcal6524>;
>>> + interrupts = <1 IRQ_TYPE_EDGE_FALLING>;
>>> + status = "okay";
>>
>> Really, just drop...
> Ok, will drop the status in next version.
> Thanks for your comment!
Please read DTS coding style.
Best regards,
Krzysztof
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ 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