* [PATCH 6/6] arm: dts: nsp: Add USB nodes to device tree
From: Yendapally Reddy Dhananjaya Reddy @ 2016-11-09 9:33 UTC (permalink / raw)
To: Rob Herring, Mark Rutland, Russell King, Ray Jui, Scott Branden,
Jon Mason, Florian Fainelli, Kishon Vijay Abraham I
Cc: bcm-kernel-feedback-list, netdev, devicetree, linux-kernel,
linux-arm-kernel, Yendapally Reddy Dhananjaya Reddy
In-Reply-To: <1478683994-12008-1-git-send-email-yendapally.reddy@broadcom.com>
Add USB nodes to the Northstar plus device tree file
Signed-off-by: Yendapally Reddy Dhananjaya Reddy <yendapally.reddy@broadcom.com>
---
arch/arm/boot/dts/bcm-nsp.dtsi | 57 ++++++++++++++++++++++++++++++++++++++++
arch/arm/boot/dts/bcm958625k.dts | 16 +++++++++++
2 files changed, 73 insertions(+)
diff --git a/arch/arm/boot/dts/bcm-nsp.dtsi b/arch/arm/boot/dts/bcm-nsp.dtsi
index 7c9e0fa..acdb576 100644
--- a/arch/arm/boot/dts/bcm-nsp.dtsi
+++ b/arch/arm/boot/dts/bcm-nsp.dtsi
@@ -249,6 +249,34 @@
status = "disabled";
};
+ xhci: usb@29000 {
+ compatible = "generic-xhci";
+ reg = <0x29000 0x1000>;
+ interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>;
+ phys = <&usb3_phy>;
+ phy-names = "usb";
+ status = "disabled";
+ };
+
+ ehci0: usb@2a000 {
+ compatible = "generic-ehci";
+ reg = <0x2a000 0x100>;
+ interrupts = <GIC_SPI 79 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ };
+
+ ohci0: usb@2b000 {
+ compatible = "generic-ohci";
+ reg = <0x2b000 0x100>;
+ interrupts = <GIC_SPI 79 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ };
+
+ mdio: mdio@32000 {
+ compatible = "brcm,iproc-mdio";
+ reg = <0x32000 0x8>;
+ };
+
rng: rng@33000 {
compatible = "brcm,bcm-nsp-rng";
reg = <0x33000 0x14>;
@@ -319,6 +347,30 @@
"sata2";
};
+ mdio_mux: mdio-mux@3f190 {
+ compatible = "brcm,mdio-mux-nsp";
+ reg = <0x3f190 0x4>,
+ <0x32000 0x4>;
+ reg-names = "bus-ctrl", "mgmt-ctrl";
+ mdio-parent-bus = <&mdio>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ mdio@0 {
+ reg = <0x0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ usb3_phy: usb3-phy@10 {
+ compatible = "brcm,nsp-usb3-phy";
+ reg = <0x10>;
+ usb3-ctrl-syscon = <&usb3_ctrl>;
+ #phy-cells = <0>;
+ status = "disabled";
+ };
+ };
+ };
+
pinctrl: pinctrl@3f1c0 {
compatible = "brcm,nsp-pinmux";
reg = <0x3f1c0 0x04>,
@@ -367,6 +419,11 @@
phy-names = "sata-phy";
};
};
+
+ usb3_ctrl: syscon@104408 {
+ compatible = "brcm,nsp-usb3-ctrl", "syscon";
+ reg = <0x104408 0x3fc>;
+ };
};
pcie0: pcie@18012000 {
diff --git a/arch/arm/boot/dts/bcm958625k.dts b/arch/arm/boot/dts/bcm958625k.dts
index 05c5f98..c7303fa 100644
--- a/arch/arm/boot/dts/bcm958625k.dts
+++ b/arch/arm/boot/dts/bcm958625k.dts
@@ -53,6 +53,22 @@
};
};
+&ehci0 {
+ status = "okay";
+};
+
+&ohci0 {
+ status = "okay";
+};
+
+&usb3_phy {
+ status = "okay";
+};
+
+&xhci {
+ status = "okay";
+};
+
&uart0 {
status = "okay";
};
--
2.1.0
^ permalink raw reply related
* Re: [PATCH 1/6] clk: stm32f4: Add PLL_I2S & PLL_SAI for STM32F429/469 boards
From: Gabriel Fernandez @ 2016-11-09 9:51 UTC (permalink / raw)
To: Radosław Pietrzyk
Cc: Mark Rutland, devicetree, Daniel Thompson, Alexandre Torgue,
Arnd Bergmann, Nicolas Pitre, Andrea Merello, linux-kernel,
Michael Turquette, olivier.bideau, Stephen Boyd, Russell King,
amelie.delaunay, Rob Herring, linux-arm-kernel, Maxime Coquelin,
linux-clk, ludovic.barre, kernel
In-Reply-To: <CAFvLkMSUg8=nYY9Zm2Q4ZW=GqUaczK_TA5b5jjb45vYyhoVLZA@mail.gmail.com>
On 11/09/2016 09:10 AM, Radosław Pietrzyk wrote:
> I would expect that VCO clock will force recalculation for all its
> children if I am not mistaken.
Sure
BR
Gabriel.
>
> 2016-11-08 17:19 GMT+01:00 Gabriel Fernandez <gabriel.fernandez@st.com>:
>> On 11/08/2016 09:52 AM, Radosław Pietrzyk wrote:
>>> 2016-11-08 9:35 GMT+01:00 Gabriel Fernandez <gabriel.fernandez@st.com>:
>>>> Hi Radosław
>>>>
>>>> Many thanks for reviewing.
>>>>
>>>> On 11/07/2016 03:57 PM, Radosław Pietrzyk wrote:
>>>>>> +static struct clk_hw *clk_register_pll_div(const char *name,
>>>>>> + const char *parent_name, unsigned long flags,
>>>>>> + void __iomem *reg, u8 shift, u8 width,
>>>>>> + u8 clk_divider_flags, const struct clk_div_table
>>>>>> *table,
>>>>>> + struct clk_hw *pll_hw, spinlock_t *lock)
>>>>>> +{
>>>>>> + struct stm32f4_pll_div *pll_div;
>>>>>> + struct clk_hw *hw;
>>>>>> + struct clk_init_data init;
>>>>>> + int ret;
>>>>>> +
>>>>>> + /* allocate the divider */
>>>>>> + pll_div = kzalloc(sizeof(*pll_div), GFP_KERNEL);
>>>>>> + if (!pll_div)
>>>>>> + return ERR_PTR(-ENOMEM);
>>>>>> +
>>>>>> + init.name = name;
>>>>>> + init.ops = &stm32f4_pll_div_ops;
>>>>>> + init.flags = flags;
>>>>> Maybe it's worth to have CLK_SET_RATE_PARENT here and the VCO clock
>>>>> should have CLK_SET_RATE_GATE flag and we can get rid of custom
>>>>> divider ops.
>>>> I don't want to offer the possibility to change the vco clock through the
>>>> divisor of the pll (only by a boot-loader or by DT).
>>>>
>>>> e.g. if i make a set rate on lcd-tft clock, i don't want to change the
>>>> SAI
>>>> frequencies.
>>>>
>>>> I used same structure for internal divisors of the pll (p, q, r) and for
>>>> post divisors (plli2s-q-div, pllsai-q-div & pllsai-r-div).
>>>> That why the CLK_SET_RATE_PARENT flag is transmit by parameter.
>>>>
>>>> These divisors are similar because we have to switch off the pll before
>>>> changing the rate.
>>>>
>>> But changing pll and lcd dividers only may not be enough for getting
>>> very specific pixelclocks and that might require changing the VCO
>>> frequency itself. The rest of the SAI tree should be recalculated
>>> then.
>> I agree but it seems to be too much complicated to recalculate all PLL
>> divisors if we change the vco clock.
>> You mean to use Clock notifier callback ?
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH v2 1/3] i2c: pxa: Add support for the I2C units found in Armada 3700
From: Romain Perier @ 2016-11-09 9:55 UTC (permalink / raw)
To: Baruch Siach
Cc: Mark Rutland, Andrew Lunn, Wolfram Sang, Hanna Hawa, Nadav Haklai,
Neta Zur Hershkovits, linux-i2c, Yahuda Yitschak,
linux-arm-kernel, Sebastian Hesselbarth, devicetree, Jason Cooper,
Pawel Moll, Ian Campbell, Omri Itach, Rob Herring,
Gregory Clement, Marcin Wojtas, Igal Liberman, Thomas Petazzoni,
Shadi Ammouri, Kumar Gala
In-Reply-To: <20161109085946.cmd4ltaxpiojq7il@tarshish>
Hi Baruch
Le 09/11/2016 à 09:59, Baruch Siach a écrit :
>> @@ -193,6 +204,8 @@ struct pxa_i2c {
>> unsigned char master_code;
>> unsigned long rate;
>> bool highmode_enter;
>> + unsigned long fm_mask;
>> + unsigned long hs_mask;
>
> Do you really need 64bit for that?
>
> baruch
Mhhh, good point. No I think that I can use an unsigned int.
I will fix it.
Thanks,
Romain
--
Romain Perier, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
^ permalink raw reply
* [PATCH v3 0/3] Add basic support for the I2C units of the Armada 3700
From: Romain Perier @ 2016-11-09 10:13 UTC (permalink / raw)
To: Wolfram Sang, linux-i2c
Cc: devicetree, Rob Herring, Ian Campbell, Pawel Moll, Mark Rutland,
Kumar Gala, Jason Cooper, Andrew Lunn, Sebastian Hesselbarth,
Gregory Clement, linux-arm-kernel, Thomas Petazzoni, Nadav Haklai,
Omri Itach, Shadi Ammouri, Yahuda Yitschak, Hanna Hawa,
Neta Zur Hershkovits, Igal Liberman, Marcin Wojtas <mw>
This series add basic support for the I2C bus interface units present
in the Armada 3700 to the pxa-i2c driver. It also add the definitions of
the device nodes to the devicetree at the SoC level and for its official
development board: the Armada 3720 DB.
Romain Perier (3):
i2c: pxa: Add support for the I2C units found in Armada 3700
arm64: dts: marvell: Add I2C definitions for the Armada 3700
dt-bindings: i2c: pxa: Update the documentation for the Armada 3700
Documentation/devicetree/bindings/i2c/i2c-pxa.txt | 1 +
arch/arm64/boot/dts/marvell/armada-3720-db.dts | 4 ++++
arch/arm64/boot/dts/marvell/armada-37xx.dtsi | 18 ++++++++++++++++
drivers/i2c/busses/Kconfig | 2 +-
drivers/i2c/busses/i2c-pxa.c | 25 +++++++++++++++++++++--
5 files changed, 47 insertions(+), 3 deletions(-)
--
2.9.3
^ permalink raw reply
* [PATCH v3 1/3] i2c: pxa: Add support for the I2C units found in Armada 3700
From: Romain Perier @ 2016-11-09 10:13 UTC (permalink / raw)
To: Wolfram Sang, linux-i2c-u79uwXL29TY76Z2rM5mHXA
Cc: devicetree-u79uwXL29TY76Z2rM5mHXA, Rob Herring, Ian Campbell,
Pawel Moll, Mark Rutland, Kumar Gala, Jason Cooper, Andrew Lunn,
Sebastian Hesselbarth, Gregory Clement,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
Thomas Petazzoni, Nadav Haklai, Omri Itach, Shadi Ammouri,
Yahuda Yitschak, Hanna Hawa, Neta Zur Hershkovits, Igal Liberman,
Marcin Wojtas <mw>
In-Reply-To: <20161109101349.18722-1-romain.perier-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
The Armada 3700 has two I2C controllers that is compliant with the I2C
Bus Specificiation 2.1, supports multi-master and different bus speed:
Standard mode (up to 100 KHz), Fast mode (up to 400 KHz),
High speed mode (up to 3.4 Mhz).
This IP block has a lot of similarity with the PXA, except some register
offsets and bitfield. This commits adds a basic support for this I2C
unit.
Signed-off-by: Romain Perier <romain.perier-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
Tested-by: Gregory CLEMENT <gregory.clement-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
---
Changes in v3:
- Replaced the type of hm_mask and fm_mask by unsigned int,
instead of unsigned long.
drivers/i2c/busses/Kconfig | 2 +-
drivers/i2c/busses/i2c-pxa.c | 25 +++++++++++++++++++++++--
2 files changed, 24 insertions(+), 3 deletions(-)
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index d252276..2f56a26 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -763,7 +763,7 @@ config I2C_PUV3
config I2C_PXA
tristate "Intel PXA2XX I2C adapter"
- depends on ARCH_PXA || ARCH_MMP || (X86_32 && PCI && OF)
+ depends on ARCH_PXA || ARCH_MMP || ARCH_MVEBU || (X86_32 && PCI && OF)
help
If you have devices in the PXA I2C bus, say yes to this option.
This driver can also be built as a module. If so, the module
diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c
index e28b825..09619db 100644
--- a/drivers/i2c/busses/i2c-pxa.c
+++ b/drivers/i2c/busses/i2c-pxa.c
@@ -55,6 +55,7 @@ enum pxa_i2c_types {
REGS_PXA3XX,
REGS_CE4100,
REGS_PXA910,
+ REGS_A3700,
};
/*
@@ -91,6 +92,13 @@ static struct pxa_reg_layout pxa_reg_layout[] = {
.ilcr = 0x28,
.iwcr = 0x30,
},
+ [REGS_A3700] = {
+ .ibmr = 0x00,
+ .idbr = 0x04,
+ .icr = 0x08,
+ .isr = 0x0c,
+ .isar = 0x10,
+ },
};
static const struct platform_device_id i2c_pxa_id_table[] = {
@@ -98,6 +106,7 @@ static const struct platform_device_id i2c_pxa_id_table[] = {
{ "pxa3xx-pwri2c", REGS_PXA3XX },
{ "ce4100-i2c", REGS_CE4100 },
{ "pxa910-i2c", REGS_PXA910 },
+ { "armada-3700-i2c", REGS_A3700 },
{ },
};
MODULE_DEVICE_TABLE(platform, i2c_pxa_id_table);
@@ -122,7 +131,9 @@ MODULE_DEVICE_TABLE(platform, i2c_pxa_id_table);
#define ICR_SADIE (1 << 13) /* slave address detected int enable */
#define ICR_UR (1 << 14) /* unit reset */
#define ICR_FM (1 << 15) /* fast mode */
+#define ICR_BUSMODE_FM (1 << 16) /* shifted fast mode for armada-3700 */
#define ICR_HS (1 << 16) /* High Speed mode */
+#define ICR_BUSMODE_HS (1 << 17) /* shifted high speed mode for armada-3700 */
#define ICR_GPIOEN (1 << 19) /* enable GPIO mode for SCL in HS */
#define ISR_RWM (1 << 0) /* read/write mode */
@@ -193,6 +204,8 @@ struct pxa_i2c {
unsigned char master_code;
unsigned long rate;
bool highmode_enter;
+ unsigned int fm_mask;
+ unsigned int hs_mask;
};
#define _IBMR(i2c) ((i2c)->reg_ibmr)
@@ -503,8 +516,8 @@ static void i2c_pxa_reset(struct pxa_i2c *i2c)
writel(i2c->slave_addr, _ISAR(i2c));
/* set control register values */
- writel(I2C_ICR_INIT | (i2c->fast_mode ? ICR_FM : 0), _ICR(i2c));
- writel(readl(_ICR(i2c)) | (i2c->high_mode ? ICR_HS : 0), _ICR(i2c));
+ writel(I2C_ICR_INIT | (i2c->fast_mode ? i2c->fm_mask : 0), _ICR(i2c));
+ writel(readl(_ICR(i2c)) | (i2c->high_mode ? i2c->hs_mask : 0), _ICR(i2c));
#ifdef CONFIG_I2C_PXA_SLAVE
dev_info(&i2c->adap.dev, "Enabling slave mode\n");
@@ -1137,6 +1150,7 @@ static const struct of_device_id i2c_pxa_dt_ids[] = {
{ .compatible = "mrvl,pxa-i2c", .data = (void *)REGS_PXA2XX },
{ .compatible = "mrvl,pwri2c", .data = (void *)REGS_PXA3XX },
{ .compatible = "mrvl,mmp-twsi", .data = (void *)REGS_PXA910 },
+ { .compatible = "marvell,armada-3700-i2c", .data = (void *)REGS_A3700 },
{}
};
MODULE_DEVICE_TABLE(of, i2c_pxa_dt_ids);
@@ -1158,6 +1172,13 @@ static int i2c_pxa_probe_dt(struct platform_device *pdev, struct pxa_i2c *i2c,
i2c->use_pio = 1;
if (of_get_property(np, "mrvl,i2c-fast-mode", NULL))
i2c->fast_mode = 1;
+ if (of_device_is_compatible(np, "marvell,armada-3700-i2c")) {
+ i2c->fm_mask = ICR_BUSMODE_FM;
+ i2c->hs_mask = ICR_BUSMODE_HS;
+ } else {
+ i2c->fm_mask = ICR_FM;
+ i2c->hs_mask = ICR_HS;
+ }
*i2c_types = (enum pxa_i2c_types)(of_id->data);
--
2.9.3
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH v3 2/3] arm64: dts: marvell: Add I2C definitions for the Armada 3700
From: Romain Perier @ 2016-11-09 10:13 UTC (permalink / raw)
To: Wolfram Sang, linux-i2c-u79uwXL29TY76Z2rM5mHXA
Cc: devicetree-u79uwXL29TY76Z2rM5mHXA, Rob Herring, Ian Campbell,
Pawel Moll, Mark Rutland, Kumar Gala, Jason Cooper, Andrew Lunn,
Sebastian Hesselbarth, Gregory Clement,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
Thomas Petazzoni, Nadav Haklai, Omri Itach, Shadi Ammouri,
Yahuda Yitschak, Hanna Hawa, Neta Zur Hershkovits, Igal Liberman,
Marcin Wojtas <mw>
In-Reply-To: <20161109101349.18722-1-romain.perier-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
The Armada 3700 has two i2c bus interface units, this commit adds the
definitions of the corresponding device nodes. It also enables the node
on the development board for this SoC.
Signed-off-by: Romain Perier <romain.perier-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
Acked-by: Gregory CLEMENT <gregory.clement-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
---
arch/arm64/boot/dts/marvell/armada-3720-db.dts | 4 ++++
arch/arm64/boot/dts/marvell/armada-37xx.dtsi | 18 ++++++++++++++++++
2 files changed, 22 insertions(+)
diff --git a/arch/arm64/boot/dts/marvell/armada-3720-db.dts b/arch/arm64/boot/dts/marvell/armada-3720-db.dts
index 1372e9a6..16d84af 100644
--- a/arch/arm64/boot/dts/marvell/armada-3720-db.dts
+++ b/arch/arm64/boot/dts/marvell/armada-3720-db.dts
@@ -62,6 +62,10 @@
};
};
+&i2c0 {
+ status = "okay";
+};
+
/* CON3 */
&sata {
status = "okay";
diff --git a/arch/arm64/boot/dts/marvell/armada-37xx.dtsi b/arch/arm64/boot/dts/marvell/armada-37xx.dtsi
index c476253..bf2d73d 100644
--- a/arch/arm64/boot/dts/marvell/armada-37xx.dtsi
+++ b/arch/arm64/boot/dts/marvell/armada-37xx.dtsi
@@ -98,6 +98,24 @@
/* 32M internal register @ 0xd000_0000 */
ranges = <0x0 0x0 0xd0000000 0x2000000>;
+ i2c0: i2c@11000 {
+ compatible = "marvell,armada-3700-i2c";
+ reg = <0x11000 0x24>;
+ clocks = <&nb_perih_clk 10>;
+ interrupts = <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>;
+ mrvl,i2c-fast-mode;
+ status = "disabled";
+ };
+
+ i2c1: i2c@11080 {
+ compatible = "marvell,armada-3700-i2c";
+ reg = <0x11080 0x24>;
+ clocks = <&nb_perih_clk 9>;
+ interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>;
+ mrvl,i2c-fast-mode;
+ status = "disabled";
+ };
+
uart0: serial@12000 {
compatible = "marvell,armada-3700-uart";
reg = <0x12000 0x400>;
--
2.9.3
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH v3 3/3] dt-bindings: i2c: pxa: Update the documentation for the Armada 3700
From: Romain Perier @ 2016-11-09 10:13 UTC (permalink / raw)
To: Wolfram Sang, linux-i2c
Cc: devicetree, Rob Herring, Ian Campbell, Pawel Moll, Mark Rutland,
Kumar Gala, Jason Cooper, Andrew Lunn, Sebastian Hesselbarth,
Gregory Clement, linux-arm-kernel, Thomas Petazzoni, Nadav Haklai,
Omri Itach, Shadi Ammouri, Yahuda Yitschak, Hanna Hawa,
Neta Zur Hershkovits, Igal Liberman, Marcin Wojtas <mw>
In-Reply-To: <20161109101349.18722-1-romain.perier@free-electrons.com>
This commit documents the compatible string to have the compatibility for
the I2C unit found in the Armada 3700.
Signed-off-by: Romain Perier <romain.perier@free-electrons.com>
---
Changes in v2:
- Fixed wrong compatible string, it should be "marvell,armada-3700-i2c"
and not "marvell,armada-3700".
Documentation/devicetree/bindings/i2c/i2c-pxa.txt | 1 +
1 file changed, 1 insertion(+)
diff --git a/Documentation/devicetree/bindings/i2c/i2c-pxa.txt b/Documentation/devicetree/bindings/i2c/i2c-pxa.txt
index 12b78ac..d30f0b1 100644
--- a/Documentation/devicetree/bindings/i2c/i2c-pxa.txt
+++ b/Documentation/devicetree/bindings/i2c/i2c-pxa.txt
@@ -7,6 +7,7 @@ Required properties :
compatible processor, e.g. pxa168, pxa910, mmp2, mmp3.
For the pxa2xx/pxa3xx, an additional node "mrvl,pxa-i2c" is required
as shown in the example below.
+ For the Armada 3700, the compatible should be "marvell,armada-3700-i2c".
Recommended properties :
--
2.9.3
^ permalink raw reply related
* Re: [PATCH v3 1/3] i2c: pxa: Add support for the I2C units found in Armada 3700
From: Gregory CLEMENT @ 2016-11-09 10:21 UTC (permalink / raw)
To: Romain Perier
Cc: Mark Rutland, devicetree, Yahuda Yitschak, Omri Itach,
Jason Cooper, Pawel Moll, Ian Campbell, Igal Liberman, Hanna Hawa,
Wolfram Sang, Neta Zur Hershkovits, Nadav Haklai, Rob Herring,
Andrew Lunn, linux-i2c, Kumar Gala, Shadi Ammouri, Marcin Wojtas,
Thomas Petazzoni, linux-arm-kernel, Sebastian Hesselbarth
In-Reply-To: <20161109101349.18722-2-romain.perier@free-electrons.com>
Hi Romain,
You was too fast I didn't have time to commnent about Baruch suggestion.
On mer., nov. 09 2016, Romain Perier <romain.perier@free-electrons.com> wrote:
> The Armada 3700 has two I2C controllers that is compliant with the I2C
> Bus Specificiation 2.1, supports multi-master and different bus speed:
> Standard mode (up to 100 KHz), Fast mode (up to 400 KHz),
> High speed mode (up to 3.4 Mhz).
>
> This IP block has a lot of similarity with the PXA, except some register
> offsets and bitfield. This commits adds a basic support for this I2C
> unit.
>
> Signed-off-by: Romain Perier <romain.perier@free-electrons.com>
> Tested-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
> ---
>
> Changes in v3:
> - Replaced the type of hm_mask and fm_mask by unsigned int,
> instead of unsigned long.
[...]
> #define ISR_RWM (1 << 0) /* read/write mode */
> @@ -193,6 +204,8 @@ struct pxa_i2c {
> unsigned char master_code;
> unsigned long rate;
> bool highmode_enter;
> + unsigned int fm_mask;
> + unsigned int hs_mask;
These masks are used with writel and readl which use an u32. So the
better is to use this type.
Gregory
> };
>
> #define _IBMR(i2c) ((i2c)->reg_ibmr)
> @@ -503,8 +516,8 @@ static void i2c_pxa_reset(struct pxa_i2c *i2c)
> writel(i2c->slave_addr, _ISAR(i2c));
>
> /* set control register values */
> - writel(I2C_ICR_INIT | (i2c->fast_mode ? ICR_FM : 0), _ICR(i2c));
> - writel(readl(_ICR(i2c)) | (i2c->high_mode ? ICR_HS : 0), _ICR(i2c));
> + writel(I2C_ICR_INIT | (i2c->fast_mode ? i2c->fm_mask : 0), _ICR(i2c));
> + writel(readl(_ICR(i2c)) | (i2c->high_mode ? i2c->hs_mask : 0), _ICR(i2c));
>
--
Gregory Clement, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com
^ permalink raw reply
* Re: [PATCH v3 2/3] PCI: qcom: add support to msm8996 PCIE controller
From: Vivek Gautam @ 2016-11-09 10:37 UTC (permalink / raw)
To: Srinivas Kandagatla
Cc: svarbanov, Bjorn Helgaas, linux-pci, Rob Herring, Mark Rutland,
devicetree@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-arm-msm
In-Reply-To: <1478264387-17914-3-git-send-email-srinivas.kandagatla@linaro.org>
Hi,
On Fri, Nov 4, 2016 at 6:29 PM, Srinivas Kandagatla
<srinivas.kandagatla@linaro.org> wrote:
> This patch adds support to msm8996/apq8096 pcie, MSM8996 supports
> Gen 1/2, One lane, 3 pcie root-complex with support to MSI and
> legacy interrupts and it conforms to PCI Express Base 2.1 specification.
>
> This patch adds post_init callback to qcom_pcie_ops, as this is pcie
> pipe clocks are only setup after the phy is powered on.
> It also adds ltssm_enable callback as it is very much different to other
> supported SOCs in the driver.
>
> Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
> ---
Few minor nits.
> .../devicetree/bindings/pci/qcom,pcie.txt | 68 +++++++-
> drivers/pci/host/pcie-qcom.c | 177 ++++++++++++++++++++-
> 2 files changed, 239 insertions(+), 6 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/pci/qcom,pcie.txt b/Documentation/devicetree/bindings/pci/qcom,pcie.txt
> index 4059a6f..4a0538d 100644
> --- a/Documentation/devicetree/bindings/pci/qcom,pcie.txt
> +++ b/Documentation/devicetree/bindings/pci/qcom,pcie.txt
> @@ -7,6 +7,7 @@
> - "qcom,pcie-ipq8064" for ipq8064
> - "qcom,pcie-apq8064" for apq8064
> - "qcom,pcie-apq8084" for apq8084
> + - "qcom,pcie-msm8996" for msm8996 or apq8096
Since this works for both apq8096 and msm8996, compatible -
"qcom,pcie-apq8096" for uniformity ?
[snip]
> @@ -231,3 +242,58 @@
> pinctrl-0 = <&pcie0_pins_default>;
> pinctrl-names = "default";
> };
> +
> +* Example for apq8096:
> +
> + pcie@00608000{
> + compatible = "qcom,pcie-msm8996", "snps,dw-pcie";
this will change accordingly.
> + power-domains = <&gcc PCIE1_GDSC>;
> + bus-range = <0x00 0xff>;
> + num-lanes = <1>;
> +
[snip]
> +
> +static int qcom_pcie_init_v2(struct qcom_pcie *pcie)
> +{
> + struct qcom_pcie_resources_v2 *res = &pcie->res.v2;
> + struct device *dev = pcie->pp.dev;
> + u32 val;
> + int ret = 0;
you don't need to initialize ret here.
> +
> + ret = clk_prepare_enable(res->aux_clk);
> + if (ret) {
> + dev_err(dev, "cannot prepare/enable aux clock\n");
> + return ret;
> + }
[snip]
> @@ -429,6 +571,17 @@ static int qcom_pcie_link_up(struct pcie_port *pp)
> return !!(val & PCI_EXP_LNKSTA_DLLLA);
> }
>
> +static void qcom_pcie_deinit_v2(struct qcom_pcie *pcie)
> +{
> + struct qcom_pcie_resources_v2 *res = &pcie->res.v2;
> +
> + clk_disable_unprepare(res->slave_clk);
> + clk_disable_unprepare(res->master_clk);
> + clk_disable_unprepare(res->cfg_clk);
> + clk_disable_unprepare(res->aux_clk);
> + clk_disable_unprepare(res->pipe_clk);
i am sure, this is not affecting the functionality, but the pipe clock
is enabled after all the clocks.
so it makes sense to disable it in the first place. you can just move
this above slave_clk.
[snip]
> @@ -572,6 +738,7 @@ static const struct of_device_id qcom_pcie_match[] = {
> { .compatible = "qcom,pcie-ipq8064", .data = &ops_v0 },
> { .compatible = "qcom,pcie-apq8064", .data = &ops_v0 },
> { .compatible = "qcom,pcie-apq8084", .data = &ops_v1 },
> + { .compatible = "qcom,pcie-msm8996", .data = &ops_v2 },
this will change according to earlier comment in bindings.
Thanks
Vivek
--
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
^ permalink raw reply
* [PATCH v2] mtd/spi-nor: Add SPI memory controllers for Aspeed SoCs
From: Cédric Le Goater @ 2016-11-09 10:42 UTC (permalink / raw)
To: linux-mtd
Cc: Mark Rutland, Boris Brezillon, devicetree, Richard Weinberger,
Marek Vasut, Rob Herring, Joel Stanley, Cyrille Pitchen,
Brian Norris, David Woodhouse, Cédric Le Goater
This driver adds mtd support for spi-nor attached to either or both of
the Firmware Memory Controller or the SPI Flash Controller (AST2400
only).
The SMC controllers on the Aspeed AST2500 SoC are very similar to the
ones found on the AST2400. The differences are on the number of
supported flash modules and their default mappings in the SoC address
space.
The Aspeed AST2500 has one SPI controller for the BMC firmware and two
for the host firmware. All controllers have now the same set of
registers compatible with the AST2400 FMC controller and the legacy
'SMC' controller is fully gone.
Each controller has a memory range on which it maps its flash module
slaves. Each slave is assigned a memory window for its mapping that
can be changed at bootime with the Segment Address Register.
Each SPI flash slave can then be accessed in two modes: Command and
User. When in User mode, accesses to the memory segment of the slaves
are translated in SPI transfers. When in Command mode, the HW
generates the SPI commands automatically and the memory segment is
accessed as if doing a MMIO.
Currently, only the User mode is supported. Command mode needs a
little more work to check that the memory window on the AHB bus fits
the module size.
Based on previous work from Milton D. Miller II <miltonm@us.ibm.com>
Signed-off-by: Cédric Le Goater <clg@kaod.org>
---
Tested on:
* OpenPOWER Palmetto (AST2400) with
FMC controller : n25q256a
SPI controller : mx25l25635e and n25q512ax3
* Evaluation board (AST2500) with
FMC controller : w25q256
SPI controller : w25q256
* OpenPOWER Witherspoon (AST2500) with
FMC controller : mx25l25635e * 2
SPI controller : mx66l1g45g
Changes since v2:
- added a set4b ops to handle difference in the controllers
- simplified the IO routines
- prepared for fast read using dummy cycles
Work in progress:
- read optimization using higher SPI clock frequencies
- command mode to direct reads from AHB
- DMA support
.../devicetree/bindings/mtd/aspeed-smc.txt | 72 ++
drivers/mtd/spi-nor/Kconfig | 12 +
drivers/mtd/spi-nor/Makefile | 1 +
drivers/mtd/spi-nor/aspeed-smc.c | 783 +++++++++++++++++++++
4 files changed, 868 insertions(+)
create mode 100644 Documentation/devicetree/bindings/mtd/aspeed-smc.txt
create mode 100644 drivers/mtd/spi-nor/aspeed-smc.c
diff --git a/Documentation/devicetree/bindings/mtd/aspeed-smc.txt b/Documentation/devicetree/bindings/mtd/aspeed-smc.txt
new file mode 100644
index 000000000000..7516b0c01fcf
--- /dev/null
+++ b/Documentation/devicetree/bindings/mtd/aspeed-smc.txt
@@ -0,0 +1,72 @@
+* Aspeed Static Memory controller
+* Aspeed SPI Flash Controller
+
+The Static memory controller in the ast2400 supports 5 chip selects
+each can be attached to NAND, parallel NOR, or SPI NOR attached flash.
+The Firmware Memory Controller in the ast2500 supports 3 chip selects,
+two of which are always in SPI-NOR mode and the third can be SPI-NOR
+or parallel flash. The SPI flash controller in the ast2400 supports
+one of 2 chip selects selected by pinmux. The two SPI flash
+controllers in the ast2500 each support two chip selects.
+
+Required properties:
+ - compatible : Should be one of
+ "aspeed,ast2400-fmc" for the AST2400 Static Memory Controller
+ "aspeed,ast2400-smc" for the AST2400 SPI Flash Controller
+ "aspeed,ast2500-fmc" for the AST2500 Firmware SPI Memory Controller
+ "aspeed,ast2500-smc" for the AST2500 SPI Flash Controllers
+ - reg : the first contains the control register location and length,
+ the second contains the memory window mapping address and length
+ - #address-cells : must be 1 corresponding to chip select child binding
+ - #size-cells : must be 0 corresponding to chip select child binding
+
+Optional properties:
+ - interrupts : Should contain the interrupt for the dma device if an fmc
+
+The child nodes are the SPI Flash modules which must have a compatible
+property as specified in bindings/mtd/jedec,spi-nor.txt
+
+Optionally, the child node can contain properties for SPI mode (may be
+ignored):
+ - spi-max-frequency - (optional) max frequency of spi bus
+
+
+Example:
+fmc: fmc@1e620000 {
+ compatible = "aspeed,ast2400-fmc";
+ reg = < 0x1e620000 0x94
+ 0x20000000 0x02000000
+ 0x22000000 0x02000000 >;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ interrupts = <19>;
+ flash@0 {
+ reg = < 0 >;
+ compatible = "jedec,spi-nor" ;
+ /* spi-max-frequency = <>; */
+ /* m25p,fast-read; */
+ #address-cells = <1>;
+ #size-cells = <1>;
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ boot@0 {
+ label = "boot-loader";
+ reg = < 0 0x8000 >;
+ };
+ image@8000 {
+ label = "kernel-image";
+ reg = < 0x8000 0x1f8000 >;
+ };
+ };
+ };
+ flash@1 {
+ reg = < 1 >;
+ compatible = "jedec,spi-nor" ;
+ label = "alt";
+ /* spi-max-frequency = <>; */
+ status = "fail";
+ /* m25p,fast-read; */
+ };
+};
diff --git a/drivers/mtd/spi-nor/Kconfig b/drivers/mtd/spi-nor/Kconfig
index 4a682ee0f632..96148600fdab 100644
--- a/drivers/mtd/spi-nor/Kconfig
+++ b/drivers/mtd/spi-nor/Kconfig
@@ -76,4 +76,16 @@ config SPI_NXP_SPIFI
Flash. Enable this option if you have a device with a SPIFI
controller and want to access the Flash as a mtd device.
+config ASPEED_FLASH_SPI
+ tristate "Aspeed flash controllers in SPI mode"
+ depends on HAS_IOMEM && OF
+ depends on ARCH_ASPEED || COMPILE_TEST
+ # IO_SPACE_LIMIT must be equivalent to (~0UL)
+ depends on !NEED_MACH_IO_H
+ help
+ This enables support for the New Static Memory Controller
+ (FMC) in the Aspeed SoCs (AST2400 and AST2500) when attached
+ to SPI nor chips, and support for the SPI Memory controller
+ (SPI) for the BIOS.
+
endif # MTD_SPI_NOR
diff --git a/drivers/mtd/spi-nor/Makefile b/drivers/mtd/spi-nor/Makefile
index 121695e83542..c3174ebc45c2 100644
--- a/drivers/mtd/spi-nor/Makefile
+++ b/drivers/mtd/spi-nor/Makefile
@@ -4,4 +4,5 @@ obj-$(CONFIG_SPI_CADENCE_QUADSPI) += cadence-quadspi.o
obj-$(CONFIG_SPI_FSL_QUADSPI) += fsl-quadspi.o
obj-$(CONFIG_SPI_HISI_SFC) += hisi-sfc.o
obj-$(CONFIG_MTD_MT81xx_NOR) += mtk-quadspi.o
+obj-$(CONFIG_ASPEED_FLASH_SPI) += aspeed-smc.o
obj-$(CONFIG_SPI_NXP_SPIFI) += nxp-spifi.o
diff --git a/drivers/mtd/spi-nor/aspeed-smc.c b/drivers/mtd/spi-nor/aspeed-smc.c
new file mode 100644
index 000000000000..30662daf89ca
--- /dev/null
+++ b/drivers/mtd/spi-nor/aspeed-smc.c
@@ -0,0 +1,783 @@
+/*
+ * ASPEED Static Memory Controller driver
+ *
+ * Copyright (c) 2015-2016, IBM Corporation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/bug.h>
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/spi-nor.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/sysfs.h>
+
+#define DEVICE_NAME "aspeed-smc"
+
+/*
+ * In user mode all data bytes read or written to the chip decode address
+ * range are transferred to or from the SPI bus. The range is treated as a
+ * fifo of arbitratry 1, 2, or 4 byte width but each write has to be aligned
+ * to its size. The address within the multiple 8kB range is ignored when
+ * sending bytes to the SPI bus.
+ *
+ * On the arm architecture, as of Linux version 4.3, memcpy_fromio and
+ * memcpy_toio on little endian targets use the optimized memcpy routines
+ * that were designed for well behavied memory storage. These routines
+ * have a stutter if the source and destination are not both word aligned,
+ * once with a duplicate access to the source after aligning to the
+ * destination to a word boundary, and again with a duplicate access to
+ * the source when the final byte count is not word aligned.
+ *
+ * When writing or reading the fifo this stutter discards data or sends
+ * too much data to the fifo and can not be used by this driver.
+ *
+ * While the low level io string routines that implement the insl family do
+ * the desired accesses and memory increments, the cross architecture io
+ * macros make them essentially impossible to use on a memory mapped address
+ * instead of a a token from the call to iomap of an io port.
+ *
+ * These fifo routines use readl and friends to a constant io port and update
+ * the memory buffer pointer and count via explicit code. The final updates
+ * to len are optimistically suppressed.
+ */
+static int aspeed_smc_read_from_ahb(void *buf, const void __iomem *src,
+ size_t len)
+{
+ if ((((unsigned long)src | (unsigned long)buf | len) & 3) == 0) {
+ while (len > 3) {
+ *(u32 *)buf = readl(src);
+ buf += 4;
+ src += 4;
+ len -= 4;
+ }
+ }
+
+ while (len--) {
+ *(u8 *)buf = readb(src);
+ buf += 1;
+ src += 1;
+ }
+ return 0;
+}
+
+static int aspeed_smc_write_to_ahb(void __iomem *dst, const void *buf,
+ size_t len)
+{
+ if ((((unsigned long)dst | (unsigned long)buf | len) & 3) == 0) {
+ while (len > 3) {
+ u32 val = *(u32 *)buf;
+
+ writel(val, dst);
+ buf += 4;
+ dst += 4;
+ len -= 4;
+ }
+ }
+
+ while (len--) {
+ u8 val = *(u8 *)buf;
+
+ writeb(val, dst);
+ buf += 1;
+ dst += 1;
+ }
+ return 0;
+}
+
+enum smc_flash_type {
+ smc_type_nor = 0, /* controller connected to nor flash */
+ smc_type_nand = 1, /* controller connected to nand flash */
+ smc_type_spi = 2, /* controller connected to spi flash */
+};
+
+struct aspeed_smc_chip;
+
+struct aspeed_smc_info {
+ u32 maxsize; /* maximum size of 1 chip window */
+ u8 nce; /* number of chip enables */
+ u8 maxwidth; /* max width of spi bus */
+ bool hastype; /* flash type field exists in cfg reg */
+ u8 we0; /* shift for write enable bit for ce 0 */
+ u8 ctl0; /* offset in regs of ctl for ce 0 */
+ u8 time; /* offset in regs of timing */
+ u8 misc; /* offset in regs of misc settings */
+
+ void (*set_4b)(struct aspeed_smc_chip *chip);
+};
+
+static void aspeed_smc_chip_set_4b_smc_2400(struct aspeed_smc_chip *chip);
+static void aspeed_smc_chip_set_4b(struct aspeed_smc_chip *chip);
+
+static const struct aspeed_smc_info fmc_2400_info = {
+ .maxsize = 64 * 1024 * 1024,
+ .nce = 5,
+ .maxwidth = 4,
+ .hastype = true,
+ .we0 = 16,
+ .ctl0 = 0x10,
+ .time = 0x94,
+ .misc = 0x54,
+ .set_4b = aspeed_smc_chip_set_4b,
+};
+
+static const struct aspeed_smc_info smc_2400_info = {
+ .maxsize = 64 * 1024 * 1024,
+ .nce = 1,
+ .maxwidth = 2,
+ .hastype = false,
+ .we0 = 0,
+ .ctl0 = 0x04,
+ .time = 0x14,
+ .misc = 0x10,
+ .set_4b = aspeed_smc_chip_set_4b_smc_2400,
+};
+
+static const struct aspeed_smc_info fmc_2500_info = {
+ .maxsize = 256 * 1024 * 1024,
+ .nce = 3,
+ .maxwidth = 2,
+ .hastype = true,
+ .we0 = 16,
+ .ctl0 = 0x10,
+ .time = 0x94,
+ .misc = 0x54,
+ .set_4b = aspeed_smc_chip_set_4b,
+};
+
+static const struct aspeed_smc_info smc_2500_info = {
+ .maxsize = 128 * 1024 * 1024,
+ .nce = 2,
+ .maxwidth = 2,
+ .hastype = false,
+ .we0 = 16,
+ .ctl0 = 0x10,
+ .time = 0x94,
+ .misc = 0x54,
+ .set_4b = aspeed_smc_chip_set_4b,
+};
+
+enum smc_ctl_reg_value {
+ smc_base, /* base value without mode for other commands */
+ smc_read, /* command reg for (maybe fast) reads */
+ smc_write, /* command reg for writes with timings */
+ smc_num_ctl_reg_values /* last value to get count of commands */
+};
+
+struct aspeed_smc_controller;
+
+struct aspeed_smc_chip {
+ int cs;
+ struct aspeed_smc_controller *controller;
+ __le32 __iomem *ctl; /* control register */
+ void __iomem *base; /* base of chip window */
+ __le32 ctl_val[smc_num_ctl_reg_values]; /* controls with timing */
+ enum smc_flash_type type; /* what type of flash */
+ struct spi_nor nor;
+};
+
+struct aspeed_smc_controller {
+ struct device *dev;
+
+ struct mutex mutex; /* controller access mutex */
+ const struct aspeed_smc_info *info; /* type info of controller */
+ void __iomem *regs; /* controller registers */
+ void __iomem *windows; /* per-chip windows resource */
+
+ struct aspeed_smc_chip *chips[0]; /* pointers to attached chips */
+};
+
+/*
+ * SPI Flash Configuration Register (AST2400 SPI)
+ */
+#define CONFIG_REG 0x0
+#define CONFIG_ENABLE_CE_INACTIVE BIT(1)
+#define CONFIG_WRITE BIT(0)
+
+/*
+ * SPI Flash Configuration Register (AST2500 SPI)
+ * Type setting Register (AST2500 FMC and AST2400 FMC)
+ */
+#define TYPE_SETTING_REG 0x0
+#define CONFIG_DISABLE_LEGACY BIT(31) /* 1 on AST2500 FMC */
+
+#define CONFIG_CE2_WRITE BIT(18)
+#define CONFIG_CE1_WRITE BIT(17)
+#define CONFIG_CE0_WRITE BIT(16)
+
+#define CONFIG_CE2_TYPE BIT(4) /* FMC only */
+#define CONFIG_CE1_TYPE BIT(2) /* FMC only */
+#define CONFIG_CE0_TYPE BIT(0) /* FMC only */
+
+/*
+ * CE Control Register (AST2500 SPI,FMC and AST2400 FMC)
+ */
+#define CE_CONTROL_REG 0x4
+#define CE2_ENABLE_CE_INACTIVE BIT(10)
+#define CE1_ENABLE_CE_INACTIVE BIT(9)
+#define CE0_ENABLE_CE_INACTIVE BIT(8)
+#define CE2_CONTROL_EXTENDED BIT(2)
+#define CE1_CONTROL_EXTENDED BIT(1)
+#define CE0_CONTROL_EXTENDED BIT(0)
+
+/* CE0 Control Register (depends on the controller type) */
+#define CONTROL_SPI_AAF_MODE BIT(31)
+#define CONTROL_SPI_IO_MODE_MASK GENMASK(30, 28)
+#define CONTROL_SPI_IO_DUAL_DATA BIT(29)
+#define CONTROL_SPI_IO_DUAL_ADDR_DATA (BIT(29) | BIT(28))
+#define CONTROL_SPI_IO_QUAD_DATA BIT(30)
+#define CONTROL_SPI_IO_QUAD_ADDR_DATA (BIT(30) | BIT(28))
+#define CONTROL_SPI_CE_INACTIVE_SHIFT 24
+#define CONTROL_SPI_CE_INACTIVE_MASK GENMASK(27, CONTROL_SPI_CE_INACTIVE_SHIFT)
+/* 0 = 16T ... 15 = 1T T=HCLK */
+#define CONTROL_SPI_COMMAND_SHIFT 16
+#define CONTROL_SPI_DUMMY_CYCLE_COMMAND_OUTPUT BIT(15)
+#define CONTROL_SPI_IO_DUMMY_CYCLES_HI BIT(14)
+#define CONTROL_SPI_IO_DUMMY_CYCLES_HI_SHIFT 14
+#define CONTROL_SPI_IO_ADDRESS_4B BIT(13) /* AST2400 SPI */
+#define CONTROL_SPI_CLK_DIV4 BIT(13) /* others */
+#define CONTROL_SPI_RW_MERGE BIT(12)
+#define CONTROL_SPI_IO_DUMMY_CYCLES_LO_SHIFT 6
+#define CONTROL_SPI_IO_DUMMY_CYCLES_LO GENMASK(7, \
+ CONTROL_SPI_IO_DUMMY_CYCLES_LO_SHIFT)
+#define CONTROL_SPI_IO_DUMMY_CYCLES_MASK (CONTROL_SPI_IO_DUMMY_CYCLES_HI | \
+ CONTROL_SPI_IO_DUMMY_CYCLES_LO)
+#define CONTROL_SPI_IO_DUMMY_CYCLES_SET(dummy) \
+ (((((dummy) >> 2) & 0x1) << CONTROL_SPI_IO_DUMMY_CYCLES_HI_SHIFT) | \
+ (((dummy) & 0x3) << CONTROL_SPI_IO_DUMMY_CYCLES_LO_SHIFT))
+
+#define CONTROL_SPI_CLOCK_FREQ_SEL_SHIFT 8
+#define CONTROL_SPI_CLOCK_FREQ_SEL_MASK GENMASK(11, \
+ CONTROL_SPI_CLOCK_FREQ_SEL_SHIFT)
+#define CONTROL_SPI_LSB_FIRST BIT(5)
+#define CONTROL_SPI_CLOCK_MODE_3 BIT(4)
+#define CONTROL_SPI_IN_DUAL_DATA BIT(3)
+#define CONTROL_SPI_CE_STOP_ACTIVE_CONTROL BIT(2)
+#define CONTROL_SPI_COMMAND_MODE_MASK GENMASK(1, 0)
+#define CONTROL_SPI_COMMAND_MODE_NORMAL (0)
+#define CONTROL_SPI_COMMAND_MODE_FREAD (1)
+#define CONTROL_SPI_COMMAND_MODE_WRITE (2)
+#define CONTROL_SPI_COMMAND_MODE_USER (3)
+
+#define CONTROL_SPI_KEEP_MASK (CONTROL_SPI_AAF_MODE | \
+ CONTROL_SPI_CE_INACTIVE_MASK | CONTROL_SPI_CLK_DIV4 | \
+ CONTROL_SPI_IO_DUMMY_CYCLES_MASK | CONTROL_SPI_CLOCK_FREQ_SEL_MASK | \
+ CONTROL_SPI_LSB_FIRST | CONTROL_SPI_CLOCK_MODE_3)
+
+/* Segment Address Registers */
+#define SEGMENT_ADDR_REG0 0x30
+#define SEGMENT_ADDR_START(_r) ((((_r) >> 16) & 0xFF) << 23)
+#define SEGMENT_ADDR_END(_r) ((((_r) >> 24) & 0xFF) << 23)
+
+static u32 spi_control_fill_opcode(u8 opcode)
+{
+ return ((u32)(opcode)) << CONTROL_SPI_COMMAND_SHIFT;
+}
+
+static inline u32 aspeed_smc_chip_write_bit(struct aspeed_smc_chip *chip)
+{
+ return ((u32)1 << (chip->controller->info->we0 + chip->cs));
+}
+
+static void aspeed_smc_chip_check_config(struct aspeed_smc_chip *chip)
+{
+ struct aspeed_smc_controller *controller = chip->controller;
+ u32 reg;
+
+ reg = readl(controller->regs + CONFIG_REG);
+
+ if (!(reg & aspeed_smc_chip_write_bit(chip))) {
+ dev_dbg(controller->dev,
+ "config write is not set ! @%p: 0x%08x\n",
+ controller->regs + CONFIG_REG, reg);
+ reg |= aspeed_smc_chip_write_bit(chip);
+ writel(reg, controller->regs + CONFIG_REG);
+ }
+}
+
+static void aspeed_smc_start_user(struct spi_nor *nor)
+{
+ struct aspeed_smc_chip *chip = nor->priv;
+ u32 ctl = chip->ctl_val[smc_base];
+
+ /*
+ * When the chip is controlled in user mode, we need write
+ * access to send the opcodes to it. So check the config.
+ */
+ aspeed_smc_chip_check_config(chip);
+
+ ctl |= CONTROL_SPI_COMMAND_MODE_USER |
+ CONTROL_SPI_CE_STOP_ACTIVE_CONTROL;
+ writel(ctl, chip->ctl);
+
+ ctl &= ~CONTROL_SPI_CE_STOP_ACTIVE_CONTROL;
+ writel(ctl, chip->ctl);
+}
+
+static void aspeed_smc_stop_user(struct spi_nor *nor)
+{
+ struct aspeed_smc_chip *chip = nor->priv;
+
+ u32 ctl = chip->ctl_val[smc_read];
+ u32 ctl2 = ctl | CONTROL_SPI_COMMAND_MODE_USER |
+ CONTROL_SPI_CE_STOP_ACTIVE_CONTROL;
+
+ writel(ctl2, chip->ctl); /* stop user CE control */
+ writel(ctl, chip->ctl); /* default to fread or read */
+}
+
+static int aspeed_smc_read_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len)
+{
+ struct aspeed_smc_chip *chip = nor->priv;
+
+ mutex_lock(&chip->controller->mutex);
+
+ aspeed_smc_start_user(nor);
+ aspeed_smc_write_to_ahb(chip->base, &opcode, 1);
+ aspeed_smc_read_from_ahb(buf, chip->base, len);
+ aspeed_smc_stop_user(nor);
+
+ mutex_unlock(&chip->controller->mutex);
+
+ return 0;
+}
+
+static int aspeed_smc_write_reg(struct spi_nor *nor, u8 opcode, u8 *buf,
+ int len)
+{
+ struct aspeed_smc_chip *chip = nor->priv;
+
+ mutex_lock(&chip->controller->mutex);
+
+ aspeed_smc_start_user(nor);
+ aspeed_smc_write_to_ahb(chip->base, &opcode, 1);
+ aspeed_smc_write_to_ahb(chip->base, buf, len);
+ aspeed_smc_stop_user(nor);
+
+ mutex_unlock(&chip->controller->mutex);
+
+ return 0;
+}
+
+static void aspeed_smc_send_cmd_addr(struct spi_nor *nor, u8 cmd, u32 addr)
+{
+ struct aspeed_smc_chip *chip = nor->priv;
+ __be32 temp;
+ u32 cmdaddr;
+
+ switch (nor->addr_width) {
+ default:
+ WARN_ONCE(1, "Unexpected address width %u, defaulting to 3\n",
+ nor->addr_width);
+ /* FALLTHROUGH */
+ case 3:
+ cmdaddr = addr & 0xFFFFFF;
+
+ cmdaddr |= (u32)cmd << 24;
+
+ temp = cpu_to_be32(cmdaddr);
+ aspeed_smc_write_to_ahb(chip->base, &temp, 4);
+ break;
+ case 4:
+ temp = cpu_to_be32(addr);
+ aspeed_smc_write_to_ahb(chip->base, &cmd, 1);
+ aspeed_smc_write_to_ahb(chip->base, &temp, 4);
+ break;
+ }
+}
+
+static ssize_t aspeed_smc_read_user(struct spi_nor *nor, loff_t from,
+ size_t len, u_char *read_buf)
+{
+ struct aspeed_smc_chip *chip = nor->priv;
+
+ mutex_lock(&chip->controller->mutex);
+
+ aspeed_smc_start_user(nor);
+ aspeed_smc_send_cmd_addr(nor, nor->read_opcode, from);
+ aspeed_smc_read_from_ahb(read_buf, chip->base, len);
+ aspeed_smc_stop_user(nor);
+
+ mutex_unlock(&chip->controller->mutex);
+
+ return len;
+}
+
+static ssize_t aspeed_smc_write_user(struct spi_nor *nor, loff_t to, size_t len,
+ const u_char *write_buf)
+{
+ struct aspeed_smc_chip *chip = nor->priv;
+
+ mutex_lock(&chip->controller->mutex);
+
+ aspeed_smc_start_user(nor);
+ aspeed_smc_send_cmd_addr(nor, nor->program_opcode, to);
+ aspeed_smc_write_to_ahb(chip->base, write_buf, len);
+ aspeed_smc_stop_user(nor);
+
+ mutex_unlock(&chip->controller->mutex);
+
+ return len;
+}
+
+static int aspeed_smc_remove(struct platform_device *dev)
+{
+ struct aspeed_smc_chip *chip;
+ struct aspeed_smc_controller *controller = platform_get_drvdata(dev);
+ int n;
+
+ for (n = 0; n < controller->info->nce; n++) {
+ chip = controller->chips[n];
+ if (chip)
+ mtd_device_unregister(&chip->nor.mtd);
+ }
+
+ return 0;
+}
+
+static const struct of_device_id aspeed_smc_matches[] = {
+ { .compatible = "aspeed,ast2400-fmc", .data = &fmc_2400_info },
+ { .compatible = "aspeed,ast2400-smc", .data = &smc_2400_info },
+ { .compatible = "aspeed,ast2500-fmc", .data = &fmc_2500_info },
+ { .compatible = "aspeed,ast2500-smc", .data = &smc_2500_info },
+ { }
+};
+MODULE_DEVICE_TABLE(of, aspeed_smc_matches);
+
+static struct platform_device *
+of_platform_device_create_or_find(struct device_node *child,
+ struct device *parent)
+{
+ struct platform_device *cdev;
+
+ cdev = of_platform_device_create(child, NULL, parent);
+ if (!cdev)
+ cdev = of_find_device_by_node(child);
+ return cdev;
+}
+
+static void __iomem *window_start(struct aspeed_smc_controller *controller,
+ struct resource *r, unsigned int n)
+{
+ u32 offset = 0;
+ u32 reg;
+
+ if (controller->info->nce > 1) {
+ reg = readl(controller->regs + SEGMENT_ADDR_REG0 + n * 4);
+
+ if (SEGMENT_ADDR_START(reg) >= SEGMENT_ADDR_END(reg))
+ return NULL;
+
+ offset = SEGMENT_ADDR_START(reg) - r->start;
+ }
+
+ return controller->windows + offset;
+}
+
+static void aspeed_smc_chip_enable_write(struct aspeed_smc_chip *chip)
+{
+ struct aspeed_smc_controller *controller = chip->controller;
+ u32 reg;
+
+ reg = readl(controller->regs + CONFIG_REG);
+
+ reg |= aspeed_smc_chip_write_bit(chip);
+ writel(reg, controller->regs + CONFIG_REG);
+}
+
+static void aspeed_smc_chip_set_type(struct aspeed_smc_chip *chip, int type)
+{
+ struct aspeed_smc_controller *controller = chip->controller;
+ u32 reg;
+
+ reg = readl(controller->regs + CONFIG_REG);
+
+ chip->type = type;
+
+ reg &= ~(3 << (chip->cs * 2));
+ reg |= chip->type << (chip->cs * 2);
+ writel(reg, controller->regs + CONFIG_REG);
+}
+
+/*
+ * The AST2500 FMC and AST2400 FMC flash controllers should be
+ * strapped by hardware, or autodetected, but the AST2500 SPI flash
+ * needs to be set.
+ */
+static void aspeed_smc_chip_set_4b(struct aspeed_smc_chip *chip)
+{
+ struct aspeed_smc_controller *controller = chip->controller;
+ u32 reg;
+
+ if (chip->controller->info == &smc_2500_info) {
+ reg = readl(controller->regs + CE_CONTROL_REG);
+ reg |= 1 << chip->cs;
+ writel(reg, controller->regs + CE_CONTROL_REG);
+ }
+}
+
+/*
+ * The AST2400 SPI flash controller does not have a CE Control
+ * register. It uses the CE0 control register to set 4Byte mode at the
+ * controller level.
+ */
+static void aspeed_smc_chip_set_4b_smc_2400(struct aspeed_smc_chip *chip)
+{
+ chip->ctl_val[smc_base] |= CONTROL_SPI_IO_ADDRESS_4B;
+ chip->ctl_val[smc_read] |= CONTROL_SPI_IO_ADDRESS_4B;
+}
+
+static int aspeed_smc_chip_setup_init(struct aspeed_smc_chip *chip,
+ struct resource *r)
+{
+ struct aspeed_smc_controller *controller = chip->controller;
+ const struct aspeed_smc_info *info = controller->info;
+ u32 reg, base_reg;
+
+ /*
+ * Always turn on the write enable bit to allow opcodes to be
+ * sent in user mode.
+ */
+ aspeed_smc_chip_enable_write(chip);
+
+ /* The driver only supports SPI type flash for the moment */
+ if (info->hastype)
+ aspeed_smc_chip_set_type(chip, smc_type_spi);
+
+ /*
+ * Configure chip base address in memory
+ */
+ chip->base = window_start(controller, r, chip->cs);
+ if (!chip->base) {
+ dev_warn(chip->nor.dev, "CE segment window closed.\n");
+ return -1;
+ }
+
+ /*
+ * Read the existing control register to get basic values.
+ *
+ * XXX This register probably needs more sanitation.
+ *
+ * Do we need support for mode 3 vs mode 0 clock phasing?
+ */
+ reg = readl(chip->ctl);
+ dev_dbg(controller->dev, "control register: %08x\n", reg);
+
+ base_reg = reg & CONTROL_SPI_KEEP_MASK;
+ if (base_reg != reg) {
+ dev_info(controller->dev,
+ "control register changed to: %08x\n",
+ base_reg);
+ }
+ chip->ctl_val[smc_base] = base_reg;
+
+ /*
+ * Retain the prior value of the control register as the
+ * default if it was normal access mode. Otherwise start with
+ * the sanitized base value set to read mode.
+ */
+ if ((reg & CONTROL_SPI_COMMAND_MODE_MASK) ==
+ CONTROL_SPI_COMMAND_MODE_NORMAL)
+ chip->ctl_val[smc_read] = reg;
+ else
+ chip->ctl_val[smc_read] = chip->ctl_val[smc_base] |
+ CONTROL_SPI_COMMAND_MODE_NORMAL;
+
+ dev_dbg(controller->dev, "default control register: %08x\n",
+ chip->ctl_val[smc_read]);
+ return 0;
+}
+
+static int aspeed_smc_chip_setup_finish(struct aspeed_smc_chip *chip)
+{
+ struct aspeed_smc_controller *controller = chip->controller;
+ const struct aspeed_smc_info *info = controller->info;
+ u32 cmd;
+
+ if (chip->nor.addr_width == 4 && info->set_4b)
+ info->set_4b(chip);
+
+ /*
+ * base mode has not been optimized yet. use it for writes.
+ */
+ chip->ctl_val[smc_write] = chip->ctl_val[smc_base] |
+ spi_control_fill_opcode(chip->nor.program_opcode) |
+ CONTROL_SPI_COMMAND_MODE_WRITE;
+
+ dev_dbg(controller->dev, "write control register: %08x\n",
+ chip->ctl_val[smc_write]);
+
+ /*
+ * XXX TODO
+ * Adjust clocks if fast read and write are supported.
+ * Interpret spi-nor flags to adjust controller settings.
+ * Check if resource size big enough for detected chip and
+ * add support assisted (normal or fast-) read and dma.
+ */
+ switch (chip->nor.flash_read) {
+ case SPI_NOR_NORMAL:
+ cmd = CONTROL_SPI_COMMAND_MODE_NORMAL;
+ break;
+ case SPI_NOR_FAST:
+ cmd = CONTROL_SPI_COMMAND_MODE_FREAD;
+ break;
+ default:
+ dev_err(chip->nor.dev, "unsupported SPI read mode\n");
+ return -EINVAL;
+ }
+
+ chip->ctl_val[smc_read] |= cmd |
+ CONTROL_SPI_IO_DUMMY_CYCLES_SET(chip->nor.read_dummy / 8);
+
+ dev_dbg(controller->dev, "base control register: %08x\n",
+ chip->ctl_val[smc_read]);
+ return 0;
+}
+
+static int aspeed_smc_probe(struct platform_device *pdev)
+{
+ struct aspeed_smc_controller *controller;
+ const struct of_device_id *match;
+ const struct aspeed_smc_info *info;
+ struct resource *r;
+ struct device_node *child;
+ int err = 0;
+ unsigned int n;
+
+ match = of_match_device(aspeed_smc_matches, &pdev->dev);
+ if (!match || !match->data)
+ return -ENODEV;
+ info = match->data;
+
+ controller = devm_kzalloc(&pdev->dev, sizeof(*controller) +
+ info->nce * sizeof(controller->chips[0]), GFP_KERNEL);
+ if (!controller)
+ return -ENOMEM;
+ controller->info = info;
+
+ mutex_init(&controller->mutex);
+ platform_set_drvdata(pdev, controller);
+
+ r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ controller->regs = devm_ioremap_resource(&pdev->dev, r);
+ if (IS_ERR(controller->regs))
+ return PTR_ERR(controller->regs);
+
+ r = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ controller->windows = devm_ioremap_resource(&pdev->dev, r);
+ if (IS_ERR(controller->windows))
+ return PTR_ERR(controller->windows);
+
+ controller->dev = &pdev->dev;
+
+ /* The pinmux or bootloader will disable the legacy mode controller */
+
+ /*
+ * XXX Need to add arbitration to the SMC (BIOS) controller if access
+ * is shared by the host.
+ */
+ for_each_available_child_of_node(controller->dev->of_node, child) {
+ struct platform_device *cdev;
+ struct aspeed_smc_chip *chip;
+
+ /* This version does not support nand or nor flash devices. */
+ if (!of_device_is_compatible(child, "jedec,spi-nor"))
+ continue;
+
+ /*
+ * create a platform device from the of node. If the device
+ * already was created (eg from a prior bind/unbind cycle)
+ * reuse it.
+ *
+ * The creating the device node for the child here allows its
+ * use for error reporting via dev_err below.
+ */
+ cdev = of_platform_device_create_or_find(child,
+ controller->dev);
+ if (!cdev)
+ continue;
+
+ err = of_property_read_u32(child, "reg", &n);
+ if (err == -EINVAL && info->nce == 1)
+ n = 0;
+ else if (err || n >= info->nce)
+ continue;
+ if (controller->chips[n]) {
+ dev_err(&cdev->dev,
+ "chip-id %u already in use in use by %s\n",
+ n, dev_name(controller->chips[n]->nor.dev));
+ continue;
+ }
+
+ chip = devm_kzalloc(controller->dev, sizeof(*chip), GFP_KERNEL);
+ if (!chip)
+ continue;
+ chip->controller = controller;
+ chip->ctl = controller->regs + info->ctl0 + n * 4;
+ chip->cs = n;
+
+ chip->nor.dev = &cdev->dev;
+ chip->nor.priv = chip;
+ spi_nor_set_flash_node(&chip->nor, child);
+ chip->nor.mtd.name = of_get_property(child, "label", NULL);
+ chip->nor.read = aspeed_smc_read_user;
+ chip->nor.write = aspeed_smc_write_user;
+ chip->nor.read_reg = aspeed_smc_read_reg;
+ chip->nor.write_reg = aspeed_smc_write_reg;
+
+ err = aspeed_smc_chip_setup_init(chip, r);
+ if (err)
+ continue;
+
+ /*
+ * XXX Add support for SPI_NOR_QUAD and SPI_NOR_DUAL attach
+ * when board support is present as determined by of property.
+ */
+ err = spi_nor_scan(&chip->nor, NULL, SPI_NOR_NORMAL);
+ if (err)
+ continue;
+
+ err = aspeed_smc_chip_setup_finish(chip);
+ if (err)
+ continue;
+
+ err = mtd_device_register(&chip->nor.mtd, NULL, 0);
+ if (err)
+ continue;
+ controller->chips[n] = chip;
+ }
+
+ /* Were any children registered? */
+ for (n = 0; n < info->nce; n++)
+ if (controller->chips[n])
+ break;
+
+ if (n == info->nce)
+ return -ENODEV;
+
+ return 0;
+}
+
+static struct platform_driver aspeed_smc_driver = {
+ .probe = aspeed_smc_probe,
+ .remove = aspeed_smc_remove,
+ .driver = {
+ .name = DEVICE_NAME,
+ .of_match_table = aspeed_smc_matches,
+ }
+};
+
+module_platform_driver(aspeed_smc_driver);
+
+MODULE_DESCRIPTION("ASPEED Static Memory Controller Driver");
+MODULE_AUTHOR("Milton Miller");
+MODULE_LICENSE("GPL v2");
--
2.7.4
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply related
* Re: [PATCH V5 2/3] ARM64 LPC: Add missing range exception for special ISA
From: Mark Rutland @ 2016-11-09 11:20 UTC (permalink / raw)
To: Benjamin Herrenschmidt
Cc: zhichang.yuan, catalin.marinas, will.deacon, robh+dt, bhelgaas,
olof, arnd, linux-arm-kernel, lorenzo.pieralisi, linux-kernel,
linuxarm, devicetree, linux-pci, linux-serial, minyard,
liviu.dudau, zourongrong, john.garry, gabriele.paoloni,
zhichang.yuan02, kantyzc, xuwei5, marc.zyngier
In-Reply-To: <1478646779.7430.66.camel@kernel.crashing.org>
On Wed, Nov 09, 2016 at 10:12:59AM +1100, Benjamin Herrenschmidt wrote:
> On Tue, 2016-11-08 at 11:49 +0000, Mark Rutland wrote:
> > I believe that we could theoretically have multiple independent LPC/ISA
> > busses, as is possible with PCI on !x86 systems. If the current ISA code
> > assumes a singleton bus, I think that's something that needs to be fixed
> > up more generically.
> >
> > I don't see why we should need any architecture-specific code here. Why
> > can we not fix up the ISA bus code in drivers/of/address.c such that it
> > handles multiple ISA bus instances, and translates all sub-device
> > addresses relative to the specific bus instance?
>
> What in that code prevents that today ?
It appears I was mistaken w.r.t. the singleton comment. We can already
translate MMIO->MMIO addresses per-instance (in the presence of a ranges
property).
The big change would be to handle !MMIO translations, for which we'd
need a runtime registry of ISA bus instance to find the relevant
accessor ops and instance-specific data.
Thanks,
Mark.
^ permalink raw reply
* Re: [PATCH V5 1/3] ARM64 LPC: Indirect ISA port IO introduced
From: John Garry @ 2016-11-09 11:29 UTC (permalink / raw)
To: Arnd Bergmann, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
Cc: Will Deacon, mark.rutland-5wv7dgnIgG8,
catalin.marinas-5wv7dgnIgG8,
gabriele.paoloni-hv44wF8Li93QT0dZR+AlfA,
linux-pci-u79uwXL29TY76Z2rM5mHXA, liviu.dudau-5wv7dgnIgG8,
linuxarm-hv44wF8Li93QT0dZR+AlfA, lorenzo.pieralisi-5wv7dgnIgG8,
minyard-HInyCGIudOg, xuwei5-C8/M+/jPZTeaMJb+Lgu22Q,
linux-serial-u79uwXL29TY76Z2rM5mHXA,
benh-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r,
devicetree-u79uwXL29TY76Z2rM5mHXA,
zhichang.yuan02-Re5JQEeQqe8AvxtiuMwx3w,
olof-nZhT3qVonbNeoWH0uzbU5w, robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
bhelgaas-hpIqsD4AKlfQT0dZR+AlfA, kantyzc-9Onoh4P/yGk,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, zhichang.yuan,
zourongrong-Re5JQEeQqe8AvxtiuMwx3w
In-Reply-To: <2479288.4UmF9SBrq1@wuerfel>
On 08/11/2016 22:35, Arnd Bergmann wrote:
> On Tuesday, November 8, 2016 4:49:49 PM CET Will Deacon wrote:
>> On Tue, Nov 08, 2016 at 04:33:44PM +0000, John Garry wrote:
>>> On 08/11/2016 16:12, Will Deacon wrote:
>>>> On Tue, Nov 08, 2016 at 11:47:07AM +0800, zhichang.yuan wrote:
>
>>>> Is there no way to make this slightly more generic, so that it can be
>>>> re-used elsewhere? For example, if struct extio_ops was common, then
>>>> you could have the singleton (which maybe should be an interval tree?),
>>>> type definition, setter function and the BUILD_EXTIO invocations
>>>> somewhere generic, rather than squirelled away in the arch backend.
>>>>
>>> The concern would be that some architecture which uses generic higher-level
>>> ISA accessor ops, but have IO space, could be affected.
>>
>> You're already adding a Kconfig symbol for this stuff, so you can keep
>> that if you don't want it on other architectures. I'm just arguing that
>> plumbing drivers directly into arch code via arm64_set_extops is not
>> something I'm particularly fond of, especially when it looks like it
>> could be avoided with a small amount of effort.
>
> Agreed, I initially suggested putting this into arch/arm64/, but there isn't
> really a reason why it couldn't just live in lib/ with the header file
> bits moved to include/asm-generic/io.h which we already use.
>
Right, Zhichang will check the logistics of this. The generic io.h is
quite clean, so as long as you don't mind new build switches of this
nature being added, it should be ok; and we'll plan on moving extio.h
into include/asm-generic as well.
Cheers,
John
> Arnd
>
> .
>
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH] ata: xgene: Enable NCQ support for APM X-Gene SATA controller hardware v1.1
From: Rameshwar Sahu @ 2016-11-09 11:39 UTC (permalink / raw)
To: Olof Johansson, tj, Arnd Bergmann
Cc: Devicetree List, mlangsdo, linux-scsi, Jon Masters,
Rameshwar Prasad Sahu, patches, linux-ide, linux-arm
In-Reply-To: <1476962064-8775-1-git-send-email-rsahu@apm.com>
Hi Olof/Tejun,
On Thu, Oct 20, 2016 at 4:44 PM, Rameshwar Prasad Sahu <rsahu@apm.com> wrote:
>
> This patch enables NCQ support for APM X-Gene SATA controller
> hardware v1.1 that was broken with hardware v1.0.
>
> Signed-off-by: Rameshwar Prasad Sahu <rsahu@apm.com>
> ---
> drivers/ata/ahci_xgene.c | 14 ++++++++------
> 1 files changed, 8 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/ata/ahci_xgene.c b/drivers/ata/ahci_xgene.c
> index 73b19b2..8b88be9 100644
> --- a/drivers/ata/ahci_xgene.c
> +++ b/drivers/ata/ahci_xgene.c
> @@ -87,6 +87,7 @@
>
> enum xgene_ahci_version {
> XGENE_AHCI_V1 = 1,
> + XGENE_AHCI_V1_1,
> XGENE_AHCI_V2,
> };
>
> @@ -734,6 +735,7 @@ static struct scsi_host_template ahci_platform_sht = {
> #ifdef CONFIG_ACPI
> static const struct acpi_device_id xgene_ahci_acpi_match[] = {
> { "APMC0D0D", XGENE_AHCI_V1},
> + { "APMC0D67", XGENE_AHCI_V1_1},
> { "APMC0D32", XGENE_AHCI_V2},
> {},
> };
> @@ -742,6 +744,7 @@ MODULE_DEVICE_TABLE(acpi, xgene_ahci_acpi_match);
>
> static const struct of_device_id xgene_ahci_of_match[] = {
> {.compatible = "apm,xgene-ahci", .data = (void *) XGENE_AHCI_V1},
> + {.compatible = "apm,xgene-ahci-v1-1", .data = (void *) XGENE_AHCI_V1_1},
> {.compatible = "apm,xgene-ahci-v2", .data = (void *) XGENE_AHCI_V2},
> {},
> };
> @@ -755,8 +758,7 @@ static int xgene_ahci_probe(struct platform_device *pdev)
> struct resource *res;
> const struct of_device_id *of_devid;
> enum xgene_ahci_version version = XGENE_AHCI_V1;
> - const struct ata_port_info *ppi[] = { &xgene_ahci_v1_port_info,
> - &xgene_ahci_v2_port_info };
> + const struct ata_port_info *ppi;
> int rc;
>
> hpriv = ahci_platform_get_resources(pdev);
> @@ -821,8 +823,6 @@ static int xgene_ahci_probe(struct platform_device *pdev)
> dev_warn(&pdev->dev, "%s: Error reading device info. Assume version1\n",
> __func__);
> version = XGENE_AHCI_V1;
> - } else if (info->valid & ACPI_VALID_CID) {
> - version = XGENE_AHCI_V2;
> }
> }
> }
> @@ -858,18 +858,20 @@ skip_clk_phy:
>
> switch (version) {
> case XGENE_AHCI_V1:
> + ppi = &xgene_ahci_v1_port_info;
> hpriv->flags = AHCI_HFLAG_NO_NCQ;
> break;
> case XGENE_AHCI_V2:
> + ppi = &xgene_ahci_v2_port_info;
> hpriv->flags |= AHCI_HFLAG_YES_FBS;
> hpriv->irq_handler = xgene_ahci_irq_intr;
> break;
> default:
> + ppi = &xgene_ahci_v1_port_info;
> break;
> }
>
> - rc = ahci_platform_init_host(pdev, hpriv, ppi[version - 1],
> - &ahci_platform_sht);
> + rc = ahci_platform_init_host(pdev, hpriv, ppi, &ahci_platform_sht);
> if (rc)
> goto disable_resources;
>
> --
> 1.7.1
Any comment on above patch ??
^ permalink raw reply
* Re: [PATCH V5 2/3] ARM64 LPC: Add missing range exception for special ISA
From: liviu.dudau-5wv7dgnIgG8 @ 2016-11-09 11:39 UTC (permalink / raw)
To: zhichang.yuan
Cc: catalin.marinas-5wv7dgnIgG8, will.deacon-5wv7dgnIgG8,
robh+dt-DgEjT+Ai2ygdnm+yROfE0A, bhelgaas-hpIqsD4AKlfQT0dZR+AlfA,
mark.rutland-5wv7dgnIgG8, olof-nZhT3qVonbNeoWH0uzbU5w,
arnd-r2nGTMty4D4,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
lorenzo.pieralisi-5wv7dgnIgG8,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linuxarm-hv44wF8Li93QT0dZR+AlfA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-pci-u79uwXL29TY76Z2rM5mHXA,
linux-serial-u79uwXL29TY76Z2rM5mHXA, minyard-HInyCGIudOg,
benh-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r,
zourongrong-Re5JQEeQqe8AvxtiuMwx3w,
john.garry-hv44wF8Li93QT0dZR+AlfA,
gabriele.paoloni-hv44wF8Li93QT0dZR+AlfA,
zhichang.yuan02-Re5JQEeQqe8AvxtiuMwx3w, kantyzc-9Onoh4P/yGk,
xuwei5-C8/M+/jPZTeaMJb+Lgu22Q
In-Reply-To: <1478576829-112707-3-git-send-email-yuanzhichang-C8/M+/jPZTeaMJb+Lgu22Q@public.gmane.org>
On Tue, Nov 08, 2016 at 11:47:08AM +0800, zhichang.yuan wrote:
> This patch solves two issues:
> 1) parse and get the right I/O range from DTS node whose parent does not
> define the corresponding ranges property;
>
> There are some special ISA/LPC devices that work on a specific I/O range where
> it is not correct to specify a ranges property in DTS parent node as cpu
> addresses translated from DTS node are only for memory space on some
> architectures, such as Arm64. Without the parent 'ranges' property, current
> of_translate_address() return an error.
> Here we add a fixup function, of_get_isa_indirect_io(). During the OF address
> translation, this fixup will be called to check the 'reg' address to be
> translating is for those sepcial ISA/LPC devices and get the I/O range
> directly from the 'reg' property.
>
> 2) eliminate the I/O range conflict risk with PCI/PCIE leagecy I/O device;
>
> The current __of_address_to_resource() always translates the I/O range to PIO.
> But this processing is not suitable for our ISA/LPC devices whose I/O range is
> not cpu address(Arnd had stressed this in his comments on V2,V3 patch-set).
> Here, we bypass the mapping between cpu address and PIO for the special
> ISA/LPC devices. But to drive these ISA/LPC devices, a I/O port address below
> PCIBIOS_MIN_IO is needed by in*/out*(). Which means there is conflict risk
> between I/O range of [0, PCIBIOS_MIN_IO) and PCI/PCIE legacy I/O range of [0,
> IO_SPACE_LIMIT).
> To avoid the I/O conflict, this patch reserve the I/O range below
> PCIBIOS_MIN_IO.
>
> Signed-off-by: zhichang.yuan <yuanzhichang-C8/M+/jPZTeaMJb+Lgu22Q@public.gmane.org>
> Signed-off-by: Gabriele Paoloni <gabriele.paoloni-hv44wF8Li93QT0dZR+AlfA@public.gmane.org>
> ---
> .../arm/hisilicon/hisilicon-low-pin-count.txt | 31 ++++++++++++
> arch/arm64/include/asm/io.h | 6 +++
> arch/arm64/kernel/extio.c | 25 ++++++++++
> drivers/of/address.c | 56 +++++++++++++++++++++-
> drivers/pci/pci.c | 6 +--
> include/linux/of_address.h | 17 +++++++
> include/linux/pci.h | 8 ++++
> 7 files changed, 145 insertions(+), 4 deletions(-)
> create mode 100644 Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-count.txt
>
> diff --git a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-count.txt b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-count.txt
> new file mode 100644
> index 0000000..13c8ddd
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-count.txt
> @@ -0,0 +1,31 @@
> +Hisilicon Hip06 low-pin-count device
> + Usually LPC controller is part of PCI host bridge, so the legacy ISA ports
> + locate on LPC bus can be accessed direclty. But some SoCs have independent
> + LPC controller, and access the legacy ports by triggering LPC I/O cycles.
> + Hisilicon Hip06 implements this LPC device.
> +
> +Required properties:
> +- compatible: should be "hisilicon,low-pin-count"
> +- #address-cells: must be 2 which stick to the ISA/EISA binding doc.
> +- #size-cells: must be 1 which stick to the ISA/EISA binding doc.
> +- reg: base memory range where the register set of this device is mapped.
> +
> +Note:
> + The node name before '@' must be "isa" to represent the binding stick to the
> + ISA/EISA binding specification.
> +
> +Example:
> +
> +isa@a01b0000 {
> + compatible = "hisilicom,low-pin-count";
> + #address-cells = <2>;
> + #size-cells = <1>;
> + reg = <0x0 0xa01b0000 0x0 0x1000>;
> +
> + ipmi0: bt@e4 {
> + compatible = "ipmi-bt";
> + device_type = "ipmi";
> + reg = <0x01 0xe4 0x04>;
> + status = "disabled";
> + };
> +};
This documentation file needs to be part of the next patch. It has nothing to do with
what you are trying to fix here.
> diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h
> index 136735d..c26b7cc 100644
> --- a/arch/arm64/include/asm/io.h
> +++ b/arch/arm64/include/asm/io.h
> @@ -175,6 +175,12 @@ static inline u64 __raw_readq(const volatile void __iomem *addr)
> #define outsl outsl
>
> DECLARE_EXTIO(l, u32)
> +
> +#define indirect_io_enabled indirect_io_enabled
> +extern bool indirect_io_enabled(void);
> +
> +#define addr_is_indirect_io addr_is_indirect_io
> +extern int addr_is_indirect_io(u64 taddr);
> #endif
>
>
> diff --git a/arch/arm64/kernel/extio.c b/arch/arm64/kernel/extio.c
> index 647b3fa..3d45fa8 100644
> --- a/arch/arm64/kernel/extio.c
> +++ b/arch/arm64/kernel/extio.c
> @@ -19,6 +19,31 @@
>
> struct extio_ops *arm64_extio_ops;
>
> +/**
> + * indirect_io_enabled - check whether indirectIO is enabled.
> + * arm64_extio_ops will be set only when indirectIO mechanism had been
> + * initialized.
> + *
> + * Returns true when indirectIO is enabled.
> + */
> +bool indirect_io_enabled(void)
> +{
> + return arm64_extio_ops ? true : false;
> +}
> +
> +/**
> + * addr_is_indirect_io - check whether the input taddr is for indirectIO.
> + * @taddr: the io address to be checked.
> + *
> + * Returns 1 when taddr is in the range; otherwise return 0.
> + */
> +int addr_is_indirect_io(u64 taddr)
> +{
> + if (arm64_extio_ops->start > taddr || arm64_extio_ops->end < taddr)
start >= taddr ?
> + return 0;
> +
> + return 1;
> +}
>
> BUILD_EXTIO(b, u8)
>
> diff --git a/drivers/of/address.c b/drivers/of/address.c
> index 02b2903..cc2a05d 100644
> --- a/drivers/of/address.c
> +++ b/drivers/of/address.c
> @@ -479,6 +479,50 @@ static int of_empty_ranges_quirk(struct device_node *np)
> return false;
> }
>
> +
> +/*
> + * of_isa_indirect_io - get the IO address from some isa reg property value.
> + * For some isa/lpc devices, no ranges property in ancestor node.
> + * The device addresses are described directly in their regs property.
> + * This fixup function will be called to get the IO address of isa/lpc
> + * devices when the normal of_translation failed.
> + *
> + * @parent: points to the parent dts node;
> + * @bus: points to the of_bus which can be used to parse address;
> + * @addr: the address from reg property;
> + * @na: the address cell counter of @addr;
> + * @presult: store the address paresed from @addr;
> + *
> + * return 1 when successfully get the I/O address;
> + * 0 will return for some failures.
Bah, you are returning a signed int, why 0 for failure? Return a negative value with
error codes. Otherwise change the return value into a bool.
> + */
> +static int of_get_isa_indirect_io(struct device_node *parent,
> + struct of_bus *bus, __be32 *addr,
> + int na, u64 *presult)
> +{
> + unsigned int flags;
> + unsigned int rlen;
> +
> + /* whether support indirectIO */
> + if (!indirect_io_enabled())
> + return 0;
> +
> + if (!of_bus_isa_match(parent))
> + return 0;
> +
> + flags = bus->get_flags(addr);
> + if (!(flags & IORESOURCE_IO))
> + return 0;
> +
> + /* there is ranges property, apply the normal translation directly. */
s/there is ranges/if we have a 'ranges'/
> + if (of_get_property(parent, "ranges", &rlen))
> + return 0;
> +
> + *presult = of_read_number(addr + 1, na - 1);
> + /* this fixup is only valid for specific I/O range. */
> + return addr_is_indirect_io(*presult);
> +}
> +
> static int of_translate_one(struct device_node *parent, struct of_bus *bus,
> struct of_bus *pbus, __be32 *addr,
> int na, int ns, int pna, const char *rprop)
> @@ -595,6 +639,15 @@ static u64 __of_translate_address(struct device_node *dev,
> result = of_read_number(addr, na);
> break;
> }
> + /*
> + * For indirectIO device which has no ranges property, get
> + * the address from reg directly.
> + */
> + if (of_get_isa_indirect_io(dev, bus, addr, na, &result)) {
> + pr_debug("isa indirectIO matched(%s)..addr = 0x%llx\n",
> + of_node_full_name(dev), result);
> + break;
> + }
>
> /* Get new parent bus and counts */
> pbus = of_match_bus(parent);
> @@ -688,8 +741,9 @@ static int __of_address_to_resource(struct device_node *dev,
> if (taddr == OF_BAD_ADDR)
> return -EINVAL;
> memset(r, 0, sizeof(struct resource));
> - if (flags & IORESOURCE_IO) {
> + if (flags & IORESOURCE_IO && taddr >= PCIBIOS_MIN_IO) {
> unsigned long port;
> +
> port = pci_address_to_pio(taddr);
> if (port == (unsigned long)-1)
> return -EINVAL;
> diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> index ba34907..1a08511 100644
> --- a/drivers/pci/pci.c
> +++ b/drivers/pci/pci.c
> @@ -3263,7 +3263,7 @@ int __weak pci_register_io_range(phys_addr_t addr, resource_size_t size)
>
> #ifdef PCI_IOBASE
> struct io_range *range;
> - resource_size_t allocated_size = 0;
> + resource_size_t allocated_size = PCIBIOS_MIN_IO;
>
> /* check if the range hasn't been previously recorded */
> spin_lock(&io_range_lock);
> @@ -3312,7 +3312,7 @@ phys_addr_t pci_pio_to_address(unsigned long pio)
>
> #ifdef PCI_IOBASE
> struct io_range *range;
> - resource_size_t allocated_size = 0;
> + resource_size_t allocated_size = PCIBIOS_MIN_IO;
Have you checked that pci_pio_to_address still returns valid values after this? I know that
you are trying to take into account PCIBIOS_MIN_IO limit when allocating reserving the IO ranges,
but the values added in the io_range_list are still starting from zero, no from PCIBIOS_MIN_IO,
so the calculation of the address in this function could return negative values casted to pci_addr_t.
Maybe you want to adjust the range->start value in pci_register_io_range() as well to have it
offset by PCIBIOS_MIN_IO as well.
Best regards,
Liviu
>
> if (pio > IO_SPACE_LIMIT)
> return address;
> @@ -3335,7 +3335,7 @@ unsigned long __weak pci_address_to_pio(phys_addr_t address)
> {
> #ifdef PCI_IOBASE
> struct io_range *res;
> - resource_size_t offset = 0;
> + resource_size_t offset = PCIBIOS_MIN_IO;
> unsigned long addr = -1;
>
> spin_lock(&io_range_lock);
> diff --git a/include/linux/of_address.h b/include/linux/of_address.h
> index 3786473..deec469 100644
> --- a/include/linux/of_address.h
> +++ b/include/linux/of_address.h
> @@ -24,6 +24,23 @@ struct of_pci_range {
> #define for_each_of_pci_range(parser, range) \
> for (; of_pci_range_parser_one(parser, range);)
>
> +
> +#ifndef indirect_io_enabled
> +#define indirect_io_enabled indirect_io_enabled
> +static inline bool indirect_io_enabled(void)
> +{
> + return false;
> +}
> +#endif
> +
> +#ifndef addr_is_indirect_io
> +#define addr_is_indirect_io addr_is_indirect_io
> +static inline int addr_is_indirect_io(u64 taddr)
> +{
> + return 0;
> +}
> +#endif
> +
> /* Translate a DMA address from device space to CPU space */
> extern u64 of_translate_dma_address(struct device_node *dev,
> const __be32 *in_addr);
> diff --git a/include/linux/pci.h b/include/linux/pci.h
> index 0e49f70..7f6bbb6 100644
> --- a/include/linux/pci.h
> +++ b/include/linux/pci.h
> @@ -2130,4 +2130,12 @@ static inline bool pci_ari_enabled(struct pci_bus *bus)
> /* provide the legacy pci_dma_* API */
> #include <linux/pci-dma-compat.h>
>
> +/*
> + * define this macro here to refrain from compilation error for some
> + * platforms. Please keep this macro at the end of this header file.
> + */
> +#ifndef PCIBIOS_MIN_IO
> +#define PCIBIOS_MIN_IO 0
> +#endif
> +
> #endif /* LINUX_PCI_H */
> --
> 1.9.1
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-pci" in
> the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
--
====================
| I would like to |
| fix the world, |
| but they're not |
| giving me the |
\ source code! /
---------------
¯\_(ツ)_/¯
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH v6 02/14] clk: qcom: Add rcg ops to return floor value closest to the requested rate
From: Ritesh Harjani @ 2016-11-09 11:53 UTC (permalink / raw)
To: Stephen Boyd
Cc: ulf.hansson, linux-mmc, adrian.hunter, shawn.lin, devicetree,
linux-clk, david.brown, andy.gross, linux-arm-msm, georgi.djakov,
alex.lemberg, mateusz.nowak, Yuliy.Izrailov, asutoshd, kdorfman,
david.griego, stummala, venkatg, rnayak, pramod.gurav
In-Reply-To: <20161108230217.GM16026@codeaurora.org>
Hi Stephen,
Thanks for the review.
On 11/9/2016 4:32 AM, Stephen Boyd wrote:
> On 11/07, Ritesh Harjani wrote:
>> diff --git a/drivers/clk/qcom/clk-rcg.h b/drivers/clk/qcom/clk-rcg.h
>> index b904c33..1b3e8d2 100644
>> --- a/drivers/clk/qcom/clk-rcg.h
>> +++ b/drivers/clk/qcom/clk-rcg.h
>> @@ -173,6 +173,7 @@ struct clk_rcg2 {
>> #define to_clk_rcg2(_hw) container_of(to_clk_regmap(_hw), struct clk_rcg2, clkr)
>>
>> extern const struct clk_ops clk_rcg2_ops;
>> +extern const struct clk_ops clk_rcg2_floor_ops;
>> extern const struct clk_ops clk_rcg2_shared_ops;
>> extern const struct clk_ops clk_edp_pixel_ops;
>> extern const struct clk_ops clk_byte_ops;
>> diff --git a/drivers/clk/qcom/clk-rcg2.c b/drivers/clk/qcom/clk-rcg2.c
>> index a071bba..04433a6 100644
>> --- a/drivers/clk/qcom/clk-rcg2.c
>> +++ b/drivers/clk/qcom/clk-rcg2.c
>> @@ -47,6 +47,11 @@
>> #define N_REG 0xc
>> #define D_REG 0x10
>>
>> +enum {
>> + FLOOR,
>> + CEIL,
>> +};
>
> Give it a name.
Yes, sure. I will keep it as freq_policy.
>
>> +
>> static int clk_rcg2_is_enabled(struct clk_hw *hw)
>> {
>> struct clk_rcg2 *rcg = to_clk_rcg2(hw);
>> @@ -176,15 +181,25 @@ static int clk_rcg2_set_parent(struct clk_hw *hw, u8 index)
>> return calc_rate(parent_rate, m, n, mode, hid_div);
>> }
>>
>> -static int _freq_tbl_determine_rate(struct clk_hw *hw,
>> - const struct freq_tbl *f, struct clk_rate_request *req)
>> +static int _freq_tbl_determine_rate(struct clk_hw *hw, const struct freq_tbl *f,
>> + struct clk_rate_request *req, bool match)
>
> Use the enum please. Also name it something besides match.
> policy?
Sure. (freq_policy)
>
>> {
>> unsigned long clk_flags, rate = req->rate;
>> struct clk_hw *p;
>> struct clk_rcg2 *rcg = to_clk_rcg2(hw);
>> int index;
>>
>> - f = qcom_find_freq(f, rate);
>> + switch (match) {
>> + case FLOOR:
>> + f = qcom_find_freq_floor(f, rate);
>> + break;
>> + case CEIL:
>> + f = qcom_find_freq(f, rate);
>> + break;
>> + default:
>> + return -EINVAL;
>> + };
>> +
>> if (!f)
>> return -EINVAL;
>>
>> diff --git a/drivers/clk/qcom/common.c b/drivers/clk/qcom/common.c
>> index fffcbaf..cf6b87f 100644
>> --- a/drivers/clk/qcom/common.c
>> +++ b/drivers/clk/qcom/common.c
>> @@ -46,6 +46,32 @@ struct freq_tbl *qcom_find_freq(const struct freq_tbl *f, unsigned long rate)
>> }
>> EXPORT_SYMBOL_GPL(qcom_find_freq);
>>
>> +const
>> +struct freq_tbl *qcom_find_freq_floor(const struct freq_tbl *f,
>
> We can't put const and struct on the same line?
Ok sure.
>
>> + unsigned long rate)
>> +{
>> + int size = 0;
>> +
>> + if (!f)
>> + return NULL;
>> +
>> + /*
>> + * The freq table has entries in the ascending order of frequencies
>> + * To find the floor for a given frequency, we need to do a reverse
>> + * lookup of the table
>> + */
>> + for (; f->freq; f++, size++)
>> + ;
>> +
>> + for (f--; size; f--, size--)
>> + if (rate >= f->freq)
>> + return f;
>
> I don't understand why we can't do this while iterating through
> the table. We shouldn't need to size up the frequency table first.
>
> const struct freq_tbl *best = NULL;
>
> for ( ; f->freq; f++) {
> if (rate >= f->freq)
> best = f->freq;
> else
> break;
> }
>
> return best;
>
Yes, will do above change.
>> +
>> + /* could not find any rates lower than *rate* */
>
>> + return NULL;
>> +}
>> +EXPORT_SYMBOL_GPL(qcom_find_freq_floor);
>
--
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
^ permalink raw reply
* Re: [PATCH v2 1/3] hwmon: (mcp3021) rework for DT support
From: Guenter Roeck @ 2016-11-09 11:53 UTC (permalink / raw)
To: Clemens Gruber, linux-hwmon-u79uwXL29TY76Z2rM5mHXA
Cc: Rob Herring, Jean Delvare, devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-doc-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20161027223345.16733-1-clemens.gruber-lZxf/j91sTNWk0Htik3J/w@public.gmane.org>
On 10/27/2016 03:33 PM, Clemens Gruber wrote:
> Support setting the reference voltage from the device tree.
> Rework of driver structure, put chip specific data in a separate
> structure and assign it depending on device id from platform data or
> DT match.
>
> Signed-off-by: Clemens Gruber <clemens.gruber-lZxf/j91sTNWk0Htik3J/w@public.gmane.org>
> ---
> Documentation/hwmon/mcp3021 | 6 ++
> drivers/hwmon/mcp3021.c | 145 ++++++++++++++++++++++++++++++++------------
> 2 files changed, 111 insertions(+), 40 deletions(-)
>
> diff --git a/Documentation/hwmon/mcp3021 b/Documentation/hwmon/mcp3021
> index 74a6b72..be252b7 100644
> --- a/Documentation/hwmon/mcp3021
> +++ b/Documentation/hwmon/mcp3021
> @@ -12,6 +12,7 @@ Supported chips:
> Authors:
> Mingkai Hu
> Sven Schuchmann <schuchmann-ogs+x9k7xBHcX9AoAvVr1bNAH6kLmebB@public.gmane.org>
> + Clemens Gruber <clemens.gruber-lZxf/j91sTNWk0Htik3J/w@public.gmane.org>
>
> Description
> -----------
> @@ -27,3 +28,8 @@ Communication to the MCP3021/MCP3221 is performed using a 2-wire I2C
> compatible interface. Standard (100 kHz) and Fast (400 kHz) I2C modes are
> available. The default I2C device address is 0x4d (contact the Microchip
> factory for additional address options).
> +
> +The reference voltage used in the conversion can be set through platform data
> +in millivolt (for backwards compatibility) or via device tree in microvolt.
> +Please refer to Documentation/devicetree/bindings/i2c/mcp3021.txt for details
> +about the device tree bindings.
> diff --git a/drivers/hwmon/mcp3021.c b/drivers/hwmon/mcp3021.c
> index 972444a..a8cf97f 100644
> --- a/drivers/hwmon/mcp3021.c
> +++ b/drivers/hwmon/mcp3021.c
> @@ -4,6 +4,7 @@
> * Copyright (C) 2008-2009, 2012 Freescale Semiconductor, Inc.
> * Author: Mingkai Hu <Mingkai.hu-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
> * Reworked by Sven Schuchmann <schuchmann-ogs+x9k7xBHcX9AoAvVr1bNAH6kLmebB@public.gmane.org>
> + * Copyright (C) 2016 Clemens Gruber <clemens.gruber-lZxf/j91sTNWk0Htik3J/w@public.gmane.org>
> *
> * This driver export the value of analog input voltage to sysfs, the
> * voltage unit is mV. Through the sysfs interface, lm-sensors tool
> @@ -22,37 +23,56 @@
> #include <linux/i2c.h>
> #include <linux/err.h>
> #include <linux/device.h>
> +#include <linux/of.h>
> +#include <linux/of_device.h>
>
> -/* Vdd info */
> +/* Vdd / reference voltage in millivolt */
> #define MCP3021_VDD_MAX 5500
> #define MCP3021_VDD_MIN 2700
> -#define MCP3021_VDD_REF 3300
> -
> -/* output format */
> -#define MCP3021_SAR_SHIFT 2
> -#define MCP3021_SAR_MASK 0x3ff
> -#define MCP3021_OUTPUT_RES 10 /* 10-bit resolution */
> -
> -#define MCP3221_SAR_SHIFT 0
> -#define MCP3221_SAR_MASK 0xfff
> -#define MCP3221_OUTPUT_RES 12 /* 12-bit resolution */
> +#define MCP3021_VDD_DEFAULT 3300
>
There is no technical reason to drop / change those defines and use literals
in the code instead. Please don't.
> enum chips {
> mcp3021,
> mcp3221
> };
>
> +struct mcp3021_chip_info {
> + u16 sar_shift;
> + u16 sar_mask;
> + u8 output_res;
> +};
> +
> /*
> * Client data (each client gets its own)
> */
> struct mcp3021_data {
> struct device *hwmon_dev;
> - u32 vdd; /* device power supply */
> - u16 sar_shift;
> - u16 sar_mask;
> - u8 output_res;
> + const struct mcp3021_chip_info *chip_info;
> + u32 vdd; /* device power supply and reference voltage in millivolt */
> };
>
> +static const struct mcp3021_chip_info mcp3021_chip_info_tbl[] = {
> + [mcp3021] = {
> + .sar_shift = 2,
> + .sar_mask = 0x3ff,
> + .output_res = 10, /* 10-bit resolution */
> + },
> + [mcp3221] = {
> + .sar_shift = 0,
> + .sar_mask = 0xfff,
> + .output_res = 12, /* 12-bit resolution */
> + },
> +};
> +
> +#ifdef CONFIG_OF
> +static const struct of_device_id of_mcp3021_match[] = {
> + { .compatible = "microchip,mcp3021", .data = (void *)mcp3021 },
> + { .compatible = "microchip,mcp3221", .data = (void *)mcp3221 },
> + { }
> +};
> +MODULE_DEVICE_TABLE(of, of_mcp3021_match);
> +#endif
> +
> static int mcp3021_read16(struct i2c_client *client)
> {
> struct mcp3021_data *data = i2c_get_clientdata(client);
> @@ -73,14 +93,15 @@ static int mcp3021_read16(struct i2c_client *client)
> * The ten-bit output code is composed of the lower 4-bit of the
> * first byte and the upper 6-bit of the second byte.
> */
> - reg = (reg >> data->sar_shift) & data->sar_mask;
> + reg = (reg >> data->chip_info->sar_shift) & data->chip_info->sar_mask;
>
> return reg;
> }
>
> static inline u16 volts_from_reg(struct mcp3021_data *data, u16 val)
> {
> - return DIV_ROUND_CLOSEST(data->vdd * val, 1 << data->output_res);
> + return DIV_ROUND_CLOSEST(data->vdd * val,
> + 1 << data->chip_info->output_res);
> }
>
> static ssize_t show_in_input(struct device *dev, struct device_attribute *attr,
> @@ -101,44 +122,85 @@ static ssize_t show_in_input(struct device *dev, struct device_attribute *attr,
>
> static DEVICE_ATTR(in0_input, S_IRUGO, show_in_input, NULL);
>
> -static int mcp3021_probe(struct i2c_client *client,
> +#ifdef CONFIG_OF
> +static int mcp3021_probe_dt(struct i2c_client *client,
> const struct i2c_device_id *id)
> {
> - int err;
> - struct mcp3021_data *data = NULL;
> + struct mcp3021_data *data = i2c_get_clientdata(client);
> + struct device_node *np = client->dev.of_node;
> + const struct of_device_id *match;
> + int devid, ret;
>
> - if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
> + match = of_match_device(of_mcp3021_match, &client->dev);
> + if (!match)
> return -ENODEV;
>
> - data = devm_kzalloc(&client->dev, sizeof(struct mcp3021_data),
> - GFP_KERNEL);
> - if (!data)
> - return -ENOMEM;
> -
> - i2c_set_clientdata(client, data);
> + devid = (int)(uintptr_t)match->data;
> + data->chip_info = &mcp3021_chip_info_tbl[devid];
>
> - switch (id->driver_data) {
> - case mcp3021:
> - data->sar_shift = MCP3021_SAR_SHIFT;
> - data->sar_mask = MCP3021_SAR_MASK;
> - data->output_res = MCP3021_OUTPUT_RES;
> - break;
> -
> - case mcp3221:
> - data->sar_shift = MCP3221_SAR_SHIFT;
> - data->sar_mask = MCP3221_SAR_MASK;
> - data->output_res = MCP3221_OUTPUT_RES;
> - break;
> + ret = of_property_read_u32(np, "reference-voltage-microvolt",
> + &data->vdd);
> + if (ret) {
> + /* fallback */
> + data->vdd = MCP3021_VDD_DEFAULT;
> + return 0;
> }
>
> + /* Convert microvolt from DT to millivolt used in the formula */
> + data->vdd /= 1000;
> +
> + if (data->vdd > MCP3021_VDD_MAX || data->vdd < MCP3021_VDD_MIN)
> + return -EINVAL;
> +
> + return 0;
> +}
> +#else
> +static int mcp3021_probe_dt(struct i2c_client *client,
> + const struct i2c_device_id *id)
> +{
> + return 1;
> +}
> +#endif
> +
> +static int mcp3021_probe_pdata(struct i2c_client *client,
> + const struct i2c_device_id *id)
> +{
> + struct mcp3021_data *data = i2c_get_clientdata(client);
> +
> + data->chip_info = &mcp3021_chip_info_tbl[id->driver_data];
> +
> if (dev_get_platdata(&client->dev)) {
> data->vdd = *(u32 *)dev_get_platdata(&client->dev);
> if (data->vdd > MCP3021_VDD_MAX || data->vdd < MCP3021_VDD_MIN)
> return -EINVAL;
> } else {
> - data->vdd = MCP3021_VDD_REF;
> + data->vdd = MCP3021_VDD_DEFAULT;
> }
>
> + return 0;
> +}
> +
> +static int mcp3021_probe(struct i2c_client *client,
> + const struct i2c_device_id *id)
> +{
> + struct mcp3021_data *data = NULL;
> + int err;
> +
> + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
> + return -ENODEV;
> +
> + data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
> + if (!data)
> + return -ENOMEM;
> +
> + i2c_set_clientdata(client, data);
> +
> + err = mcp3021_probe_dt(client, id);
> + if (err > 0)
> + mcp3021_probe_pdata(client, id);
> + else if (err < 0)
> + return err;
> +
Most other drivers generate the platform data from devicetree data.
if (of_match_device())
pdata = probe_dt();
else
pdata = dev_get_platdata();
In this case, this is even simpler, since the only devicetree property is the reference
voltage.
if (np) {
if (of_property_read_u32(np, "reference-voltage-microvolt", &vdd))
vdd = MCP3021_VDD_REF * 1000;
vdd /= 1000;
devid = (int)(uintptr_t)match->data;
} else {
u32 *pdata = dev_get_platdata(&client->dev);
if (pdata)
vdd = *pdata;
else
vdd = MCP3021_VDD_REF;
devid = id->driver_data;
}
You should actually be able to use id->driver_data directly in both cases since it is
always passed as parameter from the i2c core.
This would be much simpler than your suggested changes.
> err = sysfs_create_file(&client->dev.kobj, &dev_attr_in0_input.attr);
> if (err)
> return err;
> @@ -176,6 +238,9 @@ MODULE_DEVICE_TABLE(i2c, mcp3021_id);
> static struct i2c_driver mcp3021_driver = {
> .driver = {
> .name = "mcp3021",
> +#ifdef CONFIG_OF
> + .of_match_table = of_match_ptr(of_mcp3021_match),
> +#endif
of_match_ptr() is already protected with #ifdef CONFIG_OF and otherwise
returns NULL, so this ifdef is unnecessary.
> },
> .probe = mcp3021_probe,
> .remove = mcp3021_remove,
>
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH v6 04/14] mmc: sdhci-msm: Change poor style writel/readl of registers
From: Ritesh Harjani @ 2016-11-09 11:55 UTC (permalink / raw)
To: Stephen Boyd
Cc: ulf.hansson-QSEj5FYQhm4dnm+yROfE0A,
linux-mmc-u79uwXL29TY76Z2rM5mHXA,
adrian.hunter-ral2JQCrhuEAvxtiuMwx3w,
shawn.lin-TNX95d0MmH7DzftRWevZcw,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-clk-u79uwXL29TY76Z2rM5mHXA,
david.brown-QSEj5FYQhm4dnm+yROfE0A,
andy.gross-QSEj5FYQhm4dnm+yROfE0A,
linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
georgi.djakov-QSEj5FYQhm4dnm+yROfE0A,
alex.lemberg-XdAiOPVOjttBDgjK7y7TUQ,
mateusz.nowak-ral2JQCrhuEAvxtiuMwx3w,
Yuliy.Izrailov-XdAiOPVOjttBDgjK7y7TUQ,
asutoshd-sgV2jX0FEOL9JmXXK+q4OQ, kdorfman-sgV2jX0FEOL9JmXXK+q4OQ,
david.griego-QSEj5FYQhm4dnm+yROfE0A,
stummala-sgV2jX0FEOL9JmXXK+q4OQ, venkatg-sgV2jX0FEOL9JmXXK+q4OQ,
rnayak-sgV2jX0FEOL9JmXXK+q4OQ,
pramod.gurav-QSEj5FYQhm4dnm+yROfE0A
In-Reply-To: <20161108230724.GO16026-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
Hi Stephen,
On 11/9/2016 4:37 AM, Stephen Boyd wrote:
> On 11/07, Ritesh Harjani wrote:
>> diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
>> index 8ef44a2a..42f42aa 100644
>> --- a/drivers/mmc/host/sdhci-msm.c
>> +++ b/drivers/mmc/host/sdhci-msm.c
>> @@ -137,8 +137,9 @@ static int msm_config_cm_dll_phase(struct sdhci_host *host, u8 phase)
>> writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
>>
>> /* Set CK_OUT_EN bit of DLL_CONFIG register to 1. */
>> - writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG)
>> - | CORE_CK_OUT_EN), host->ioaddr + CORE_DLL_CONFIG);
>> + config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG);
>> + config |= CORE_CK_OUT_EN;
>> + writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
>>
>> /* Wait until CK_OUT_EN bit of DLL_CONFIG register becomes '1' */
>> rc = msm_dll_poll_ck_out_en(host, 1);
>> @@ -305,6 +306,7 @@ static int msm_init_cm_dll(struct sdhci_host *host)
>> struct mmc_host *mmc = host->mmc;
>> int wait_cnt = 50;
>> unsigned long flags;
>> + u32 config = 0;
>
> It needs to be initialized?
No, will make it uninitialized.
>
>>
>> spin_lock_irqsave(&host->lock, flags);
>>
>> @@ -313,33 +315,40 @@ static int msm_init_cm_dll(struct sdhci_host *host)
>> * tuning is in progress. Keeping PWRSAVE ON may
>> * turn off the clock.
>> */
>> - writel_relaxed((readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC)
>> - & ~CORE_CLK_PWRSAVE), host->ioaddr + CORE_VENDOR_SPEC);
>> + config = readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC);
>
> It's written here unconditionally though?
>
>> + config &= ~CORE_CLK_PWRSAVE;
>
--
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [PATCH v4 0/3] Add basic support for the I2C units of the Armada 3700
From: Romain Perier @ 2016-11-09 11:57 UTC (permalink / raw)
To: Wolfram Sang, linux-i2c-u79uwXL29TY76Z2rM5mHXA
Cc: devicetree-u79uwXL29TY76Z2rM5mHXA, Rob Herring, Ian Campbell,
Pawel Moll, Mark Rutland, Kumar Gala, Jason Cooper, Andrew Lunn,
Sebastian Hesselbarth, Gregory Clement,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
Thomas Petazzoni, Nadav Haklai, Omri Itach, Shadi Ammouri,
Yahuda Yitschak, Hanna Hawa, Neta Zur Hershkovits, Igal Liberman,
Marcin Wojtas <mw>
This series add basic support for the I2C bus interface units present
in the Armada 3700 to the pxa-i2c driver. It also add the definitions of
the device nodes to the devicetree at the SoC level and for its official
development board: the Armada 3720 DB.
Romain Perier (3):
i2c: pxa: Add support for the I2C units found in Armada 3700
arm64: dts: marvell: Add I2C definitions for the Armada 3700
dt-bindings: i2c: pxa: Update the documentation for the Armada 3700
Documentation/devicetree/bindings/i2c/i2c-pxa.txt | 1 +
arch/arm64/boot/dts/marvell/armada-3720-db.dts | 4 ++++
arch/arm64/boot/dts/marvell/armada-37xx.dtsi | 18 ++++++++++++++++
drivers/i2c/busses/Kconfig | 2 +-
drivers/i2c/busses/i2c-pxa.c | 25 +++++++++++++++++++++--
5 files changed, 47 insertions(+), 3 deletions(-)
--
2.9.3
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [PATCH v4 1/3] i2c: pxa: Add support for the I2C units found in Armada 3700
From: Romain Perier @ 2016-11-09 11:57 UTC (permalink / raw)
To: Wolfram Sang, linux-i2c-u79uwXL29TY76Z2rM5mHXA
Cc: devicetree-u79uwXL29TY76Z2rM5mHXA, Rob Herring, Ian Campbell,
Pawel Moll, Mark Rutland, Kumar Gala, Jason Cooper, Andrew Lunn,
Sebastian Hesselbarth, Gregory Clement,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
Thomas Petazzoni, Nadav Haklai, Omri Itach, Shadi Ammouri,
Yahuda Yitschak, Hanna Hawa, Neta Zur Hershkovits, Igal Liberman,
Marcin Wojtas <mw>
In-Reply-To: <20161109115715.2557-1-romain.perier-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
The Armada 3700 has two I2C controllers that is compliant with the I2C
Bus Specificiation 2.1, supports multi-master and different bus speed:
Standard mode (up to 100 KHz), Fast mode (up to 400 KHz),
High speed mode (up to 3.4 Mhz).
This IP block has a lot of similarity with the PXA, except some register
offsets and bitfield. This commits adds a basic support for this I2C
unit.
Signed-off-by: Romain Perier <romain.perier-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
Tested-by: Gregory CLEMENT <gregory.clement-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
---
Changes in v4:
- Replaced the type of hs_mask and fm_mask by u32, instead of
unsigned int, As writel() take an u32 as first argument...
Changes in v3:
- Replaced the type of hs_mask and fm_mask by unsigned int,
instead of unsigned long.
drivers/i2c/busses/Kconfig | 2 +-
drivers/i2c/busses/i2c-pxa.c | 25 +++++++++++++++++++++++--
2 files changed, 24 insertions(+), 3 deletions(-)
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index d252276..2f56a26 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -763,7 +763,7 @@ config I2C_PUV3
config I2C_PXA
tristate "Intel PXA2XX I2C adapter"
- depends on ARCH_PXA || ARCH_MMP || (X86_32 && PCI && OF)
+ depends on ARCH_PXA || ARCH_MMP || ARCH_MVEBU || (X86_32 && PCI && OF)
help
If you have devices in the PXA I2C bus, say yes to this option.
This driver can also be built as a module. If so, the module
diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c
index e28b825..09b4705 100644
--- a/drivers/i2c/busses/i2c-pxa.c
+++ b/drivers/i2c/busses/i2c-pxa.c
@@ -55,6 +55,7 @@ enum pxa_i2c_types {
REGS_PXA3XX,
REGS_CE4100,
REGS_PXA910,
+ REGS_A3700,
};
/*
@@ -91,6 +92,13 @@ static struct pxa_reg_layout pxa_reg_layout[] = {
.ilcr = 0x28,
.iwcr = 0x30,
},
+ [REGS_A3700] = {
+ .ibmr = 0x00,
+ .idbr = 0x04,
+ .icr = 0x08,
+ .isr = 0x0c,
+ .isar = 0x10,
+ },
};
static const struct platform_device_id i2c_pxa_id_table[] = {
@@ -98,6 +106,7 @@ static const struct platform_device_id i2c_pxa_id_table[] = {
{ "pxa3xx-pwri2c", REGS_PXA3XX },
{ "ce4100-i2c", REGS_CE4100 },
{ "pxa910-i2c", REGS_PXA910 },
+ { "armada-3700-i2c", REGS_A3700 },
{ },
};
MODULE_DEVICE_TABLE(platform, i2c_pxa_id_table);
@@ -122,7 +131,9 @@ MODULE_DEVICE_TABLE(platform, i2c_pxa_id_table);
#define ICR_SADIE (1 << 13) /* slave address detected int enable */
#define ICR_UR (1 << 14) /* unit reset */
#define ICR_FM (1 << 15) /* fast mode */
+#define ICR_BUSMODE_FM (1 << 16) /* shifted fast mode for armada-3700 */
#define ICR_HS (1 << 16) /* High Speed mode */
+#define ICR_BUSMODE_HS (1 << 17) /* shifted high speed mode for armada-3700 */
#define ICR_GPIOEN (1 << 19) /* enable GPIO mode for SCL in HS */
#define ISR_RWM (1 << 0) /* read/write mode */
@@ -193,6 +204,8 @@ struct pxa_i2c {
unsigned char master_code;
unsigned long rate;
bool highmode_enter;
+ u32 fm_mask;
+ u32 hs_mask;
};
#define _IBMR(i2c) ((i2c)->reg_ibmr)
@@ -503,8 +516,8 @@ static void i2c_pxa_reset(struct pxa_i2c *i2c)
writel(i2c->slave_addr, _ISAR(i2c));
/* set control register values */
- writel(I2C_ICR_INIT | (i2c->fast_mode ? ICR_FM : 0), _ICR(i2c));
- writel(readl(_ICR(i2c)) | (i2c->high_mode ? ICR_HS : 0), _ICR(i2c));
+ writel(I2C_ICR_INIT | (i2c->fast_mode ? i2c->fm_mask : 0), _ICR(i2c));
+ writel(readl(_ICR(i2c)) | (i2c->high_mode ? i2c->hs_mask : 0), _ICR(i2c));
#ifdef CONFIG_I2C_PXA_SLAVE
dev_info(&i2c->adap.dev, "Enabling slave mode\n");
@@ -1137,6 +1150,7 @@ static const struct of_device_id i2c_pxa_dt_ids[] = {
{ .compatible = "mrvl,pxa-i2c", .data = (void *)REGS_PXA2XX },
{ .compatible = "mrvl,pwri2c", .data = (void *)REGS_PXA3XX },
{ .compatible = "mrvl,mmp-twsi", .data = (void *)REGS_PXA910 },
+ { .compatible = "marvell,armada-3700-i2c", .data = (void *)REGS_A3700 },
{}
};
MODULE_DEVICE_TABLE(of, i2c_pxa_dt_ids);
@@ -1158,6 +1172,13 @@ static int i2c_pxa_probe_dt(struct platform_device *pdev, struct pxa_i2c *i2c,
i2c->use_pio = 1;
if (of_get_property(np, "mrvl,i2c-fast-mode", NULL))
i2c->fast_mode = 1;
+ if (of_device_is_compatible(np, "marvell,armada-3700-i2c")) {
+ i2c->fm_mask = ICR_BUSMODE_FM;
+ i2c->hs_mask = ICR_BUSMODE_HS;
+ } else {
+ i2c->fm_mask = ICR_FM;
+ i2c->hs_mask = ICR_HS;
+ }
*i2c_types = (enum pxa_i2c_types)(of_id->data);
--
2.9.3
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH v4 2/3] arm64: dts: marvell: Add I2C definitions for the Armada 3700
From: Romain Perier @ 2016-11-09 11:57 UTC (permalink / raw)
To: Wolfram Sang, linux-i2c
Cc: devicetree, Rob Herring, Ian Campbell, Pawel Moll, Mark Rutland,
Kumar Gala, Jason Cooper, Andrew Lunn, Sebastian Hesselbarth,
Gregory Clement, linux-arm-kernel, Thomas Petazzoni, Nadav Haklai,
Omri Itach, Shadi Ammouri, Yahuda Yitschak, Hanna Hawa,
Neta Zur Hershkovits, Igal Liberman, Marcin Wojtas <mw>
In-Reply-To: <20161109115715.2557-1-romain.perier@free-electrons.com>
The Armada 3700 has two i2c bus interface units, this commit adds the
definitions of the corresponding device nodes. It also enables the node
on the development board for this SoC.
Signed-off-by: Romain Perier <romain.perier@free-electrons.com>
Acked-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
---
arch/arm64/boot/dts/marvell/armada-3720-db.dts | 4 ++++
arch/arm64/boot/dts/marvell/armada-37xx.dtsi | 18 ++++++++++++++++++
2 files changed, 22 insertions(+)
diff --git a/arch/arm64/boot/dts/marvell/armada-3720-db.dts b/arch/arm64/boot/dts/marvell/armada-3720-db.dts
index 1372e9a6..16d84af 100644
--- a/arch/arm64/boot/dts/marvell/armada-3720-db.dts
+++ b/arch/arm64/boot/dts/marvell/armada-3720-db.dts
@@ -62,6 +62,10 @@
};
};
+&i2c0 {
+ status = "okay";
+};
+
/* CON3 */
&sata {
status = "okay";
diff --git a/arch/arm64/boot/dts/marvell/armada-37xx.dtsi b/arch/arm64/boot/dts/marvell/armada-37xx.dtsi
index c476253..bf2d73d 100644
--- a/arch/arm64/boot/dts/marvell/armada-37xx.dtsi
+++ b/arch/arm64/boot/dts/marvell/armada-37xx.dtsi
@@ -98,6 +98,24 @@
/* 32M internal register @ 0xd000_0000 */
ranges = <0x0 0x0 0xd0000000 0x2000000>;
+ i2c0: i2c@11000 {
+ compatible = "marvell,armada-3700-i2c";
+ reg = <0x11000 0x24>;
+ clocks = <&nb_perih_clk 10>;
+ interrupts = <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>;
+ mrvl,i2c-fast-mode;
+ status = "disabled";
+ };
+
+ i2c1: i2c@11080 {
+ compatible = "marvell,armada-3700-i2c";
+ reg = <0x11080 0x24>;
+ clocks = <&nb_perih_clk 9>;
+ interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>;
+ mrvl,i2c-fast-mode;
+ status = "disabled";
+ };
+
uart0: serial@12000 {
compatible = "marvell,armada-3700-uart";
reg = <0x12000 0x400>;
--
2.9.3
^ permalink raw reply related
* [PATCH v4 3/3] dt-bindings: i2c: pxa: Update the documentation for the Armada 3700
From: Romain Perier @ 2016-11-09 11:57 UTC (permalink / raw)
To: Wolfram Sang, linux-i2c-u79uwXL29TY76Z2rM5mHXA
Cc: devicetree-u79uwXL29TY76Z2rM5mHXA, Rob Herring, Ian Campbell,
Pawel Moll, Mark Rutland, Kumar Gala, Jason Cooper, Andrew Lunn,
Sebastian Hesselbarth, Gregory Clement,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
Thomas Petazzoni, Nadav Haklai, Omri Itach, Shadi Ammouri,
Yahuda Yitschak, Hanna Hawa, Neta Zur Hershkovits, Igal Liberman,
Marcin Wojtas <mw>
In-Reply-To: <20161109115715.2557-1-romain.perier-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
This commit documents the compatible string to have the compatibility for
the I2C unit found in the Armada 3700.
Signed-off-by: Romain Perier <romain.perier-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
---
Changes in v2:
- Fixed wrong compatible string, it should be "marvell,armada-3700-i2c"
and not "marvell,armada-3700".
Documentation/devicetree/bindings/i2c/i2c-pxa.txt | 1 +
1 file changed, 1 insertion(+)
diff --git a/Documentation/devicetree/bindings/i2c/i2c-pxa.txt b/Documentation/devicetree/bindings/i2c/i2c-pxa.txt
index 12b78ac..d30f0b1 100644
--- a/Documentation/devicetree/bindings/i2c/i2c-pxa.txt
+++ b/Documentation/devicetree/bindings/i2c/i2c-pxa.txt
@@ -7,6 +7,7 @@ Required properties :
compatible processor, e.g. pxa168, pxa910, mmp2, mmp3.
For the pxa2xx/pxa3xx, an additional node "mrvl,pxa-i2c" is required
as shown in the example below.
+ For the Armada 3700, the compatible should be "marvell,armada-3700-i2c".
Recommended properties :
--
2.9.3
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* Re: [PATCH v8 3/3] fpga: Add support for Lattice iCE40 FPGAs
From: Marek Vasut @ 2016-11-09 12:01 UTC (permalink / raw)
To: Joel Holdsworth, Moritz Fischer
Cc: Alan Tull, Geert Uytterhoeven, Rob Herring, Devicetree List,
Linux Kernel Mailing List, linux-spi, Clifford Wolf
In-Reply-To: <feae0954-7e85-3946-defe-ce252869786d@airwebreathe.org.uk>
On 11/08/2016 06:30 PM, Joel Holdsworth wrote:
>>>> On the whole, I don't think the zero-length transfers are too
>>>> egregiously bad, and all the alternatives seem worse to me.
>>>
>>> So why not turn the CS line into GPIO and just toggle the GPIO?
>>
>> Does that work with *all* SPI controllers?
>>
>
> It does not - no. See my other email.
And is that line an actual CS of that lattice chip or a generic input
which almost works like CS?
--
Best regards,
Marek Vasut
^ permalink raw reply
* Re: [PATCH v6 05/14] mmc: sdhci-msm: Update DLL reset sequence
From: Ritesh Harjani @ 2016-11-09 12:06 UTC (permalink / raw)
To: Stephen Boyd
Cc: ulf.hansson, linux-mmc, adrian.hunter, shawn.lin, devicetree,
linux-clk, david.brown, andy.gross, linux-arm-msm, georgi.djakov,
alex.lemberg, mateusz.nowak, Yuliy.Izrailov, asutoshd, kdorfman,
david.griego, stummala, venkatg, rnayak, pramod.gurav
In-Reply-To: <20161108230622.GN16026@codeaurora.org>
Hi Stephen,
On 11/9/2016 4:36 AM, Stephen Boyd wrote:
> On 11/07, Ritesh Harjani wrote:
>>
>> diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
>> index 42f42aa..32b0b79 100644
>> --- a/drivers/mmc/host/sdhci-msm.c
>> +++ b/drivers/mmc/host/sdhci-msm.c
>> @@ -58,11 +58,17 @@
>> #define CORE_DLL_CONFIG 0x100
>> #define CORE_DLL_STATUS 0x108
>>
>> +#define CORE_DLL_CONFIG_2 0x1b4
>> +#define CORE_FLL_CYCLE_CNT BIT(18)
>> +#define CORE_DLL_CLOCK_DISABLE BIT(21)
>> +
>> #define CORE_VENDOR_SPEC 0x10c
>> #define CORE_CLK_PWRSAVE BIT(1)
>>
>> #define CORE_VENDOR_SPEC_CAPABILITIES0 0x11c
>>
>> +#define TCXO_FREQ 19200000
>
> TCXO_FREQ could change based on the board. For example, IPQ has
> it as 25 MHz.
Actually not sure of the proper way on how to get this freq in driver
today. We may use xo_board clock but, it is not available for all boards
except 8996/8916 I guess.
Also, there is no sdhc for IPQ board and for all other boards TCXO_FREQ
is same where sdhci-msm driver is used. For that purpose this was
defined here for sdhci-msm driver.
Do you think in that case we should keep it this way for now and later
change if a need arise to change the TCXO_FREQ ?
>
>> +
>> #define CDR_SELEXT_SHIFT 20
>> #define CDR_SELEXT_MASK (0xf << CDR_SELEXT_SHIFT)
>> #define CMUX_SHIFT_PHASE_SHIFT 24
>> @@ -330,6 +349,24 @@ static int msm_init_cm_dll(struct sdhci_host *host)
>> writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
>> msm_cm_dll_set_freq(host);
>>
>> + if (msm_host->use_14lpp_dll_reset) {
>> + u32 mclk_freq = 0;
>> +
>> + if ((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG_2)
>> + & CORE_FLL_CYCLE_CNT))
>
> I suggest you grow a local variable.
Ok.
>
>> + mclk_freq = (u32)((host->clock / TCXO_FREQ) * 8);
>
> Is the cast necessary?
Will remove it.
>
>> + else
>> + mclk_freq = (u32)((host->clock / TCXO_FREQ) * 4);
>
> Ditto
Will remove it.
>
>> +
>> + config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG_2);
>> + config &= ~(0xFF << 10);
>> + config |= mclk_freq << 10;
>> +
>> + writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG_2);
>> + /* wait for 5us before enabling DLL clock */
>
> Usually there's a barrier between writel_relaxed() and delay
> because we don't know when the writel will be posted out and the
> delay is there to wait for the operation to happen. Probably
> should change this to be a writel() instead.
Arnd, already explained here.
We do need the udelay here as per the HW sequence itself.
>
>> + udelay(5);
>> + }
>> +
>> /* Write 0 to DLL_RST bit of DLL_CONFIG register */
>> config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG);
>> config &= ~CORE_DLL_RST;
>> @@ -340,6 +377,14 @@ static int msm_init_cm_dll(struct sdhci_host *host)
>> config &= ~CORE_DLL_PDN;
>> writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
>>
>> + if (msm_host->use_14lpp_dll_reset) {
>> + msm_cm_dll_set_freq(host);
>> + /* Enable the DLL clock */
>> + config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG_2);
>> + config &= ~CORE_DLL_CLOCK_DISABLE;
>> + writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG_2);
>> + }
>> +
>> /* Set DLL_EN bit to 1. */
>> config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG);
>> config |= CORE_DLL_EN;
>> @@ -641,6 +686,9 @@ static int sdhci_msm_probe(struct platform_device *pdev)
>> dev_dbg(&pdev->dev, "MCI Version: 0x%08x, major: 0x%04x, minor: 0x%02x\n",
>> core_version, core_major, core_minor);
>>
>> + if ((core_major == 1) && (core_minor >= 0x42))
>
> Why so many parenthesis?
Sure, will remove it.
>
>> + msm_host->use_14lpp_dll_reset = true;
>> +
>> /*
>
--
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
^ permalink raw reply
* RE: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
From: Gabriele Paoloni @ 2016-11-09 12:10 UTC (permalink / raw)
To: Arnd Bergmann, Yuanzhichang
Cc: catalin.marinas-5wv7dgnIgG8@public.gmane.org,
will.deacon-5wv7dgnIgG8@public.gmane.org,
robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org,
bhelgaas-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org,
mark.rutland-5wv7dgnIgG8@public.gmane.org,
olof-nZhT3qVonbNeoWH0uzbU5w@public.gmane.org,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org,
lorenzo.pieralisi-5wv7dgnIgG8@public.gmane.org,
linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, Linuxarm,
devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-pci-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-serial-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
minyard-HInyCGIudOg@public.gmane.org,
benh-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r@public.gmane.org
In-Reply-To: <1555494.4IFvGxvsfe@wuerfel>
Hi Arnd
> -----Original Message-----
> From: Arnd Bergmann [mailto:arnd-r2nGTMty4D4@public.gmane.org]
> Sent: 08 November 2016 16:25
> To: Yuanzhichang
> Cc: catalin.marinas-5wv7dgnIgG8@public.gmane.org; will.deacon-5wv7dgnIgG8@public.gmane.org; robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org;
> bhelgaas-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org; mark.rutland-5wv7dgnIgG8@public.gmane.org; olof-nZhT3qVonbNeoWH0uzbU5w@public.gmane.org; linux-arm-
> kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org; lorenzo.pieralisi-5wv7dgnIgG8@public.gmane.org; linux-
> kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org; Linuxarm; devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org; linux-
> pci-u79uwXL29TY76Z2rM5mHXA@public.gmane.org; linux-serial-u79uwXL29TY76Z2rM5mHXA@public.gmane.org; minyard-HInyCGIudOg@public.gmane.org;
> benh-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r@public.gmane.org; liviu.dudau-5wv7dgnIgG8@public.gmane.org; zourongrong-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org;
> John Garry; Gabriele Paoloni; zhichang.yuan02-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org;
> kantyzc-9Onoh4P/yGk@public.gmane.org; xuwei (O)
> Subject: Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on
> Hip06
>
> On Tuesday, November 8, 2016 11:47:09 AM CET zhichang.yuan wrote:
> > + /*
> > + * The first PCIBIOS_MIN_IO is reserved specifically for
> indirectIO.
> > + * It will separate indirectIO range from pci host bridge to
> > + * avoid the possible PIO conflict.
> > + * Set the indirectIO range directly here.
> > + */
> > + lpcdev->io_ops.start = 0;
> > + lpcdev->io_ops.end = PCIBIOS_MIN_IO - 1;
> > + lpcdev->io_ops.devpara = lpcdev;
> > + lpcdev->io_ops.pfin = hisilpc_comm_in;
> > + lpcdev->io_ops.pfout = hisilpc_comm_out;
> > + lpcdev->io_ops.pfins = hisilpc_comm_ins;
> > + lpcdev->io_ops.pfouts = hisilpc_comm_outs;
>
> I have to look at patch 2 in more detail again, after missing a few
> review
> rounds. I'm still a bit skeptical about hardcoding a logical I/O port
> range here, and would hope that we can just go through the same
> assignment of logical port ranges that we have for PCI buses,
> decoupling
> the bus addresses from the linux-internal ones.
The point here is that we want to avoid any conflict/overlap between
the LPC I/O space and the PCI I/O space. With the assignment above
we make sure that LPC never interfere with PCI I/O space.
Thanks
Gab
>
> Arnd
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [PATCH V2 0/2] pinctrl: tegra: Add support for IO pad control
From: Laxman Dewangan @ 2016-11-09 13:06 UTC (permalink / raw)
To: linus.walleij, robh+dt, mark.rutland, swarren, thierry.reding
Cc: gnurou, yamada.masahiro, jonathanh, linux-gpio, devicetree,
linux-tegra, linux-kernel, Laxman Dewangan
NVIDIA Tegra124 and later SoCs support the multi-voltage level and
low power state of some of its IO pads. The IO pads can work in
the voltage of the 1.8V and 3.3V of IO power rail sources. When IO
interface are not used then IO pads can be configure in low power
state to reduce the power from that IO pads.
This series add the support of configuration of IO pad via pinctrl
framework. The io pad driver uses the tegra PMC interface.
---
This driver was sent earlier for review along with soc/tegra pmc
changes. During review, decided to first conclude in soc/tegra pmc
patches and then review this.
Thierry applied the pmc patches in the private tree
https://github.com/thierryreding/linux/tree/tegra186
and he wanted to have the patches for user of the new APIs so that
it can be pushed to mainline.
Sending the pinctrl driver. This needs Ack/reviewed from pinctrl subsystem
i.e. Linus Welleij to apply in the Thierry's T186 branch along with
PMC patches.
---
Changes from V1:
- use the regulator framework to get the IO voltage instead of table from
DT. The regulator handle is provided from DT.
Laxman Dewangan (2):
pinctrl: tegra: Add DT binding for io pads control
pinctrl: tegra: Add driver to configure voltage and power of io pads
.../bindings/pinctrl/nvidia,tegra-io-pad.txt | 112 +++++++
drivers/pinctrl/tegra/Kconfig | 12 +
drivers/pinctrl/tegra/Makefile | 1 +
drivers/pinctrl/tegra/pinctrl-tegra-io-pad.c | 369 +++++++++++++++++++++
include/dt-bindings/pinctrl/pinctrl-tegra-io-pad.h | 21 ++
5 files changed, 515 insertions(+)
create mode 100644 Documentation/devicetree/bindings/pinctrl/nvidia,tegra-io-pad.txt
create mode 100644 drivers/pinctrl/tegra/pinctrl-tegra-io-pad.c
create mode 100644 include/dt-bindings/pinctrl/pinctrl-tegra-io-pad.h
--
2.1.4
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox