[v1,03/43] soc: Add SoC driver for Cirrus ep93xx
Commit Message
This adds an SoC driver for the ep93xx. Currently there
is only one thing not fitting into any other framework,
and that is the swlock setting.
It's used for clock settings and restart.
Signed-off-by: Nikita Shubin <nikita.shubin@maquefel.me>
Tested-by: Alexander Sverdlin <alexander.sverdlin@gmail.com>
Acked-by: Alexander Sverdlin <alexander.sverdlin@gmail.com>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
---
Notes:
v0 -> v1
Replaced defines to make this patch compile:
CONFIG_ARCH_EP93XX -> CONFIG_EP93XX_SOC_COMMON
And made changed depend on CONFIG_EP93XX_SOC,
which is selected when !EP93XX_SOC_COMMON
rfc -> v0
Alexander Sverdlin:
- replace spinlock with local_irq
Arnd Bergmann:
- wildcards changed to ep9301
Linus Walleij:
- added tag, i hope changes are not significant enough to drop
Reviewed-by tag
drivers/soc/Kconfig | 1 +
drivers/soc/Makefile | 1 +
drivers/soc/cirrus/Kconfig | 11 +++
drivers/soc/cirrus/Makefile | 2 +
drivers/soc/cirrus/soc-ep93xx.c | 134 ++++++++++++++++++++++++++++++
include/linux/soc/cirrus/ep93xx.h | 16 +++-
6 files changed, 161 insertions(+), 4 deletions(-)
create mode 100644 drivers/soc/cirrus/Kconfig
create mode 100644 drivers/soc/cirrus/Makefile
create mode 100644 drivers/soc/cirrus/soc-ep93xx.c
Comments
Dear Nikita,
Thank you for your patch. Some small nit picks.
Am 01.06.23 um 07:33 schrieb Nikita Shubin:
> This adds an SoC driver for the ep93xx. Currently there
> is only one thing not fitting into any other framework,
> and that is the swlock setting.
If you reflow for 75 characters per line, this would fit into two lines.
> It's used for clock settings and restart.
What datasheet did you use, and on what board did you test this?
> Signed-off-by: Nikita Shubin <nikita.shubin@maquefel.me>
> Tested-by: Alexander Sverdlin <alexander.sverdlin@gmail.com>
> Acked-by: Alexander Sverdlin <alexander.sverdlin@gmail.com>
> Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
> ---
[…]
> drivers/soc/Kconfig | 1 +
> drivers/soc/Makefile | 1 +
> drivers/soc/cirrus/Kconfig | 11 +++
> drivers/soc/cirrus/Makefile | 2 +
> drivers/soc/cirrus/soc-ep93xx.c | 134 ++++++++++++++++++++++++++++++
> include/linux/soc/cirrus/ep93xx.h | 16 +++-
> 6 files changed, 161 insertions(+), 4 deletions(-)
> create mode 100644 drivers/soc/cirrus/Kconfig
> create mode 100644 drivers/soc/cirrus/Makefile
> create mode 100644 drivers/soc/cirrus/soc-ep93xx.c
>
> diff --git a/drivers/soc/Kconfig b/drivers/soc/Kconfig
> index 4e176280113a..6149f0447b61 100644
> --- a/drivers/soc/Kconfig
> +++ b/drivers/soc/Kconfig
> @@ -30,5 +30,6 @@ source "drivers/soc/ti/Kconfig"
> source "drivers/soc/ux500/Kconfig"
> source "drivers/soc/versatile/Kconfig"
> source "drivers/soc/xilinx/Kconfig"
> +source "drivers/soc/cirrus/Kconfig"
>
> endmenu
> diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile
> index 3b0f9fb3b5c8..7a8a154b8d96 100644
> --- a/drivers/soc/Makefile
> +++ b/drivers/soc/Makefile
> @@ -36,3 +36,4 @@ obj-y += ti/
> obj-$(CONFIG_ARCH_U8500) += ux500/
> obj-$(CONFIG_PLAT_VERSATILE) += versatile/
> obj-y += xilinx/
> +obj-$(CONFIG_EP93XX_SOC) += cirrus/
> diff --git a/drivers/soc/cirrus/Kconfig b/drivers/soc/cirrus/Kconfig
> new file mode 100644
> index 000000000000..bc82c0422325
> --- /dev/null
> +++ b/drivers/soc/cirrus/Kconfig
> @@ -0,0 +1,11 @@
> +# SPDX-License-Identifier: GPL-2.0
> +
> +if ARCH_EP93XX
> +
> +config EP93XX_SOC
> + bool "Cirrus EP93xx chips SoC"
> + default y if !EP93XX_SOC_COMMON
> + help
> + Support Soc for Cirrus EP93xx chips.
Above (and more common in the whole SOC directory) you spell it SoC.
> +
> +endif
> diff --git a/drivers/soc/cirrus/Makefile b/drivers/soc/cirrus/Makefile
> new file mode 100644
> index 000000000000..ed6752844c6f
> --- /dev/null
> +++ b/drivers/soc/cirrus/Makefile
> @@ -0,0 +1,2 @@
> +# SPDX-License-Identifier: GPL-2.0
> +obj-y += soc-ep93xx.o
> diff --git a/drivers/soc/cirrus/soc-ep93xx.c b/drivers/soc/cirrus/soc-ep93xx.c
> new file mode 100644
> index 000000000000..64842e9e2316
> --- /dev/null
> +++ b/drivers/soc/cirrus/soc-ep93xx.c
> @@ -0,0 +1,134 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Soc driver for Cirrus EP93xx chips.
Ditto.
> + * Copyright (C) 2022 Nikita Shubin <nikita.shubin@maquefel.me>
> + *
> + * Based on a rewrite of arch/arm/mach-ep93xx/core.c
> + * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
> + * Copyright (C) 2007 Herbert Valerio Riedel <hvr@gnu.org>
> + *
> + * Thanks go to Michael Burian and Ray Lehtiniemi for their key
> + * role in the ep93xx linux community
If you know their email addresses, you could add those too. Maybe also
add a dot/period at the end.
> + */
> +
> +#include <linux/soc/cirrus/ep93xx.h>
> +#include <linux/init.h>
> +#include <linux/kernel.h>
> +#include <linux/mfd/syscon.h>
> +#include <linux/regmap.h>
> +#include <linux/of.h>
> +
> +#define EP93XX_SYSCON_DEVCFG 0x80
> +
> +#define EP93XX_SWLOCK_MAGICK 0xaa
> +#define EP93XX_SYSCON_SWLOCK 0xc0
> +#define EP93XX_SYSCON_SYSCFG 0x9c
> +#define EP93XX_SYSCON_SYSCFG_REV_MASK (0xf0000000)
> +#define EP93XX_SYSCON_SYSCFG_REV_SHIFT (28)
[…]
Kind regards,
Paul
Hello Paul.
Thnak you for your comments.
On Thu, 1 Jun 2023 07:53:38 +0200
Paul Menzel <pmenzel@molgen.mpg.de> wrote:
> Dear Nikita,
>
>
> Thank you for your patch. Some small nit picks.
>
> Am 01.06.23 um 07:33 schrieb Nikita Shubin:
> > This adds an SoC driver for the ep93xx. Currently there
> > is only one thing not fitting into any other framework,
> > and that is the swlock setting.
>
> If you reflow for 75 characters per line, this would fit into two
> lines.
>
> > It's used for clock settings and restart.
>
> What datasheet did you use, and on what board did you test this?
Adding link to v0 series:
https://lore.kernel.org/all/20230424123522.18302-1-nikita.shubin@maquefel.me/
Tested on ts7250 64 RAM/128 MiB Nand flash, edb9302.
> What datasheet did you use
ep9301/ep9302/ep9307/ep9312/ep9315 datasheet
ep93xx user guide
>
> > Signed-off-by: Nikita Shubin <nikita.shubin@maquefel.me>
> > Tested-by: Alexander Sverdlin <alexander.sverdlin@gmail.com>
> > Acked-by: Alexander Sverdlin <alexander.sverdlin@gmail.com>
> > Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
> > ---
>
> […]
>
> > drivers/soc/Kconfig | 1 +
> > drivers/soc/Makefile | 1 +
> > drivers/soc/cirrus/Kconfig | 11 +++
> > drivers/soc/cirrus/Makefile | 2 +
> > drivers/soc/cirrus/soc-ep93xx.c | 134
> > ++++++++++++++++++++++++++++++ include/linux/soc/cirrus/ep93xx.h |
> > 16 +++- 6 files changed, 161 insertions(+), 4 deletions(-)
> > create mode 100644 drivers/soc/cirrus/Kconfig
> > create mode 100644 drivers/soc/cirrus/Makefile
> > create mode 100644 drivers/soc/cirrus/soc-ep93xx.c
> >
> > diff --git a/drivers/soc/Kconfig b/drivers/soc/Kconfig
> > index 4e176280113a..6149f0447b61 100644
> > --- a/drivers/soc/Kconfig
> > +++ b/drivers/soc/Kconfig
> > @@ -30,5 +30,6 @@ source "drivers/soc/ti/Kconfig"
> > source "drivers/soc/ux500/Kconfig"
> > source "drivers/soc/versatile/Kconfig"
> > source "drivers/soc/xilinx/Kconfig"
> > +source "drivers/soc/cirrus/Kconfig"
> >
> > endmenu
> > diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile
> > index 3b0f9fb3b5c8..7a8a154b8d96 100644
> > --- a/drivers/soc/Makefile
> > +++ b/drivers/soc/Makefile
> > @@ -36,3 +36,4 @@ obj-y += ti/
> > obj-$(CONFIG_ARCH_U8500) += ux500/
> > obj-$(CONFIG_PLAT_VERSATILE) += versatile/
> > obj-y += xilinx/
> > +obj-$(CONFIG_EP93XX_SOC) += cirrus/
> > diff --git a/drivers/soc/cirrus/Kconfig b/drivers/soc/cirrus/Kconfig
> > new file mode 100644
> > index 000000000000..bc82c0422325
> > --- /dev/null
> > +++ b/drivers/soc/cirrus/Kconfig
> > @@ -0,0 +1,11 @@
> > +# SPDX-License-Identifier: GPL-2.0
> > +
> > +if ARCH_EP93XX
> > +
> > +config EP93XX_SOC
> > + bool "Cirrus EP93xx chips SoC"
> > + default y if !EP93XX_SOC_COMMON
> > + help
> > + Support Soc for Cirrus EP93xx chips.
>
> Above (and more common in the whole SOC directory) you spell it SoC.
>
> > +
> > +endif
> > diff --git a/drivers/soc/cirrus/Makefile
> > b/drivers/soc/cirrus/Makefile new file mode 100644
> > index 000000000000..ed6752844c6f
> > --- /dev/null
> > +++ b/drivers/soc/cirrus/Makefile
> > @@ -0,0 +1,2 @@
> > +# SPDX-License-Identifier: GPL-2.0
> > +obj-y += soc-ep93xx.o
> > diff --git a/drivers/soc/cirrus/soc-ep93xx.c
> > b/drivers/soc/cirrus/soc-ep93xx.c new file mode 100644
> > index 000000000000..64842e9e2316
> > --- /dev/null
> > +++ b/drivers/soc/cirrus/soc-ep93xx.c
> > @@ -0,0 +1,134 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * Soc driver for Cirrus EP93xx chips.
>
> Ditto.
>
> > + * Copyright (C) 2022 Nikita Shubin <nikita.shubin@maquefel.me>
> > + *
> > + * Based on a rewrite of arch/arm/mach-ep93xx/core.c
> > + * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
> > + * Copyright (C) 2007 Herbert Valerio Riedel <hvr@gnu.org>
> > + *
> > + * Thanks go to Michael Burian and Ray Lehtiniemi for their key
> > + * role in the ep93xx linux community
>
> If you know their email addresses, you could add those too. Maybe
> also add a dot/period at the end.
>
> > + */
> > +
> > +#include <linux/soc/cirrus/ep93xx.h>
> > +#include <linux/init.h>
> > +#include <linux/kernel.h>
> > +#include <linux/mfd/syscon.h>
> > +#include <linux/regmap.h>
> > +#include <linux/of.h>
> > +
> > +#define EP93XX_SYSCON_DEVCFG 0x80
> > +
> > +#define EP93XX_SWLOCK_MAGICK 0xaa
> > +#define EP93XX_SYSCON_SWLOCK 0xc0
> > +#define EP93XX_SYSCON_SYSCFG 0x9c
> > +#define EP93XX_SYSCON_SYSCFG_REV_MASK (0xf0000000)
> > +#define EP93XX_SYSCON_SYSCFG_REV_SHIFT (28)
>
> […]
>
>
> Kind regards,
>
> Paul
Thu, Jun 01, 2023 at 08:33:54AM +0300, Nikita Shubin kirjoitti:
> This adds an SoC driver for the ep93xx. Currently there
> is only one thing not fitting into any other framework,
> and that is the swlock setting.
>
> It's used for clock settings and restart.
...
> source "drivers/soc/ux500/Kconfig"
> source "drivers/soc/versatile/Kconfig"
> source "drivers/soc/xilinx/Kconfig"
> +source "drivers/soc/cirrus/Kconfig"
Why not ordered?
...
> obj-$(CONFIG_ARCH_U8500) += ux500/
> obj-$(CONFIG_PLAT_VERSATILE) += versatile/
> obj-y += xilinx/
> +obj-$(CONFIG_EP93XX_SOC) += cirrus/
Ditto.
...
> +/*
> + * Soc driver for Cirrus EP93xx chips.
SoC
> + * Copyright (C) 2022 Nikita Shubin <nikita.shubin@maquefel.me>
> + *
> + * Based on a rewrite of arch/arm/mach-ep93xx/core.c
> + * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
> + * Copyright (C) 2007 Herbert Valerio Riedel <hvr@gnu.org>
> + *
> + * Thanks go to Michael Burian and Ray Lehtiniemi for their key
> + * role in the ep93xx linux community
Linux
community.
> + */
...
> +#include <linux/soc/cirrus/ep93xx.h>
> +#include <linux/init.h>
> +#include <linux/kernel.h>
> +#include <linux/mfd/syscon.h>
> +#include <linux/regmap.h>
> +#include <linux/of.h>
Can this be ordered?
...
> +#define EP93XX_SYSCON_SYSCFG_REV_MASK (0xf0000000)
GENMASK() ?
(will need bits.h)
> +#define EP93XX_SYSCON_SYSCFG_REV_SHIFT (28)
Here and above, do you need parentheses?
...
> +static struct regmap *map;
Global?!
...
> +EXPORT_SYMBOL_GPL(ep93xx_syscon_swlocked_write);
Can it (and other exported symbols) be exported with a namespace?
...
> +/**
> + * ep93xx_chip_revision() - returns the EP93xx chip revision
> + *
Redundant (?) blank line, but...
kernel doc validation will complain here a lot. Either drop kernel doc style or
fill it correctly.
> + */
...
> +static int __init ep93xx_soc_init(void)
> +{
> + /* Multiplatform guard, only proceed on ep93xx */
> + if (!of_machine_is_compatible("cirrus,ep9301"))
> + return 0;
> +
> + map = syscon_regmap_lookup_by_compatible("cirrus,ep9301-syscon");
> + if (IS_ERR(map))
> + return PTR_ERR(map);
> +
> + pr_info("EP93xx SoC revision %s\n", ep93xx_get_soc_rev());
> +
> + return 0;
> +}
> +
Unneeded blank line.
> +core_initcall(ep93xx_soc_init);
> +
Trailing blank line.
@@ -30,5 +30,6 @@ source "drivers/soc/ti/Kconfig"
source "drivers/soc/ux500/Kconfig"
source "drivers/soc/versatile/Kconfig"
source "drivers/soc/xilinx/Kconfig"
+source "drivers/soc/cirrus/Kconfig"
endmenu
@@ -36,3 +36,4 @@ obj-y += ti/
obj-$(CONFIG_ARCH_U8500) += ux500/
obj-$(CONFIG_PLAT_VERSATILE) += versatile/
obj-y += xilinx/
+obj-$(CONFIG_EP93XX_SOC) += cirrus/
new file mode 100644
@@ -0,0 +1,11 @@
+# SPDX-License-Identifier: GPL-2.0
+
+if ARCH_EP93XX
+
+config EP93XX_SOC
+ bool "Cirrus EP93xx chips SoC"
+ default y if !EP93XX_SOC_COMMON
+ help
+ Support Soc for Cirrus EP93xx chips.
+
+endif
new file mode 100644
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0
+obj-y += soc-ep93xx.o
new file mode 100644
@@ -0,0 +1,134 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Soc driver for Cirrus EP93xx chips.
+ * Copyright (C) 2022 Nikita Shubin <nikita.shubin@maquefel.me>
+ *
+ * Based on a rewrite of arch/arm/mach-ep93xx/core.c
+ * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
+ * Copyright (C) 2007 Herbert Valerio Riedel <hvr@gnu.org>
+ *
+ * Thanks go to Michael Burian and Ray Lehtiniemi for their key
+ * role in the ep93xx linux community
+ */
+
+#include <linux/soc/cirrus/ep93xx.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/mfd/syscon.h>
+#include <linux/regmap.h>
+#include <linux/of.h>
+
+#define EP93XX_SYSCON_DEVCFG 0x80
+
+#define EP93XX_SWLOCK_MAGICK 0xaa
+#define EP93XX_SYSCON_SWLOCK 0xc0
+#define EP93XX_SYSCON_SYSCFG 0x9c
+#define EP93XX_SYSCON_SYSCFG_REV_MASK (0xf0000000)
+#define EP93XX_SYSCON_SYSCFG_REV_SHIFT (28)
+
+static struct regmap *map;
+
+/* EP93xx System Controller software locked register write */
+void ep93xx_syscon_swlocked_write(unsigned int val, unsigned int reg)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+
+ regmap_write(map, EP93XX_SYSCON_SWLOCK, EP93XX_SWLOCK_MAGICK);
+ regmap_write(map, reg, val);
+
+ local_irq_restore(flags);
+}
+EXPORT_SYMBOL_GPL(ep93xx_syscon_swlocked_write);
+
+void ep93xx_devcfg_set_clear(unsigned int set_bits, unsigned int clear_bits)
+{
+ unsigned long flags;
+ unsigned int val;
+
+ local_irq_save(flags);
+
+ regmap_read(map, EP93XX_SYSCON_DEVCFG, &val);
+ val &= ~clear_bits;
+ val |= set_bits;
+ regmap_write(map, EP93XX_SYSCON_SWLOCK, EP93XX_SWLOCK_MAGICK);
+ regmap_write(map, EP93XX_SYSCON_DEVCFG, val);
+
+ local_irq_restore(flags);
+}
+EXPORT_SYMBOL_GPL(ep93xx_devcfg_set_clear);
+
+void ep93xx_swlocked_update_bits(unsigned int reg,
+ unsigned int mask,
+ unsigned int val)
+{
+ unsigned long flags;
+ unsigned int tmp, orig;
+
+ local_irq_save(flags);
+
+ regmap_read(map, EP93XX_SYSCON_DEVCFG, &orig);
+ tmp = orig & ~mask;
+ tmp |= val & mask;
+ if (tmp != orig) {
+ regmap_write(map, EP93XX_SYSCON_SWLOCK, EP93XX_SWLOCK_MAGICK);
+ regmap_write(map, reg, tmp);
+ }
+
+ local_irq_restore(flags);
+}
+EXPORT_SYMBOL_GPL(ep93xx_swlocked_update_bits);
+
+/**
+ * ep93xx_chip_revision() - returns the EP93xx chip revision
+ *
+ */
+unsigned int ep93xx_chip_revision(void)
+{
+ unsigned int val;
+
+ regmap_read(map, EP93XX_SYSCON_SYSCFG, &val);
+ val &= EP93XX_SYSCON_SYSCFG_REV_MASK;
+ val >>= EP93XX_SYSCON_SYSCFG_REV_SHIFT;
+ return val;
+}
+EXPORT_SYMBOL_GPL(ep93xx_chip_revision);
+
+static const char __init *ep93xx_get_soc_rev(void)
+{
+ int rev = ep93xx_chip_revision();
+
+ switch (rev) {
+ case EP93XX_CHIP_REV_D0:
+ return "D0";
+ case EP93XX_CHIP_REV_D1:
+ return "D1";
+ case EP93XX_CHIP_REV_E0:
+ return "E0";
+ case EP93XX_CHIP_REV_E1:
+ return "E1";
+ case EP93XX_CHIP_REV_E2:
+ return "E2";
+ default:
+ return "unknown";
+ }
+}
+
+static int __init ep93xx_soc_init(void)
+{
+ /* Multiplatform guard, only proceed on ep93xx */
+ if (!of_machine_is_compatible("cirrus,ep9301"))
+ return 0;
+
+ map = syscon_regmap_lookup_by_compatible("cirrus,ep9301-syscon");
+ if (IS_ERR(map))
+ return PTR_ERR(map);
+
+ pr_info("EP93xx SoC revision %s\n", ep93xx_get_soc_rev());
+
+ return 0;
+}
+
+core_initcall(ep93xx_soc_init);
+
@@ -10,7 +10,7 @@ struct platform_device;
#define EP93XX_CHIP_REV_E1 6
#define EP93XX_CHIP_REV_E2 7
-#ifdef CONFIG_ARCH_EP93XX
+#if defined(CONFIG_EP93XX_SOC_COMMON)
int ep93xx_pwm_acquire_gpio(struct platform_device *pdev);
void ep93xx_pwm_release_gpio(struct platform_device *pdev);
int ep93xx_ide_acquire_gpio(struct platform_device *pdev);
@@ -19,8 +19,6 @@ int ep93xx_keypad_acquire_gpio(struct platform_device *pdev);
void ep93xx_keypad_release_gpio(struct platform_device *pdev);
int ep93xx_i2s_acquire(void);
void ep93xx_i2s_release(void);
-unsigned int ep93xx_chip_revision(void);
-
#else
static inline int ep93xx_pwm_acquire_gpio(struct platform_device *pdev) { return 0; }
static inline void ep93xx_pwm_release_gpio(struct platform_device *pdev) {}
@@ -30,8 +28,18 @@ static inline int ep93xx_keypad_acquire_gpio(struct platform_device *pdev) { ret
static inline void ep93xx_keypad_release_gpio(struct platform_device *pdev) {}
static inline int ep93xx_i2s_acquire(void) { return 0; }
static inline void ep93xx_i2s_release(void) {}
-static inline unsigned int ep93xx_chip_revision(void) { return 0; }
+#endif
+#if defined(CONFIG_ARCH_EP93XX)
+unsigned int ep93xx_chip_revision(void);
+#if defined(CONFIG_EP93XX_SOC)
+void ep93xx_devcfg_set_clear(unsigned int set_bits, unsigned int clear_bits);
+void ep93xx_syscon_swlocked_write(unsigned int val, unsigned int reg);
+void ep93xx_swlocked_update_bits(unsigned int reg,
+ unsigned int mask, unsigned int val);
+#endif
+#else
+static inline unsigned int ep93xx_chip_revision(void) { return 0; }
#endif
#endif