* Re: Add Apple M1 support to PASemi i2c driver
From: Wolfram Sang @ 2021-09-27 7:07 UTC (permalink / raw)
To: Sven Peter
Cc: Hector Martin, Arnd Bergmann, Christian Zigotzky,
Linux Kernel Mailing List, linux-i2c, Darren Stevens,
Paul Mackerras, Alyssa Rosenzweig, R.T.Dickinson, Olof Johansson,
mohamed.mediouni, Matthew Leaman, Mark Kettenis, linuxppc-dev,
R.T.Dickinson, linux-arm-kernel, Stan Skowronek
In-Reply-To: <d0a646c7-426b-4b40-b3fc-9776c6a1025d@www.fastmail.com>
[-- Attachment #1: Type: text/plain, Size: 145 bytes --]
> Sure, will do that later as well!
But please do it privately. For upstreaming, the patch series you sent
is way better than a single patch.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply
* Re: ppc32 doesn't boot when linkaddr=0x00900000
From: Christophe Leroy @ 2021-09-27 6:53 UTC (permalink / raw)
To: cp, linuxppc-dev; +Cc: paulus, torvalds
In-Reply-To: <CA+QBN9AFNSf3+U4iMhwZx7c69MLk-BtSbVODBEA97ObYWRczbQ@mail.gmail.com>
Hi,
Le 25/09/2021 à 11:49, cp a écrit :
> hi
> I am new to this list. Hope this is the right place to ask.
>
> I am working with a PPC405GP board, and as far as I understand, the
> support for ppc40x platforms like Acadia and Walnut were dropped with
> kernel 5.8.0, so this seems like a pretty straightforward question,
> but extensive experiments from kernel 4.11 to kernel 5.7.19 haven't
> shown a really clear, up-to-date answer.
>
> In k4.11 .. k5.7.19, when the kernel size is bigger than 8 MB, the
> final kernel doesn't boot but rather arch/powerpc/boot/main.c dies
> before the first message from the kernel shows up.
>
> Why?
>
...
>
> The following is the same kernel, compiled with the same .config, but
> with two link_addr values
>
> A) with link_addr=0x0080.0000
...
> Finalizing device tree... flat tree at 0xf23b80
...
> B) with link_addr=0x0080.0000
...
> Finalizing device tree... flat tree at 0x1023b80
...
> Any ideas?
> I am lost ...
>
As you can see above, when it works you have "flat tree at 0xf23b80",
when it fails you have "flat tree at 0x1023b80".
The reason for the failure is likely that ppc 40x only maps 16 Mbytes at
startup, so when your device tree is outside that map if fails.
See
https://elixir.bootlin.com/linux/v5.15-rc2/source/arch/powerpc/kernel/head_40x.S#L656
Called from
https://elixir.bootlin.com/linux/v5.15-rc2/source/arch/powerpc/kernel/head_40x.S#L56
As you can see it maps one 16Mbytes page.
Allthough I'm not an expert on 40x I think it should be easy to map a
second 16Mbytes page to get 32Mbytes mapped. I will send a patch later
today for you to test.
Christophe
^ permalink raw reply
* Re: Add Apple M1 support to PASemi i2c driver
From: Sven Peter @ 2021-09-27 5:39 UTC (permalink / raw)
To: Christian Zigotzky
Cc: Darren Stevens, Arnd Bergmann, Hector Martin,
Linux Kernel Mailing List, linux-i2c, Paul Mackerras,
Alyssa Rosenzweig, R.T.Dickinson, Olof Johansson,
mohamed.mediouni, Matthew Leaman, Mark Kettenis, linuxppc-dev,
R.T.Dickinson, linux-arm-kernel, Stan Skowronek
In-Reply-To: <3dcc6c36-a0dd-0cad-428d-a6ed0f73e687@xenosoft.de>
Hi Christian,
Thanks already for volunteering to test this!
On Sun, Sep 26, 2021, at 22:27, Christian Zigotzky wrote:
> Hi Sven,
>
> I can't apply your patch 5 (i2c: pasemi: Split pci driver to its own
> file). [1]
That's strange because it should apply cleanly. I'll double check
after to work today to see if I messed up while sending this.
>
> Error message:
>
> patching file b/drivers/i2c/busses/i2c-pasemi-core.c (renamed from
> a/drivers/i2c/busses/i2c-pasemi.c)
> Hunk #3 FAILED at 344.
> 1 out of 3 hunks FAILED -- saving rejects to file
> b/drivers/i2c/busses/i2c-pasemi-core.c.rej
> patching file b/drivers/i2c/busses/i2c-pasemi-core.h
> patching file b/drivers/i2c/busses/i2c-pasemi-pci.c
>
> Please post one patch with all your modifications.
>
Sure, will do that later as well!
Best,
Sven
^ permalink raw reply
* [PATCH] powerpc/eeh:Fix some mistakes in comments
From: Kai Song @ 2021-09-27 2:35 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Kai Song, linux-kernel, oohall, paulus
Get rid of warning:
arch/powerpc/kernel/eeh.c:774: warning: expecting prototype for eeh_set_pe_freset(). Prototype was for eeh_set_dev_freset() instead
Signed-off-by: Kai Song <songkai01@inspur.com>
---
arch/powerpc/kernel/eeh.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/powerpc/kernel/eeh.c b/arch/powerpc/kernel/eeh.c
index e9b597ed423c..4cd4acb049ec 100644
--- a/arch/powerpc/kernel/eeh.c
+++ b/arch/powerpc/kernel/eeh.c
@@ -761,8 +761,8 @@ int pcibios_set_pcie_reset_state(struct pci_dev *dev, enum pcie_reset_state stat
}
/**
- * eeh_set_pe_freset - Check the required reset for the indicated device
- * @data: EEH device
+ * eeh_set_dev_freset - Check the required reset for the indicated device
+ * @edev: EEH device
* @flag: return value
*
* Each device might have its preferred reset type: fundamental or
--
2.27.0
^ permalink raw reply related
* Re: [PATCH] mm: Remove HARDENED_USERCOPY_FALLBACK
From: David Rientjes @ 2021-09-26 20:49 UTC (permalink / raw)
To: Stephen Kitt
Cc: Andrew Morton, Kees Cook, James Morris, linux-kernel,
Pekka Enberg, linux-mm, linux-security-module, linux-hardening,
Christoph Lameter, linuxppc-dev, Joonsoo Kim, Vlastimil Babka,
Serge E . Hallyn
In-Reply-To: <20210921061149.1091163-1-steve@sk2.org>
On Tue, 21 Sep 2021, Stephen Kitt wrote:
> This has served its purpose and is no longer used. All usercopy
> violations appear to have been handled by now, any remaining
> instances (or new bugs) will cause copies to be rejected.
>
> This isn't a direct revert of commit 2d891fbc3bb6 ("usercopy: Allow
> strict enforcement of whitelists"); since usercopy_fallback is
> effectively 0, the fallback handling is removed too.
>
> This also removes the usercopy_fallback module parameter on
> slab_common.
>
> Link: https://github.com/KSPP/linux/issues/153
> Signed-off-by: Stephen Kitt <steve@sk2.org>
> Suggested-by: Kees Cook <keescook@chromium.org>
Acked-by: David Rientjes <rientjes@google.com>
^ permalink raw reply
* Re: Add Apple M1 support to PASemi i2c driver
From: Christian Zigotzky @ 2021-09-26 20:27 UTC (permalink / raw)
To: sven
Cc: Darren Stevens, arnd, marcan, Linux Kernel Mailing List,
linux-i2c, Paul Mackerras, alyssa, R.T.Dickinson, Olof Johansson,
mohamed.mediouni, Matthew Leaman, mark.kettenis, linuxppc-dev,
R.T.Dickinson, linux-arm-kernel, stan
In-Reply-To: <6487d099-e0d6-4ea3-d312-6adbd94589f4@xenosoft.de>
Hi Sven,
I can't apply your patch 5 (i2c: pasemi: Split pci driver to its own
file). [1]
Error message:
patching file b/drivers/i2c/busses/i2c-pasemi-core.c (renamed from
a/drivers/i2c/busses/i2c-pasemi.c)
Hunk #3 FAILED at 344.
1 out of 3 hunks FAILED -- saving rejects to file
b/drivers/i2c/busses/i2c-pasemi-core.c.rej
patching file b/drivers/i2c/busses/i2c-pasemi-core.h
patching file b/drivers/i2c/busses/i2c-pasemi-pci.c
Please post one patch with all your modifications.
Thanks,
Christian
[1]
https://lists.ozlabs.org/pipermail/linuxppc-dev/2021-September/234636.html
On 26 September 2021 at 04:55 pm, Christian Zigotzky wrote:
> Hi Sven,
>
> Thanks a lot for your nice explanation of the history of the PASemi
> i2c driver.
>
> We are using Nemo boards with 64-bit dual-core PWRficient PA6T-1682M
> CPUs (A-EON AmigaOne X1000). [1]
>
> The RC2 of kernel 5.15 works without any problems on our Nemo boards. [2]
>
> Could you please post all your patches merged in one patch? It's
> easier for me to apply one patch.
>
> Thanks,
> Christian
>
> [1] https://en.wikipedia.org/wiki/AmigaOne_X1000
> [2] https://forum.hyperion-entertainment.com/viewtopic.php?p=54056#p54056
^ permalink raw reply
* Add Apple M1 support to PASemi i2c driver
From: Christian Zigotzky @ 2021-09-26 14:55 UTC (permalink / raw)
To: sven
Cc: Darren Stevens, arnd, marcan, Linux Kernel Mailing List,
linux-i2c, Paul Mackerras, alyssa, R.T.Dickinson, Olof Johansson,
mohamed.mediouni, Matthew Leaman, mark.kettenis, linuxppc-dev,
R.T.Dickinson, linux-arm-kernel, stan
Hi Sven,
Thanks a lot for your nice explanation of the history of the PASemi i2c
driver.
We are using Nemo boards with 64-bit dual-core PWRficient PA6T-1682M
CPUs (A-EON AmigaOne X1000). [1]
The RC2 of kernel 5.15 works without any problems on our Nemo boards. [2]
Could you please post all your patches merged in one patch? It's easier
for me to apply one patch.
Thanks,
Christian
[1] https://en.wikipedia.org/wiki/AmigaOne_X1000
[2] https://forum.hyperion-entertainment.com/viewtopic.php?p=54056#p54056
^ permalink raw reply
* [PATCH 01/10] dt-bindings: i2c: Add Apple I2C controller bindings
From: Sven Peter @ 2021-09-26 9:58 UTC (permalink / raw)
To: Michael Ellerman, Benjamin Herrenschmidt, Paul Mackerras,
Olof Johansson, Rob Herring
Cc: devicetree, Arnd Bergmann, Sven Peter, Hector Martin,
linux-kernel, linux-i2c, linux-arm-kernel, Mohamed Mediouni,
Stan Skowronek, linuxppc-dev, Alyssa Rosenzweig, Mark Kettenis
In-Reply-To: <20210926095847.38261-1-sven@svenpeter.dev>
The Apple I2C controller is based on the PASemi I2C controller.
It is present on Apple SoCs such as the M1.
Signed-off-by: Sven Peter <sven@svenpeter.dev>
---
.../devicetree/bindings/i2c/apple,i2c.yaml | 61 +++++++++++++++++++
MAINTAINERS | 1 +
2 files changed, 62 insertions(+)
create mode 100644 Documentation/devicetree/bindings/i2c/apple,i2c.yaml
diff --git a/Documentation/devicetree/bindings/i2c/apple,i2c.yaml b/Documentation/devicetree/bindings/i2c/apple,i2c.yaml
new file mode 100644
index 000000000000..22fc8483256f
--- /dev/null
+++ b/Documentation/devicetree/bindings/i2c/apple,i2c.yaml
@@ -0,0 +1,61 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: "http://devicetree.org/schemas/i2c/apple,i2c.yaml#"
+$schema: "http://devicetree.org/meta-schemas/core.yaml#"
+
+title: Apple/PASemi I2C controller
+
+maintainers:
+ - Sven Peter <sven@svenpeter.dev>
+
+description: |
+ Apple SoCs such as the M1 come with a I2C controller based on the one found
+ in machines with P. A. Semi's PWRficient processors.
+ The bus is used to communicate with e.g. USB PD chips or the speaker
+ amp.
+
+allOf:
+ - $ref: /schemas/i2c/i2c-controller.yaml#
+
+properties:
+ compatible:
+ enum:
+ - apple,t8103-i2c
+ - apple,i2c
+
+ reg:
+ maxItems: 1
+
+ clocks:
+ items:
+ - description: I2C bus reference clock
+
+ interrupts:
+ maxItems: 1
+
+ clock-frequency:
+ description: |
+ Desired I2C bus clock frequency in Hz. If not specified, 100 kHz will be
+ used. This frequency is generated by dividing the reference clock.
+ Allowed values are between ref_clk/(16*4) and ref_clk/(16*255).
+
+required:
+ - compatible
+ - reg
+ - clocks
+ - interrupts
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ i2c@35010000 {
+ compatible = "apple,t8103-i2c";
+ reg = <0x35010000 0x4000>;
+ interrupt-parent = <&aic>;
+ interrupts = <0 627 4>;
+ clocks = <&ref_clk>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
diff --git a/MAINTAINERS b/MAINTAINERS
index 329d3a0a9fdb..380a680db92f 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1734,6 +1734,7 @@ B: https://github.com/AsahiLinux/linux/issues
C: irc://irc.oftc.net/asahi-dev
T: git https://github.com/AsahiLinux/linux.git
F: Documentation/devicetree/bindings/arm/apple.yaml
+F: Documentation/devicetree/bindings/i2c/apple,i2c.yaml
F: Documentation/devicetree/bindings/interrupt-controller/apple,aic.yaml
F: Documentation/devicetree/bindings/pinctrl/apple,pinctrl.yaml
F: arch/arm64/boot/dts/apple/
--
2.25.1
^ permalink raw reply related
* [PATCH 07/10] i2c: pasemi: Allow to configure bus frequency
From: Sven Peter @ 2021-09-26 9:58 UTC (permalink / raw)
To: Michael Ellerman, Benjamin Herrenschmidt, Paul Mackerras,
Olof Johansson
Cc: Arnd Bergmann, Sven Peter, Hector Martin, linux-kernel, linux-i2c,
linux-arm-kernel, Mohamed Mediouni, Stan Skowronek, linuxppc-dev,
Alyssa Rosenzweig, Mark Kettenis
In-Reply-To: <20210926095847.38261-1-sven@svenpeter.dev>
Right now the bus frequency has always been hardcoded as
100 KHz with the specific reference clock used in the PASemi
PCI controllers. Make this configurable to prepare for the
platform driver.
Signed-off-by: Sven Peter <sven@svenpeter.dev>
---
drivers/i2c/busses/i2c-pasemi-core.c | 8 +++-----
drivers/i2c/busses/i2c-pasemi-core.h | 1 +
drivers/i2c/busses/i2c-pasemi-pci.c | 4 ++++
3 files changed, 8 insertions(+), 5 deletions(-)
diff --git a/drivers/i2c/busses/i2c-pasemi-core.c b/drivers/i2c/busses/i2c-pasemi-core.c
index 7c6715f5dbb8..a39e3258b162 100644
--- a/drivers/i2c/busses/i2c-pasemi-core.c
+++ b/drivers/i2c/busses/i2c-pasemi-core.c
@@ -39,9 +39,6 @@
#define CTL_MTR 0x00000200
#define CTL_CLK_M 0x000000ff
-#define CLK_100K_DIV 84
-#define CLK_400K_DIV 21
-
static inline void reg_write(struct pasemi_smbus *smbus, int reg, int val)
{
dev_dbg(smbus->dev, "smbus write reg %lx val %08x\n",
@@ -63,8 +60,9 @@ static inline int reg_read(struct pasemi_smbus *smbus, int reg)
static void pasemi_reset(struct pasemi_smbus *smbus)
{
- reg_write(smbus, REG_CTL, (CTL_MTR | CTL_MRR |
- (CLK_100K_DIV & CTL_CLK_M)));
+ u32 val = (CTL_MTR | CTL_MRR | (smbus->clk_div & CTL_CLK_M));
+
+ reg_write(smbus, REG_CTL, val);
}
static void pasemi_smb_clear(struct pasemi_smbus *smbus)
diff --git a/drivers/i2c/busses/i2c-pasemi-core.h b/drivers/i2c/busses/i2c-pasemi-core.h
index 7acc33de6ce1..30a7990825ef 100644
--- a/drivers/i2c/busses/i2c-pasemi-core.h
+++ b/drivers/i2c/busses/i2c-pasemi-core.h
@@ -14,6 +14,7 @@ struct pasemi_smbus {
void __iomem *ioaddr;
unsigned long base;
int size;
+ unsigned int clk_div;
};
int pasemi_i2c_common_probe(struct pasemi_smbus *smbus);
diff --git a/drivers/i2c/busses/i2c-pasemi-pci.c b/drivers/i2c/busses/i2c-pasemi-pci.c
index 9a19df31866b..7405e0b48514 100644
--- a/drivers/i2c/busses/i2c-pasemi-pci.c
+++ b/drivers/i2c/busses/i2c-pasemi-pci.c
@@ -17,6 +17,9 @@
#include "i2c-pasemi-core.h"
+#define CLK_100K_DIV 84
+#define CLK_400K_DIV 21
+
static struct pci_driver pasemi_smb_pci_driver;
static int pasemi_smb_pci_probe(struct pci_dev *dev,
@@ -35,6 +38,7 @@ static int pasemi_smb_pci_probe(struct pci_dev *dev,
smbus->dev = &dev->dev;
smbus->base = pci_resource_start(dev, 0);
smbus->size = pci_resource_len(dev, 0);
+ smbus->clk_div = CLK_100K_DIV;
if (!request_region(smbus->base, smbus->size,
pasemi_smb_pci_driver.name)) {
--
2.25.1
^ permalink raw reply related
* [PATCH 03/10] i2c: pasemi: Remove usage of pci_dev
From: Sven Peter @ 2021-09-26 9:58 UTC (permalink / raw)
To: Michael Ellerman, Benjamin Herrenschmidt, Paul Mackerras,
Olof Johansson
Cc: Arnd Bergmann, Sven Peter, Hector Martin, linux-kernel, linux-i2c,
linux-arm-kernel, Mohamed Mediouni, Stan Skowronek, linuxppc-dev,
Alyssa Rosenzweig, Mark Kettenis
In-Reply-To: <20210926095847.38261-1-sven@svenpeter.dev>
Prepare to create a platform driver by removing all usages of pci_dev we
can.
Signed-off-by: Sven Peter <sven@svenpeter.dev>
---
drivers/i2c/busses/i2c-pasemi.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/drivers/i2c/busses/i2c-pasemi.c b/drivers/i2c/busses/i2c-pasemi.c
index dd31d902a621..5a25c2e54b9e 100644
--- a/drivers/i2c/busses/i2c-pasemi.c
+++ b/drivers/i2c/busses/i2c-pasemi.c
@@ -18,7 +18,7 @@
static struct pci_driver pasemi_smb_driver;
struct pasemi_smbus {
- struct pci_dev *dev;
+ struct device *dev;
struct i2c_adapter adapter;
void __iomem *ioaddr;
unsigned long base;
@@ -52,7 +52,7 @@ struct pasemi_smbus {
static inline void reg_write(struct pasemi_smbus *smbus, int reg, int val)
{
- dev_dbg(&smbus->dev->dev, "smbus write reg %lx val %08x\n",
+ dev_dbg(smbus->dev, "smbus write reg %lx val %08x\n",
smbus->base + reg, val);
iowrite32(val, smbus->ioaddr + reg);
}
@@ -61,7 +61,7 @@ static inline int reg_read(struct pasemi_smbus *smbus, int reg)
{
int ret;
ret = ioread32(smbus->ioaddr + reg);
- dev_dbg(&smbus->dev->dev, "smbus read reg %lx val %08x\n",
+ dev_dbg(smbus->dev, "smbus read reg %lx val %08x\n",
smbus->base + reg, ret);
return ret;
}
@@ -94,7 +94,7 @@ static int pasemi_smb_waitready(struct pasemi_smbus *smbus)
return -ENXIO;
if (timeout < 0) {
- dev_warn(&smbus->dev->dev, "Timeout, status 0x%08x\n", status);
+ dev_warn(smbus->dev, "Timeout, status 0x%08x\n", status);
reg_write(smbus, REG_SMSTA, status);
return -ETIME;
}
@@ -342,7 +342,7 @@ static int pasemi_smb_probe(struct pci_dev *dev,
if (!smbus)
return -ENOMEM;
- smbus->dev = dev;
+ smbus->dev = &dev->dev;
smbus->base = pci_resource_start(dev, 0);
smbus->size = pci_resource_len(dev, 0);
@@ -366,7 +366,7 @@ static int pasemi_smb_probe(struct pci_dev *dev,
smbus->adapter.algo_data = smbus;
/* set up the sysfs linkage to our parent device */
- smbus->adapter.dev.parent = &dev->dev;
+ smbus->adapter.dev.parent = smbus->dev;
reg_write(smbus, REG_CTL, (CTL_MTR | CTL_MRR |
(CLK_100K_DIV & CTL_CLK_M)));
--
2.25.1
^ permalink raw reply related
* [PATCH 02/10] i2c: pasemi: Use io{read,write}32
From: Sven Peter @ 2021-09-26 9:58 UTC (permalink / raw)
To: Michael Ellerman, Benjamin Herrenschmidt, Paul Mackerras,
Olof Johansson
Cc: Arnd Bergmann, Sven Peter, Hector Martin, linux-kernel, linux-i2c,
linux-arm-kernel, Mohamed Mediouni, Stan Skowronek, linuxppc-dev,
Alyssa Rosenzweig, Mark Kettenis
In-Reply-To: <20210926095847.38261-1-sven@svenpeter.dev>
In preparation for splitting this driver up into a platform_driver
and a pci_driver, replace outl/inl usage with ioport_map and
ioread32/iowrite32.
Signed-off-by: Sven Peter <sven@svenpeter.dev>
---
drivers/i2c/busses/i2c-pasemi.c | 16 +++++++++++++---
1 file changed, 13 insertions(+), 3 deletions(-)
diff --git a/drivers/i2c/busses/i2c-pasemi.c b/drivers/i2c/busses/i2c-pasemi.c
index 20f2772c0e79..dd31d902a621 100644
--- a/drivers/i2c/busses/i2c-pasemi.c
+++ b/drivers/i2c/busses/i2c-pasemi.c
@@ -20,6 +20,7 @@ static struct pci_driver pasemi_smb_driver;
struct pasemi_smbus {
struct pci_dev *dev;
struct i2c_adapter adapter;
+ void __iomem *ioaddr;
unsigned long base;
int size;
};
@@ -53,13 +54,13 @@ static inline void reg_write(struct pasemi_smbus *smbus, int reg, int val)
{
dev_dbg(&smbus->dev->dev, "smbus write reg %lx val %08x\n",
smbus->base + reg, val);
- outl(val, smbus->base + reg);
+ iowrite32(val, smbus->ioaddr + reg);
}
static inline int reg_read(struct pasemi_smbus *smbus, int reg)
{
int ret;
- ret = inl(smbus->base + reg);
+ ret = ioread32(smbus->ioaddr + reg);
dev_dbg(&smbus->dev->dev, "smbus read reg %lx val %08x\n",
smbus->base + reg, ret);
return ret;
@@ -351,6 +352,12 @@ static int pasemi_smb_probe(struct pci_dev *dev,
goto out_kfree;
}
+ smbus->ioaddr = ioport_map(smbus->base, smbus->size);
+ if (!smbus->ioaddr) {
+ error = -EBUSY;
+ goto out_release_region;
+ }
+
smbus->adapter.owner = THIS_MODULE;
snprintf(smbus->adapter.name, sizeof(smbus->adapter.name),
"PA Semi SMBus adapter at 0x%lx", smbus->base);
@@ -366,12 +373,14 @@ static int pasemi_smb_probe(struct pci_dev *dev,
error = i2c_add_adapter(&smbus->adapter);
if (error)
- goto out_release_region;
+ goto out_ioport_unmap;
pci_set_drvdata(dev, smbus);
return 0;
+ out_ioport_unmap:
+ ioport_unmap(smbus->ioaddr);
out_release_region:
release_region(smbus->base, smbus->size);
out_kfree:
@@ -384,6 +393,7 @@ static void pasemi_smb_remove(struct pci_dev *dev)
struct pasemi_smbus *smbus = pci_get_drvdata(dev);
i2c_del_adapter(&smbus->adapter);
+ ioport_unmap(smbus->ioaddr);
release_region(smbus->base, smbus->size);
kfree(smbus);
}
--
2.25.1
^ permalink raw reply related
* [PATCH 04/10] i2c: pasemi: Split off common probing code
From: Sven Peter @ 2021-09-26 9:58 UTC (permalink / raw)
To: Michael Ellerman, Benjamin Herrenschmidt, Paul Mackerras,
Olof Johansson
Cc: Arnd Bergmann, Sven Peter, Hector Martin, linux-kernel, linux-i2c,
linux-arm-kernel, Mohamed Mediouni, Stan Skowronek, linuxppc-dev,
Alyssa Rosenzweig, Mark Kettenis
In-Reply-To: <20210926095847.38261-1-sven@svenpeter.dev>
Split off common probing code that will be used by both the PCI and the
platform device.
Signed-off-by: Sven Peter <sven@svenpeter.dev>
---
drivers/i2c/busses/i2c-pasemi.c | 39 +++++++++++++++++++++------------
1 file changed, 25 insertions(+), 14 deletions(-)
diff --git a/drivers/i2c/busses/i2c-pasemi.c b/drivers/i2c/busses/i2c-pasemi.c
index 5a25c2e54b9e..9d69ff63f674 100644
--- a/drivers/i2c/busses/i2c-pasemi.c
+++ b/drivers/i2c/busses/i2c-pasemi.c
@@ -329,6 +329,30 @@ static const struct i2c_algorithm smbus_algorithm = {
.functionality = pasemi_smb_func,
};
+static int pasemi_i2c_common_probe(struct pasemi_smbus *smbus)
+{
+ int error;
+
+ smbus->adapter.owner = THIS_MODULE;
+ snprintf(smbus->adapter.name, sizeof(smbus->adapter.name),
+ "PA Semi SMBus adapter at 0x%lx", smbus->base);
+ smbus->adapter.class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
+ smbus->adapter.algo = &smbus_algorithm;
+ smbus->adapter.algo_data = smbus;
+
+ /* set up the sysfs linkage to our parent device */
+ smbus->adapter.dev.parent = smbus->dev;
+
+ reg_write(smbus, REG_CTL, (CTL_MTR | CTL_MRR |
+ (CLK_100K_DIV & CTL_CLK_M)));
+
+ error = i2c_add_adapter(&smbus->adapter);
+ if (error)
+ return error;
+
+ return 0;
+}
+
static int pasemi_smb_probe(struct pci_dev *dev,
const struct pci_device_id *id)
{
@@ -358,20 +382,7 @@ static int pasemi_smb_probe(struct pci_dev *dev,
goto out_release_region;
}
- smbus->adapter.owner = THIS_MODULE;
- snprintf(smbus->adapter.name, sizeof(smbus->adapter.name),
- "PA Semi SMBus adapter at 0x%lx", smbus->base);
- smbus->adapter.class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
- smbus->adapter.algo = &smbus_algorithm;
- smbus->adapter.algo_data = smbus;
-
- /* set up the sysfs linkage to our parent device */
- smbus->adapter.dev.parent = smbus->dev;
-
- reg_write(smbus, REG_CTL, (CTL_MTR | CTL_MRR |
- (CLK_100K_DIV & CTL_CLK_M)));
-
- error = i2c_add_adapter(&smbus->adapter);
+ int error = pasemi_i2c_common_probe(smbus);
if (error)
goto out_ioport_unmap;
--
2.25.1
^ permalink raw reply related
* [PATCH 08/10] i2c: pasemi: Refactor _probe to use devm_*
From: Sven Peter @ 2021-09-26 9:58 UTC (permalink / raw)
To: Michael Ellerman, Benjamin Herrenschmidt, Paul Mackerras,
Olof Johansson
Cc: Arnd Bergmann, Sven Peter, Hector Martin, linux-kernel, linux-i2c,
linux-arm-kernel, Mohamed Mediouni, Stan Skowronek, linuxppc-dev,
Alyssa Rosenzweig, Mark Kettenis
In-Reply-To: <20210926095847.38261-1-sven@svenpeter.dev>
Using managed device resources means there's nothing left to be done in
pasemi_smb_pci_remove and also allows to remove base and size from
struct pasemi_smbus.
Signed-off-by: Sven Peter <sven@svenpeter.dev>
---
drivers/i2c/busses/i2c-pasemi-core.c | 10 +++----
drivers/i2c/busses/i2c-pasemi-core.h | 2 --
drivers/i2c/busses/i2c-pasemi-pci.c | 45 ++++++++--------------------
3 files changed, 16 insertions(+), 41 deletions(-)
diff --git a/drivers/i2c/busses/i2c-pasemi-core.c b/drivers/i2c/busses/i2c-pasemi-core.c
index a39e3258b162..0ec65263fd08 100644
--- a/drivers/i2c/busses/i2c-pasemi-core.c
+++ b/drivers/i2c/busses/i2c-pasemi-core.c
@@ -41,8 +41,7 @@
static inline void reg_write(struct pasemi_smbus *smbus, int reg, int val)
{
- dev_dbg(smbus->dev, "smbus write reg %lx val %08x\n",
- smbus->base + reg, val);
+ dev_dbg(smbus->dev, "smbus write reg %x val %08x\n", reg, val);
iowrite32(val, smbus->ioaddr + reg);
}
@@ -50,8 +49,7 @@ static inline int reg_read(struct pasemi_smbus *smbus, int reg)
{
int ret;
ret = ioread32(smbus->ioaddr + reg);
- dev_dbg(smbus->dev, "smbus read reg %lx val %08x\n",
- smbus->base + reg, ret);
+ dev_dbg(smbus->dev, "smbus read reg %x val %08x\n", reg, ret);
return ret;
}
@@ -329,7 +327,7 @@ int pasemi_i2c_common_probe(struct pasemi_smbus *smbus)
smbus->adapter.owner = THIS_MODULE;
snprintf(smbus->adapter.name, sizeof(smbus->adapter.name),
- "PA Semi SMBus adapter at 0x%lx", smbus->base);
+ "PA Semi SMBus adapter at 0x%p", smbus->ioaddr);
smbus->adapter.class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
smbus->adapter.algo = &smbus_algorithm;
smbus->adapter.algo_data = smbus;
@@ -339,7 +337,7 @@ int pasemi_i2c_common_probe(struct pasemi_smbus *smbus)
pasemi_reset(smbus);
- error = i2c_add_adapter(&smbus->adapter);
+ error = devm_i2c_add_adapter(smbus->dev, &smbus->adapter);
if (error)
return error;
diff --git a/drivers/i2c/busses/i2c-pasemi-core.h b/drivers/i2c/busses/i2c-pasemi-core.h
index 30a7990825ef..aca4e2da9089 100644
--- a/drivers/i2c/busses/i2c-pasemi-core.h
+++ b/drivers/i2c/busses/i2c-pasemi-core.h
@@ -12,8 +12,6 @@ struct pasemi_smbus {
struct device *dev;
struct i2c_adapter adapter;
void __iomem *ioaddr;
- unsigned long base;
- int size;
unsigned int clk_div;
};
diff --git a/drivers/i2c/busses/i2c-pasemi-pci.c b/drivers/i2c/busses/i2c-pasemi-pci.c
index 7405e0b48514..c1b8901110c0 100644
--- a/drivers/i2c/busses/i2c-pasemi-pci.c
+++ b/drivers/i2c/busses/i2c-pasemi-pci.c
@@ -26,57 +26,37 @@ static int pasemi_smb_pci_probe(struct pci_dev *dev,
const struct pci_device_id *id)
{
struct pasemi_smbus *smbus;
+ unsigned long base;
+ int size;
int error;
if (!(pci_resource_flags(dev, 0) & IORESOURCE_IO))
return -ENODEV;
- smbus = kzalloc(sizeof(struct pasemi_smbus), GFP_KERNEL);
+ smbus = devm_kzalloc(&dev->dev, sizeof(*smbus), GFP_KERNEL);
if (!smbus)
return -ENOMEM;
smbus->dev = &dev->dev;
- smbus->base = pci_resource_start(dev, 0);
- smbus->size = pci_resource_len(dev, 0);
+ base = pci_resource_start(dev, 0);
+ size = pci_resource_len(dev, 0);
smbus->clk_div = CLK_100K_DIV;
- if (!request_region(smbus->base, smbus->size,
- pasemi_smb_pci_driver.name)) {
- error = -EBUSY;
- goto out_kfree;
- }
+ if (!devm_request_region(&dev->dev, base, size,
+ pasemi_smb_pci_driver.name))
+ return -EBUSY;
- smbus->ioaddr = ioport_map(smbus->base, smbus->size);
- if (!smbus->ioaddr) {
- error = -EBUSY;
- goto out_release_region;
- }
+ smbus->ioaddr = devm_ioport_map(&dev->dev, base, size);
+ if (!smbus->ioaddr)
+ return -EBUSY;
error = pasemi_i2c_common_probe(smbus);
if (error)
- goto out_ioport_unmap;
+ return error;
pci_set_drvdata(dev, smbus);
return 0;
-
- out_ioport_unmap:
- ioport_unmap(smbus->ioaddr);
- out_release_region:
- release_region(smbus->base, smbus->size);
- out_kfree:
- kfree(smbus);
- return error;
-}
-
-static void pasemi_smb_pci_remove(struct pci_dev *dev)
-{
- struct pasemi_smbus *smbus = pci_get_drvdata(dev);
-
- i2c_del_adapter(&smbus->adapter);
- ioport_unmap(smbus->ioaddr);
- release_region(smbus->base, smbus->size);
- kfree(smbus);
}
static const struct pci_device_id pasemi_smb_pci_ids[] = {
@@ -90,7 +70,6 @@ static struct pci_driver pasemi_smb_pci_driver = {
.name = "i2c-pasemi",
.id_table = pasemi_smb_pci_ids,
.probe = pasemi_smb_pci_probe,
- .remove = pasemi_smb_pci_remove,
};
module_pci_driver(pasemi_smb_pci_driver);
--
2.25.1
^ permalink raw reply related
* [PATCH 09/10] i2c: pasemi: Add Apple platform driver
From: Sven Peter @ 2021-09-26 9:58 UTC (permalink / raw)
To: Michael Ellerman, Benjamin Herrenschmidt, Paul Mackerras,
Olof Johansson
Cc: Arnd Bergmann, Sven Peter, Hector Martin, linux-kernel, linux-i2c,
linux-arm-kernel, Mohamed Mediouni, Stan Skowronek, linuxppc-dev,
Alyssa Rosenzweig, Mark Kettenis
In-Reply-To: <20210926095847.38261-1-sven@svenpeter.dev>
With all the previous preparations we can now finally add
the platform driver to support the PASemi-based controllers
in Apple SoCs. This does not work on the M1 yet but should
work on the early iPhones already.
Signed-off-by: Sven Peter <sven@svenpeter.dev>
---
MAINTAINERS | 1 +
drivers/i2c/busses/Kconfig | 11 +++
drivers/i2c/busses/Makefile | 2 +
drivers/i2c/busses/i2c-pasemi-apple.c | 122 ++++++++++++++++++++++++++
4 files changed, 136 insertions(+)
create mode 100644 drivers/i2c/busses/i2c-pasemi-apple.c
diff --git a/MAINTAINERS b/MAINTAINERS
index 380a680db92f..6e952158b6e1 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1738,6 +1738,7 @@ F: Documentation/devicetree/bindings/i2c/apple,i2c.yaml
F: Documentation/devicetree/bindings/interrupt-controller/apple,aic.yaml
F: Documentation/devicetree/bindings/pinctrl/apple,pinctrl.yaml
F: arch/arm64/boot/dts/apple/
+F: drivers/i2c/busses/i2c-pasemi-apple.c
F: drivers/irqchip/irq-apple-aic.c
F: include/dt-bindings/interrupt-controller/apple-aic.h
F: include/dt-bindings/pinctrl/apple.h
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index e17790fe35a7..cf4dae07e319 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -856,6 +856,17 @@ config I2C_PASEMI
help
Supports the PA Semi PWRficient on-chip SMBus interfaces.
+config I2C_APPLE
+ tristate "Apple SMBus platform driver"
+ depends on ARCH_APPLE || COMPILE_TEST
+ default ARCH_APPLE
+ help
+ Say Y here if you want to use the I2C controller present on Apple
+ Silicon chips such as the M1.
+
+ This driver can also be built as a module. If so, the module
+ will be called i2c-apple.
+
config I2C_PCA_PLATFORM
tristate "PCA9564/PCA9665 as platform device"
select I2C_ALGOPCA
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index 0ab1b4cb2228..474fe2c520d0 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -86,6 +86,8 @@ obj-$(CONFIG_I2C_OMAP) += i2c-omap.o
obj-$(CONFIG_I2C_OWL) += i2c-owl.o
i2c-pasemi-objs := i2c-pasemi-core.o i2c-pasemi-pci.o
obj-$(CONFIG_I2C_PASEMI) += i2c-pasemi.o
+i2c-apple-objs := i2c-pasemi-core.o i2c-pasemi-apple.o
+obj-$(CONFIG_I2C_APPLE) += i2c-apple.o
obj-$(CONFIG_I2C_PCA_PLATFORM) += i2c-pca-platform.o
obj-$(CONFIG_I2C_PNX) += i2c-pnx.o
obj-$(CONFIG_I2C_PXA) += i2c-pxa.o
diff --git a/drivers/i2c/busses/i2c-pasemi-apple.c b/drivers/i2c/busses/i2c-pasemi-apple.c
new file mode 100644
index 000000000000..c87f8e516eff
--- /dev/null
+++ b/drivers/i2c/busses/i2c-pasemi-apple.c
@@ -0,0 +1,122 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2021 The Asahi Linux Contributors
+ *
+ * PA Semi PWRficient SMBus host driver for Apple SoCs
+ */
+
+#include <linux/clk.h>
+#include <linux/i2c.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/types.h>
+
+#include "i2c-pasemi-core.h"
+
+struct pasemi_apple_i2c_data {
+ struct pasemi_smbus smbus;
+ struct clk *clk_ref;
+ struct pinctrl *pctrl;
+};
+
+static int pasemi_apple_i2c_calc_clk_div(struct pasemi_apple_i2c_data *data,
+ u32 frequency)
+{
+ unsigned long clk_rate = clk_get_rate(data->clk_ref);
+
+ if (!clk_rate)
+ return -EINVAL;
+
+ data->smbus.clk_div = DIV_ROUND_UP(clk_rate, 16 * frequency);
+ if (data->smbus.clk_div < 4)
+ return dev_err_probe(data->smbus.dev, -EINVAL,
+ "Bus frequency %d is too fast.\n",
+ frequency);
+ if (data->smbus.clk_div > 0xff)
+ return dev_err_probe(data->smbus.dev, -EINVAL,
+ "Bus frequency %d is too slow.\n",
+ frequency);
+
+ return 0;
+}
+
+static int pasemi_apple_i2c_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct pasemi_apple_i2c_data *data;
+ struct pasemi_smbus *smbus;
+ u32 frequency;
+ int error;
+
+ data = devm_kzalloc(dev, sizeof(struct pasemi_apple_i2c_data),
+ GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ smbus = &data->smbus;
+ smbus->dev = dev;
+
+ smbus->ioaddr = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(smbus->ioaddr))
+ return PTR_ERR(smbus->ioaddr);
+
+ if (of_property_read_u32(dev->of_node, "clock-frequency", &frequency))
+ frequency = I2C_MAX_STANDARD_MODE_FREQ;
+
+ data->clk_ref = devm_clk_get(dev, NULL);
+ if (IS_ERR(data->clk_ref))
+ return PTR_ERR(data->clk_ref);
+
+ error = clk_prepare_enable(data->clk_ref);
+ if (error)
+ return error;
+
+ error = pasemi_apple_i2c_calc_clk_div(data, frequency);
+ if (error)
+ goto out_clk_disable;
+
+ smbus->adapter.dev.of_node = pdev->dev.of_node;
+ error = pasemi_i2c_common_probe(smbus);
+ if (error)
+ goto out_clk_disable;
+
+ platform_set_drvdata(pdev, data);
+
+ return 0;
+
+out_clk_disable:
+ clk_disable_unprepare(data->clk_ref);
+
+ return error;
+}
+
+static int pasemi_apple_i2c_remove(struct platform_device *pdev)
+{
+ struct pasemi_apple_i2c_data *data = platform_get_drvdata(pdev);
+
+ clk_disable_unprepare(data->clk_ref);
+ return 0;
+}
+
+static const struct of_device_id pasemi_apple_i2c_of_match[] = {
+ { .compatible = "apple,t8103-i2c" },
+ { .compatible = "apple,i2c" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, pasemi_apple_i2c_of_match);
+
+static struct platform_driver pasemi_apple_i2c_driver = {
+ .driver = {
+ .name = "i2c-apple",
+ .of_match_table = pasemi_apple_i2c_of_match,
+ },
+ .probe = pasemi_apple_i2c_probe,
+ .remove = pasemi_apple_i2c_remove,
+};
+module_platform_driver(pasemi_apple_i2c_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Sven Peter <sven@svenpeter.dev>");
+MODULE_DESCRIPTION("Apple/PASemi SMBus platform driver");
--
2.25.1
^ permalink raw reply related
* [PATCH 05/10] i2c: pasemi: Split pci driver to its own file
From: Sven Peter @ 2021-09-26 9:58 UTC (permalink / raw)
To: Michael Ellerman, Benjamin Herrenschmidt, Paul Mackerras,
Olof Johansson
Cc: Arnd Bergmann, Sven Peter, Hector Martin, linux-kernel, linux-i2c,
linux-arm-kernel, Mohamed Mediouni, Stan Skowronek, linuxppc-dev,
Alyssa Rosenzweig, Mark Kettenis
In-Reply-To: <20210926095847.38261-1-sven@svenpeter.dev>
Split off the PCI driver so that we can reuse common code for the
platform driver.
Signed-off-by: Sven Peter <sven@svenpeter.dev>
---
drivers/i2c/busses/Makefile | 1 +
.../{i2c-pasemi.c => i2c-pasemi-core.c} | 88 +----------------
drivers/i2c/busses/i2c-pasemi-core.h | 19 ++++
drivers/i2c/busses/i2c-pasemi-pci.c | 96 +++++++++++++++++++
4 files changed, 118 insertions(+), 86 deletions(-)
rename drivers/i2c/busses/{i2c-pasemi.c => i2c-pasemi-core.c} (81%)
create mode 100644 drivers/i2c/busses/i2c-pasemi-core.h
create mode 100644 drivers/i2c/busses/i2c-pasemi-pci.c
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index 1336b04f40e2..0ab1b4cb2228 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -84,6 +84,7 @@ obj-$(CONFIG_I2C_NPCM7XX) += i2c-npcm7xx.o
obj-$(CONFIG_I2C_OCORES) += i2c-ocores.o
obj-$(CONFIG_I2C_OMAP) += i2c-omap.o
obj-$(CONFIG_I2C_OWL) += i2c-owl.o
+i2c-pasemi-objs := i2c-pasemi-core.o i2c-pasemi-pci.o
obj-$(CONFIG_I2C_PASEMI) += i2c-pasemi.o
obj-$(CONFIG_I2C_PCA_PLATFORM) += i2c-pca-platform.o
obj-$(CONFIG_I2C_PNX) += i2c-pnx.o
diff --git a/drivers/i2c/busses/i2c-pasemi.c b/drivers/i2c/busses/i2c-pasemi-core.c
similarity index 81%
rename from drivers/i2c/busses/i2c-pasemi.c
rename to drivers/i2c/busses/i2c-pasemi-core.c
index 9d69ff63f674..3eda5e375fa2 100644
--- a/drivers/i2c/busses/i2c-pasemi.c
+++ b/drivers/i2c/busses/i2c-pasemi-core.c
@@ -15,15 +15,7 @@
#include <linux/slab.h>
#include <linux/io.h>
-static struct pci_driver pasemi_smb_driver;
-
-struct pasemi_smbus {
- struct device *dev;
- struct i2c_adapter adapter;
- void __iomem *ioaddr;
- unsigned long base;
- int size;
-};
+#include "i2c-pasemi-core.h"
/* Register offsets */
#define REG_MTXFIFO 0x00
@@ -329,7 +321,7 @@ static const struct i2c_algorithm smbus_algorithm = {
.functionality = pasemi_smb_func,
};
-static int pasemi_i2c_common_probe(struct pasemi_smbus *smbus)
+int pasemi_i2c_common_probe(struct pasemi_smbus *smbus)
{
int error;
@@ -352,79 +344,3 @@ static int pasemi_i2c_common_probe(struct pasemi_smbus *smbus)
return 0;
}
-
-static int pasemi_smb_probe(struct pci_dev *dev,
- const struct pci_device_id *id)
-{
- struct pasemi_smbus *smbus;
- int error;
-
- if (!(pci_resource_flags(dev, 0) & IORESOURCE_IO))
- return -ENODEV;
-
- smbus = kzalloc(sizeof(struct pasemi_smbus), GFP_KERNEL);
- if (!smbus)
- return -ENOMEM;
-
- smbus->dev = &dev->dev;
- smbus->base = pci_resource_start(dev, 0);
- smbus->size = pci_resource_len(dev, 0);
-
- if (!request_region(smbus->base, smbus->size,
- pasemi_smb_driver.name)) {
- error = -EBUSY;
- goto out_kfree;
- }
-
- smbus->ioaddr = ioport_map(smbus->base, smbus->size);
- if (!smbus->ioaddr) {
- error = -EBUSY;
- goto out_release_region;
- }
-
- int error = pasemi_i2c_common_probe(smbus);
- if (error)
- goto out_ioport_unmap;
-
- pci_set_drvdata(dev, smbus);
-
- return 0;
-
- out_ioport_unmap:
- ioport_unmap(smbus->ioaddr);
- out_release_region:
- release_region(smbus->base, smbus->size);
- out_kfree:
- kfree(smbus);
- return error;
-}
-
-static void pasemi_smb_remove(struct pci_dev *dev)
-{
- struct pasemi_smbus *smbus = pci_get_drvdata(dev);
-
- i2c_del_adapter(&smbus->adapter);
- ioport_unmap(smbus->ioaddr);
- release_region(smbus->base, smbus->size);
- kfree(smbus);
-}
-
-static const struct pci_device_id pasemi_smb_ids[] = {
- { PCI_DEVICE(0x1959, 0xa003) },
- { 0, }
-};
-
-MODULE_DEVICE_TABLE(pci, pasemi_smb_ids);
-
-static struct pci_driver pasemi_smb_driver = {
- .name = "i2c-pasemi",
- .id_table = pasemi_smb_ids,
- .probe = pasemi_smb_probe,
- .remove = pasemi_smb_remove,
-};
-
-module_pci_driver(pasemi_smb_driver);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR ("Olof Johansson <olof@lixom.net>");
-MODULE_DESCRIPTION("PA Semi PWRficient SMBus driver");
diff --git a/drivers/i2c/busses/i2c-pasemi-core.h b/drivers/i2c/busses/i2c-pasemi-core.h
new file mode 100644
index 000000000000..7acc33de6ce1
--- /dev/null
+++ b/drivers/i2c/busses/i2c-pasemi-core.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#include <linux/atomic.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/i2c.h>
+#include <linux/i2c-smbus.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+
+struct pasemi_smbus {
+ struct device *dev;
+ struct i2c_adapter adapter;
+ void __iomem *ioaddr;
+ unsigned long base;
+ int size;
+};
+
+int pasemi_i2c_common_probe(struct pasemi_smbus *smbus);
diff --git a/drivers/i2c/busses/i2c-pasemi-pci.c b/drivers/i2c/busses/i2c-pasemi-pci.c
new file mode 100644
index 000000000000..9a19df31866b
--- /dev/null
+++ b/drivers/i2c/busses/i2c-pasemi-pci.c
@@ -0,0 +1,96 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2006-2007 PA Semi, Inc
+ *
+ * SMBus host driver for PA Semi PWRficient
+ */
+
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/stddef.h>
+#include <linux/sched.h>
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+
+#include "i2c-pasemi-core.h"
+
+static struct pci_driver pasemi_smb_pci_driver;
+
+static int pasemi_smb_pci_probe(struct pci_dev *dev,
+ const struct pci_device_id *id)
+{
+ struct pasemi_smbus *smbus;
+ int error;
+
+ if (!(pci_resource_flags(dev, 0) & IORESOURCE_IO))
+ return -ENODEV;
+
+ smbus = kzalloc(sizeof(struct pasemi_smbus), GFP_KERNEL);
+ if (!smbus)
+ return -ENOMEM;
+
+ smbus->dev = &dev->dev;
+ smbus->base = pci_resource_start(dev, 0);
+ smbus->size = pci_resource_len(dev, 0);
+
+ if (!request_region(smbus->base, smbus->size,
+ pasemi_smb_pci_driver.name)) {
+ error = -EBUSY;
+ goto out_kfree;
+ }
+
+ smbus->ioaddr = ioport_map(smbus->base, smbus->size);
+ if (!smbus->ioaddr) {
+ error = -EBUSY;
+ goto out_release_region;
+ }
+
+ error = pasemi_i2c_common_probe(smbus);
+ if (error)
+ goto out_ioport_unmap;
+
+ pci_set_drvdata(dev, smbus);
+
+ return 0;
+
+ out_ioport_unmap:
+ ioport_unmap(smbus->ioaddr);
+ out_release_region:
+ release_region(smbus->base, smbus->size);
+ out_kfree:
+ kfree(smbus);
+ return error;
+}
+
+static void pasemi_smb_pci_remove(struct pci_dev *dev)
+{
+ struct pasemi_smbus *smbus = pci_get_drvdata(dev);
+
+ i2c_del_adapter(&smbus->adapter);
+ ioport_unmap(smbus->ioaddr);
+ release_region(smbus->base, smbus->size);
+ kfree(smbus);
+}
+
+static const struct pci_device_id pasemi_smb_pci_ids[] = {
+ { PCI_DEVICE(0x1959, 0xa003) },
+ { 0, }
+};
+
+MODULE_DEVICE_TABLE(pci, pasemi_smb_pci_ids);
+
+static struct pci_driver pasemi_smb_pci_driver = {
+ .name = "i2c-pasemi",
+ .id_table = pasemi_smb_pci_ids,
+ .probe = pasemi_smb_pci_probe,
+ .remove = pasemi_smb_pci_remove,
+};
+
+module_pci_driver(pasemi_smb_pci_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Olof Johansson <olof@lixom.net>");
+MODULE_DESCRIPTION("PA Semi PWRficient SMBus driver");
--
2.25.1
^ permalink raw reply related
* [PATCH 10/10] i2c: pasemi: Set enable bit for Apple variant
From: Sven Peter @ 2021-09-26 9:58 UTC (permalink / raw)
To: Michael Ellerman, Benjamin Herrenschmidt, Paul Mackerras,
Olof Johansson
Cc: Arnd Bergmann, Sven Peter, Hector Martin, linux-kernel, linux-i2c,
linux-arm-kernel, Mohamed Mediouni, Stan Skowronek, linuxppc-dev,
Alyssa Rosenzweig, Mark Kettenis
In-Reply-To: <20210926095847.38261-1-sven@svenpeter.dev>
Some later revisions after the original PASemi I2C controller introduce
what likely is an enable bit to the CTL register. Without setting it the
actual i2c transmission is never started.
Signed-off-by: Sven Peter <sven@svenpeter.dev>
---
drivers/i2c/busses/i2c-pasemi-core.c | 8 ++++++++
drivers/i2c/busses/i2c-pasemi-core.h | 3 +++
drivers/i2c/busses/i2c-pasemi-pci.c | 6 ++++++
3 files changed, 17 insertions(+)
diff --git a/drivers/i2c/busses/i2c-pasemi-core.c b/drivers/i2c/busses/i2c-pasemi-core.c
index 0ec65263fd08..b52a65beda99 100644
--- a/drivers/i2c/busses/i2c-pasemi-core.c
+++ b/drivers/i2c/busses/i2c-pasemi-core.c
@@ -22,6 +22,7 @@
#define REG_MRXFIFO 0x04
#define REG_SMSTA 0x14
#define REG_CTL 0x1c
+#define REG_REV 0x28
/* Register defs */
#define MTXFIFO_READ 0x00000400
@@ -37,6 +38,7 @@
#define CTL_MRR 0x00000400
#define CTL_MTR 0x00000200
+#define CTL_EN 0x00000800
#define CTL_CLK_M 0x000000ff
static inline void reg_write(struct pasemi_smbus *smbus, int reg, int val)
@@ -60,6 +62,9 @@ static void pasemi_reset(struct pasemi_smbus *smbus)
{
u32 val = (CTL_MTR | CTL_MRR | (smbus->clk_div & CTL_CLK_M));
+ if (smbus->hw_rev >= 6)
+ val |= CTL_EN;
+
reg_write(smbus, REG_CTL, val);
}
@@ -335,6 +340,9 @@ int pasemi_i2c_common_probe(struct pasemi_smbus *smbus)
/* set up the sysfs linkage to our parent device */
smbus->adapter.dev.parent = smbus->dev;
+ if (smbus->hw_rev != PASEMI_HW_REV_PCI)
+ smbus->hw_rev = reg_read(smbus, REG_REV);
+
pasemi_reset(smbus);
error = devm_i2c_add_adapter(smbus->dev, &smbus->adapter);
diff --git a/drivers/i2c/busses/i2c-pasemi-core.h b/drivers/i2c/busses/i2c-pasemi-core.h
index aca4e2da9089..4655124a37f3 100644
--- a/drivers/i2c/busses/i2c-pasemi-core.h
+++ b/drivers/i2c/busses/i2c-pasemi-core.h
@@ -8,11 +8,14 @@
#include <linux/io.h>
#include <linux/kernel.h>
+#define PASEMI_HW_REV_PCI -1
+
struct pasemi_smbus {
struct device *dev;
struct i2c_adapter adapter;
void __iomem *ioaddr;
unsigned int clk_div;
+ int hw_rev;
};
int pasemi_i2c_common_probe(struct pasemi_smbus *smbus);
diff --git a/drivers/i2c/busses/i2c-pasemi-pci.c b/drivers/i2c/busses/i2c-pasemi-pci.c
index c1b8901110c0..2b7be35421bc 100644
--- a/drivers/i2c/busses/i2c-pasemi-pci.c
+++ b/drivers/i2c/busses/i2c-pasemi-pci.c
@@ -42,6 +42,12 @@ static int pasemi_smb_pci_probe(struct pci_dev *dev,
size = pci_resource_len(dev, 0);
smbus->clk_div = CLK_100K_DIV;
+ /*
+ * The original PASemi PCI controllers don't have a register for
+ * their HW revision.
+ */
+ smbus->hw_rev = PASEMI_HW_REV_PCI;
+
if (!devm_request_region(&dev->dev, base, size,
pasemi_smb_pci_driver.name))
return -EBUSY;
--
2.25.1
^ permalink raw reply related
* [PATCH 06/10] i2c: pasemi: Move common reset code to own function
From: Sven Peter @ 2021-09-26 9:58 UTC (permalink / raw)
To: Michael Ellerman, Benjamin Herrenschmidt, Paul Mackerras,
Olof Johansson
Cc: Arnd Bergmann, Sven Peter, Hector Martin, linux-kernel, linux-i2c,
linux-arm-kernel, Mohamed Mediouni, Stan Skowronek, linuxppc-dev,
Alyssa Rosenzweig, Mark Kettenis
In-Reply-To: <20210926095847.38261-1-sven@svenpeter.dev>
Split out common reset call to its own function so that we
can later add support for selecting the clock frequency
and an additional enable bit found in newer revisions.
Signed-off-by: Sven Peter <sven@svenpeter.dev>
---
drivers/i2c/busses/i2c-pasemi-core.c | 15 +++++++++------
1 file changed, 9 insertions(+), 6 deletions(-)
diff --git a/drivers/i2c/busses/i2c-pasemi-core.c b/drivers/i2c/busses/i2c-pasemi-core.c
index 3eda5e375fa2..7c6715f5dbb8 100644
--- a/drivers/i2c/busses/i2c-pasemi-core.c
+++ b/drivers/i2c/busses/i2c-pasemi-core.c
@@ -61,6 +61,12 @@ static inline int reg_read(struct pasemi_smbus *smbus, int reg)
#define TXFIFO_WR(smbus, reg) reg_write((smbus), REG_MTXFIFO, (reg))
#define RXFIFO_RD(smbus) reg_read((smbus), REG_MRXFIFO)
+static void pasemi_reset(struct pasemi_smbus *smbus)
+{
+ reg_write(smbus, REG_CTL, (CTL_MTR | CTL_MRR |
+ (CLK_100K_DIV & CTL_CLK_M)));
+}
+
static void pasemi_smb_clear(struct pasemi_smbus *smbus)
{
unsigned int status;
@@ -135,8 +141,7 @@ static int pasemi_i2c_xfer_msg(struct i2c_adapter *adapter,
return 0;
reset_out:
- reg_write(smbus, REG_CTL, (CTL_MTR | CTL_MRR |
- (CLK_100K_DIV & CTL_CLK_M)));
+ pasemi_reset(smbus);
return err;
}
@@ -302,8 +307,7 @@ static int pasemi_smb_xfer(struct i2c_adapter *adapter,
return 0;
reset_out:
- reg_write(smbus, REG_CTL, (CTL_MTR | CTL_MRR |
- (CLK_100K_DIV & CTL_CLK_M)));
+ pasemi_reset(smbus);
return err;
}
@@ -335,8 +339,7 @@ int pasemi_i2c_common_probe(struct pasemi_smbus *smbus)
/* set up the sysfs linkage to our parent device */
smbus->adapter.dev.parent = smbus->dev;
- reg_write(smbus, REG_CTL, (CTL_MTR | CTL_MRR |
- (CLK_100K_DIV & CTL_CLK_M)));
+ pasemi_reset(smbus);
error = i2c_add_adapter(&smbus->adapter);
if (error)
--
2.25.1
^ permalink raw reply related
* [PATCH 00/10] Add Apple M1 support to PASemi i2c driver
From: Sven Peter @ 2021-09-26 9:58 UTC (permalink / raw)
To: Michael Ellerman, Benjamin Herrenschmidt, Paul Mackerras,
Olof Johansson
Cc: Arnd Bergmann, Sven Peter, Hector Martin, linux-kernel, linux-i2c,
linux-arm-kernel, Mohamed Mediouni, Stan Skowronek, linuxppc-dev,
Alyssa Rosenzweig, Mark Kettenis
Hi,
This series adds support for the I2C controller found on Apple Silicon Macs
which has quite a bit of history:
Apple bought P.A. Semi in 2008 and it looks like a part of its legacy continues
to live on in the M1. This controller has actually been used since at least the
iPhone 4S and hasn't changed much since then.
Essentially, there are only a few differences that matter:
- The controller no longer is a PCI device
- Starting at some iPhone an additional bit in one register
must be set in order to start transmissions.
- The reference clock and hence the clock dividers are different
In order to add support for a platform device I first replaced PCI-specific
bits and split out the PCI driver to its own file. Then I added support
to make the clock divider configurable and converted the driver to use
managed device resources to make it a bit simpler.
The Apple and PASemi driver will never be compiled in the same kernel
since the Apple one will run on arm64 while the original PASemi driver
will only be useful on powerpc.
I've thus followed the octeon (mips)/thunderx(arm64) approach to do the
split: I created a -core.c file which contains the shared logic and just
compile that one for both the PASemi and the new Apple driver.
Now unfortunately I don't have access to any old PASemi hardware and
cannot confirm that my changes haven't broken anything for those.
I believe Hector was in contact with Olof a few months ago who
said that he might still have an old machine on which he could
test this.
I'd very much appreciate if he (or anyone else for that matter :-))
could give this series a quick test on the old PASemi machines.
Best,
Sven
Sven Peter (10):
dt-bindings: i2c: Add Apple I2C controller bindings
i2c: pasemi: Use io{read,write}32
i2c: pasemi: Remove usage of pci_dev
i2c: pasemi: Split off common probing code
i2c: pasemi: Split pci driver to its own file
i2c: pasemi: Move common reset code to own function
i2c: pasemi: Allow to configure bus frequency
i2c: pasemi: Refactor _probe to use devm_*
i2c: pasemi: Add Apple platform driver
i2c: pasemi: Set enable bit for Apple variant
.../devicetree/bindings/i2c/apple,i2c.yaml | 61 +++++++++
MAINTAINERS | 2 +
drivers/i2c/busses/Kconfig | 11 ++
drivers/i2c/busses/Makefile | 3 +
drivers/i2c/busses/i2c-pasemi-apple.c | 122 ++++++++++++++++++
.../{i2c-pasemi.c => i2c-pasemi-core.c} | 114 +++++-----------
drivers/i2c/busses/i2c-pasemi-core.h | 21 +++
drivers/i2c/busses/i2c-pasemi-pci.c | 85 ++++++++++++
8 files changed, 334 insertions(+), 85 deletions(-)
create mode 100644 Documentation/devicetree/bindings/i2c/apple,i2c.yaml
create mode 100644 drivers/i2c/busses/i2c-pasemi-apple.c
rename drivers/i2c/busses/{i2c-pasemi.c => i2c-pasemi-core.c} (77%)
create mode 100644 drivers/i2c/busses/i2c-pasemi-core.h
create mode 100644 drivers/i2c/busses/i2c-pasemi-pci.c
--
2.25.1
^ permalink raw reply
* Re: [PATCH] powerpc:85xx: fix timebase sync issue when CONFIG_HOTPLUG_CPU=n
From: Xiaoming Ni @ 2021-09-26 12:34 UTC (permalink / raw)
To: linux-kernel, oss, mpe, benh, paulus, paul.gortmaker,
Yuantian.Tang, chenhui.zhao, linuxppc-dev
Cc: wangle6, wangxiongfeng2
In-Reply-To: <20210926025144.55674-1-nixiaoming@huawei.com>
On 2021/9/26 10:51, Xiaoming Ni wrote:
> When CONFIG_SMP=y, timebase synchronization is required when the second
> kernel is started.
> arch/powerpc/kernel/smp.c:
> int __cpu_up(unsigned int cpu, struct task_struct *tidle)
> {
> ...
> if (smp_ops->give_timebase)
> smp_ops->give_timebase();
> ...
> }
>
> void start_secondary(void *unused)
> {
> ...
> if (smp_ops->take_timebase)
> smp_ops->take_timebase();
> ...
> }
>
> When CONFIG_HOTPLUG_CPU=n and CONFIG_KEXEC_CORE=n,
> smp_85xx_ops.give_timebase is NULL,
> smp_85xx_ops.take_timebase is NULL,
> As a result, the timebase is not synchronized.
>
> Timebase synchronization does not depend on CONFIG_HOTPLUG_CPU.
>
> Fixes: 56f1ba280719 ("powerpc/mpc85xx: refactor the PM operations")
> Cc: stable@vger.kernel.org #v4.6
> Signed-off-by: Xiaoming Ni <nixiaoming@huawei.com>
> ---
> arch/powerpc/platforms/85xx/Makefile | 2 +-
> arch/powerpc/platforms/85xx/mpc85xx_pm_ops.c | 4 ++++
> arch/powerpc/platforms/85xx/smp.c | 9 ++++-----
> 3 files changed, 9 insertions(+), 6 deletions(-)
>
> diff --git a/arch/powerpc/platforms/85xx/Makefile b/arch/powerpc/platforms/85xx/Makefile
> index 60e4e97a929d..71ce1f6b6966 100644
> --- a/arch/powerpc/platforms/85xx/Makefile
> +++ b/arch/powerpc/platforms/85xx/Makefile
> @@ -3,7 +3,7 @@
> # Makefile for the PowerPC 85xx linux kernel.
> #
> obj-$(CONFIG_SMP) += smp.o
> -obj-$(CONFIG_FSL_PMC) += mpc85xx_pm_ops.o
> +obj-$(CONFIG_SMP) += mpc85xx_pm_ops.o
>
> obj-y += common.o
>
> diff --git a/arch/powerpc/platforms/85xx/mpc85xx_pm_ops.c b/arch/powerpc/platforms/85xx/mpc85xx_pm_ops.c
> index 7c0133f558d0..a5656b3e9701 100644
> --- a/arch/powerpc/platforms/85xx/mpc85xx_pm_ops.c
> +++ b/arch/powerpc/platforms/85xx/mpc85xx_pm_ops.c
> @@ -17,6 +17,7 @@
>
> static struct ccsr_guts __iomem *guts;
>
> +#ifdef CONFIG_FSL_PMC
> static void mpc85xx_irq_mask(int cpu)
> {
>
> @@ -49,6 +50,7 @@ static void mpc85xx_cpu_up_prepare(int cpu)
> {
>
> }
> +#endif
>
> static void mpc85xx_freeze_time_base(bool freeze)
> {
> @@ -76,10 +78,12 @@ static const struct of_device_id mpc85xx_smp_guts_ids[] = {
>
> static const struct fsl_pm_ops mpc85xx_pm_ops = {
> .freeze_time_base = mpc85xx_freeze_time_base,
> +#ifdef CONFIG_FSL_PMC
> .irq_mask = mpc85xx_irq_mask,
> .irq_unmask = mpc85xx_irq_unmask,
> .cpu_die = mpc85xx_cpu_die,
> .cpu_up_prepare = mpc85xx_cpu_up_prepare,
> +#endif
> };
>
> int __init mpc85xx_setup_pmc(void)
> diff --git a/arch/powerpc/platforms/85xx/smp.c b/arch/powerpc/platforms/85xx/smp.c
> index c6df294054fe..349298cd9671 100644
> --- a/arch/powerpc/platforms/85xx/smp.c
> +++ b/arch/powerpc/platforms/85xx/smp.c
> @@ -40,7 +40,6 @@ struct epapr_spin_table {
> u32 pir;
> };
>
> -#ifdef CONFIG_HOTPLUG_CPU
> static u64 timebase;
> static int tb_req;
> static int tb_valid;
> @@ -112,6 +111,7 @@ static void mpc85xx_take_timebase(void)
> local_irq_restore(flags);
> }
>
> +#ifdef CONFIG_HOTPLUG_CPU
> static void smp_85xx_cpu_offline_self(void)
> {
> unsigned int cpu = smp_processor_id();
> @@ -499,17 +499,16 @@ void __init mpc85xx_smp_init(void)
> #ifdef CONFIG_FSL_CORENET_RCPM
> fsl_rcpm_init();
> #endif
> -
> -#ifdef CONFIG_FSL_PMC
> - mpc85xx_setup_pmc();
> #endif
> + mpc85xx_setup_pmc();
> if (qoriq_pm_ops) {
> smp_85xx_ops.give_timebase = mpc85xx_give_timebase;
> smp_85xx_ops.take_timebase = mpc85xx_take_timebase;
> +#ifdef CONFIG_HOTPLUG_CPU
> smp_85xx_ops.cpu_offline_self = smp_85xx_cpu_offline_self;
> smp_85xx_ops.cpu_die = qoriq_cpu_kill;
> - }
> #endif
> + }
> smp_ops = &smp_85xx_ops;
>
> #ifdef CONFIG_KEXEC_CORE
>
I found inconsistent time values on different CPUs on my mpc8572 and
used this patch to fix it.
But today I found out in ppc64 testing that this patch causes the system
to trigger oops in the function mpc85xx_freeze_time_base(): the variable
"guts" is a null pointer.
I'm sorry to bother you.
I'll fix it and resend v2 later,
Thanks
Xiaoming Ni
^ permalink raw reply
* [PATCH] ASoC: fsl_spdif: implement bypass mode from in to out
From: Shengjiu Wang @ 2021-09-26 9:49 UTC (permalink / raw)
To: timur, nicoleotsuka, Xiubo.Lee, festevam, broonie, perex, tiwai,
alsa-devel
Cc: linuxppc-dev, linux-kernel
From: Viorel Suman <viorel.suman@nxp.com>
Implement SPDIF bypass mode. It implies internal SoC
routing of SPDIF input signal to SPDIF output signal. The
test bed requires two boards: B1 configured in bypass mode,
and B2 to feed B1 SPDIF RX port and read B1 SPDIF TX port:
B2 TX -> B1 RX,
B2 RX <- B1 TX.
The test procedure:
a) Boot both boards
b) B2: start "arecord <spdifcard> -r 48kHz | aplay <local DAC>"
c) B2: start "aplay <spdifcard> -r 48kHz <2ch 48kHz audio file>"
d) B1: enable bypass mode:
amixer -cimxspdif cset numid=8,iface=PCM,name='Bypass Mode' on
e) B2: check DAC audio, make sure the same sample rate is used at
steps b) and c), in example above the rate is 48kHz.
f) B1: try to run "aplay" or "arecord" on imxspdif card while in
bypass mode - both must fail until bypass mode is disabled
g) B1: disable bypass mode:
amixer -cimxspdif cset numid=8,iface=PCM,name='Bypass Mode' off
h) B1: check the usual playback and capture on imxspdif card.
During this test try to set bypass mode - must not be allowed
while playback or capture is running.
Signed-off-by: Viorel Suman <viorel.suman@nxp.com>
Signed-off-by: Shengjiu Wang <shengjiu.wang@nxp.com>
---
sound/soc/fsl/fsl_spdif.c | 74 +++++++++++++++++++++++++++++++++++++++
1 file changed, 74 insertions(+)
diff --git a/sound/soc/fsl/fsl_spdif.c b/sound/soc/fsl/fsl_spdif.c
index 928b59069283..d178b479c8bd 100644
--- a/sound/soc/fsl/fsl_spdif.c
+++ b/sound/soc/fsl/fsl_spdif.c
@@ -111,6 +111,7 @@ struct spdif_mixer_control {
* @dma_params_tx: DMA parameters for transmit channel
* @dma_params_rx: DMA parameters for receive channel
* @regcache_srpc: regcache for SRPC
+ * @bypass: status of bypass input to output
*/
struct fsl_spdif_priv {
const struct fsl_spdif_soc_data *soc;
@@ -133,6 +134,7 @@ struct fsl_spdif_priv {
struct snd_dmaengine_dai_dma_data dma_params_rx;
/* regcache for SRPC */
u32 regcache_srpc;
+ bool bypass;
};
static struct fsl_spdif_soc_data fsl_spdif_vf610 = {
@@ -905,6 +907,69 @@ static int fsl_spdif_rx_rcm_put(struct snd_kcontrol *kcontrol,
return 0;
}
+static int fsl_spdif_bypass_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_dai *dai = snd_kcontrol_chip(kcontrol);
+ struct fsl_spdif_priv *priv = snd_soc_dai_get_drvdata(dai);
+
+ ucontrol->value.integer.value[0] = priv->bypass ? 1 : 0;
+
+ return 0;
+}
+
+static int fsl_spdif_bypass_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_dai *dai = snd_kcontrol_chip(kcontrol);
+ struct fsl_spdif_priv *priv = snd_soc_dai_get_drvdata(dai);
+ struct snd_soc_card *card = dai->component->card;
+ bool set = (ucontrol->value.integer.value[0] != 0);
+ struct regmap *regmap = priv->regmap;
+ struct snd_soc_pcm_runtime *rtd;
+ u32 scr, mask;
+ int stream;
+
+ rtd = snd_soc_get_pcm_runtime(card, card->dai_link);
+
+ if (priv->bypass == set)
+ return 0; /* nothing to do */
+
+ if (snd_soc_dai_active(dai)) {
+ dev_err(dai->dev, "Cannot change BYPASS mode while stream is running.\n");
+ return -EBUSY;
+ }
+
+ pm_runtime_get_sync(dai->dev);
+
+ if (set) {
+ /* Disable interrupts */
+ regmap_update_bits(regmap, REG_SPDIF_SIE, 0xffffff, 0);
+
+ /* Configure BYPASS mode */
+ scr = SCR_TXSEL_RX | SCR_RXFIFO_OFF;
+ mask = SCR_RXFIFO_FSEL_MASK | SCR_RXFIFO_AUTOSYNC_MASK |
+ SCR_RXFIFO_CTL_MASK | SCR_RXFIFO_OFF_MASK | SCR_TXSEL_MASK;
+ /* Power up SPDIF module */
+ mask |= SCR_LOW_POWER;
+ } else {
+ /* Power down SPDIF module, disable TX */
+ scr = SCR_LOW_POWER | SCR_TXSEL_OFF;
+ mask = SCR_LOW_POWER | SCR_TXSEL_MASK;
+ }
+
+ regmap_update_bits(regmap, REG_SPDIF_SCR, mask, scr);
+
+ /* Disable playback & capture if BYPASS mode is enabled, enable otherwise */
+ for_each_pcm_streams(stream)
+ rtd->pcm->streams[stream].substream_count = (set ? 0 : 1);
+
+ priv->bypass = set;
+ pm_runtime_put_sync(dai->dev);
+
+ return 0;
+}
+
/* DPLL lock information */
static int fsl_spdif_rxrate_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
@@ -1075,6 +1140,15 @@ static struct snd_kcontrol_new fsl_spdif_ctrls[] = {
.info = fsl_spdif_rxrate_info,
.get = fsl_spdif_rxrate_get,
},
+ /* RX bypass controller */
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+ .name = "Bypass Mode",
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+ .info = snd_ctl_boolean_mono_info,
+ .get = fsl_spdif_bypass_get,
+ .put = fsl_spdif_bypass_put,
+ },
/* User bit sync mode set/get controller */
{
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
--
2.17.1
^ permalink raw reply related
* [PATCH v3 4/9] sections: Move is_kernel_inittext() into sections.h
From: Kefeng Wang @ 2021-09-26 7:20 UTC (permalink / raw)
To: arnd, linux-arch, linux-kernel, linuxppc-dev, rostedt, mingo,
davem, ast, ryabinin.a.a, akpm
Cc: Kefeng Wang, x86, paulus, bpf, Thomas Gleixner
In-Reply-To: <20210926072048.190336-1-wangkefeng.wang@huawei.com>
The is_kernel_inittext() and init_kernel_text() are with same
functionality, let's just keep is_kernel_inittext() and move
it into sections.h, then update all the callers.
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: x86@kernel.org
Signed-off-by: Kefeng Wang <wangkefeng.wang@huawei.com>
---
arch/x86/kernel/unwind_orc.c | 2 +-
include/asm-generic/sections.h | 14 ++++++++++++++
include/linux/kallsyms.h | 8 --------
include/linux/kernel.h | 1 -
kernel/extable.c | 12 ++----------
5 files changed, 17 insertions(+), 20 deletions(-)
diff --git a/arch/x86/kernel/unwind_orc.c b/arch/x86/kernel/unwind_orc.c
index a1202536fc57..d92ec2ced059 100644
--- a/arch/x86/kernel/unwind_orc.c
+++ b/arch/x86/kernel/unwind_orc.c
@@ -175,7 +175,7 @@ static struct orc_entry *orc_find(unsigned long ip)
}
/* vmlinux .init slow lookup: */
- if (init_kernel_text(ip))
+ if (is_kernel_inittext(ip))
return __orc_find(__start_orc_unwind_ip, __start_orc_unwind,
__stop_orc_unwind_ip - __start_orc_unwind_ip, ip);
diff --git a/include/asm-generic/sections.h b/include/asm-generic/sections.h
index 24780c0f40b1..811583ca8bd0 100644
--- a/include/asm-generic/sections.h
+++ b/include/asm-generic/sections.h
@@ -172,4 +172,18 @@ static inline bool is_kernel_rodata(unsigned long addr)
addr < (unsigned long)__end_rodata;
}
+/**
+ * is_kernel_inittext - checks if the pointer address is located in the
+ * .init.text section
+ *
+ * @addr: address to check
+ *
+ * Returns: true if the address is located in .init.text, false otherwise.
+ */
+static inline bool is_kernel_inittext(unsigned long addr)
+{
+ return addr >= (unsigned long)_sinittext &&
+ addr < (unsigned long)_einittext;
+}
+
#endif /* _ASM_GENERIC_SECTIONS_H_ */
diff --git a/include/linux/kallsyms.h b/include/linux/kallsyms.h
index b016c62f30a6..8a9d329c927c 100644
--- a/include/linux/kallsyms.h
+++ b/include/linux/kallsyms.h
@@ -24,14 +24,6 @@
struct cred;
struct module;
-static inline int is_kernel_inittext(unsigned long addr)
-{
- if (addr >= (unsigned long)_sinittext
- && addr < (unsigned long)_einittext)
- return 1;
- return 0;
-}
-
static inline int is_kernel_text(unsigned long addr)
{
if ((addr >= (unsigned long)_stext && addr < (unsigned long)_etext))
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index e5a9af8a4e20..445d0dceefb8 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -229,7 +229,6 @@ extern bool parse_option_str(const char *str, const char *option);
extern char *next_arg(char *args, char **param, char **val);
extern int core_kernel_text(unsigned long addr);
-extern int init_kernel_text(unsigned long addr);
extern int __kernel_text_address(unsigned long addr);
extern int kernel_text_address(unsigned long addr);
extern int func_ptr_is_kernel_text(void *ptr);
diff --git a/kernel/extable.c b/kernel/extable.c
index da26203841d4..98ca627ac5ef 100644
--- a/kernel/extable.c
+++ b/kernel/extable.c
@@ -62,14 +62,6 @@ const struct exception_table_entry *search_exception_tables(unsigned long addr)
return e;
}
-int init_kernel_text(unsigned long addr)
-{
- if (addr >= (unsigned long)_sinittext &&
- addr < (unsigned long)_einittext)
- return 1;
- return 0;
-}
-
int notrace core_kernel_text(unsigned long addr)
{
if (addr >= (unsigned long)_stext &&
@@ -77,7 +69,7 @@ int notrace core_kernel_text(unsigned long addr)
return 1;
if (system_state < SYSTEM_RUNNING &&
- init_kernel_text(addr))
+ is_kernel_inittext(addr))
return 1;
return 0;
}
@@ -94,7 +86,7 @@ int __kernel_text_address(unsigned long addr)
* Since we are after the module-symbols check, there's
* no danger of address overlap:
*/
- if (init_kernel_text(addr))
+ if (is_kernel_inittext(addr))
return 1;
return 0;
}
--
2.26.2
^ permalink raw reply related
* [PATCH v3 3/9] sections: Move and rename core_kernel_data() to is_kernel_core_data()
From: Kefeng Wang @ 2021-09-26 7:20 UTC (permalink / raw)
To: arnd, linux-arch, linux-kernel, linuxppc-dev, rostedt, mingo,
davem, ast, ryabinin.a.a, akpm
Cc: bpf, paulus, Kefeng Wang
In-Reply-To: <20210926072048.190336-1-wangkefeng.wang@huawei.com>
Move core_kernel_data() into sections.h and rename it to
is_kernel_core_data(), also make it return bool value, then
update all the callers.
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: "David S. Miller" <davem@davemloft.net>
Signed-off-by: Kefeng Wang <wangkefeng.wang@huawei.com>
---
include/asm-generic/sections.h | 16 ++++++++++++++++
include/linux/kernel.h | 1 -
kernel/extable.c | 18 ------------------
kernel/trace/ftrace.c | 2 +-
net/sysctl_net.c | 2 +-
5 files changed, 18 insertions(+), 21 deletions(-)
diff --git a/include/asm-generic/sections.h b/include/asm-generic/sections.h
index 817309e289db..24780c0f40b1 100644
--- a/include/asm-generic/sections.h
+++ b/include/asm-generic/sections.h
@@ -142,6 +142,22 @@ static inline bool init_section_intersects(void *virt, size_t size)
return memory_intersects(__init_begin, __init_end, virt, size);
}
+/**
+ * is_kernel_core_data - checks if the pointer address is located in the
+ * .data section
+ *
+ * @addr: address to check
+ *
+ * Returns: true if the address is located in .data, false otherwise.
+ * Note: On some archs it may return true for core RODATA, and false
+ * for others. But will always be true for core RW data.
+ */
+static inline bool is_kernel_core_data(unsigned long addr)
+{
+ return addr >= (unsigned long)_sdata &&
+ addr < (unsigned long)_edata;
+}
+
/**
* is_kernel_rodata - checks if the pointer address is located in the
* .rodata section
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index 2776423a587e..e5a9af8a4e20 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -230,7 +230,6 @@ extern char *next_arg(char *args, char **param, char **val);
extern int core_kernel_text(unsigned long addr);
extern int init_kernel_text(unsigned long addr);
-extern int core_kernel_data(unsigned long addr);
extern int __kernel_text_address(unsigned long addr);
extern int kernel_text_address(unsigned long addr);
extern int func_ptr_is_kernel_text(void *ptr);
diff --git a/kernel/extable.c b/kernel/extable.c
index b0ea5eb0c3b4..da26203841d4 100644
--- a/kernel/extable.c
+++ b/kernel/extable.c
@@ -82,24 +82,6 @@ int notrace core_kernel_text(unsigned long addr)
return 0;
}
-/**
- * core_kernel_data - tell if addr points to kernel data
- * @addr: address to test
- *
- * Returns true if @addr passed in is from the core kernel data
- * section.
- *
- * Note: On some archs it may return true for core RODATA, and false
- * for others. But will always be true for core RW data.
- */
-int core_kernel_data(unsigned long addr)
-{
- if (addr >= (unsigned long)_sdata &&
- addr < (unsigned long)_edata)
- return 1;
- return 0;
-}
-
int __kernel_text_address(unsigned long addr)
{
if (kernel_text_address(addr))
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index 7efbc8aaf7f6..f15badf31f52 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -323,7 +323,7 @@ int __register_ftrace_function(struct ftrace_ops *ops)
if (!ftrace_enabled && (ops->flags & FTRACE_OPS_FL_PERMANENT))
return -EBUSY;
- if (!core_kernel_data((unsigned long)ops))
+ if (!is_kernel_core_data((unsigned long)ops))
ops->flags |= FTRACE_OPS_FL_DYNAMIC;
add_ftrace_ops(&ftrace_ops_list, ops);
diff --git a/net/sysctl_net.c b/net/sysctl_net.c
index f6cb0d4d114c..4b45ed631eb8 100644
--- a/net/sysctl_net.c
+++ b/net/sysctl_net.c
@@ -144,7 +144,7 @@ static void ensure_safe_net_sysctl(struct net *net, const char *path,
addr = (unsigned long)ent->data;
if (is_module_address(addr))
where = "module";
- else if (core_kernel_data(addr))
+ else if (is_kernel_core_data(addr))
where = "kernel";
else
continue;
--
2.26.2
^ permalink raw reply related
* [PATCH v3 6/9] sections: Provide internal __is_kernel() and __is_kernel_text() helper
From: Kefeng Wang @ 2021-09-26 7:20 UTC (permalink / raw)
To: arnd, linux-arch, linux-kernel, linuxppc-dev, rostedt, mingo,
davem, ast, ryabinin.a.a, akpm
Cc: bpf, paulus, Kefeng Wang
In-Reply-To: <20210926072048.190336-1-wangkefeng.wang@huawei.com>
An internal __is_kernel() helper which only check the kernel address ranges,
and an internal __is_kernel_text() helper which only check text section ranges.
Signed-off-by: Kefeng Wang <wangkefeng.wang@huawei.com>
---
include/asm-generic/sections.h | 29 +++++++++++++++++++++++++++++
include/linux/kallsyms.h | 4 ++--
2 files changed, 31 insertions(+), 2 deletions(-)
diff --git a/include/asm-generic/sections.h b/include/asm-generic/sections.h
index 811583ca8bd0..a7abeadddc7a 100644
--- a/include/asm-generic/sections.h
+++ b/include/asm-generic/sections.h
@@ -186,4 +186,33 @@ static inline bool is_kernel_inittext(unsigned long addr)
addr < (unsigned long)_einittext;
}
+/**
+ * __is_kernel_text - checks if the pointer address is located in the
+ * .text section
+ *
+ * @addr: address to check
+ *
+ * Returns: true if the address is located in .text, false otherwise.
+ * Note: an internal helper, only check the range of _stext to _etext.
+ */
+static inline bool __is_kernel_text(unsigned long addr)
+{
+ return addr >= (unsigned long)_stext &&
+ addr < (unsigned long)_etext;
+}
+
+/**
+ * __is_kernel - checks if the pointer address is located in the kernel range
+ *
+ * @addr: address to check
+ *
+ * Returns: true if the address is located in the kernel range, false otherwise.
+ * Note: an internal helper, only check the range of _stext to _end.
+ */
+static inline bool __is_kernel(unsigned long addr)
+{
+ return addr >= (unsigned long)_stext &&
+ addr < (unsigned long)_end;
+}
+
#endif /* _ASM_GENERIC_SECTIONS_H_ */
diff --git a/include/linux/kallsyms.h b/include/linux/kallsyms.h
index 8a9d329c927c..5fb17dd4b6fa 100644
--- a/include/linux/kallsyms.h
+++ b/include/linux/kallsyms.h
@@ -26,14 +26,14 @@ struct module;
static inline int is_kernel_text(unsigned long addr)
{
- if ((addr >= (unsigned long)_stext && addr < (unsigned long)_etext))
+ if (__is_kernel_text(addr))
return 1;
return in_gate_area_no_mm(addr);
}
static inline int is_kernel(unsigned long addr)
{
- if (addr >= (unsigned long)_stext && addr < (unsigned long)_end)
+ if (__is_kernel(addr))
return 1;
return in_gate_area_no_mm(addr);
}
--
2.26.2
^ permalink raw reply related
* [PATCH v3 9/9] powerpc/mm: Use is_kernel_text() and is_kernel_inittext() helper
From: Kefeng Wang @ 2021-09-26 7:20 UTC (permalink / raw)
To: arnd, linux-arch, linux-kernel, linuxppc-dev, rostedt, mingo,
davem, ast, ryabinin.a.a, akpm
Cc: bpf, paulus, Kefeng Wang
In-Reply-To: <20210926072048.190336-1-wangkefeng.wang@huawei.com>
Use is_kernel_text() and is_kernel_inittext() helper to simplify code,
also drop etext, _stext, _sinittext, _einittext declaration which
already declared in section.h.
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: linuxppc-dev@lists.ozlabs.org
Signed-off-by: Kefeng Wang <wangkefeng.wang@huawei.com>
---
arch/powerpc/mm/pgtable_32.c | 7 ++-----
1 file changed, 2 insertions(+), 5 deletions(-)
diff --git a/arch/powerpc/mm/pgtable_32.c b/arch/powerpc/mm/pgtable_32.c
index dcf5ecca19d9..13c798308c2e 100644
--- a/arch/powerpc/mm/pgtable_32.c
+++ b/arch/powerpc/mm/pgtable_32.c
@@ -33,8 +33,6 @@
#include <mm/mmu_decl.h>
-extern char etext[], _stext[], _sinittext[], _einittext[];
-
static u8 early_fixmap_pagetable[FIXMAP_PTE_SIZE] __page_aligned_data;
notrace void __init early_ioremap_init(void)
@@ -104,14 +102,13 @@ static void __init __mapin_ram_chunk(unsigned long offset, unsigned long top)
{
unsigned long v, s;
phys_addr_t p;
- int ktext;
+ bool ktext;
s = offset;
v = PAGE_OFFSET + s;
p = memstart_addr + s;
for (; s < top; s += PAGE_SIZE) {
- ktext = ((char *)v >= _stext && (char *)v < etext) ||
- ((char *)v >= _sinittext && (char *)v < _einittext);
+ ktext = (is_kernel_text(v) || is_kernel_inittext(v));
map_kernel_page(v, p, ktext ? PAGE_KERNEL_TEXT : PAGE_KERNEL);
v += PAGE_SIZE;
p += PAGE_SIZE;
--
2.26.2
^ permalink raw reply related
* [PATCH v3 8/9] extable: Use is_kernel_text() helper
From: Kefeng Wang @ 2021-09-26 7:20 UTC (permalink / raw)
To: arnd, linux-arch, linux-kernel, linuxppc-dev, rostedt, mingo,
davem, ast, ryabinin.a.a, akpm
Cc: bpf, paulus, Kefeng Wang
In-Reply-To: <20210926072048.190336-1-wangkefeng.wang@huawei.com>
The core_kernel_text() should check the gate area, as it is part
of kernel text range.
Cc: Steven Rostedt <rostedt@goodmis.org>
Signed-off-by: Kefeng Wang <wangkefeng.wang@huawei.com>
---
kernel/extable.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/kernel/extable.c b/kernel/extable.c
index 98ca627ac5ef..0ba383d850ff 100644
--- a/kernel/extable.c
+++ b/kernel/extable.c
@@ -64,8 +64,7 @@ const struct exception_table_entry *search_exception_tables(unsigned long addr)
int notrace core_kernel_text(unsigned long addr)
{
- if (addr >= (unsigned long)_stext &&
- addr < (unsigned long)_etext)
+ if (is_kernel_text(addr))
return 1;
if (system_state < SYSTEM_RUNNING &&
--
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