* Re: [PATCH v4 11/17] drm/mediatek: Get rid of mtk_smi_larb_get/put
From: Chun-Kuang Hu @ 2020-05-30 11:08 UTC (permalink / raw)
To: Yong Wu
Cc: Matthias Brugger, Joerg Roedel, Rob Herring, Will Deacon,
youlin.pei, Nicolas Boichat, Evan Green, eizan, Matthias Kaehlcke,
Linux ARM, CK Hu, devicetree, cui.zhang, Tomasz Figa,
moderated list:ARM/Mediatek SoC support, ming-fan.chen, anan.sun,
acourbot, srv_heupstream, linux-kernel, chao.hao, iommu,
Philipp Zabel, Robin Murphy
In-Reply-To: <1590826218-23653-12-git-send-email-yong.wu@mediatek.com>
Hi, Yong:
Yong Wu <yong.wu@mediatek.com> 於 2020年5月30日 週六 下午4:27寫道:
>
> MediaTek IOMMU has already added the device_link between the consumer
> and smi-larb device. If the drm device call the pm_runtime_get_sync,
> the smi-larb's pm_runtime_get_sync also be called automatically.
>
Acked-by: Chun-Kuang Hu <chunkuang.hu@kernel.org>
> CC: CK Hu <ck.hu@mediatek.com>
> CC: Philipp Zabel <p.zabel@pengutronix.de>
> Signed-off-by: Yong Wu <yong.wu@mediatek.com>
> Reviewed-by: Evan Green <evgreen@chromium.org>
> ---
> drivers/gpu/drm/mediatek/mtk_drm_crtc.c | 9 ---------
> drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c | 21 ---------------------
> drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h | 1 -
> 3 files changed, 31 deletions(-)
>
> diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
> index c9bc844..d4c4078 100644
> --- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
> +++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
> @@ -8,7 +8,6 @@
> #include <linux/soc/mediatek/mtk-cmdq.h>
>
> #include <asm/barrier.h>
> -#include <soc/mediatek/smi.h>
>
> #include <drm/drm_atomic_helper.h>
> #include <drm/drm_plane_helper.h>
> @@ -532,12 +531,6 @@ static void mtk_drm_crtc_atomic_enable(struct drm_crtc *crtc,
>
> DRM_DEBUG_DRIVER("%s %d\n", __func__, crtc->base.id);
>
> - ret = mtk_smi_larb_get(comp->larb_dev);
> - if (ret) {
> - DRM_ERROR("Failed to get larb: %d\n", ret);
> - return;
> - }
> -
> ret = pm_runtime_get_sync(comp->dev);
> if (ret < 0)
> DRM_DEV_ERROR(comp->dev, "Failed to enable power domain: %d\n",
> @@ -545,7 +538,6 @@ static void mtk_drm_crtc_atomic_enable(struct drm_crtc *crtc,
>
> ret = mtk_crtc_ddp_hw_init(mtk_crtc);
> if (ret) {
> - mtk_smi_larb_put(comp->larb_dev);
> pm_runtime_put(comp->dev);
> return;
> }
> @@ -582,7 +574,6 @@ static void mtk_drm_crtc_atomic_disable(struct drm_crtc *crtc,
>
> drm_crtc_vblank_off(crtc);
> mtk_crtc_ddp_hw_fini(mtk_crtc);
> - mtk_smi_larb_put(comp->larb_dev);
> ret = pm_runtime_put(comp->dev);
> if (ret < 0)
> DRM_DEV_ERROR(comp->dev, "Failed to disable power domain: %d\n",
> diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c
> index 593027a..a6e7f3a 100644
> --- a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c
> +++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c
> @@ -432,8 +432,6 @@ int mtk_ddp_comp_init(struct device *dev, struct device_node *node,
> const struct mtk_ddp_comp_funcs *funcs)
> {
> enum mtk_ddp_comp_type type;
> - struct device_node *larb_node;
> - struct platform_device *larb_pdev;
> #if IS_REACHABLE(CONFIG_MTK_CMDQ)
> struct resource res;
> struct cmdq_client_reg cmdq_reg;
> @@ -468,31 +466,12 @@ int mtk_ddp_comp_init(struct device *dev, struct device_node *node,
> if (IS_ERR(comp->clk))
> return PTR_ERR(comp->clk);
>
> - /* Only DMA capable components need the LARB property */
> - comp->larb_dev = NULL;
> if (type != MTK_DISP_OVL &&
> type != MTK_DISP_OVL_2L &&
> type != MTK_DISP_RDMA &&
> type != MTK_DISP_WDMA)
> return 0;
>
> - larb_node = of_parse_phandle(node, "mediatek,larb", 0);
> - if (!larb_node) {
> - dev_err(dev,
> - "Missing mediadek,larb phandle in %pOF node\n", node);
> - return -EINVAL;
> - }
> -
> - larb_pdev = of_find_device_by_node(larb_node);
> - if (!larb_pdev) {
> - dev_warn(dev, "Waiting for larb device %pOF\n", larb_node);
> - of_node_put(larb_node);
> - return -EPROBE_DEFER;
> - }
> - of_node_put(larb_node);
> -
> - comp->larb_dev = &larb_pdev->dev;
> -
> comp->dev = dev;
>
> #if IS_REACHABLE(CONFIG_MTK_CMDQ)
> diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h
> index 4c063e0..11c7120 100644
> --- a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h
> +++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h
> @@ -98,7 +98,6 @@ struct mtk_ddp_comp {
> struct clk *clk;
> void __iomem *regs;
> int irq;
> - struct device *larb_dev;
> struct device *dev;
> enum mtk_ddp_comp_id id;
> const struct mtk_ddp_comp_funcs *funcs;
> --
> 1.9.1
> _______________________________________________
> Linux-mediatek mailing list
> Linux-mediatek@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-mediatek
^ permalink raw reply
* Re: [PATCH v6 08/11] i2c: designware: Convert driver to using regmap API
From: Wolfram Sang @ 2020-05-30 11:09 UTC (permalink / raw)
To: Serge Semin
Cc: Jarkko Nikula, Andy Shevchenko, Mika Westerberg, Serge Semin,
Alexey Malahov, Thomas Bogendoerfer, Rob Herring, devicetree,
linux-mips, linux-i2c, linux-kernel
In-Reply-To: <20200528093322.23553-9-Sergey.Semin@baikalelectronics.ru>
[-- Attachment #1: Type: text/plain, Size: 2248 bytes --]
On Thu, May 28, 2020 at 12:33:18PM +0300, Serge Semin wrote:
> Seeing the DW I2C driver is using flags-based accessors with two
> conditional clauses it would be better to replace them with the regmap
> API IO methods and to initialize the regmap object with read/write
> callbacks specific to the controller registers map implementation. This
> will be also handy for the drivers with non-standard registers mapping
> (like an embedded into the Baikal-T1 System Controller DW I2C block, which
> glue-driver is a part of this series).
>
> As before the driver tries to detect the mapping setup at probe stage and
> creates a regmap object accordingly, which will be used by the rest of the
> code to correctly access the controller registers. In two places it was
> appropriate to convert the hand-written read-modify-write and
> read-poll-loop design patterns to the corresponding regmap API
> ready-to-use methods.
>
> Note the regmap IO methods return value is checked only at the probe
> stage. The rest of the code won't do this because basically we have
> MMIO-based regmap so non of the read/write methods can fail (this also
> won't be needed for the Baikal-T1-specific I2C controller).
>
> Suggested-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
> Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
> Tested-by: Jarkko Nikula <jarkko.nikula@linux.intel.com>
> Acked-by: Jarkko Nikula <jarkko.nikula@linux.intel.com>
> Cc: Alexey Malahov <Alexey.Malahov@baikalelectronics.ru>
> Cc: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
> Cc: Rob Herring <robh+dt@kernel.org>
> Cc: devicetree@vger.kernel.org
> Cc: linux-mips@vger.kernel.org
My codecheckers found these, rightfully I'd say:
SPARSE
drivers/i2c/busses/i2c-designware-master.c:427:53: warning: incorrect type in argument 3 (different signedness)
drivers/i2c/busses/i2c-designware-master.c:427:53: expected unsigned int *val
drivers/i2c/busses/i2c-designware-master.c:427:53: got int *
CC
drivers/i2c/busses/i2c-designware-common.c:127: warning: Excess function parameter 'base' description in 'i2c_dw_init_regmap'
^ means there is an argument documented which does not exist in the
function declaration
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply
* Re: [PATCH v6 01/11] dt-bindings: i2c: Convert DW I2C binding to DT schema
From: Wolfram Sang @ 2020-05-30 11:10 UTC (permalink / raw)
To: Serge Semin
Cc: Serge Semin, Jarkko Nikula, Rob Herring, Rob Herring,
Alexey Malahov, Thomas Bogendoerfer, Andy Shevchenko,
Mika Westerberg, linux-mips, linux-i2c, devicetree, linux-kernel
In-Reply-To: <20200530102419.gtgh77eaxoort3zh@mobilestation>
[-- Attachment #1: Type: text/plain, Size: 423 bytes --]
> > WARNING: DT binding documents should be licensed (GPL-2.0-only OR BSD-2-Clause)
> >
>
> Hope you don't mind me answering on a question for Rob. That warning concerns
> new bindings and bindings converted by a person eligible to change the license.
> Otherwise by default any converted binding is supposed to be left under pure
> GPL as the rest of kernel code.
Thanks for the heads up. OK for me, then.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply
* Re: [PATCH dt-schema] Fix interrupt controllers with interrupt-map
From: Geert Uytterhoeven @ 2020-05-30 12:30 UTC (permalink / raw)
To: Rob Herring
Cc: open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
Rasmus Villemoes
In-Reply-To: <CAL_Jsq+goALPsbhQ=Euh7fUupfC1gXO+AZXR=Obm9G_zMN7q4A@mail.gmail.com>
Hi Rob,
Cc Rasmus
On Fri, May 29, 2020 at 11:44 PM Rob Herring <robh+dt@kernel.org> wrote:
> On Fri, May 29, 2020 at 10:02 AM Geert Uytterhoeven
> <geert@linux-m68k.org> wrote:
> > On Fri, May 29, 2020 at 5:54 PM Rob Herring <robh+dt@kernel.org> wrote:
> > > On Thu, May 28, 2020 at 7:23 AM Geert Uytterhoeven
> > > <geert+renesas@glider.be> wrote:
> > > > When an interrupt controller has an "interrupt-map" property, an "is
> > > > valid under each of" error is triggered.
> > > >
> > > > Fix this by allowing "interrupt-controller" and "interrupt-map" to
> > > > coexist, in both the interrrupts meta-schema and the
> > > > interrupt-controller schema.
> > >
> > > But both should not be present. If 'interrupt-controller' is present,
> >
> > Why not?
>
> Well, maybe I'm wrong. If you have more than just transparent
> remapping (i.e. mask/unmask/clear), then perhaps both are appropriate
> because you want get the irq domain for the first irq parent.
Indeed, that's the case for rza1-irqc.
> > > the Linux irq parsing code will ignore 'interrupt-map'. Seems like
> > > that's backwards, but this parsing code is older than dirt and we'd
> > > probably break some 1990s machine changing it.
> >
> > That's fine. rza1_irqc_parse_map() parses the interrupt-map itself,
> > to map from downstream to upstream interrupts.
>
> You shouldn't really be parsing interrupt-map yourself. The code there
Of course I had tried that before[1];
| I also considered extracting the parsing code in of_irq_parse_raw() in a
| new public helper function:
|
| int of_irq_parse_map(struct device_node **ipar, u32 *addrsize,
| u32 *intsize, const __be32 **match_array,
| struct of_phandle_args *out_irq);
|
| However, that API is a bit ugly due to many output parameters
| (of_irq_parse_raw() needs to iterate the interrupt hierarchy).
| In addition, it's less efficient for irq-renesas-rza1.c, as the
| interrupt-map must be parsed 8 times.
Or is there a better way?
In the mean time, drivers/irqchip/irq-ls-extirq.c has landed, which was
mimiced after irq-renesas-rza1.c.
> doesn't account for #address-cells which can be a factor for
> interrupt-map. dtc is gaining some checks for 'interrupt-map', so
> let's hope you have it right.
The driver code indeed doesn't account for #address-cells, but the
binding says it must be zero anyway.
[1] "[PATCH v4 2/2] irqchip: Add Renesas RZ/A1 Interrupt Controller driver"
http://lore.kernel.org/r/20190527121711.5138-3-geert+renesas@glider.be
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
^ permalink raw reply
* [PATCH 1/2] dt-bindings: abx80x: Add autocal-filter property
From: Kevin P. Fleming @ 2020-05-30 12:48 UTC (permalink / raw)
To: devicetree, linux-rtc
Cc: Kevin P. Fleming, Alessandro Zummo, Alexandre Belloni,
Rob Herring
Add a property to allow control of the autocalibration filter
capacitor.
Signed-off-by: Kevin P. Fleming <kevin+linux@km6g.us>
Cc: Alessandro Zummo <a.zummo@towertech.it>
Cc: Alexandre Belloni <alexandre.belloni@bootlin.com>
Cc: Rob Herring <robh+dt@kernel.org>
To: linux-rtc@vger.kernel.org
To: devicetree@vger.kernel.org
---
Documentation/devicetree/bindings/rtc/abracon,abx80x.txt | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/Documentation/devicetree/bindings/rtc/abracon,abx80x.txt b/Documentation/devicetree/bindings/rtc/abracon,abx80x.txt
index 2405e35a1bc0..ad5d59ed6f24 100644
--- a/Documentation/devicetree/bindings/rtc/abracon,abx80x.txt
+++ b/Documentation/devicetree/bindings/rtc/abracon,abx80x.txt
@@ -29,3 +29,9 @@ and valid to enable charging:
- "abracon,tc-diode": should be "standard" (0.6V) or "schottky" (0.3V)
- "abracon,tc-resistor": should be <0>, <3>, <6> or <11>. 0 disables the output
resistor, the other values are in kOhm.
+
+All of the devices can have a 47pf capacitor attached to increase the
+autocalibration accuracy of their RC oscillators. To enable usage of the
+capacitor the following property has to be defined:
+
+ - "abracon,autocal-filter"
--
2.26.2
^ permalink raw reply related
* [PATCH 2/2] rtc: abx80x: Add support for autocalibration filter capacitor
From: Kevin P. Fleming @ 2020-05-30 12:49 UTC (permalink / raw)
To: devicetree, linux-rtc
Cc: Kevin P. Fleming, Alessandro Zummo, Alexandre Belloni,
Rob Herring
In-Reply-To: <20200530124900.363399-1-kevin+linux@km6g.us>
All of the parts supported by this driver can make use of a
small capacitor to improve the accuracy of the autocalibration
process for their RC oscillators. If a capacitor is connected,
a configuration register must be set to enable its use, so a
new Device Tree property has been added for that purpose.
Signed-off-by: Kevin P. Fleming <kevin+linux@km6g.us>
Cc: Alessandro Zummo <a.zummo@towertech.it>
Cc: Alexandre Belloni <alexandre.belloni@bootlin.com>
Cc: Rob Herring <robh+dt@kernel.org>
To: linux-rtc@vger.kernel.org
To: devicetree@vger.kernel.org
---
drivers/rtc/rtc-abx80x.c | 34 ++++++++++++++++++++++++++++++++++
1 file changed, 34 insertions(+)
diff --git a/drivers/rtc/rtc-abx80x.c b/drivers/rtc/rtc-abx80x.c
index 3521d8e8dc38..be5a814e8c0b 100644
--- a/drivers/rtc/rtc-abx80x.c
+++ b/drivers/rtc/rtc-abx80x.c
@@ -76,6 +76,9 @@
#define ABX8XX_CFG_KEY_OSC 0xa1
#define ABX8XX_CFG_KEY_MISC 0x9d
+#define ABX8XX_REG_AFCTRL 0x26
+#define ABX8XX_AUTOCAL_FILTER_ENABLE 0xa0
+
#define ABX8XX_REG_ID0 0x28
#define ABX8XX_REG_OUT_CTRL 0x30
@@ -130,6 +133,31 @@ static int abx80x_is_rc_mode(struct i2c_client *client)
return (flags & ABX8XX_OSS_OMODE) ? 1 : 0;
}
+static int abx80x_enable_autocal_filter(struct i2c_client *client)
+{
+ int err;
+
+ /*
+ * Write the configuration key register to enable access to the AFCTRL
+ * register
+ */
+ err = i2c_smbus_write_byte_data(client, ABX8XX_REG_CFG_KEY,
+ ABX8XX_CFG_KEY_MISC);
+ if (err < 0) {
+ dev_err(&client->dev, "Unable to write configuration key\n");
+ return -EIO;
+ }
+
+ err = i2c_smbus_write_byte_data(client, ABX8XX_REG_AFCTRL,
+ ABX8XX_AUTOCAL_FILTER_ENABLE);
+ if (err < 0) {
+ dev_err(&client->dev, "Unable to write autocal filter register\n");
+ return -EIO;
+ }
+
+ return 0;
+}
+
static int abx80x_enable_trickle_charger(struct i2c_client *client,
u8 trickle_cfg)
{
@@ -825,6 +853,12 @@ static int abx80x_probe(struct i2c_client *client,
return err;
}
+ if (of_property_read_bool(np, "abracon,autocal_filter")) {
+ err = abx80x_enable_autocal_filter(client);
+ if (err)
+ return err;
+ }
+
if (client->irq > 0) {
dev_info(&client->dev, "IRQ %d supplied\n", client->irq);
err = devm_request_threaded_irq(&client->dev, client->irq, NULL,
--
2.26.2
^ permalink raw reply related
* Re: [PATCH] rtc: abx80x: Add support for autocalibration filter capacitor
From: Kevin P. Fleming @ 2020-05-30 12:50 UTC (permalink / raw)
To: Kevin P. Fleming
Cc: linux-rtc, devicetree, Alessandro Zummo, Alexandre Belloni,
Rob Herring
In-Reply-To: <20200530123222.361104-1-kevin+linux@km6g.us>
Sorry, this was sent prematurely and should have been split into two
patches. It has been resent properly.
On Sat, May 30, 2020 at 8:32 AM Kevin P. Fleming <kevin+linux@km6g.us> wrote:
>
> All of the parts supported by this driver can make use of a
> small capacitor to improve the accuracy of the autocalibration
> process for their RC oscillators. If a capacitor is connected,
> a configuration register must be set to enable its use, so a
> new Device Tree property has been added for that purpose.
>
> Signed-off-by: Kevin P. Fleming <kevin+linux@km6g.us>
> Cc: Alessandro Zummo <a.zummo@towertech.it>
> Cc: Alexandre Belloni <alexandre.belloni@bootlin.com>
> Cc: Rob Herring <robh+dt@kernel.org>
> To: linux-rtc@vger.kernel.org
> To: devicetree@vger.kernel.org
> ---
> .../bindings/rtc/abracon,abx80x.txt | 6 ++++
> drivers/rtc/rtc-abx80x.c | 34 +++++++++++++++++++
> 2 files changed, 40 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/rtc/abracon,abx80x.txt b/Documentation/devicetree/bindings/rtc/abracon,abx80x.txt
> index 2405e35a1bc0..ad5d59ed6f24 100644
> --- a/Documentation/devicetree/bindings/rtc/abracon,abx80x.txt
> +++ b/Documentation/devicetree/bindings/rtc/abracon,abx80x.txt
> @@ -29,3 +29,9 @@ and valid to enable charging:
> - "abracon,tc-diode": should be "standard" (0.6V) or "schottky" (0.3V)
> - "abracon,tc-resistor": should be <0>, <3>, <6> or <11>. 0 disables the output
> resistor, the other values are in kOhm.
> +
> +All of the devices can have a 47pf capacitor attached to increase the
> +autocalibration accuracy of their RC oscillators. To enable usage of the
> +capacitor the following property has to be defined:
> +
> + - "abracon,autocal-filter"
> diff --git a/drivers/rtc/rtc-abx80x.c b/drivers/rtc/rtc-abx80x.c
> index 3521d8e8dc38..be5a814e8c0b 100644
> --- a/drivers/rtc/rtc-abx80x.c
> +++ b/drivers/rtc/rtc-abx80x.c
> @@ -76,6 +76,9 @@
> #define ABX8XX_CFG_KEY_OSC 0xa1
> #define ABX8XX_CFG_KEY_MISC 0x9d
>
> +#define ABX8XX_REG_AFCTRL 0x26
> +#define ABX8XX_AUTOCAL_FILTER_ENABLE 0xa0
> +
> #define ABX8XX_REG_ID0 0x28
>
> #define ABX8XX_REG_OUT_CTRL 0x30
> @@ -130,6 +133,31 @@ static int abx80x_is_rc_mode(struct i2c_client *client)
> return (flags & ABX8XX_OSS_OMODE) ? 1 : 0;
> }
>
> +static int abx80x_enable_autocal_filter(struct i2c_client *client)
> +{
> + int err;
> +
> + /*
> + * Write the configuration key register to enable access to the AFCTRL
> + * register
> + */
> + err = i2c_smbus_write_byte_data(client, ABX8XX_REG_CFG_KEY,
> + ABX8XX_CFG_KEY_MISC);
> + if (err < 0) {
> + dev_err(&client->dev, "Unable to write configuration key\n");
> + return -EIO;
> + }
> +
> + err = i2c_smbus_write_byte_data(client, ABX8XX_REG_AFCTRL,
> + ABX8XX_AUTOCAL_FILTER_ENABLE);
> + if (err < 0) {
> + dev_err(&client->dev, "Unable to write autocal filter register\n");
> + return -EIO;
> + }
> +
> + return 0;
> +}
> +
> static int abx80x_enable_trickle_charger(struct i2c_client *client,
> u8 trickle_cfg)
> {
> @@ -825,6 +853,12 @@ static int abx80x_probe(struct i2c_client *client,
> return err;
> }
>
> + if (of_property_read_bool(np, "abracon,autocal_filter")) {
> + err = abx80x_enable_autocal_filter(client);
> + if (err)
> + return err;
> + }
> +
> if (client->irq > 0) {
> dev_info(&client->dev, "IRQ %d supplied\n", client->irq);
> err = devm_request_threaded_irq(&client->dev, client->irq, NULL,
> --
> 2.26.2
>
^ permalink raw reply
* [PATCH] rtc: abx80x: Add support for autocalibration filter capacitor
From: Kevin P. Fleming @ 2020-05-30 12:32 UTC (permalink / raw)
To: linux-rtc, devicetree
Cc: Kevin P. Fleming, Alessandro Zummo, Alexandre Belloni,
Rob Herring
All of the parts supported by this driver can make use of a
small capacitor to improve the accuracy of the autocalibration
process for their RC oscillators. If a capacitor is connected,
a configuration register must be set to enable its use, so a
new Device Tree property has been added for that purpose.
Signed-off-by: Kevin P. Fleming <kevin+linux@km6g.us>
Cc: Alessandro Zummo <a.zummo@towertech.it>
Cc: Alexandre Belloni <alexandre.belloni@bootlin.com>
Cc: Rob Herring <robh+dt@kernel.org>
To: linux-rtc@vger.kernel.org
To: devicetree@vger.kernel.org
---
.../bindings/rtc/abracon,abx80x.txt | 6 ++++
drivers/rtc/rtc-abx80x.c | 34 +++++++++++++++++++
2 files changed, 40 insertions(+)
diff --git a/Documentation/devicetree/bindings/rtc/abracon,abx80x.txt b/Documentation/devicetree/bindings/rtc/abracon,abx80x.txt
index 2405e35a1bc0..ad5d59ed6f24 100644
--- a/Documentation/devicetree/bindings/rtc/abracon,abx80x.txt
+++ b/Documentation/devicetree/bindings/rtc/abracon,abx80x.txt
@@ -29,3 +29,9 @@ and valid to enable charging:
- "abracon,tc-diode": should be "standard" (0.6V) or "schottky" (0.3V)
- "abracon,tc-resistor": should be <0>, <3>, <6> or <11>. 0 disables the output
resistor, the other values are in kOhm.
+
+All of the devices can have a 47pf capacitor attached to increase the
+autocalibration accuracy of their RC oscillators. To enable usage of the
+capacitor the following property has to be defined:
+
+ - "abracon,autocal-filter"
diff --git a/drivers/rtc/rtc-abx80x.c b/drivers/rtc/rtc-abx80x.c
index 3521d8e8dc38..be5a814e8c0b 100644
--- a/drivers/rtc/rtc-abx80x.c
+++ b/drivers/rtc/rtc-abx80x.c
@@ -76,6 +76,9 @@
#define ABX8XX_CFG_KEY_OSC 0xa1
#define ABX8XX_CFG_KEY_MISC 0x9d
+#define ABX8XX_REG_AFCTRL 0x26
+#define ABX8XX_AUTOCAL_FILTER_ENABLE 0xa0
+
#define ABX8XX_REG_ID0 0x28
#define ABX8XX_REG_OUT_CTRL 0x30
@@ -130,6 +133,31 @@ static int abx80x_is_rc_mode(struct i2c_client *client)
return (flags & ABX8XX_OSS_OMODE) ? 1 : 0;
}
+static int abx80x_enable_autocal_filter(struct i2c_client *client)
+{
+ int err;
+
+ /*
+ * Write the configuration key register to enable access to the AFCTRL
+ * register
+ */
+ err = i2c_smbus_write_byte_data(client, ABX8XX_REG_CFG_KEY,
+ ABX8XX_CFG_KEY_MISC);
+ if (err < 0) {
+ dev_err(&client->dev, "Unable to write configuration key\n");
+ return -EIO;
+ }
+
+ err = i2c_smbus_write_byte_data(client, ABX8XX_REG_AFCTRL,
+ ABX8XX_AUTOCAL_FILTER_ENABLE);
+ if (err < 0) {
+ dev_err(&client->dev, "Unable to write autocal filter register\n");
+ return -EIO;
+ }
+
+ return 0;
+}
+
static int abx80x_enable_trickle_charger(struct i2c_client *client,
u8 trickle_cfg)
{
@@ -825,6 +853,12 @@ static int abx80x_probe(struct i2c_client *client,
return err;
}
+ if (of_property_read_bool(np, "abracon,autocal_filter")) {
+ err = abx80x_enable_autocal_filter(client);
+ if (err)
+ return err;
+ }
+
if (client->irq > 0) {
dev_info(&client->dev, "IRQ %d supplied\n", client->irq);
err = devm_request_threaded_irq(&client->dev, client->irq, NULL,
--
2.26.2
^ permalink raw reply related
* Re: [RFC PATCH 1/6] dt-bindings: display/bridge: Add binding for input mux bridge
From: Guido Günther @ 2020-05-30 13:26 UTC (permalink / raw)
To: Rob Herring
Cc: Laurent Pinchart, David Airlie, Daniel Vetter, Shawn Guo,
Pengutronix Kernel Team, Fabio Estevam, NXP Linux Team,
Andrzej Hajda, Sam Ravnborg, Anson Huang, Leonard Crestez,
Lucas Stach, Peng Fan, Robert Chiras, dri-devel, devicetree,
linux-kernel, linux-arm-kernel
In-Reply-To: <20200528194804.GA541078@bogus>
Hi Rob,
On Thu, May 28, 2020 at 01:48:04PM -0600, Rob Herring wrote:
> On Fri, May 15, 2020 at 03:12:10PM +0200, Guido Günther wrote:
> > The bridge allows to select the input source via a mux controller.
> >
> > Signed-off-by: Guido Günther <agx@sigxcpu.org>
> > ---
> > .../display/bridge/mux-input-bridge.yaml | 123 ++++++++++++++++++
> > 1 file changed, 123 insertions(+)
> > create mode 100644 Documentation/devicetree/bindings/display/bridge/mux-input-bridge.yaml
> >
> > diff --git a/Documentation/devicetree/bindings/display/bridge/mux-input-bridge.yaml b/Documentation/devicetree/bindings/display/bridge/mux-input-bridge.yaml
> > new file mode 100644
> > index 000000000000..4029cf63ee5c
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/display/bridge/mux-input-bridge.yaml
> > @@ -0,0 +1,123 @@
> > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> > +%YAML 1.2
> > +---
> > +$id: http://devicetree.org/schemas/display/bridge/mux-input-bridge.yaml#
> > +$schema: http://devicetree.org/meta-schemas/core.yaml#
> > +
> > +title: DRM input source selection via multiplexer
>
> DRM is not a hardware thing.
I thought about naming the mux pixel-input-mux (input-mux sounding too
generic) but then i hit rockchip-drm and went for that name. The
binding itself is not a drm thing in itself it really aims to model how
the mux is placed in the 'display pipeline' of the SoC (as Laurent
explained). Should I go with pixel-input-mux?
> The graph binding is already designed to support muxing. Generally,
> multiple endpoints on an input node is a mux. So either the device with
> the input ports knows how to select the input, or you just need a
> mux-control property for the port to have some other device implement
> the control.
A mux control property is how it's modeled at the moment but that is
very SoC specific.
> You could do it like you have below. That would be appropriate if
> there's a separate h/w device controlling the muxing. Say for example
> some board level device controlled by i2c.
It's a different part of the SoC that lives in a register range very
separate (iomuxc_gpr) from MIPI/DSI (nwl). Does that qualify?
Cheers,
-- Guido
>
> Rob
>
^ permalink raw reply
* Re: [PATCH v3 02/25] dt-bindings: clock: Add a binding for the RPi Firmware clocks
From: Maxime Ripard @ 2020-05-30 16:23 UTC (permalink / raw)
To: Stephen Boyd
Cc: Nicolas Saenz Julienne, linux-rpi-kernel,
bcm-kernel-feedback-list, linux-arm-kernel, linux-kernel,
Dave Stevenson, Tim Gover, Phil Elwell, Michael Turquette,
Rob Herring, linux-clk, devicetree
In-Reply-To: <159078703613.69627.13627047580756230984@swboyd.mtv.corp.google.com>
[-- Attachment #1: Type: text/plain, Size: 445 bytes --]
Hi Stephen,
Thanks for your review :)
On Fri, May 29, 2020 at 02:17:16PM -0700, Stephen Boyd wrote:
> > + "#clock-cells":
> > + const: 1
> > + description: >
>
> Just curious if this is the same as the | syntax? I haven't seen this
> used before.
It differs on how it keeps the formatting of text below. | will keep the
formatting as is, > will leave the formatting to whatever is going to use it.
Maxime
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply
* [PATCH 1/2] dt-bindings: USB: Add Ingenic X1000 and X1830 bindings.
From: 周琰杰 (Zhou Yanjie) @ 2020-05-30 16:52 UTC (permalink / raw)
To: linux-usb
Cc: linux-kernel, devicetree, balbi, gregkh, robh+dt, dongsheng.qiu,
aric.pzqi, rick.tyliu, yanfei.li, sernia.zhou, zhenwenjin
In-Reply-To: <20200530165253.17445-1-zhouyanjie@wanyeetech.com>
Add the USB PHY bindings for the X1000 SoC and
the X1830 SoC from Ingenic.
Signed-off-by: 周琰杰 (Zhou Yanjie) <zhouyanjie@wanyeetech.com>
---
Documentation/devicetree/bindings/usb/ingenic,jz4770-phy.yaml | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/Documentation/devicetree/bindings/usb/ingenic,jz4770-phy.yaml b/Documentation/devicetree/bindings/usb/ingenic,jz4770-phy.yaml
index a81b0b1a2226..95ba3b9aa801 100644
--- a/Documentation/devicetree/bindings/usb/ingenic,jz4770-phy.yaml
+++ b/Documentation/devicetree/bindings/usb/ingenic,jz4770-phy.yaml
@@ -4,10 +4,11 @@
$id: http://devicetree.org/schemas/usb/ingenic,jz4770-phy.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: Ingenic JZ4770 USB PHY devicetree bindings
+title: Ingenic SoCs USB PHY devicetree bindings
maintainers:
- Paul Cercueil <paul@crapouillou.net>
+ - 周琰杰 (Zhou Yanjie) <zhouyanjie@wanyeetech.com>
properties:
$nodename:
@@ -16,6 +17,8 @@ properties:
compatible:
enum:
- ingenic,jz4770-phy
+ - ingenic,x1000-phy
+ - ingenic,x1830-phy
reg:
maxItems: 1
--
2.11.0
^ permalink raw reply related
* [PATCH 0/2] Add USB PHY support for Ingenic X1000 and X1830.
From: 周琰杰 (Zhou Yanjie) @ 2020-05-30 16:52 UTC (permalink / raw)
To: linux-usb
Cc: linux-kernel, devicetree, balbi, gregkh, robh+dt, dongsheng.qiu,
aric.pzqi, rick.tyliu, yanfei.li, sernia.zhou, zhenwenjin
1.Add the USB PHY bindings for the X1000 SoC and
the X1830 SoC from Ingenic.
2.Add support for probing the phy-jz4770 driver on the
X1000 SoC and the X1830 SoC from Ingenic.
周琰杰 (Zhou Yanjie) (2):
dt-bindings: USB: Add Ingenic X1000 and X1830 bindings.
USB: PHY: JZ4770: Add support for Ingenic X1000 and X1830.
.../bindings/usb/ingenic,jz4770-phy.yaml | 5 +-
drivers/usb/phy/Kconfig | 4 +-
drivers/usb/phy/phy-jz4770.c | 250 ++++++++++++++-------
3 files changed, 173 insertions(+), 86 deletions(-)
--
2.11.0
^ permalink raw reply
* [PATCH 2/2] USB: PHY: JZ4770: Add support for Ingenic X1000 and X1830.
From: 周琰杰 (Zhou Yanjie) @ 2020-05-30 16:52 UTC (permalink / raw)
To: linux-usb
Cc: linux-kernel, devicetree, balbi, gregkh, robh+dt, dongsheng.qiu,
aric.pzqi, rick.tyliu, yanfei.li, sernia.zhou, zhenwenjin
In-Reply-To: <20200530165253.17445-1-zhouyanjie@wanyeetech.com>
Add support for probing the phy-jz4770 driver on the
X1000 SoC and the X1830 SoC from Ingenic.
Signed-off-by: qipengzhen <aric.pzqi@ingenic.com>
Signed-off-by: 周琰杰 (Zhou Yanjie) <zhouyanjie@wanyeetech.com>
---
drivers/usb/phy/Kconfig | 4 +-
drivers/usb/phy/phy-jz4770.c | 250 +++++++++++++++++++++++++++++--------------
2 files changed, 169 insertions(+), 85 deletions(-)
diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig
index 4b3fa78995cf..fb7e32d07646 100644
--- a/drivers/usb/phy/Kconfig
+++ b/drivers/usb/phy/Kconfig
@@ -185,11 +185,11 @@ config USB_ULPI_VIEWPORT
controllers with a viewport register (e.g. Chipidea/ARC controllers).
config JZ4770_PHY
- tristate "Ingenic JZ4770 Transceiver Driver"
+ tristate "Ingenic SOCs Transceiver Driver"
depends on MIPS || COMPILE_TEST
select USB_PHY
help
This driver provides PHY support for the USB controller found
- on the JZ4770 SoC from Ingenic.
+ on the JZ4770/X1000/X1830 SoC from Ingenic.
endmenu
diff --git a/drivers/usb/phy/phy-jz4770.c b/drivers/usb/phy/phy-jz4770.c
index 3ea1f5b9bcf8..b31d70bb778c 100644
--- a/drivers/usb/phy/phy-jz4770.c
+++ b/drivers/usb/phy/phy-jz4770.c
@@ -1,77 +1,111 @@
// SPDX-License-Identifier: GPL-2.0
/*
- * Ingenic JZ4770 USB PHY driver
+ * Ingenic SoCs USB PHY driver
* Copyright (c) Paul Cercueil <paul@crapouillou.net>
+ * Copyright (c) qipengzhen <aric.pzqi@ingenic.com>
+ * Copyright (c) 周琰杰 (Zhou Yanjie) <zhouyanjie@wanyeetech.com>
*/
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/module.h>
+#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/regulator/consumer.h>
#include <linux/usb/otg.h>
#include <linux/usb/phy.h>
-#define REG_USBPCR_OFFSET 0x00
-#define REG_USBRDT_OFFSET 0x04
-#define REG_USBVBFIL_OFFSET 0x08
-#define REG_USBPCR1_OFFSET 0x0c
-
-/* USBPCR */
-#define USBPCR_USB_MODE BIT(31)
-#define USBPCR_AVLD_REG BIT(30)
-#define USBPCR_INCRM BIT(27)
-#define USBPCR_CLK12_EN BIT(26)
-#define USBPCR_COMMONONN BIT(25)
-#define USBPCR_VBUSVLDEXT BIT(24)
-#define USBPCR_VBUSVLDEXTSEL BIT(23)
-#define USBPCR_POR BIT(22)
-#define USBPCR_SIDDQ BIT(21)
-#define USBPCR_OTG_DISABLE BIT(20)
-#define USBPCR_TXPREEMPHTUNE BIT(6)
-
-#define USBPCR_IDPULLUP_LSB 28
-#define USBPCR_IDPULLUP_MASK GENMASK(29, USBPCR_IDPULLUP_LSB)
-#define USBPCR_IDPULLUP_ALWAYS (3 << USBPCR_IDPULLUP_LSB)
-#define USBPCR_IDPULLUP_SUSPEND (1 << USBPCR_IDPULLUP_LSB)
-#define USBPCR_IDPULLUP_OTG (0 << USBPCR_IDPULLUP_LSB)
-
-#define USBPCR_COMPDISTUNE_LSB 17
-#define USBPCR_COMPDISTUNE_MASK GENMASK(19, USBPCR_COMPDISTUNE_LSB)
-#define USBPCR_COMPDISTUNE_DFT 4
-
-#define USBPCR_OTGTUNE_LSB 14
-#define USBPCR_OTGTUNE_MASK GENMASK(16, USBPCR_OTGTUNE_LSB)
-#define USBPCR_OTGTUNE_DFT 4
-
-#define USBPCR_SQRXTUNE_LSB 11
-#define USBPCR_SQRXTUNE_MASK GENMASK(13, USBPCR_SQRXTUNE_LSB)
-#define USBPCR_SQRXTUNE_DFT 3
-
-#define USBPCR_TXFSLSTUNE_LSB 7
-#define USBPCR_TXFSLSTUNE_MASK GENMASK(10, USBPCR_TXFSLSTUNE_LSB)
-#define USBPCR_TXFSLSTUNE_DFT 3
-
-#define USBPCR_TXRISETUNE_LSB 4
-#define USBPCR_TXRISETUNE_MASK GENMASK(5, USBPCR_TXRISETUNE_LSB)
-#define USBPCR_TXRISETUNE_DFT 3
-
-#define USBPCR_TXVREFTUNE_LSB 0
-#define USBPCR_TXVREFTUNE_MASK GENMASK(3, USBPCR_TXVREFTUNE_LSB)
-#define USBPCR_TXVREFTUNE_DFT 5
-
-/* USBRDT */
-#define USBRDT_VBFIL_LD_EN BIT(25)
-#define USBRDT_IDDIG_EN BIT(24)
-#define USBRDT_IDDIG_REG BIT(23)
-
-#define USBRDT_USBRDT_LSB 0
-#define USBRDT_USBRDT_MASK GENMASK(22, USBRDT_USBRDT_LSB)
-
-/* USBPCR1 */
-#define USBPCR1_UHC_POWON BIT(5)
+#define REG_USBPCR_OFFSET 0x00
+#define REG_USBRDT_OFFSET 0x04
+#define REG_USBVBFIL_OFFSET 0x08
+#define REG_USBPCR1_OFFSET 0x0c
+
+/*USB Parameter Control Register*/
+#define USBPCR_USB_MODE BIT(31)
+#define USBPCR_AVLD_REG BIT(30)
+#define USBPCR_INCR_MASK BIT(27)
+#define USBPCR_COMMONONN BIT(25)
+#define USBPCR_VBUSVLDEXT BIT(24)
+#define USBPCR_VBUSVLDEXTSEL BIT(23)
+#define USBPCR_POR BIT(22)
+#define USBPCR_SIDDQ BIT(21)
+#define USBPCR_OTG_DISABLE BIT(20)
+#define USBPCR_TXPREEMPHTUNE BIT(6)
+
+#define USBPCR_IDPULLUP_LSB 28
+#define USBPCR_IDPULLUP_MASK GENMASK(29, USBPCR_IDPULLUP_LSB)
+#define USBPCR_IDPULLUP_ALWAYS (0x2 << USBPCR_IDPULLUP_LSB)
+#define USBPCR_IDPULLUP_SUSPEND (0x1 << USBPCR_IDPULLUP_LSB)
+#define USBPCR_IDPULLUP_OTG (0x0 << USBPCR_IDPULLUP_LSB)
+
+#define USBPCR_COMPDISTUNE_LSB 17
+#define USBPCR_COMPDISTUNE_MASK GENMASK(19, USBPCR_COMPDISTUNE_LSB)
+#define USBPCR_COMPDISTUNE_DFT (0x4 << USBPCR_COMPDISTUNE_LSB)
+
+#define USBPCR_OTGTUNE_LSB 14
+#define USBPCR_OTGTUNE_MASK GENMASK(16, USBPCR_OTGTUNE_LSB)
+#define USBPCR_OTGTUNE_DFT (0x4 << USBPCR_OTGTUNE_LSB)
+
+#define USBPCR_SQRXTUNE_LSB 11
+#define USBPCR_SQRXTUNE_MASK GENMASK(13, USBPCR_SQRXTUNE_LSB)
+#define USBPCR_SQRXTUNE_DCR_20PCT (0x7 << USBPCR_SQRXTUNE_LSB)
+#define USBPCR_SQRXTUNE_DFT (0x3 << USBPCR_SQRXTUNE_LSB)
+
+#define USBPCR_TXFSLSTUNE_LSB 7
+#define USBPCR_TXFSLSTUNE_MASK GENMASK(10, USBPCR_TXFSLSTUNE_LSB)
+#define USBPCR_TXFSLSTUNE_DCR_50PPT (0xf << USBPCR_TXFSLSTUNE_LSB)
+#define USBPCR_TXFSLSTUNE_DCR_25PPT (0x7 << USBPCR_TXFSLSTUNE_LSB)
+#define USBPCR_TXFSLSTUNE_DFT (0x3 << USBPCR_TXFSLSTUNE_LSB)
+#define USBPCR_TXFSLSTUNE_INC_25PPT (0x1 << USBPCR_TXFSLSTUNE_LSB)
+#define USBPCR_TXFSLSTUNE_INC_50PPT (0x0 << USBPCR_TXFSLSTUNE_LSB)
+
+#define USBPCR_TXHSXVTUNE_LSB 4
+#define USBPCR_TXHSXVTUNE_MASK GENMASK(5, USBPCR_TXHSXVTUNE_LSB)
+#define USBPCR_TXHSXVTUNE_DFT (0x3 << USBPCR_TXHSXVTUNE_LSB)
+#define USBPCR_TXHSXVTUNE_DCR_15MV (0x1 << USBPCR_TXHSXVTUNE_LSB)
+
+#define USBPCR_TXRISETUNE_LSB 4
+#define USBPCR_TXRISETUNE_MASK GENMASK(5, USBPCR_TXRISETUNE_LSB)
+#define USBPCR_TXRISETUNE_DFT (0x3 << USBPCR_TXRISETUNE_LSB)
+
+#define USBPCR_TXVREFTUNE_LSB 0
+#define USBPCR_TXVREFTUNE_MASK GENMASK(3, USBPCR_TXVREFTUNE_LSB)
+#define USBPCR_TXVREFTUNE_INC_25PPT (0x7 << USBPCR_TXVREFTUNE_LSB)
+#define USBPCR_TXVREFTUNE_DFT (0x5 << USBPCR_TXVREFTUNE_LSB)
+
+/*USB Reset Detect Timer Register*/
+#define USBRDT_UTMI_RST BIT(27)
+#define USBRDT_HB_MASK BIT(26)
+#define USBRDT_VBFIL_LD_EN BIT(25)
+#define USBRDT_IDDIG_EN BIT(24)
+#define USBRDT_IDDIG_REG BIT(23)
+#define USBRDT_VBFIL_EN BIT(2)
+
+/*USB Parameter Control Register 1*/
+#define USBPCR1_BVLD_REG BIT(31)
+#define USBPCR1_DPPD BIT(29)
+#define USBPCR1_DMPD BIT(28)
+#define USBPCR1_WORD_IF_16BIT BIT(19)
+
+#define USBPCR1_REFCLKSEL_LSB 26
+#define USBPCR1_REFCLKSEL_MASK GENMASK(27, USBPCR1_REFCLKDIV_LSB)
+#define USBPCR1_REFCLKSEL_CLKCORE (0x3 << USBPCR1_REFCLKSEL_LSB)
+
+#define USBPCR1_REFCLKDIV_LSB 24
+#define USBPCR1_REFCLKDIV_MASK GENMASK(25, USBPCR1_REFCLKDIV_LSB)
+#define USBPCR1_REFCLKDIV_48M (0x2 << USBPCR1_REFCLKDIV_LSB)
+#define USBPCR1_REFCLKDIV_24M (0x1 << USBPCR1_REFCLKDIV_LSB)
+#define USBPCR1_REFCLKDIV_12M (0x0 << USBPCR1_REFCLKDIV_LSB)
+
+enum ingenic_usb_phy_version {
+ ID_JZ4770,
+ ID_X1000,
+ ID_X1830,
+};
struct jz4770_phy {
+ enum ingenic_usb_phy_version version;
+
struct usb_phy phy;
struct usb_otg otg;
struct device *dev;
@@ -96,6 +130,12 @@ static int jz4770_phy_set_peripheral(struct usb_otg *otg,
struct jz4770_phy *priv = otg_to_jz4770_phy(otg);
u32 reg;
+ if (priv->version >= ID_X1000) {
+ reg = readl(priv->base + REG_USBPCR1_OFFSET);
+ reg |= USBPCR1_BVLD_REG;
+ writel(reg, priv->base + REG_USBPCR1_OFFSET);
+ }
+
reg = readl(priv->base + REG_USBPCR_OFFSET);
reg &= ~USBPCR_USB_MODE;
reg |= USBPCR_VBUSVLDEXT | USBPCR_VBUSVLDEXTSEL | USBPCR_OTG_DISABLE;
@@ -135,17 +175,54 @@ static int jz4770_phy_init(struct usb_phy *phy)
return err;
}
- reg = USBPCR_AVLD_REG | USBPCR_COMMONONN | USBPCR_IDPULLUP_ALWAYS |
- (USBPCR_COMPDISTUNE_DFT << USBPCR_COMPDISTUNE_LSB) |
- (USBPCR_OTGTUNE_DFT << USBPCR_OTGTUNE_LSB) |
- (USBPCR_SQRXTUNE_DFT << USBPCR_SQRXTUNE_LSB) |
- (USBPCR_TXFSLSTUNE_DFT << USBPCR_TXFSLSTUNE_LSB) |
- (USBPCR_TXRISETUNE_DFT << USBPCR_TXRISETUNE_LSB) |
- (USBPCR_TXVREFTUNE_DFT << USBPCR_TXVREFTUNE_LSB) |
- USBPCR_POR;
+ if (priv->version >= ID_X1830) {
+ /* rdt */
+ writel(USBRDT_VBFIL_EN | USBRDT_UTMI_RST, priv->base + REG_USBRDT_OFFSET);
+
+ reg = readl(priv->base + REG_USBPCR1_OFFSET) | USBPCR1_WORD_IF_16BIT |
+ USBPCR1_DMPD | USBPCR1_DPPD;
+ writel(reg, priv->base + REG_USBPCR1_OFFSET);
+
+ reg = USBPCR_IDPULLUP_OTG | USBPCR_VBUSVLDEXT | USBPCR_VBUSVLDEXTSEL |
+ USBPCR_TXPREEMPHTUNE;
+ } else if (priv->version >= ID_X1000) {
+ reg = readl(priv->base + REG_USBPCR1_OFFSET) | USBPCR1_WORD_IF_16BIT;
+ writel(reg, priv->base + REG_USBPCR1_OFFSET);
+
+ reg = USBPCR_SQRXTUNE_DCR_20PCT | USBPCR_TXPREEMPHTUNE |
+ USBPCR_TXHSXVTUNE_DCR_15MV | USBPCR_TXVREFTUNE_INC_25PPT;
+ } else {
+ reg = USBPCR_AVLD_REG | USBPCR_IDPULLUP_ALWAYS |
+ USBPCR_COMPDISTUNE_DFT | USBPCR_OTGTUNE_DFT |
+ USBPCR_SQRXTUNE_DFT | USBPCR_TXFSLSTUNE_DFT |
+ USBPCR_TXRISETUNE_DFT | USBPCR_TXVREFTUNE_DFT;
+ }
+
+ reg = USBPCR_COMMONONN | USBPCR_POR;
writel(reg, priv->base + REG_USBPCR_OFFSET);
- /* Wait for PHY to reset */
+ /*
+ * Power-On Reset(POR)
+ * Function:This customer-specific signal resets all test registers
+ * and state machines in the USB 2.0 nanoPHY.
+ * The POR signal must be asserted for a minimum of 10 μs.
+ * For POR timing information:
+ *
+ * T0: Power-on reset (POR) is initiated. 0 (reference).
+ * T1: T1 indicates when POR can be set to 1’b0. (To provide examples,
+ * values for T2 and T3 are also shown where T1 = T0 + 30 μs.);
+ * In general, T1 must be ≥ T0 + 10 μs. T0 + 10 μs ≤ T1.
+ * T2: T2 indicates when PHYCLOCK, CLK48MOHCI, and CLK12MOHCI are
+ * available at the macro output, based on the USB 2.0 nanoPHY
+ * reference clock source.
+ * Crystal:
+ * • When T1 = T0 + 10 μs:
+ * T2 < T1 + 805 μs = T0 + 815 μs
+ * • When T1 = T0 + 30 μs:
+ * T2 < T1 + 805 μs = T0 + 835 μs
+ * see "Reset and Power-Saving Signals" on page 60 an “Powering Up
+ * and Powering Down the USB 2.0 nanoPHY” on page 73.
+ */
usleep_range(30, 300);
writel(reg & ~USBPCR_POR, priv->base + REG_USBPCR_OFFSET);
usleep_range(300, 1000);
@@ -166,21 +243,36 @@ static void jz4770_phy_remove(void *phy)
usb_remove_phy(phy);
}
+static const struct of_device_id ingenic_usb_phy_of_matches[] = {
+ { .compatible = "ingenic,jz4770-phy", .data = (void *) ID_JZ4770 },
+ { .compatible = "ingenic,x1000-phy", .data = (void *) ID_X1000 },
+ { .compatible = "ingenic,x1830-phy", .data = (void *) ID_X1830 },
+ { }
+};
+MODULE_DEVICE_TABLE(of, ingenic_usb_phy_of_matches);
+
static int jz4770_phy_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct jz4770_phy *priv;
+ const struct of_device_id *match;
int err;
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
+ match = of_match_device(ingenic_usb_phy_of_matches, dev);
+ if (match)
+ priv->version = (enum ingenic_usb_phy_version)match->data;
+ else
+ return -ENODEV;
+
platform_set_drvdata(pdev, priv);
priv->dev = dev;
priv->phy.dev = dev;
priv->phy.otg = &priv->otg;
- priv->phy.label = "jz4770-phy";
+ priv->phy.label = "ingenic-usb-phy";
priv->phy.init = jz4770_phy_init;
priv->phy.shutdown = jz4770_phy_shutdown;
@@ -207,7 +299,7 @@ static int jz4770_phy_probe(struct platform_device *pdev)
if (IS_ERR(priv->vcc_supply)) {
err = PTR_ERR(priv->vcc_supply);
if (err != -EPROBE_DEFER)
- dev_err(dev, "failed to get regulator");
+ dev_err(dev, "Failed to get regulator");
return err;
}
@@ -221,23 +313,15 @@ static int jz4770_phy_probe(struct platform_device *pdev)
return devm_add_action_or_reset(dev, jz4770_phy_remove, &priv->phy);
}
-#ifdef CONFIG_OF
-static const struct of_device_id jz4770_phy_of_matches[] = {
- { .compatible = "ingenic,jz4770-phy" },
- { }
-};
-MODULE_DEVICE_TABLE(of, jz4770_phy_of_matches);
-#endif
-
-static struct platform_driver jz4770_phy_driver = {
+static struct platform_driver ingenic_usb_phy_driver = {
.probe = jz4770_phy_probe,
.driver = {
- .name = "jz4770-phy",
- .of_match_table = of_match_ptr(jz4770_phy_of_matches),
+ .name = "ingenic-usb-phy",
+ .of_match_table = of_match_ptr(ingenic_usb_phy_of_matches),
},
};
-module_platform_driver(jz4770_phy_driver);
+module_platform_driver(ingenic_usb_phy_driver);
MODULE_AUTHOR("Paul Cercueil <paul@crapouillou.net>");
-MODULE_DESCRIPTION("Ingenic JZ4770 USB PHY driver");
+MODULE_DESCRIPTION("Ingenic SoCs USB PHY driver");
MODULE_LICENSE("GPL");
--
2.11.0
^ permalink raw reply related
* Re: [PATCH v3 1/4] dt-bindings: clk: Add Baikal-T1 CCU PLLs binding
From: Stephen Boyd @ 2020-05-30 18:14 UTC (permalink / raw)
To: Michael Turquette, Rob Herring, Serge Semin, Thomas Bogendoerfer
Cc: Serge Semin, Serge Semin, Alexey Malahov, Arnd Bergmann,
linux-mips, linux-clk, devicetree, linux-kernel
In-Reply-To: <20200526222056.18072-2-Sergey.Semin@baikalelectronics.ru>
Quoting Serge Semin (2020-05-26 15:20:53)
> Baikal-T1 Clocks Control Unit is responsible for transformation of a
> signal coming from an external oscillator into clocks of various
> frequencies to propagate them then to the corresponding clocks
> consumers (either individual IP-blocks or clock domains). In order
> to create a set of high-frequency clocks the external signal is
> firstly handled by the embedded into CCU PLLs. So the corresponding
> dts-node is just a normal clock-provider node with standard set of
> properties. Note as being part of the Baikal-T1 System Controller its
> DT node is supposed to be a child the system controller node.
>
> Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
> Cc: Alexey Malahov <Alexey.Malahov@baikalelectronics.ru>
> Cc: Arnd Bergmann <arnd@arndb.de>
> Cc: linux-mips@vger.kernel.org
>
> ---
Applied to clk-next
^ permalink raw reply
* Re: [PATCH v3 2/4] dt-bindings: clk: Add Baikal-T1 CCU Dividers binding
From: Stephen Boyd @ 2020-05-30 18:14 UTC (permalink / raw)
To: Michael Turquette, Philipp Zabel, Rob Herring, Serge Semin,
Thomas Bogendoerfer
Cc: Serge Semin, Serge Semin, Alexey Malahov, Arnd Bergmann,
linux-mips, linux-clk, devicetree, linux-kernel
In-Reply-To: <20200526222056.18072-3-Sergey.Semin@baikalelectronics.ru>
Quoting Serge Semin (2020-05-26 15:20:54)
> After being gained by the CCU PLLs the signals must be transformed to
> be suitable for the clock-consumers. This is done by a set of dividers
> embedded into the CCU. A first block of dividers is used to create
> reference clocks for AXI-bus of high-speed peripheral IP-cores of the
> chip. The second block dividers alter the PLLs output signals to be then
> consumed by SoC peripheral devices. Both block DT nodes are ordinary
> clock-providers with standard set of properties supported. But in addition
> to that each clock provider can be used to reset the corresponding clock
> domain. This makes the AXI-bus and System Devices CCU DT nodes to be also
> reset-providers.
>
> Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
> Cc: Alexey Malahov <Alexey.Malahov@baikalelectronics.ru>
> Cc: Arnd Bergmann <arnd@arndb.de>
> Cc: linux-mips@vger.kernel.org
>
> ---
Applied to clk-next
^ permalink raw reply
* Re: [PATCH v3 3/4] clk: Add Baikal-T1 CCU PLLs driver
From: Stephen Boyd @ 2020-05-30 18:14 UTC (permalink / raw)
To: Michael Turquette, Serge Semin, Thomas Bogendoerfer
Cc: Serge Semin, Serge Semin, Alexey Malahov, Arnd Bergmann,
Rob Herring, linux-mips, devicetree, linux-kernel, linux-clk
In-Reply-To: <20200526222056.18072-4-Sergey.Semin@baikalelectronics.ru>
Quoting Serge Semin (2020-05-26 15:20:55)
> Baikal-T1 is supposed to be supplied with a high-frequency external
> oscillator. But in order to create signals suitable for each IP-block
> embedded into the SoC the oscillator output is primarily connected to
> a set of CCU PLLs. There are five of them to create clocks for the MIPS
> P5600 cores, an embedded DDR controller, SATA, Ethernet and PCIe domains.
> The last three domains though named by the biggest system interfaces in
> fact include nearly all of the rest SoC peripherals. Each of the PLLs is
> based on True Circuits TSMC CLN28HPM IP-core with an interface wrapper
> (so called safe PLL' clocks switcher) to simplify the PLL configuration
> procedure.
>
> This driver creates the of-based hardware clocks to use them then in
> the corresponding subsystems. In order to simplify the driver code we
> split the functionality up into the PLLs clocks operations and hardware
> clocks declaration/registration procedures.
>
> Even though the PLLs are based on the same IP-core, they may have some
> differences. In particular, some CCU PLLs support the output clock change
> without gating them (like CPU or PCIe PLLs), while the others don't, some
> CCU PLLs are critical and aren't supposed to be gated. In order to cover
> all of these cases the hardware clocks driver is designed with an
> info-descriptor pattern. So there are special static descriptors declared
> for each PLL, which is then used to create a hardware clock with proper
> operations. Additionally debugfs-files are provided for each PLL' field
> to make sure the implemented rate-PLLs-dividers calculation algorithm is
> correct.
>
> Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
> Cc: Alexey Malahov <Alexey.Malahov@baikalelectronics.ru>
> Cc: Arnd Bergmann <arnd@arndb.de>
> Cc: Rob Herring <robh+dt@kernel.org>
> Cc: linux-mips@vger.kernel.org
> Cc: devicetree@vger.kernel.org
>
> ---
Applied to clk-next
^ permalink raw reply
* Re: [PATCH v3 4/4] clk: Add Baikal-T1 CCU Dividers driver
From: Stephen Boyd @ 2020-05-30 18:14 UTC (permalink / raw)
To: Michael Turquette, Serge Semin, Thomas Bogendoerfer
Cc: Serge Semin, Serge Semin, Alexey Malahov, Arnd Bergmann,
Rob Herring, linux-mips, devicetree, linux-kernel, linux-clk
In-Reply-To: <20200526222056.18072-5-Sergey.Semin@baikalelectronics.ru>
Quoting Serge Semin (2020-05-26 15:20:56)
> Nearly each Baikal-T1 IP-core is supposed to have a clock source
> of particular frequency. But since there are greater than five
> IP-blocks embedded into the SoC, the CCU PLLs can't fulfill all the
> needs. Baikal-T1 CCU provides a set of fixed and configurable clock
> dividers in order to generate a necessary signal for each chip
> sub-block.
>
> This driver creates the of-based hardware clocks for each divider
> available in Baikal-T1 CCU. The same way as for PLLs we split the
> functionality up into the clocks operations (gate, ungate, set rate,
> etc) and hardware clocks declaration/registration procedures.
>
> In accordance with the CCU documentation all its dividers are distributed
> into two CCU sub-blocks: AXI-bus and system devices reference clocks.
> The former sub-block is used to supply the clocks for AXI-bus interfaces
> (AXI clock domains) and the later one provides the SoC IP-cores reference
> clocks. Each sub-block is represented by a dedicated DT node, so they
> have different compatible strings to distinguish one from another.
>
> For some reason CCU provides the dividers of different types. Some
> dividers can be gateable some can't, some are fixed while the others
> are variable, some have special divider' limitations, some've got a
> non-standard register layout and so on. In order to cover all of these
> cases the hardware clocks driver is designed with an info-descriptor
> pattern. So there are special static descriptors declared for the
> dividers of each type with additional flags describing the block
> peculiarity. These descriptors are then used to create hardware clocks
> with proper operations.
>
> Some CCU dividers provide a way to reset a domain they generate
> a clock for. So the CCU AXI-bus and CCU system devices clock
> drivers also perform the reset controller registration.
>
> Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
> Cc: Alexey Malahov <Alexey.Malahov@baikalelectronics.ru>
> Cc: Arnd Bergmann <arnd@arndb.de>
> Cc: Rob Herring <robh+dt@kernel.org>
> Cc: linux-mips@vger.kernel.org
> Cc: devicetree@vger.kernel.org
>
> ---
Applied to clk-next
^ permalink raw reply
* Re: [PATCH 0/9] DT: Improve validation for Marvell SoCs
From: Lubomir Rintel @ 2020-05-30 18:14 UTC (permalink / raw)
To: Rob Herring
Cc: Alessandro Zummo, Alexandre Belloni, Bartosz Golaszewski,
Daniel Lezcano, Jason Cooper, Linus Walleij, Marc Zyngier,
Thomas Gleixner, Ulf Hansson, devicetree, linux-kernel
In-Reply-To: <20200528225244.GA815881@bogus>
On Thu, May 28, 2020 at 04:52:44PM -0600, Rob Herring wrote:
> On Thu, May 21, 2020 at 11:13:47AM +0200, Lubomir Rintel wrote:
> > Hi,
> >
> > chained to this message is a second version of remaining patches from the
> > first spin of the "DT: Improve validation for Marvell SoCs" [1] patch set.
> >
> > [1] https://lore.kernel.org/lkml/20200317093922.20785-1-lkundrak@v3.sk/
> >
> > I've attempted to address the review of the v1, each patch includes a
> > detailed change log.
> >
> > Compared to v1, wherever the license or maintainer information was
> > missing, I've filled in GPL-2.0-only and people listed in MAINTAINERS
> > file. As I've indicated in v1 cover letter, am not sure whether this is
> > the optimal course of action. However I've included the relevant people
> > in v1 Cc list and asked for clarifications, but didn't really get any
> > feedback to that.
>
> Find someone that would care if the bindings are deleted. I'm fine
> if you put yourself. Maybe subsystem maintainers are willing to take
> orphans. I really only want my name on common things.
Thanks for clarification & fixups to the patches.
I'm wondering if Documentation/devicetree/writing-schema.rst could
perhaps be made a bit clearer about how the maintainer key in a binding
document is different from what is in the MAINTAINERS file.
> Rob
Lubo
^ permalink raw reply
* Re: [PATCH v6] support gce on mt6779 platform
From: Jassi Brar @ 2020-05-30 20:34 UTC (permalink / raw)
To: Dennis YC Hsieh
Cc: Rob Herring, Mark Rutland, Matthias Brugger, Philipp Zabel,
David Airlie, Daniel Vetter, Linux Kernel Mailing List,
linux-mediatek, Devicetree List, wsd_upstream, dri-devel,
Bibby Hsieh, CK Hu, Houlong Wei, linux-arm-kernel, HS Liao
In-Reply-To: <1590685491-17107-1-git-send-email-dennis-yc.hsieh@mediatek.com>
On Thu, May 28, 2020 at 12:05 PM Dennis YC Hsieh
<dennis-yc.hsieh@mediatek.com> wrote:
>
> This patch support gce on mt6779 platform.
>
> Change since v5:
> - spearate address shift code in client helper and mailbox controller
> - separate write_s/write_s_mask and write_s_value/write_s_mask_value so that
> client can decide use mask or not
> - fix typo in header
>
> Change since v4:
> - do not clear disp event again in drm driver
> - symbolize value 1 to jump relative
>
> [... snip ...]
>
>
>
> Dennis YC Hsieh (16):
> dt-binding: gce: add gce header file for mt6779
> mailbox: cmdq: variablize address shift in platform
> mailbox: cmdq: support mt6779 gce platform definition
> mailbox: mediatek: cmdq: clear task in channel before shutdown
> soc: mediatek: cmdq: return send msg error code
> soc: mediatek: cmdq: add address shift in jump
> soc: mediatek: cmdq: add assign function
> soc: mediatek: cmdq: add write_s function
> soc: mediatek: cmdq: add write_s_mask function
> soc: mediatek: cmdq: add read_s function
> soc: mediatek: cmdq: add write_s value function
> soc: mediatek: cmdq: add write_s_mask value function
> soc: mediatek: cmdq: export finalize function
> soc: mediatek: cmdq: add jump function
> soc: mediatek: cmdq: add clear option in cmdq_pkt_wfe api
> soc: mediatek: cmdq: add set event function
>
> .../devicetree/bindings/mailbox/mtk-gce.txt | 8 +-
> drivers/gpu/drm/mediatek/mtk_drm_crtc.c | 3 +-
> drivers/mailbox/mtk-cmdq-mailbox.c | 101 ++++++--
> drivers/soc/mediatek/mtk-cmdq-helper.c | 163 ++++++++++++-
> include/dt-bindings/gce/mt6779-gce.h | 222 ++++++++++++++++++
> include/linux/mailbox/mtk-cmdq-mailbox.h | 10 +-
> include/linux/soc/mediatek/mtk-cmdq.h | 125 +++++++++-
>
Please break the patchset into two. The lower mailbox related changes
with soc changes on top.
thanks
^ permalink raw reply
* Re: [PATCH v6 08/11] i2c: designware: Convert driver to using regmap API
From: Wolfram Sang @ 2020-05-30 21:05 UTC (permalink / raw)
To: Serge Semin
Cc: Jarkko Nikula, Andy Shevchenko, Mika Westerberg, Serge Semin,
Alexey Malahov, Thomas Bogendoerfer, Rob Herring, devicetree,
linux-mips, linux-i2c, linux-kernel
In-Reply-To: <20200530110930.GC1038@ninjato>
[-- Attachment #1: Type: text/plain, Size: 2453 bytes --]
On Sat, May 30, 2020 at 01:09:30PM +0200, Wolfram Sang wrote:
> On Thu, May 28, 2020 at 12:33:18PM +0300, Serge Semin wrote:
> > Seeing the DW I2C driver is using flags-based accessors with two
> > conditional clauses it would be better to replace them with the regmap
> > API IO methods and to initialize the regmap object with read/write
> > callbacks specific to the controller registers map implementation. This
> > will be also handy for the drivers with non-standard registers mapping
> > (like an embedded into the Baikal-T1 System Controller DW I2C block, which
> > glue-driver is a part of this series).
> >
> > As before the driver tries to detect the mapping setup at probe stage and
> > creates a regmap object accordingly, which will be used by the rest of the
> > code to correctly access the controller registers. In two places it was
> > appropriate to convert the hand-written read-modify-write and
> > read-poll-loop design patterns to the corresponding regmap API
> > ready-to-use methods.
> >
> > Note the regmap IO methods return value is checked only at the probe
> > stage. The rest of the code won't do this because basically we have
> > MMIO-based regmap so non of the read/write methods can fail (this also
> > won't be needed for the Baikal-T1-specific I2C controller).
> >
> > Suggested-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
> > Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
> > Tested-by: Jarkko Nikula <jarkko.nikula@linux.intel.com>
> > Acked-by: Jarkko Nikula <jarkko.nikula@linux.intel.com>
> > Cc: Alexey Malahov <Alexey.Malahov@baikalelectronics.ru>
> > Cc: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
> > Cc: Rob Herring <robh+dt@kernel.org>
> > Cc: devicetree@vger.kernel.org
> > Cc: linux-mips@vger.kernel.org
>
> My codecheckers found these, rightfully I'd say:
>
> SPARSE
> drivers/i2c/busses/i2c-designware-master.c:427:53: warning: incorrect type in argument 3 (different signedness)
> drivers/i2c/busses/i2c-designware-master.c:427:53: expected unsigned int *val
> drivers/i2c/busses/i2c-designware-master.c:427:53: got int *
>
> CC
> drivers/i2c/busses/i2c-designware-common.c:127: warning: Excess function parameter 'base' description in 'i2c_dw_init_regmap'
>
> ^ means there is an argument documented which does not exist in the
> function declaration
Well, I fixed these two minor things for your now...
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply
* Re: [PATCH v6 00/11] i2c: designeware: Add Baikal-T1 System I2C support
From: Wolfram Sang @ 2020-05-30 21:06 UTC (permalink / raw)
To: Serge Semin
Cc: Jarkko Nikula, Serge Semin, Alexey Malahov, Maxim Kaurkin,
Pavel Parkhomenko, Ramil Zaripov, Ekaterina Skachko, Vadim Vlasov,
Alexey Kolotnikov, Thomas Bogendoerfer, Andy Shevchenko,
Mika Westerberg, Rob Herring, linux-mips, linux-i2c, devicetree,
linux-kernel
In-Reply-To: <20200528093322.23553-1-Sergey.Semin@baikalelectronics.ru>
[-- Attachment #1: Type: text/plain, Size: 9537 bytes --]
On Thu, May 28, 2020 at 12:33:10PM +0300, Serge Semin wrote:
> Jarkko, Wolfram, the merge window is upon us, please review/merge in/whatever
> the patchset.
>
> Initially this has been a small patchset which embedded the Baikal-T1
> System I2C support into the DW APB I2C driver as is by using a simplest
> way. After a short discussion with Andy we decided to implement what he
> suggested (introduce regmap-based accessors and create a glue driver) and
> even more than that to provide some cleanups of the code. So here is what
> this patchset consists of.
>
> First of all we've found out that current implementation of scripts/dtc
> didn't support i2c dt nodes with 10bit and slave flags set in the
> reg property. You'll see an error if you try to dt_binding_check it.
> So the very first patch fixes the problem by adding these flags support
> into the check_i2c_bus_reg() method.
>
> Traditionally we converted the plain text-based DT binding to the DT schema
> and added Baikal-T1 System I2C device support there. This required to mark
> the reg property redundant for Baikal-T1 I2C since its reg-space is
> indirectly accessed by means of the System Controller cmd/read/write
> registers.
>
> Then as Andy suggested we replaced the Synopsys DW APB I2C common driver
> registers IO accessors into the regmap API methods. This doesn't change
> the code logic much, though in two places we managed to replace some bulky
> peaces of code with a ready-to-use regmap methods.
>
> Additionally before adding the glue layer API we initiated a set of cleanups:
> - Define components of the multi-object drivers (like i2c-designware-core.o
> and i2c-designware-paltform.o) with using `-y` suffixed makefile
> variables instead of `-objs` suffixed one. This is encouraged by
> Documentation/kbuild/makefiles.rst text since `-objs` is supposed to be used
> to build host programs.
> - Make DW I2C slave driver depended on the DW I2C core code instead of the
> platform one, which it really is.
> - Move Intel Baytrail semaphore feature to the platform if-clause of the
> kernel config.
>
> After this we finally can introduce the glue layer API for the DW APB I2C
> platform driver. So there are three methods exported from the driver:
> i2c_dw_plat_setup(), i2c_dw_plat_clear(), &i2c_dw_plat_dev_pm_ops to
> setup, cleanup and add PM operations to the glue driven I2C device. Before
> setting the platform DW I2C device up the glue probe code is supposed to
> create an instance of DW I2C device generic object and pre-initialize
> its `struct device` pointer together with optional platform-specific
> flags. In addition to that we converted the MSCC Ocelot SoC I2C specific
> code into the glue layer seeing it's really too specific and, which is more
> important, isn't that complicated so we could unpin it without much of
> worrying to break something.
>
> Meanwhile we discovered that MODEL_CHERRYTRAIL and MODEL_MASK actually
> were no longer used in the code. MODEL_MSCC flag has been discarded since
> the MSCC Ocelot I2C code conversion to the glue driver. So now we can get
> rid of all the MODEL-specific flags.
>
> Finally we introduced a glue driver with Baikal-T1 System I2C device
> support. The driver probe tries to find a syscon regmap, creates the DW
> APB I2C regmap based on it and passes it further to the DW I2C device
> descriptor. Then it does normal DW APB I2C platform setup by calling a
> generic setup method. Cleanup is straightforward. It's just calling a
> generic DW APB I2C clean method.
>
> This patchset is rebased and tested on the i2c/for-next (5.7-rc4):
> base-commit: 2a41d0f91443 Merge branch 'i2c/for-5.8' into i2c/for-next
>
> Note new vendor prefix for Baikal-T1 System I2C device is added in the
> framework of the next patchset:
> https://lkml.org/lkml/2020/5/6/1047
>
> Changelog v2:
> - Fix the SoB tags.
> - Use a shorter summary describing the bindings convertion patch.
> - Patch "i2c: designware: Detect the FIFO size in the common code" has
> been acked by Jarkko and applied by Wolfram to for-next so drop it from
> the set.
> - Patch "i2c: designware: Discard i2c_dw_read_comp_param() function" has
> been acked by Jarkko and applied by Wolfram to for-next so drop it from
> the set.
> - Make sure that "mscc,ocelot-i2c" compatible node may have up to two
> registers space defined in the DT node, while normal DW I2C controller
> will have only one registers space.
> - Add "mscc,ocelot-i2c" DT schema example to test the previous fix.
> - Declare "unevaluatedProperties" property instead of
> "additionalProperties" one in the DT schema.
> - Due to the previous fix we can now discard the dummy boolean properties
> declaration, since the proper type evaluation will be performed by the
> generic i2c-controller.yaml schema.
> - Refactor the DW I2C APB driver related series to address the Andies
> notes.
> - Convert DW APB I2C driver to using regmap instead of handwritten
> accessors.
> - Use `-y` to build multi-object DW APB drivers.
> - Fix DW APB I2C slave code dependency. It should depend on
> I2C_DESIGNWARE_CORE instead I2C_DESIGNWARE_PLATFORM.
> - Move Baytrail semaphore config to the platform if-clause.
> - Introduce a glue-layer platform driver API.
> - Unpin Microsemi Ocelot I2C code into a glue driver.
> - Remove MODEL_CHERRYTRAIL and MODEL_MASK as no longer needed.
> - Add support for custom regmap passed from glue driver.
> - Add Baikal-T1 System I2C support in a dedicated glue layer driver.
>
> Link: https://lore.kernel.org/linux-i2c/20200510095019.20981-1-Sergey.Semin@baikalelectronics.ru/
> Changelog v3:
> - Move fixes and less invasive patches to the head of the series.
> - Add patch "dt-bindings: i2c: Discard i2c-slave flag from the DW I2C
> example" since Rob says the flag can be discarded until dtc is fixed.
> - Add patch "i2c: designware: Retrieve quirk flags as early as possible"
> as a first preparation before adding Baikal-T1 System I2C support.
> - Add patch "i2c: designware: Move reg-space remapping into a dedicated
> function" as a second preparation before adding Baikal-T1 System I2C
> support.
> - Add patch "i2c: designware: Add Baikal-T1 System I2C support", which
> integrates the Baikal-T1 I2C support into the DW I2C platform driver.
> - Get back the reg property being mandatory even if it's Baikal-T1 System
> I2C DT node. Rob says it has to be in the DT node if there is a
> dedicated registers range in the System Controller registers space.
> - Replace if-endif clause around the I2C_DESIGNWARE_BAYTRAIL config
> with "depends on" operator.
>
> Link: https://lore.kernel.org/linux-i2c/20200526215528.16417-1-Sergey.Semin@baikalelectronics.ru/
> Changelog v4:
> - Rebase on top of the i2c/for-next branch.
> - Use PTR_ERR_OR_ZERO() helper in the bt1_i2c_request_regs() and
> in the dw_i2c_plat_request_regs() methods.
> - Discard devm_platform_get_and_ioremap_resource() utilization.
> - Discard patch "scripts/dtc: check: Add 10bit/slave i2c reg flags
> support" since it must be merged in to the dtc upstream repository.
>
> Link: https://lore.kernel.org/linux-i2c/20200527120111.5781-1-Sergey.Semin@baikalelectronics.ru
> Changelog v5:
> - Replace or-assignment with just assignment operator when getting
> the quirk flags.
> - Keep alphabetical order of the include statements.
> - Discard explicit u16-type cast in the dw_reg_write_word() method.
>
> Link: https://lore.kernel.org/linux-i2c/20200527153046.6172-1-Sergey.Semin@baikalelectronics.ru
> Changelog v6:
> - Add commas after the last member of the regmap_config instances
> initializers.
> - Replace the "linux,slave-24c02" compatible string with "atmel,24c02" one
> so the DT example would be perceived as a normal DW I2C master mode.
>
> Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
> Cc: Alexey Malahov <Alexey.Malahov@baikalelectronics.ru>
> Cc: Maxim Kaurkin <Maxim.Kaurkin@baikalelectronics.ru>
> Cc: Pavel Parkhomenko <Pavel.Parkhomenko@baikalelectronics.ru>
> Cc: Ramil Zaripov <Ramil.Zaripov@baikalelectronics.ru>
> Cc: Ekaterina Skachko <Ekaterina.Skachko@baikalelectronics.ru>
> Cc: Vadim Vlasov <V.Vlasov@baikalelectronics.ru>
> Cc: Alexey Kolotnikov <Alexey.Kolotnikov@baikalelectronics.ru>
> Cc: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
> Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
> Cc: Mika Westerberg <mika.westerberg@linux.intel.com>
> Cc: Rob Herring <robh+dt@kernel.org>
> Cc: linux-mips@vger.kernel.org
> Cc: linux-i2c@vger.kernel.org
> Cc: devicetree@vger.kernel.org
> Cc: linux-kernel@vger.kernel.org
>
> Serge Semin (11):
> dt-bindings: i2c: Convert DW I2C binding to DT schema
> dt-bindings: i2c: Convert DW I2C slave to the DW I2C master example
> dt-bindings: i2c: dw: Add Baikal-T1 SoC I2C controller
> i2c: designware: Use `-y` to build multi-object modules
> i2c: designware: slave: Set DW I2C core module dependency
> i2c: designware: Add Baytrail sem config DW I2C platform dependency
> i2c: designware: Discard Cherry Trail model flag
> i2c: designware: Convert driver to using regmap API
> i2c: designware: Retrieve quirk flags as early as possible
> i2c: designware: Move reg-space remapping into a dedicated function
> i2c: designware: Add Baikal-T1 System I2C support
>
Applied to for-next, thanks!
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply
* Re: [PATCH] i2c: add 'single-master' property to generic bindings
From: Wolfram Sang @ 2020-05-30 21:13 UTC (permalink / raw)
To: linux-i2c; +Cc: devicetree, Rob Herring, Laine Jaakko EXT
In-Reply-To: <20200527113039.5380-1-wsa+renesas@sang-engineering.com>
[-- Attachment #1: Type: text/plain, Size: 368 bytes --]
On Wed, May 27, 2020 at 01:30:39PM +0200, Wolfram Sang wrote:
> It is useful to know if we are the only master on a given bus. Because
> this is a HW description of the bus, add it to the generic bindings.
>
> Signed-off-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
> Cc: Laine Jaakko EXT <ext-jaakko.laine@vaisala.com>
Applied to for-next, thanks!
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply
* Re: [PATCH v2 4/4] pinctrl: bcm2835: Add support for wake-up interrupts
From: Florian Fainelli @ 2020-05-30 21:19 UTC (permalink / raw)
To: Stefan Wahren, Florian Fainelli, linux-kernel
Cc: open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
Geert Uytterhoeven, Scott Branden, Ray Jui, Linus Walleij,
Matti Vaittinen, open list:PIN CONTROL SUBSYSTEM, Rob Herring,
maintainer:BROADCOM BCM281XX/BCM11XXX/BCM216XX ARM ARCHITE...,
moderated list:BROADCOM BCM2711/BCM2835 ARM ARCHITECTURE,
Nicolas Saenz Julienne,
moderated list:BROADCOM BCM2711/BCM2835 ARM ARCHITECTURE
In-Reply-To: <2677905e-a9ad-a44e-93bc-ad185aa269de@i2se.com>
On 5/30/2020 12:49 AM, Stefan Wahren wrote:
> Hi Florian,
>
> Am 29.05.20 um 21:15 schrieb Florian Fainelli:
>> Leverage the IRQCHIP_MASK_ON_SUSPEND flag in order to avoid having to
>> specifically treat the GPIO interrupts during suspend and resume, and
>> simply implement an irq_set_wake() callback that is responsible for
>> enabling the parent wake-up interrupt as a wake-up interrupt.
>>
>> To avoid allocating unnecessary resources for other chips, the wake-up
>> interrupts are only initialized if we have a brcm,bcm7211-gpio
>> compatibility string.
>>
>> Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
>> ---
>> drivers/pinctrl/bcm/pinctrl-bcm2835.c | 76 ++++++++++++++++++++++++++-
>> 1 file changed, 75 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/pinctrl/bcm/pinctrl-bcm2835.c b/drivers/pinctrl/bcm/pinctrl-bcm2835.c
>> index 1b00d93aa66e..1fbf067a3eed 100644
>> --- a/drivers/pinctrl/bcm/pinctrl-bcm2835.c
>> +++ b/drivers/pinctrl/bcm/pinctrl-bcm2835.c
>> @@ -19,6 +19,7 @@
>> #include <linux/irq.h>
>> #include <linux/irqdesc.h>
>> #include <linux/init.h>
>> +#include <linux/interrupt.h>
>> #include <linux/of_address.h>
>> #include <linux/of.h>
>> #include <linux/of_irq.h>
>> @@ -76,6 +77,7 @@
>> struct bcm2835_pinctrl {
>> struct device *dev;
>> void __iomem *base;
>> + int *wake_irq;
>>
>> /* note: locking assumes each bank will have its own unsigned long */
>> unsigned long enabled_irq_map[BCM2835_NUM_BANKS];
>> @@ -435,6 +437,11 @@ static void bcm2835_gpio_irq_handler(struct irq_desc *desc)
>> chained_irq_exit(host_chip, desc);
>> }
>>
>> +static irqreturn_t bcm2835_gpio_wake_irq_handler(int irq, void *dev_id)
>> +{
>> + return IRQ_HANDLED;
>> +}
>> +
>> static inline void __bcm2835_gpio_irq_config(struct bcm2835_pinctrl *pc,
>> unsigned reg, unsigned offset, bool enable)
>> {
>> @@ -634,6 +641,34 @@ static void bcm2835_gpio_irq_ack(struct irq_data *data)
>> bcm2835_gpio_set_bit(pc, GPEDS0, gpio);
>> }
>>
>> +static int bcm2835_gpio_irq_set_wake(struct irq_data *data, unsigned int on)
>> +{
>> + struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
>> + struct bcm2835_pinctrl *pc = gpiochip_get_data(chip);
>> + unsigned gpio = irqd_to_hwirq(data);
>> + unsigned int irqgroup;
>> + int ret = -EINVAL;
>> +
>> + if (!pc->wake_irq)
>> + return ret;
>> +
>> + if (gpio <= 27)
>> + irqgroup = 0;
>> + else if (gpio >= 28 && gpio <= 45)
>> + irqgroup = 1;
>> + else if (gpio >= 46 && gpio <= 53)
>> + irqgroup = 2;
> in case the BCM7211 has 58 GPIOs, but the wake up interrupts are only
> available for the first 54 this should deserve a comment.
irqgroup 2 covers GPIOs 46 through 57, thanks for noticing. Do you have
more comments before I spin a v3? Thank you for reviewing.
--
Florian
^ permalink raw reply
* [PATCH v2 0/4] Add support for SCD30 sensor
From: Tomasz Duszynski @ 2020-05-30 21:36 UTC (permalink / raw)
To: linux-iio
Cc: linux-kernel, devicetree, robh+dt, jic23, andy.shevchenko, pmeerw,
Tomasz Duszynski
Following series adds support for Sensirion SCD30 sensor module capable of
measuring carbon dioxide, temperature and relative humidity. CO2 measurements
base on NDIR principle while temperature and relative humidity are measured by
the on board SHT31. As for sensor communication, both I2C and serial interfaces
are supported.
v2:
* move asm/byteorder.h towards the bottom of include list
* make channel address names in enum more specific
* add postfixes to defines and extra comments
* drop unneeded i2c include from scd30 header
* break generic command sending function into specialized options
* expose automatic calibration and forced calibration via the same attr
* use SAMP_FREQ to set frequency instead of meas_interval attr
* use CALISCALE to set pressure compensation instead of pressure_comp attr
* use CALIBBIAS to set temperature offset instead of temp_offset attr
* fix order in MAINTAINERS
* drop attribute allowing one to reset sensor
* as we have dt probing drop board file based probing (i2c_device_id)
* merge patches touching related files
* use fwnode API to retrieve interrupt from dt
* fix interrupt-parent spelling
* change binding license
* drop supply from required property
Tomasz Duszynski (4):
iio: chemical: scd30: add core driver
iio: chemical: scd30: add I2C interface driver
iio: chemical: scd30: add serial interface driver
dt-bindings: iio: scd30: add device binding file
Documentation/ABI/testing/sysfs-bus-iio-scd30 | 20 +
.../iio/chemical/sensirion,scd30.yaml | 68 ++
MAINTAINERS | 9 +
drivers/iio/chemical/Kconfig | 33 +
drivers/iio/chemical/Makefile | 3 +
drivers/iio/chemical/scd30.h | 75 ++
drivers/iio/chemical/scd30_core.c | 764 ++++++++++++++++++
drivers/iio/chemical/scd30_i2c.c | 134 +++
drivers/iio/chemical/scd30_serial.c | 266 ++++++
9 files changed, 1372 insertions(+)
create mode 100644 Documentation/ABI/testing/sysfs-bus-iio-scd30
create mode 100644 Documentation/devicetree/bindings/iio/chemical/sensirion,scd30.yaml
create mode 100644 drivers/iio/chemical/scd30.h
create mode 100644 drivers/iio/chemical/scd30_core.c
create mode 100644 drivers/iio/chemical/scd30_i2c.c
create mode 100644 drivers/iio/chemical/scd30_serial.c
--
2.26.2
^ permalink raw reply
* [PATCH v2 1/4] iio: chemical: scd30: add core driver
From: Tomasz Duszynski @ 2020-05-30 21:36 UTC (permalink / raw)
To: linux-iio
Cc: linux-kernel, devicetree, robh+dt, jic23, andy.shevchenko, pmeerw,
Tomasz Duszynski
In-Reply-To: <20200530213630.87159-1-tomasz.duszynski@octakon.com>
Add Sensirion SCD30 carbon dioxide core driver.
Signed-off-by: Tomasz Duszynski <tomasz.duszynski@octakon.com>
---
Documentation/ABI/testing/sysfs-bus-iio-scd30 | 20 +
MAINTAINERS | 6 +
drivers/iio/chemical/Kconfig | 11 +
drivers/iio/chemical/Makefile | 1 +
drivers/iio/chemical/scd30.h | 75 ++
drivers/iio/chemical/scd30_core.c | 764 ++++++++++++++++++
6 files changed, 877 insertions(+)
create mode 100644 Documentation/ABI/testing/sysfs-bus-iio-scd30
create mode 100644 drivers/iio/chemical/scd30.h
create mode 100644 drivers/iio/chemical/scd30_core.c
diff --git a/Documentation/ABI/testing/sysfs-bus-iio-scd30 b/Documentation/ABI/testing/sysfs-bus-iio-scd30
new file mode 100644
index 000000000000..a05b1d28e94a
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-bus-iio-scd30
@@ -0,0 +1,20 @@
+What: /sys/bus/iio/devices/iio:deviceX/calibration
+Date: June 2020
+KernelVersion: 5.8
+Contact: linux-iio@vger.kernel.org
+Description:
+ Contaminants build-up in the measurement chamber or optical
+ elements deterioration leads to sensor drift.
+
+ One can compensate for sensor drift by using either automatic
+ self calibration (asc) or forced recalibration (frc). If used
+ at once one will overwrite the other.
+
+ Writing 1 or 0 to this attribute will respectively activate or
+ deactivate asc.
+
+ Picking value from the range [400 1 2000] and writing it to the
+ sensor will set frc.
+
+ Upon reading current asc status and frc value are returned
+ respectively.
diff --git a/MAINTAINERS b/MAINTAINERS
index 60ed2963efaa..41a509cca6f1 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -15137,6 +15137,12 @@ S: Maintained
F: drivers/misc/phantom.c
F: include/uapi/linux/phantom.h
+SENSIRION SCD30 CARBON DIOXIDE SENSOR DRIVER
+M: Tomasz Duszynski <tomasz.duszynski@octakon.com>
+S: Maintained
+F: drivers/iio/chemical/scd30.h
+F: drivers/iio/chemical/scd30_core.c
+
SENSIRION SPS30 AIR POLLUTION SENSOR DRIVER
M: Tomasz Duszynski <tduszyns@gmail.com>
S: Maintained
diff --git a/drivers/iio/chemical/Kconfig b/drivers/iio/chemical/Kconfig
index 7f21afd73b1c..99e852b67e55 100644
--- a/drivers/iio/chemical/Kconfig
+++ b/drivers/iio/chemical/Kconfig
@@ -85,6 +85,17 @@ config PMS7003
To compile this driver as a module, choose M here: the module will
be called pms7003.
+config SCD30_CORE
+ tristate "SCD30 carbon dioxide sensor driver"
+ select IIO_BUFFER
+ select IIO_TRIGGERED_BUFFER
+ help
+ Say Y here to build support for the Sensirion SCD30 sensor with carbon
+ dioxide, relative humidity and temperature sensing capabilities.
+
+ To compile this driver as a module, choose M here: the module will
+ be called scd30_core.
+
config SENSIRION_SGP30
tristate "Sensirion SGPxx gas sensors"
depends on I2C
diff --git a/drivers/iio/chemical/Makefile b/drivers/iio/chemical/Makefile
index aba4167db745..c9804b041ecd 100644
--- a/drivers/iio/chemical/Makefile
+++ b/drivers/iio/chemical/Makefile
@@ -12,6 +12,7 @@ obj-$(CONFIG_BME680_SPI) += bme680_spi.o
obj-$(CONFIG_CCS811) += ccs811.o
obj-$(CONFIG_IAQCORE) += ams-iaq-core.o
obj-$(CONFIG_PMS7003) += pms7003.o
+obj-$(CONFIG_SCD30_CORE) += scd30_core.o
obj-$(CONFIG_SENSIRION_SGP30) += sgp30.o
obj-$(CONFIG_SPS30) += sps30.o
obj-$(CONFIG_VZ89X) += vz89x.o
diff --git a/drivers/iio/chemical/scd30.h b/drivers/iio/chemical/scd30.h
new file mode 100644
index 000000000000..9b25f7423142
--- /dev/null
+++ b/drivers/iio/chemical/scd30.h
@@ -0,0 +1,75 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _SCD30_H
+#define _SCD30_H
+
+#include <linux/completion.h>
+#include <linux/device.h>
+#include <linux/mutex.h>
+#include <linux/pm.h>
+#include <linux/regulator/consumer.h>
+#include <linux/types.h>
+
+struct scd30_state;
+
+enum scd30_cmd {
+ /* start continuous measurement with pressure compensation */
+ CMD_START_MEAS,
+ /* stop continuous measurement */
+ CMD_STOP_MEAS,
+ /* set/get measurement interval */
+ CMD_MEAS_INTERVAL,
+ /* check whether new measurement is ready */
+ CMD_MEAS_READY,
+ /* get measurement */
+ CMD_READ_MEAS,
+ /* turn on/off automatic self calibration */
+ CMD_ASC,
+ /* set/get forced recalibration value */
+ CMD_FRC,
+ /* set/get temperature offset */
+ CMD_TEMP_OFFSET,
+ /* get firmware version */
+ CMD_FW_VERSION,
+ /* reset sensor */
+ CMD_RESET,
+ /*
+ * Command for altitude compensation was omitted intentionally because
+ * the same can be achieved by means of CMD_START_MEAS which takes
+ * pressure above the sea level as an argument.
+ */
+};
+
+#define SCD30_MEAS_COUNT 3
+
+typedef int (*scd30_command_t)(struct scd30_state *state, enum scd30_cmd cmd,
+ u16 arg, void *response, int size);
+
+struct scd30_state {
+ /* serialize access to the device */
+ struct mutex lock;
+ struct device *dev;
+ struct regulator *vdd;
+ struct completion meas_ready;
+ void *priv;
+ int irq;
+ /*
+ * no way to retrieve current ambient pressure compensation value from
+ * the sensor so keep one around
+ */
+ u16 pressure_comp;
+ u16 meas_interval;
+ int meas[SCD30_MEAS_COUNT];
+
+ scd30_command_t command;
+};
+
+int scd30_suspend(struct device *dev);
+int scd30_resume(struct device *dev);
+
+static __maybe_unused SIMPLE_DEV_PM_OPS(scd30_pm_ops, scd30_suspend,
+ scd30_resume);
+
+int scd30_probe(struct device *dev, int irq, const char *name, void *priv,
+ scd30_command_t command);
+
+#endif
diff --git a/drivers/iio/chemical/scd30_core.c b/drivers/iio/chemical/scd30_core.c
new file mode 100644
index 000000000000..3b7d0a7ea7ae
--- /dev/null
+++ b/drivers/iio/chemical/scd30_core.c
@@ -0,0 +1,764 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Sensirion SCD30 carbon dioxide sensor core driver
+ *
+ * Copyright (c) 2020 Tomasz Duszynski <tomasz.duszynski@octakon.com>
+ */
+#include <linux/bits.h>
+#include <linux/completion.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/export.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/trigger.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
+#include <linux/iio/types.h>
+#include <linux/interrupt.h>
+#include <linux/irqreturn.h>
+#include <linux/jiffies.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/regulator/consumer.h>
+#include <linux/string.h>
+#include <linux/sysfs.h>
+#include <linux/types.h>
+#include <asm/byteorder.h>
+
+#include "scd30.h"
+
+#define SCD30_PRESSURE_COMP_MIN_MBAR 700
+#define SCD30_PRESSURE_COMP_MAX_MBAR 1400
+#define SCD30_PRESSURE_COMP_DEFAULT 1013
+#define SCD30_MEAS_INTERVAL_MIN_S 2
+#define SCD30_MEAS_INTERVAL_MAX_S 1800
+#define SCD30_MEAS_INTERVAL_DEFAULT SCD30_MEAS_INTERVAL_MIN_S
+#define SCD30_FRC_MIN_PPM 400
+#define SCD30_FRC_MAX_PPM 2000
+#define SCD30_TEMP_OFFSET_MAX 655360
+#define SCD30_EXTRA_TIMEOUT_PER_S 250
+
+enum {
+ SCD30_CONC,
+ SCD30_TEMP,
+ SCD30_HR,
+};
+
+static int scd30_command_write(struct scd30_state *state, enum scd30_cmd cmd,
+ u16 arg)
+{
+ return state->command(state, cmd, arg, NULL, 0);
+}
+
+static int scd30_command_read(struct scd30_state *state, enum scd30_cmd cmd,
+ u16 *val)
+{
+ int ret;
+
+ ret = state->command(state, cmd, 0, val, sizeof(*val));
+ *val = be16_to_cpup((__be16 *)val);
+
+ return ret;
+}
+
+static int scd30_reset(struct scd30_state *state)
+{
+ int ret;
+ u16 val;
+
+ ret = scd30_command_write(state, CMD_RESET, 0);
+ if (ret)
+ return ret;
+
+ /* sensor boots up within 2 secs */
+ msleep(2000);
+ /*
+ * Power-on-reset causes sensor to produce some glitch on i2c bus and
+ * some controllers end up in error state. Try to recover by placing
+ * any data on the bus.
+ */
+ scd30_command_read(state, CMD_MEAS_READY, &val);
+
+ return 0;
+}
+
+/* simplified float to fixed point conversion with a scaling factor of 0.01 */
+static int scd30_float_to_fp(int float32)
+{
+ int fraction, shift,
+ mantissa = float32 & GENMASK(22, 0),
+ sign = float32 & BIT(31) ? -1 : 1,
+ exp = (float32 & ~BIT(31)) >> 23;
+
+ /* special case 0 */
+ if (!exp && !mantissa)
+ return 0;
+
+ exp -= 127;
+ if (exp < 0) {
+ exp = -exp;
+ /* return values ranging from 1 to 99 */
+ return sign * ((((BIT(23) + mantissa) * 100) >> 23) >> exp);
+ }
+
+ /* return values starting at 100 */
+ shift = 23 - exp;
+ float32 = BIT(exp) + (mantissa >> shift);
+ fraction = mantissa & GENMASK(shift - 1, 0);
+
+ return sign * (float32 * 100 + ((fraction * 100) >> shift));
+}
+
+static int scd30_read_meas(struct scd30_state *state)
+{
+ int i, ret;
+
+ ret = state->command(state, CMD_READ_MEAS, 0, state->meas,
+ sizeof(state->meas));
+ if (ret)
+ return ret;
+
+ be32_to_cpu_array(state->meas, state->meas, ARRAY_SIZE(state->meas));
+
+ for (i = 0; i < ARRAY_SIZE(state->meas); i++)
+ state->meas[i] = scd30_float_to_fp(state->meas[i]);
+
+ return 0;
+}
+
+static int scd30_wait_meas_irq(struct scd30_state *state)
+{
+ int ret, timeout;
+
+ timeout = state->meas_interval * (1000 + SCD30_EXTRA_TIMEOUT_PER_S);
+ timeout = msecs_to_jiffies(timeout);
+ reinit_completion(&state->meas_ready);
+ enable_irq(state->irq);
+ ret = wait_for_completion_interruptible_timeout(&state->meas_ready,
+ timeout);
+ if (ret > 0)
+ ret = 0;
+ else if (!ret)
+ ret = -ETIMEDOUT;
+
+ disable_irq(state->irq);
+
+ return ret;
+}
+
+static int scd30_wait_meas_poll(struct scd30_state *state)
+{
+ int timeout = state->meas_interval * SCD30_EXTRA_TIMEOUT_PER_S;
+ int tries = 5;
+
+ do {
+ int ret;
+ u16 val;
+
+ ret = scd30_command_read(state, CMD_MEAS_READY, &val);
+ if (ret)
+ return -EIO;
+
+ /* new measurement available */
+ if (val)
+ break;
+
+ msleep_interruptible(timeout);
+ } while (--tries);
+
+ return tries ? 0 : -ETIMEDOUT;
+}
+
+static int scd30_read_poll(struct scd30_state *state)
+{
+ int ret;
+
+ ret = scd30_wait_meas_poll(state);
+ if (ret)
+ return ret;
+
+ return scd30_read_meas(state);
+}
+
+static int scd30_read(struct scd30_state *state)
+{
+ if (state->irq > 0)
+ return scd30_wait_meas_irq(state);
+
+ return scd30_read_poll(state);
+}
+
+static int scd30_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val, int *val2, long mask)
+{
+ struct scd30_state *state = iio_priv(indio_dev);
+ int ret, meas[SCD30_MEAS_COUNT];
+
+ switch (mask) {
+ case IIO_CHAN_INFO_RAW:
+ case IIO_CHAN_INFO_PROCESSED:
+ ret = iio_device_claim_direct_mode(indio_dev);
+ if (ret)
+ return ret;
+
+ mutex_lock(&state->lock);
+ ret = scd30_read(state);
+ memcpy(meas, state->meas, SCD30_MEAS_COUNT * sizeof(*meas));
+ mutex_unlock(&state->lock);
+ iio_device_release_direct_mode(indio_dev);
+ if (ret)
+ return ret;
+
+ switch (chan->type) {
+ case IIO_CONCENTRATION:
+ *val = meas[chan->address] / 1000000;
+ *val2 = meas[chan->address] % 1000000;
+
+ return IIO_VAL_INT_PLUS_MICRO;
+ case IIO_TEMP:
+ case IIO_HUMIDITYRELATIVE:
+ *val = meas[chan->address] * 10;
+
+ return IIO_VAL_INT;
+ default:
+ return -EINVAL;
+ }
+ case IIO_CHAN_INFO_SCALE:
+ switch (chan->type) {
+ case IIO_CONCENTRATION:
+ *val = 0;
+ *val2 = 1;
+
+ return IIO_VAL_INT_PLUS_MICRO;
+ case IIO_TEMP:
+ case IIO_HUMIDITYRELATIVE:
+ *val = 10;
+
+ return IIO_VAL_INT;
+ default:
+ return -EINVAL;
+ }
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ *val = 0;
+ *val2 = 0;
+
+ mutex_lock(&state->lock);
+ ret = scd30_command_read(state, CMD_MEAS_INTERVAL, (u16 *)val2);
+ mutex_unlock(&state->lock);
+ if (ret)
+ return ret;
+
+ *val2 = 1000000000 / *val2;
+
+ return IIO_VAL_INT_PLUS_NANO;
+ case IIO_CHAN_INFO_CALIBSCALE:
+ mutex_lock(&state->lock);
+ *val = state->pressure_comp / 10;
+ *val2 = (state->pressure_comp % 10) * 100000;
+ mutex_unlock(&state->lock);
+
+ return IIO_VAL_INT_PLUS_MICRO;
+ case IIO_CHAN_INFO_CALIBBIAS:
+ *val = 0;
+ mutex_lock(&state->lock);
+ ret = scd30_command_read(state, CMD_TEMP_OFFSET, (u16 *)val);
+ mutex_unlock(&state->lock);
+
+ return IIO_VAL_INT;
+ }
+
+ return -EINVAL;
+}
+
+static int scd30_write_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int val, int val2, long mask)
+{
+ struct scd30_state *state = iio_priv(indio_dev);
+ int ret = -EINVAL;
+
+ mutex_lock(&state->lock);
+ switch (mask) {
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ if (val)
+ break;
+
+ val = 1000000000 / val2;
+ if (val < SCD30_MEAS_INTERVAL_MIN_S ||
+ val > SCD30_MEAS_INTERVAL_MAX_S)
+ break;
+
+ ret = scd30_command_write(state, CMD_MEAS_INTERVAL, val);
+ if (ret)
+ break;
+
+ state->meas_interval = val;
+ break;
+ case IIO_CHAN_INFO_CALIBSCALE:
+ val = (val * 1000000 + val2) / 100000;
+ if (val < SCD30_PRESSURE_COMP_MIN_MBAR ||
+ val > SCD30_PRESSURE_COMP_MAX_MBAR)
+ break;
+
+ ret = scd30_command_write(state, CMD_START_MEAS, val);
+ if (ret)
+ break;
+
+ state->pressure_comp = val;
+ break;
+ case IIO_CHAN_INFO_CALIBBIAS:
+ if (val < 0 || val > SCD30_TEMP_OFFSET_MAX)
+ break;
+ /*
+ * Manufacturer does not explicitly specify min/max sensible
+ * values hence check is omitted for simplicity.
+ */
+ ret = scd30_command_write(state, CMD_TEMP_OFFSET / 10, val);
+ }
+ mutex_unlock(&state->lock);
+
+ return ret;
+}
+
+static int scd30_write_raw_get_fmt(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan, long mask)
+{
+ switch (mask) {
+ case IIO_CHAN_INFO_RAW:
+ case IIO_CHAN_INFO_CALIBBIAS:
+ return IIO_VAL_INT;
+ case IIO_CHAN_INFO_CALIBSCALE:
+ return IIO_VAL_INT_PLUS_MICRO;
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ return IIO_VAL_INT_PLUS_NANO;
+ }
+
+ return -EINVAL;
+}
+
+static const int scd30_pressure_calibscale_available[] = {
+ SCD30_PRESSURE_COMP_MIN_MBAR / 10, 0,
+ 0, 100000,
+ SCD30_PRESSURE_COMP_MAX_MBAR / 10, 0,
+};
+
+static const int scd30_temp_calibbias_available[] = {
+ 0, 10, SCD30_TEMP_OFFSET_MAX,
+};
+
+static int scd30_read_avail(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan, const int **vals,
+ int *type, int *length, long mask)
+{
+ switch (mask) {
+ case IIO_CHAN_INFO_CALIBSCALE:
+ *vals = scd30_pressure_calibscale_available;
+ *type = IIO_VAL_INT_PLUS_MICRO;
+
+ return IIO_AVAIL_RANGE;
+ case IIO_CHAN_INFO_CALIBBIAS:
+ *vals = scd30_temp_calibbias_available;
+ *type = IIO_VAL_INT;
+
+ return IIO_AVAIL_RANGE;
+ }
+
+ return -EINVAL;
+}
+
+static ssize_t sampling_frequency_available_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ int i = SCD30_MEAS_INTERVAL_MIN_S;
+ ssize_t len = 0;
+
+ do {
+ len += scnprintf(buf + len, PAGE_SIZE - len, "0.%09u ",
+ 1000000000 / i);
+ /*
+ * Not all values fit PAGE_SIZE buffer hence print every 6th
+ * (each frequency differs by 6s in time domain from the
+ * adjecent). Unlisted but valid ones are still accepted.
+ */
+ i += 6;
+ } while (i <= SCD30_MEAS_INTERVAL_MAX_S);
+
+ buf[len - 1] = '\n';
+
+ return len;
+}
+
+static ssize_t calibration_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+ struct scd30_state *state = iio_priv(indio_dev);
+ u16 asc, frc;
+ int ret;
+
+ mutex_lock(&state->lock);
+ ret = scd30_command_read(state, CMD_ASC, &asc);
+ if (ret)
+ goto out;
+
+ ret = scd30_command_read(state, CMD_FRC, &frc);
+out:
+ mutex_unlock(&state->lock);
+
+ return ret ?: sprintf(buf, "%d %d\n", asc, frc);
+}
+
+static ssize_t calibration_store(struct device *dev,
+ struct device_attribute *attr, const char *buf,
+ size_t len)
+{
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+ struct scd30_state *state = iio_priv(indio_dev);
+ int ret;
+ u16 val;
+
+ ret = kstrtou16(buf, 0, &val);
+ if (ret)
+ return ret;
+
+ mutex_lock(&state->lock);
+ if (val == 0 || val == 1)
+ ret = scd30_command_write(state, CMD_ASC, val);
+ else if (val >= SCD30_FRC_MIN_PPM && val <= SCD30_FRC_MAX_PPM)
+ ret = scd30_command_write(state, CMD_FRC, val);
+ else
+ ret = -EINVAL;
+ mutex_unlock(&state->lock);
+
+ return ret ?: len;
+}
+
+static IIO_DEVICE_ATTR_RO(sampling_frequency_available, 0);
+static IIO_DEVICE_ATTR_RW(calibration, 0);
+
+static struct attribute *scd30_attrs[] = {
+ &iio_dev_attr_sampling_frequency_available.dev_attr.attr,
+ &iio_dev_attr_calibration.dev_attr.attr,
+ NULL
+};
+
+static const struct attribute_group scd30_attr_group = {
+ .attrs = scd30_attrs,
+};
+
+static const struct iio_info scd30_info = {
+ .attrs = &scd30_attr_group,
+ .read_raw = scd30_read_raw,
+ .write_raw = scd30_write_raw,
+ .write_raw_get_fmt = scd30_write_raw_get_fmt,
+ .read_avail = scd30_read_avail,
+};
+
+#define SCD30_CHAN_SCAN_TYPE(_sign, _realbits) .scan_type = { \
+ .sign = _sign, \
+ .realbits = _realbits, \
+ .storagebits = 32, \
+ .endianness = IIO_CPU, \
+}
+
+static const struct iio_chan_spec scd30_channels[] = {
+ {
+ .type = IIO_PRESSURE,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_CALIBSCALE),
+ .info_mask_separate_available = BIT(IIO_CHAN_INFO_CALIBSCALE),
+ .scan_index = -1,
+ },
+ {
+ .type = IIO_CONCENTRATION,
+ .channel2 = IIO_MOD_CO2,
+ .address = SCD30_CONC,
+ .scan_index = SCD30_CONC,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_SCALE),
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),
+ .modified = 1,
+
+ SCD30_CHAN_SCAN_TYPE('u', 16),
+ },
+ {
+ .type = IIO_TEMP,
+ .address = SCD30_TEMP,
+ .scan_index = SCD30_TEMP,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) |
+ BIT(IIO_CHAN_INFO_CALIBBIAS) |
+ BIT(IIO_CHAN_INFO_SCALE),
+ .info_mask_separate_available = BIT(IIO_CHAN_INFO_CALIBBIAS),
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),
+
+ SCD30_CHAN_SCAN_TYPE('s', 14),
+ },
+ {
+ .type = IIO_HUMIDITYRELATIVE,
+ .address = SCD30_HR,
+ .scan_index = SCD30_HR,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) |
+ BIT(IIO_CHAN_INFO_SCALE),
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),
+
+ SCD30_CHAN_SCAN_TYPE('u', 14),
+ },
+ IIO_CHAN_SOFT_TIMESTAMP(3),
+};
+
+int __maybe_unused scd30_suspend(struct device *dev)
+{
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct scd30_state *state = iio_priv(indio_dev);
+ int ret;
+
+ ret = scd30_command_write(state, CMD_STOP_MEAS, 0);
+ if (ret)
+ return ret;
+
+ return regulator_disable(state->vdd);
+}
+EXPORT_SYMBOL(scd30_suspend);
+
+int __maybe_unused scd30_resume(struct device *dev)
+{
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct scd30_state *state = iio_priv(indio_dev);
+ int ret;
+
+ ret = regulator_enable(state->vdd);
+ if (ret)
+ return ret;
+
+ return scd30_command_write(state, CMD_START_MEAS, state->pressure_comp);
+}
+EXPORT_SYMBOL(scd30_resume);
+
+static void scd30_stop_meas(void *data)
+{
+ struct scd30_state *state = data;
+
+ scd30_command_write(state, CMD_STOP_MEAS, 0);
+}
+
+static void scd30_disable_regulator(void *data)
+{
+ struct scd30_state *state = data;
+
+ regulator_disable(state->vdd);
+}
+
+static irqreturn_t scd30_irq_handler(int irq, void *priv)
+{
+ struct iio_dev *indio_dev = priv;
+
+ if (iio_buffer_enabled(indio_dev)) {
+ iio_trigger_poll(indio_dev->trig);
+
+ return IRQ_HANDLED;
+ }
+
+ return IRQ_WAKE_THREAD;
+}
+
+static irqreturn_t scd30_irq_thread_handler(int irq, void *priv)
+{
+ struct iio_dev *indio_dev = priv;
+ struct scd30_state *state = iio_priv(indio_dev);
+ int ret;
+
+ ret = scd30_read_meas(state);
+ if (ret)
+ goto out;
+
+ complete_all(&state->meas_ready);
+out:
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t scd30_trigger_handler(int irq, void *p)
+{
+ struct iio_poll_func *pf = p;
+ struct iio_dev *indio_dev = pf->indio_dev;
+ struct scd30_state *state = iio_priv(indio_dev);
+ struct {
+ int data[SCD30_MEAS_COUNT];
+ u64 ts;
+ } scan;
+ int ret;
+
+ mutex_lock(&state->lock);
+ if (!iio_trigger_using_own(indio_dev))
+ ret = scd30_read_poll(state);
+ else
+ ret = scd30_read_meas(state);
+ memcpy(scan.data, state->meas, sizeof(state->meas));
+ mutex_unlock(&state->lock);
+ if (ret)
+ goto out;
+
+ iio_push_to_buffers_with_timestamp(indio_dev, &scan,
+ iio_get_time_ns(indio_dev));
+out:
+ iio_trigger_notify_done(indio_dev->trig);
+ return IRQ_HANDLED;
+}
+
+static int scd30_set_trigger_state(struct iio_trigger *trig, bool state)
+{
+ struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
+ struct scd30_state *st = iio_priv(indio_dev);
+
+ if (state)
+ enable_irq(st->irq);
+ else
+ disable_irq(st->irq);
+
+ return 0;
+}
+
+static const struct iio_trigger_ops scd30_trigger_ops = {
+ .set_trigger_state = scd30_set_trigger_state,
+};
+
+static int scd30_setup_trigger(struct iio_dev *indio_dev)
+{
+ struct scd30_state *state = iio_priv(indio_dev);
+ struct device *dev = indio_dev->dev.parent;
+ struct iio_trigger *trig;
+ int ret;
+
+ trig = devm_iio_trigger_alloc(dev, "%s-dev%d", indio_dev->name,
+ indio_dev->id);
+ if (!trig) {
+ dev_err(dev, "failed to allocate trigger\n");
+ return -ENOMEM;
+ }
+
+ trig->dev.parent = dev;
+ trig->ops = &scd30_trigger_ops;
+ iio_trigger_set_drvdata(trig, indio_dev);
+
+ ret = devm_iio_trigger_register(dev, trig);
+ if (ret)
+ return ret;
+
+ indio_dev->trig = iio_trigger_get(trig);
+
+ ret = devm_request_threaded_irq(dev, state->irq, scd30_irq_handler,
+ scd30_irq_thread_handler,
+ IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
+ indio_dev->name, indio_dev);
+ if (ret)
+ dev_err(dev, "failed to request irq\n");
+
+ disable_irq(state->irq);
+
+ return ret;
+}
+
+int scd30_probe(struct device *dev, int irq, const char *name, void *priv,
+ scd30_command_t command)
+{
+ static const unsigned long scd30_scan_masks[] = { 0x07, 0x00 };
+ struct scd30_state *state;
+ struct iio_dev *indio_dev;
+ int ret;
+ u16 val;
+
+ indio_dev = devm_iio_device_alloc(dev, sizeof(*state));
+ if (!indio_dev)
+ return -ENOMEM;
+
+ state = iio_priv(indio_dev);
+ state->dev = dev;
+ state->priv = priv;
+ state->irq = irq;
+ state->pressure_comp = SCD30_PRESSURE_COMP_DEFAULT;
+ state->meas_interval = SCD30_MEAS_INTERVAL_DEFAULT;
+ state->command = command;
+ mutex_init(&state->lock);
+ init_completion(&state->meas_ready);
+
+ dev_set_drvdata(dev, indio_dev);
+
+ indio_dev->dev.parent = dev;
+ indio_dev->info = &scd30_info;
+ indio_dev->name = name;
+ indio_dev->channels = scd30_channels;
+ indio_dev->num_channels = ARRAY_SIZE(scd30_channels);
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->available_scan_masks = scd30_scan_masks;
+
+ state->vdd = devm_regulator_get(dev, "vdd");
+ if (IS_ERR(state->vdd)) {
+ if (PTR_ERR(state->vdd) == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
+
+ dev_err(dev, "failed to get regulator\n");
+ return PTR_ERR(state->vdd);
+ }
+
+ ret = regulator_enable(state->vdd);
+ if (ret)
+ return ret;
+
+ ret = devm_add_action_or_reset(dev, scd30_disable_regulator, state);
+ if (ret)
+ return ret;
+
+ ret = devm_add_action_or_reset(dev, scd30_stop_meas, state);
+ if (ret)
+ return ret;
+
+ ret = scd30_reset(state);
+ if (ret) {
+ dev_err(dev, "failed to reset device: %d\n", ret);
+ return ret;
+ }
+
+ if (state->irq > 0) {
+ ret = scd30_setup_trigger(indio_dev);
+ if (ret) {
+ dev_err(dev, "failed to setup trigger: %d\n", ret);
+ return ret;
+ }
+ }
+
+ ret = devm_iio_triggered_buffer_setup(dev, indio_dev, NULL,
+ scd30_trigger_handler, NULL);
+ if (ret)
+ return ret;
+
+ ret = scd30_command_read(state, CMD_FW_VERSION, &val);
+ if (ret) {
+ dev_err(dev, "failed to read firmware version: %d\n", ret);
+ return ret;
+ }
+ dev_info(dev, "firmware version: %d.%d\n", val >> 8, (char)val);
+
+ ret = scd30_command_write(state, CMD_MEAS_INTERVAL,
+ state->meas_interval);
+ if (ret) {
+ dev_err(dev, "failed to set measurement interval: %d\n", ret);
+ return ret;
+ }
+
+ ret = scd30_command_write(state, CMD_START_MEAS, state->pressure_comp);
+ if (ret) {
+ dev_err(dev, "failed to start measurement: %d\n", ret);
+ return ret;
+ }
+
+ return devm_iio_device_register(dev, indio_dev);
+}
+EXPORT_SYMBOL(scd30_probe);
+
+MODULE_AUTHOR("Tomasz Duszynski <tomasz.duszynski@octakon.com>");
+MODULE_DESCRIPTION("Sensirion SCD30 carbon dioxide sensor core driver");
+MODULE_LICENSE("GPL v2");
--
2.26.2
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox