From: Martin Blumenstingl <martin.blumenstingl@googlemail.com> Date: 2016-06-25 16:50:23
This adds support for configuring the PRG_ETHERNET_ADDR registers on
Meson 8b (S805) and GXBB (S905) devices. The registers there are
completely different from those found in the earlier Meson 6b SoC
series, which is why a new driver was implemented.
This configuration is required when the bootloader does not configure
these registers based on the connected PHY. Symptoms are that the
DWMAC device is detected, but no packets are getting through, even
though everything else is configured correctly.
From: Martin Blumenstingl <martin.blumenstingl@googlemail.com> Date: 2016-06-25 16:50:24
This patch adds the documentation for the DWMAC ethernet controller
found in Amlogic Meson 8b (S805) and GXBB (S905) SoCs.
Compared to the standard stmmac/dwmac configuration this requires some
some additional parameters for configuring the clock-generator
depending on the actual ethernet PHY on the board.
Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
---
.../bindings/net/amlogic,meson8b-dwmac.txt | 44 ++++++++++++++++++++++
1 file changed, 44 insertions(+)
create mode 100644 Documentation/devicetree/bindings/net/amlogic,meson8b-dwmac.txt
@@ -0,0 +1,44 @@+* Amlogic Meson 8b/GXBB DWMAC Ethernet controller++The device inherits all the properties of the dwmac/stmmac devices+described in the file net/stmmac.txt with the following changes.++Required properties:+- compatible: should be "amlogic,meson8b-dwmac" along with "snps,dwmac"+ and any applicable more detailed version number+ described in net/stmmac.txt+- prg-ethernet: should contain a phandle to a syscon device mapping the+ PRG_ETHERNET registers.+++Optional properties:+- amlogic,enable-tx-phy-ref-clk: Enables the TX_CLK and PHY_REF_CLK+ clock generator.+- amlogic,mp2-clock: Sets the frequency for the mp2_clk_out clock. See+ the MESON8B_DWMAC_MP2_CLOCK_* definitions in+ "include/dt-bindings/net/amlogic-meson8b-dwmac.h".+- amlogic,tx-delay: Configures the TX clock delay. See the+ MESON8B_DWMAC_TX_CLK_DELAY_* definitions in+ "include/dt-bindings/net/amlogic-meson8b-dwmac.h".+++Example:++#include <dt-bindings/net/amlogic-meson8b-dwmac.h>++ gmac: ethernet@37000000 {+ compatible = "amlogic,meson8b-dwmac", "snps,dwmac";+ reg = <0x0 0xc9410000 0x0 0x10000>;+ interrupts = <0 8 1>;+ interrupt-names = "macirq";++ clocks = <&clkc CLKID_ETH>;+ clock-names = "stmmaceth";++ phy-mode = "rgmii";++ amlogic,prg-ethernet = <&prg_ethernet>;+ amlogic,enable-25mhz-phy-clk;+ amlogic,mp2-clock = <MESON8B_DWMAC_MP2_CLOCK_1000MHZ>;+ amlogic,tx-delay = <MESON8B_DWMAC_TX_CLK_DELAY_QUARTER_CYCLE>;+ };
From: Martin Blumenstingl <martin.blumenstingl@googlemail.com> Date: 2016-06-25 16:50:25
The Ethernet controller available in Meson8b and GXBB SoCs is a Synopsys
DesignWare MAC IP core which is already supported by the stmmac driver.
In addition to the standard stmmac driver some Meson8b / GXBB specific
registers have to be configured for the PHY clocks. These SoC specific
registers are called PRG_ETHERNET_ADDR0 and PRG_ETHERNET_ADDR1 in the
datasheet.
These registers are not backwards compatible with those on Meson 6b,
which is why a new glue driver was introduced.
Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
---
drivers/net/ethernet/stmicro/stmmac/Makefile | 2 +-
.../net/ethernet/stmicro/stmmac/dwmac-meson8b.c | 219 +++++++++++++++++++++
include/dt-bindings/net/amlogic-meson8b-dwmac.h | 33 ++++
3 files changed, 253 insertions(+), 1 deletion(-)
create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c
create mode 100644 include/dt-bindings/net/amlogic-meson8b-dwmac.h
From: Martin Blumenstingl <martin.blumenstingl@googlemail.com> Date: 2016-06-25 16:50:26
The Amlogic reference driver uses the "mc_val" devicetree property to
configure the PRG_ETHERNET_ADDR0 register. Unfortunately it uses magic
values for this configuration.
According to the datasheet the PRG_ETHERNET_ADDR0 register is at address
0xc8834108. However, the reference driver uses 0xc8834540 instead.
According to my tests, the value from the reference driver is correct.
The updated examples are representing 0x1621 from the reference driver's
mc_val property, which is used when there is an external gbit PHY
connected.
For RMII mode PHYs mc_val 0x1800 is used in the reference driver, which
translates would translate to "do not set any of the following
properties" (as the two bits are configured automatically):
- amlogic,enable-25mhz-phy-clk
- amlogic,mp2-clock
- amlogic,tx-delay
Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
---
arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts | 4 ++++
arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi | 4 ++++
arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95.dtsi | 4 ++++
arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi | 12 +++++++++---
4 files changed, 21 insertions(+), 3 deletions(-)
From: Carlo Caione <hidden> Date: 2016-06-27 09:24:51
On 25/06/16 18:50, Martin Blumenstingl wrote:
The Amlogic reference driver uses the "mc_val" devicetree property to
configure the PRG_ETHERNET_ADDR0 register. Unfortunately it uses magic
values for this configuration.
According to the datasheet the PRG_ETHERNET_ADDR0 register is at address
0xc8834108. However, the reference driver uses 0xc8834540 instead.
According to my tests, the value from the reference driver is correct.
The updated examples are representing 0x1621 from the reference driver's
mc_val property, which is used when there is an external gbit PHY
connected.
For RMII mode PHYs mc_val 0x1800 is used in the reference driver, which
translates would translate to "do not set any of the following
properties" (as the two bits are configured automatically):
- amlogic,enable-25mhz-phy-clk
- amlogic,mp2-clock
- amlogic,tx-delay
From: Martin Blumenstingl <martin.blumenstingl@googlemail.com> Date: 2016-06-27 10:44:34
On Mon, Jun 27, 2016 at 11:24 AM, Carlo Caione [off-list ref] wrote:
A syscon is a region containing a set of miscellaneous registers used
for several reasons by several devices [1]. It this case there is really
no need to define a new syscon node since those two registers are only
used by your driver.
I can easily change it back if that's the way to go.
Before I do that: could you please confirm that "mp2_clk_out" (which
is controlled by PRG_ETH0/offset 0x0 bits 7-9) is not something which
has to be available through the common clk framework?
From: Martin Blumenstingl <martin.blumenstingl@googlemail.com> Date: 2016-06-27 11:34:15
On Mon, Jun 27, 2016 at 12:44 PM, Martin Blumenstingl
[off-list ref] wrote:
On Mon, Jun 27, 2016 at 11:24 AM, Carlo Caione [off-list ref] wrote:
quoted
A syscon is a region containing a set of miscellaneous registers used
for several reasons by several devices [1]. It this case there is really
no need to define a new syscon node since those two registers are only
used by your driver.
I can easily change it back if that's the way to go.
Before I do that: could you please confirm that "mp2_clk_out" (which
is controlled by PRG_ETH0/offset 0x0 bits 7-9) is not something which
has to be available through the common clk framework?
there was just an IRC discussion with Carlo on this topic:
We tried to find whether PRG_ETH0 is used to actually configure
"mp2_clk_out". Carlo brought up that it could also be the case that
the ethernet block simply needs to be informed about the rate of the
mp2_clk_out (which is *probably* the "mpll2" clock).
I'm adding Michael Turquette to this mail, maybe you can comment on this topic.
If it turns out that the etthernet block just has to know about the
clock rate then we have two tasks:
1. identify why the mpll2 rate returns 0 on my GXBB device
2. change my patch so the new DWMAC glue gets a reference to the mpll2
clock and then use "clk_get_rate(mpll2) / (250 * 1000000)" to
configure the PRG_ETH0_MP2_CLK bits.
From: Michael Turquette <mturquette@baylibre.com> Date: 2016-07-13 21:01:24
Hi Martin,
Quoting Martin Blumenstingl (2016-06-27 04:33:49)
On Mon, Jun 27, 2016 at 12:44 PM, Martin Blumenstingl
[off-list ref] wrote:
quoted
On Mon, Jun 27, 2016 at 11:24 AM, Carlo Caione [off-list ref] wrote:
quoted
A syscon is a region containing a set of miscellaneous registers used
for several reasons by several devices [1]. It this case there is really
no need to define a new syscon node since those two registers are only
used by your driver.
I can easily change it back if that's the way to go.
Before I do that: could you please confirm that "mp2_clk_out" (which
is controlled by PRG_ETH0/offset 0x0 bits 7-9) is not something which
has to be available through the common clk framework?
there was just an IRC discussion with Carlo on this topic:
We tried to find whether PRG_ETH0 is used to actually configure
"mp2_clk_out". Carlo brought up that it could also be the case that
the ethernet block simply needs to be informed about the rate of the
mp2_clk_out (which is *probably* the "mpll2" clock).
I'm adding Michael Turquette to this mail, maybe you can comment on this topic.
If it turns out that the etthernet block just has to know about the
clock rate then we have two tasks:
1. identify why the mpll2 rate returns 0 on my GXBB device
This is in progress, but turns out it doesn't matter for Ethernet. Bit 4
in PRG_ETHERNET_ADDR0 control a mux clock inside of the Ethernet
controller.
A value of 0x0 selects fclk_div2 and a value of 0x1 selects mp2_clk_out.
The bootloader programs in sets the mux to zero, or fclk_div2 as the
input clock (which runs at 1GHz).
2. change my patch so the new DWMAC glue gets a reference to the mpll2
clock and then use "clk_get_rate(mpll2) / (250 * 1000000)" to
configure the PRG_ETH0_MP2_CLK bits.
Hmm, I'm not sure about that part. Bits 7-9 is a divider that further
divides the clock signal selected by bit 4. This is set to 0x4, which
means we divide the 1GHz fclk_div2 down to 250MHz, which seems to be the
expected value coming out of this divider.
I haven't looked further to see if there is a further programmable
divider to divide 250MHz down to 50MHz, or (more likely) there is simply
a fixed-factor divide-by-5 that results in the 50MHz rate consumed by
the PHY.
Modeling this all in the mmc driver makes sense. So we would have:
struct clk_mux clk_m250_sel ->
struct clk_divider clk_m250_div ->
struct clk_fixed_factor enet_phy_clk
I don't know what the name should be for that last one, I just chose
enet_phy_clk since it illustrates the point. The updated docs suggest
that clk_m250_{sel,div} might be reasonable names for the mux and
divider.
Kevin and I just got this info from AmLogic earlier today. The next rev
of documentation should correct these register definitions.
Regards,
Mike
From: Kevin Hilman <khilman@baylibre.com> Date: 2016-07-13 21:22:36
Michael Turquette [off-list ref] writes:
Hi Martin,
Quoting Martin Blumenstingl (2016-06-27 04:33:49)
quoted
On Mon, Jun 27, 2016 at 12:44 PM, Martin Blumenstingl
[off-list ref] wrote:
quoted
On Mon, Jun 27, 2016 at 11:24 AM, Carlo Caione [off-list ref] wrote:
quoted
A syscon is a region containing a set of miscellaneous registers used
for several reasons by several devices [1]. It this case there is really
no need to define a new syscon node since those two registers are only
used by your driver.
I can easily change it back if that's the way to go.
Before I do that: could you please confirm that "mp2_clk_out" (which
is controlled by PRG_ETH0/offset 0x0 bits 7-9) is not something which
has to be available through the common clk framework?
there was just an IRC discussion with Carlo on this topic:
We tried to find whether PRG_ETH0 is used to actually configure
"mp2_clk_out". Carlo brought up that it could also be the case that
the ethernet block simply needs to be informed about the rate of the
mp2_clk_out (which is *probably* the "mpll2" clock).
I'm adding Michael Turquette to this mail, maybe you can comment on this topic.
If it turns out that the etthernet block just has to know about the
clock rate then we have two tasks:
1. identify why the mpll2 rate returns 0 on my GXBB device
This is in progress, but turns out it doesn't matter for Ethernet. Bit 4
in PRG_ETHERNET_ADDR0 control a mux clock inside of the Ethernet
controller.
A value of 0x0 selects fclk_div2 and a value of 0x1 selects mp2_clk_out.
The bootloader programs in sets the mux to zero, or fclk_div2 as the
input clock (which runs at 1GHz).
quoted
2. change my patch so the new DWMAC glue gets a reference to the mpll2
clock and then use "clk_get_rate(mpll2) / (250 * 1000000)" to
configure the PRG_ETH0_MP2_CLK bits.
Hmm, I'm not sure about that part. Bits 7-9 is a divider that further
divides the clock signal selected by bit 4. This is set to 0x4, which
means we divide the 1GHz fclk_div2 down to 250MHz, which seems to be the
expected value coming out of this divider.
I haven't looked further to see if there is a further programmable
divider to divide 250MHz down to 50MHz, or (more likely) there is simply
a fixed-factor divide-by-5 that results in the 50MHz rate consumed by
the PHY.
Modeling this all in the mmc driver makes sense. So we would have:
struct clk_mux clk_m250_sel ->
struct clk_divider clk_m250_div ->
struct clk_fixed_factor enet_phy_clk
There's also bit 10: "Generate 25MHz clock for PHY" (which is set to 1
by the bootloaders on P200 and odroidc2)
This suggests that it might not be a fixed-factor divide-by-5 but a
choice between a divide-by-5 and a divide-by-10 for the PHY clock.
Kevin
From: Martin Blumenstingl <martin.blumenstingl@googlemail.com> Date: 2016-08-15 16:40:57
This adds a DWMAC glue driver for the PRG_ETHERNET registers found in
Meson8b and GXBB SoCs. Based on the "old" meson6b-dwmac glue driver
the register layout is completely different.
Thus I introduced a separate driver.
Changes compared to the RFC version:
- switch from syscon / regmap to assigning the corresponding register
region directly to the driver (like meson6-dwmac does it)
- dropped "fix_mac_speed" callback since the reference driver does not
implement it (I could not test if it is required due to lack of
hardware)
- switch to common clock framework now that we know what bits 5:4
(mux clock), 6:5 (250MHz divider) and 10 (configurable 5 or 10
divider) are used for
- Removed dts property "amlogic,mp2-clock" because it is now part of
the clocks which are registered by the glue driver
- Removed dts properties "amlogic,enable-tx-phy-ref-clk" and
"amlogic,tx-delay" because it seems we can guess them based on the
phy-mode (the original Amlogic dts files only supply two different
values: one value for the internal RMII PHY and another one for the
external RGMII Gbit PHY).
If required we can extend the code in the future to make these
configurable.
- This means that the only Meson8b / GXBB specific part of the binding
is the clkin0 (FCLK_DIV2) clock, as it's needed for the mux clock.
Everything else is auto-detected based on the phy-mode (which is
already mandatory in stmmac).
I have successfully tested this on a Vega S95 Meta clone which comes
with a "broken" bootloader (which programs the ethernet registers to
"Fast Ethernet / RGMII" mode, while the board has a Realtek Gbit PHY).
Before this series stmmac was detected, I got a network interface but
no traffic was flowing.
Due to lack of hardware I could not test this on a device which uses
the internal RMII (Fast Ethernet) PHY.
Martin Blumenstingl (3):
net: dt-bindings: Document the new Meson8b and GXBB DWMAC bindings
net: stmmac: add a glue driver for the Amlogic Meson 8b / GXBB DWMAC
ARM64: dts: meson-gxbb: use the new GXBB DWMAC glue driver
.../devicetree/bindings/net/meson-dwmac.txt | 43 ++-
arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi | 7 +-
drivers/net/ethernet/stmicro/stmmac/Makefile | 2 +-
.../net/ethernet/stmicro/stmmac/dwmac-meson8b.c | 327 +++++++++++++++++++++
4 files changed, 367 insertions(+), 12 deletions(-)
create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c
--
2.9.3
From: Martin Blumenstingl <martin.blumenstingl@googlemail.com> Date: 2016-08-15 16:40:58
This patch adds the documentation for the DWMAC ethernet controller
found in Amlogic Meson 8b (S805) and GXBB (S905) SoCs.
The main difference between the Meson6 glue is that different registers
(with different layout) are used.
Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
---
.../devicetree/bindings/net/meson-dwmac.txt | 43 ++++++++++++++++++----
1 file changed, 35 insertions(+), 8 deletions(-)
@@ -1,18 +1,31 @@ * Amlogic Meson DWMAC Ethernet controller The device inherits all the properties of the dwmac/stmmac devices-described in the file net/stmmac.txt with the following changes.+described in the file stmmac.txt in the current directory with the+following changes.-Required properties:+Required properties on all platforms:-- compatible: should be "amlogic,meson6-dwmac" along with "snps,dwmac"- and any applicable more detailed version number- described in net/stmmac.txt+- compatible: Depending on the platform this should be one of:+ - "amlogic,meson6-dwmac"+ - "amlogic,meson8b-dwmac"+ - "amlogic,meson-gxbb-dwmac"+ Additionally "snps,dwmac" and any applicable more+ detailed version number described in net/stmmac.txt+ should be used.-- reg: should contain a register range for the dwmac controller and- another one for the Amlogic specific configuration+- reg: The first register range should be the one of the DWMAC+ controller. The second range is is for the Amlogic specific+ configuration (for example the PRG_ETHERNET register range+ on Meson8b and newer)-Example:+Required properties on Meson8b and newer:+- clock-names: Should contain the following:+ - "stmmaceth" - see stmmac.txt+ - "clkin0" - parent clock of internal mux (usually FCLK_DIV2)+++Example for Meson6: ethmac: ethernet@c9410000 { compatible = "amlogic,meson6-dwmac", "snps,dwmac";
From: Martin Blumenstingl <martin.blumenstingl@googlemail.com> Date: 2016-08-15 16:40:59
The Ethernet controller available in Meson8b and GXBB SoCs is a Synopsys
DesignWare MAC IP core which is already supported by the stmmac driver.
In addition to the standard stmmac driver some Meson8b / GXBB specific
registers have to be configured for the PHY clocks. These SoC specific
registers are called PRG_ETHERNET_ADDR0 and PRG_ETHERNET_ADDR1 in the
datasheet.
These registers are not backwards compatible with those on Meson 6b,
which is why a new glue driver is introduced. This worked for many
boards because the bootloader programs the PRG_ETHERNET registers
correctly. Additionally the meson6-dwmac driver only sets bit 1 of
PRG_ETHERNET_ADDR0 which (according to the datasheet) is only used
during reset.
Currently all configuration values can be determined automatically,
based on the configured phy-mode (which is mandatory for the stmmac
driver). If required the tx-delay and the mux clock (so it supports
the MPLL2 clock as well) can be made configurable in the future.
Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
---
drivers/net/ethernet/stmicro/stmmac/Makefile | 2 +-
.../net/ethernet/stmicro/stmmac/dwmac-meson8b.c | 327 +++++++++++++++++++++
2 files changed, 328 insertions(+), 1 deletion(-)
create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c
@@ -0,0 +1,327 @@+/*+*AmlogicMesonS805/S905DWMACgluelayer+*+*Copyright(C)20016MartinBlumenstingl<martin.blumenstingl@googlemail.com>+*+*Thisprogramisfreesoftware;youcanredistributeitand/ormodify+*itunderthetermsoftheGNUGeneralPublicLicenseversion2as+*publishedbytheFreeSoftwareFoundation.+*+*YoushouldhavereceivedacopyoftheGNUGeneralPublicLicense+*alongwiththisprogram.Ifnot,see<http://www.gnu.org/licenses/>.+*/++#include<linux/clk.h>+#include<linux/clk-provider.h>+#include<linux/device.h>+#include<linux/ethtool.h>+#include<linux/io.h>+#include<linux/ioport.h>+#include<linux/module.h>+#include<linux/of_net.h>+#include<linux/mfd/syscon.h>+#include<linux/platform_device.h>+#include<linux/stmmac.h>++#include"stmmac_platform.h"++#define PRG_ETH0 0x0++#define PRG_ETH0_RGMII_MODE BIT(0)++/* mux to choose between fclk_div2 (bit unset) and mpll2 (bit set) */+#define PRG_ETH0_CLK_M250_SEL_SHIFT 4+#define PRG_ETH0_CLK_M250_SEL_MASK GENMASK(4, 4)++#define PRG_ETH0_TXDLY_SHIFT 5+#define PRG_ETH0_TXDLY_MASK GENMASK(6, 5)+#define PRG_ETH0_TXDLY_OFF (0x0 << PRG_ETH0_TXDLY_SHIFT)+#define PRG_ETH0_TXDLY_QUARTER (0x1 << PRG_ETH0_TXDLY_SHIFT)+#define PRG_ETH0_TXDLY_HALF (0x2 << PRG_ETH0_TXDLY_SHIFT)+#define PRG_ETH0_TXDLY_THREE_QUARTERS (0x3 << PRG_ETH0_TXDLY_SHIFT)++/* divider for the result of m250_sel */+#define PRG_ETH0_CLK_M250_DIV_SHIFT 7+#define PRG_ETH0_CLK_M250_DIV_WIDTH 3++/* divides the result of m25_sel by either 5 (bit unset) or 10 (bit set) */+#define PRG_ETH0_CLK_M25_DIV_SHIFT 10+#define PRG_ETH0_CLK_M25_DIV_WIDTH 1++#define PRG_ETH0_INVERTED_RMII_CLK BIT(11)+#define PRG_ETH0_TX_AND_PHY_REF_CLK BIT(12)++#define MUX_CLK_NUM_PARENTS 2++structmeson8b_dwmac{+structplatform_device*pdev;++void__iomem*regs;++phy_interface_tphy_mode;++structclk_muxm250_mux;+structclk*m250_mux_clk;+structclk*m250_mux_parent[MUX_CLK_NUM_PARENTS];++structclk_dividerm250_div;+structclk*m250_div_clk;++structclk_dividerm25_div;+structclk*m25_div_clk;+};++staticvoidmeson8b_dwmac_mask_bits(structmeson8b_dwmac*dwmac,u32reg,+u32mask,u32value)+{+u32data;++data=readl(dwmac->regs+reg);+data&=~mask;+data|=(value&mask);++writel(data,dwmac->regs+reg);+}++staticintmeson8b_init_clk(structmeson8b_dwmac*dwmac)+{+structclk_init_datainit;+inti,ret;+structdevice*dev=&dwmac->pdev->dev;+charclk_name[32];+constchar*clk_div_parents[1];+constchar*mux_parent_names[MUX_CLK_NUM_PARENTS];+unsignedintmux_parent_count=0;+staticstructclk_div_tableclk_25m_div_table[]={+{.val=0,.div=5},+{.val=1,.div=10},+{/* sentinel */},+};++/* get the mux parents from DT */+for(i=0;i<MUX_CLK_NUM_PARENTS;i++){+charname[16];++snprintf(name,sizeof(name),"clkin%d",i);+dwmac->m250_mux_parent[i]=devm_clk_get(dev,name);+if(IS_ERR(dwmac->m250_mux_parent[i])){+/* NOTE: the second clock (MP2) is unused on all known+*boards,thuswe'remakingitoptionalhere.+*/+if(i>0)+continue;++ret=PTR_ERR(dwmac->m250_mux_parent[i]);+if(ret!=-EPROBE_DEFER)+dev_err(dev,"Missing clock %s\n",name);+dwmac->m250_mux_parent[i]=NULL;+returnret;+}++mux_parent_names[i]=+__clk_get_name(dwmac->m250_mux_parent[i]);+mux_parent_count++;+}++/* create the m250_mux */+snprintf(clk_name,sizeof(clk_name),"%s#m250_sel",dev_name(dev));+init.name=clk_name;+init.ops=&clk_mux_ops;+init.flags=CLK_IS_BASIC;+init.parent_names=mux_parent_names;+init.num_parents=mux_parent_count;++dwmac->m250_mux.reg=dwmac->regs+PRG_ETH0;+dwmac->m250_mux.shift=PRG_ETH0_CLK_M250_SEL_SHIFT;+dwmac->m250_mux.mask=PRG_ETH0_CLK_M250_SEL_MASK;+dwmac->m250_mux.flags=0;+dwmac->m250_mux.table=NULL;+dwmac->m250_mux.hw.init=&init;++dwmac->m250_mux_clk=devm_clk_register(dev,&dwmac->m250_mux.hw);+if(WARN_ON(PTR_ERR_OR_ZERO(dwmac->m250_mux_clk)))+returnPTR_ERR(dwmac->m250_mux_clk);++/* create the m250_div */+snprintf(clk_name,sizeof(clk_name),"%s#m250_div",dev_name(dev));+init.name=devm_kstrdup(dev,clk_name,GFP_KERNEL);+init.ops=&clk_divider_ops;+init.flags=CLK_IS_BASIC|CLK_SET_RATE_PARENT;+clk_div_parents[0]=__clk_get_name(dwmac->m250_mux_clk);+init.parent_names=clk_div_parents;+init.num_parents=ARRAY_SIZE(clk_div_parents);++dwmac->m250_div.reg=dwmac->regs+PRG_ETH0;+dwmac->m250_div.shift=PRG_ETH0_CLK_M250_DIV_SHIFT;+dwmac->m250_div.width=PRG_ETH0_CLK_M250_DIV_WIDTH;+dwmac->m250_div.hw.init=&init;+dwmac->m250_div.flags=CLK_DIVIDER_ONE_BASED|CLK_DIVIDER_ALLOW_ZERO;++dwmac->m250_div_clk=devm_clk_register(dev,&dwmac->m250_div.hw);+if(WARN_ON(PTR_ERR_OR_ZERO(dwmac->m250_div_clk)))+returnPTR_ERR(dwmac->m250_div_clk);++/* create the m25_div */+snprintf(clk_name,sizeof(clk_name),"%s#m25_div",dev_name(dev));+init.name=devm_kstrdup(dev,clk_name,GFP_KERNEL);+init.ops=&clk_divider_ops;+init.flags=CLK_IS_BASIC|CLK_SET_RATE_PARENT;+clk_div_parents[0]=__clk_get_name(dwmac->m250_div_clk);+init.parent_names=clk_div_parents;+init.num_parents=ARRAY_SIZE(clk_div_parents);++dwmac->m25_div.reg=dwmac->regs+PRG_ETH0;+dwmac->m25_div.shift=PRG_ETH0_CLK_M25_DIV_SHIFT;+dwmac->m25_div.width=PRG_ETH0_CLK_M25_DIV_WIDTH;+dwmac->m25_div.table=clk_25m_div_table;+dwmac->m25_div.hw.init=&init;+dwmac->m25_div.flags=CLK_DIVIDER_ALLOW_ZERO;++dwmac->m25_div_clk=devm_clk_register(dev,&dwmac->m25_div.hw);+if(WARN_ON(PTR_ERR_OR_ZERO(dwmac->m25_div_clk)))+returnPTR_ERR(dwmac->m25_div_clk);++return0;+}++staticintmeson8b_init_prg_eth(structmeson8b_dwmac*dwmac)+{+intret;+unsignedlongclk_rate;++switch(dwmac->phy_mode){+casePHY_INTERFACE_MODE_RGMII:+casePHY_INTERFACE_MODE_RGMII_ID:+casePHY_INTERFACE_MODE_RGMII_RXID:+casePHY_INTERFACE_MODE_RGMII_TXID:+/* Generate a 25MHz clock for the PHY */+clk_rate=25*1000*1000;++/* enable RGMII mode */+meson8b_dwmac_mask_bits(dwmac,PRG_ETH0,PRG_ETH0_RGMII_MODE,+PRG_ETH0_RGMII_MODE);++/* only relevant for RMII mode -> disable in RGMII mode */+meson8b_dwmac_mask_bits(dwmac,PRG_ETH0,+PRG_ETH0_INVERTED_RMII_CLK,0);++/* TX clock delay - all known boards use a 1/4 cycle delay */+meson8b_dwmac_mask_bits(dwmac,PRG_ETH0,PRG_ETH0_TXDLY_MASK,+PRG_ETH0_TXDLY_QUARTER);+break;++casePHY_INTERFACE_MODE_RMII:+/* Use the rate of the mux clock for the internal RMII PHY */+clk_rate=clk_get_rate(dwmac->m250_mux_clk);++/* disable RGMII mode -> enables RMII mode */+meson8b_dwmac_mask_bits(dwmac,PRG_ETH0,PRG_ETH0_RGMII_MODE,+0);++/* invert internal clk_rmii_i to generate 25/2.5 tx_rx_clk */+meson8b_dwmac_mask_bits(dwmac,PRG_ETH0,+PRG_ETH0_INVERTED_RMII_CLK,+PRG_ETH0_INVERTED_RMII_CLK);++/* TX clock delay cannot be configured in RMII mode */+meson8b_dwmac_mask_bits(dwmac,PRG_ETH0,PRG_ETH0_TXDLY_MASK,+0);++break;++default:+dev_err(&dwmac->pdev->dev,"unsupported phy-mode %s\n",+phy_modes(dwmac->phy_mode));+return-EINVAL;+}++ret=clk_prepare_enable(dwmac->m25_div_clk);+if(ret){+dev_err(&dwmac->pdev->dev,"failed to enable the PHY clock\n");+returnret;+}++ret=clk_set_rate(dwmac->m25_div_clk,clk_rate);+if(ret){+clk_disable_unprepare(dwmac->m25_div_clk);++dev_err(&dwmac->pdev->dev,"failed to set PHY clock\n");+returnret;+}++/* enable TX_CLK and PHY_REF_CLK generator */+meson8b_dwmac_mask_bits(dwmac,PRG_ETH0,PRG_ETH0_TX_AND_PHY_REF_CLK,+PRG_ETH0_TX_AND_PHY_REF_CLK);++return0;+}++staticintmeson8b_dwmac_probe(structplatform_device*pdev)+{+structplat_stmmacenet_data*plat_dat;+structstmmac_resourcesstmmac_res;+structresource*res;+structmeson8b_dwmac*dwmac;+intret;++ret=stmmac_get_platform_resources(pdev,&stmmac_res);+if(ret)+returnret;++plat_dat=stmmac_probe_config_dt(pdev,&stmmac_res.mac);+if(IS_ERR(plat_dat))+returnPTR_ERR(plat_dat);++dwmac=devm_kzalloc(&pdev->dev,sizeof(*dwmac),GFP_KERNEL);+if(!dwmac)+return-ENOMEM;++res=platform_get_resource(pdev,IORESOURCE_MEM,1);+if(!res)+return-ENODEV;++dwmac->regs=devm_ioremap_resource(&pdev->dev,res);+if(IS_ERR(dwmac->regs))+returnPTR_ERR(dwmac->regs);++dwmac->pdev=pdev;+dwmac->phy_mode=of_get_phy_mode(pdev->dev.of_node);+if(dwmac->phy_mode<0){+dev_err(&pdev->dev,"missing phy-mode property\n");+return-EINVAL;+}++ret=meson8b_init_clk(dwmac);+if(ret)+returnret;++ret=meson8b_init_prg_eth(dwmac);+if(ret)+returnret;++plat_dat->bsp_priv=dwmac;++returnstmmac_dvr_probe(&pdev->dev,plat_dat,&stmmac_res);+}++staticconststructof_device_idmeson8b_dwmac_match[]={+{.compatible="amlogic,meson8b-dwmac"},+{.compatible="amlogic,meson-gxbb-dwmac"},+{}+};+MODULE_DEVICE_TABLE(of,meson8b_dwmac_match);++staticstructplatform_drivermeson8b_dwmac_driver={+.probe=meson8b_dwmac_probe,+.remove=stmmac_pltfr_remove,+.driver={+.name="meson8b-dwmac",+.pm=&stmmac_pltfr_pm_ops,+.of_match_table=meson8b_dwmac_match,+},+};+module_platform_driver(meson8b_dwmac_driver);++MODULE_AUTHOR("Martin Blumenstingl <martin.blumenstingl@googlemail.com>");+MODULE_DESCRIPTION("Amlogic Meson S805/S905 DWMAC glue layer");+MODULE_LICENSE("GPL v2");
From: Martin Blumenstingl <martin.blumenstingl@googlemail.com> Date: 2016-08-15 16:41:00
The Amlogic reference driver uses the "mc_val" devicetree property to
configure the PRG_ETHERNET_ADDR0 register. Unfortunately it uses magic
values for this configuration.
According to the datasheet the PRG_ETHERNET_ADDR0 register is at address
0xc8834108. However, the reference driver uses 0xc8834540 instead.
According to my tests, the value from the reference driver is correct.
No changes are required to the board dts files because the only
required configuration option is the phy-mode, which had to be
configured correctly before as well.
Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
---
arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
From: Rob Herring <robh@kernel.org> Date: 2016-08-16 14:25:40
On Mon, Aug 15, 2016 at 06:40:58PM +0200, Martin Blumenstingl wrote:
This patch adds the documentation for the DWMAC ethernet controller
found in Amlogic Meson 8b (S805) and GXBB (S905) SoCs.
The main difference between the Meson6 glue is that different registers
(with different layout) are used.
Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
---
.../devicetree/bindings/net/meson-dwmac.txt | 43 ++++++++++++++++++----
1 file changed, 35 insertions(+), 8 deletions(-)
From: Martin Blumenstingl <martin.blumenstingl@googlemail.com> Date: 2016-08-20 09:35:34
This adds a DWMAC glue driver for the PRG_ETHERNET registers found in
Meson8b and GXBB SoCs. Based on the "old" meson6b-dwmac glue driver
the register layout is completely different.
Thus I introduced a separate driver.
Changes since v1:
- make clkin1 mandatory because the internal mux expects two clocks
(in other words: this makes the driver consistent with how the
hardware actually works)
- expose the MPLL2 clock for use by DT so we can pass it to the ethmac
- added a .remove function to the glue driver which disables and
unprepares the clocks on driver removal
Martin Blumenstingl (4):
net: dt-bindings: Document the new Meson8b and GXBB DWMAC bindings
clk: gxbb: expose MPLL2 clock for use by DT
net: stmmac: add a glue driver for the Amlogic Meson 8b / GXBB DWMAC
ARM64: dts: meson-gxbb: use the new GXBB DWMAC glue driver
.../devicetree/bindings/net/meson-dwmac.txt | 45 ++-
arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi | 8 +-
drivers/clk/meson/gxbb.h | 2 +-
drivers/net/ethernet/stmicro/stmmac/Makefile | 2 +-
.../net/ethernet/stmicro/stmmac/dwmac-meson8b.c | 329 +++++++++++++++++++++
include/dt-bindings/clock/gxbb-clkc.h | 1 +
6 files changed, 374 insertions(+), 13 deletions(-)
create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c
--
2.9.3
From: Martin Blumenstingl <martin.blumenstingl@googlemail.com> Date: 2016-08-20 09:35:35
This patch adds the documentation for the DWMAC ethernet controller
found in Amlogic Meson 8b (S805) and GXBB (S905) SoCs.
The main difference between the Meson6 glue is that different registers
(with different layout) are used.
Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
Acked-by: Rob Herring <robh@kernel.org>
---
.../devicetree/bindings/net/meson-dwmac.txt | 45 ++++++++++++++++++----
1 file changed, 37 insertions(+), 8 deletions(-)
@@ -1,18 +1,32 @@ * Amlogic Meson DWMAC Ethernet controller The device inherits all the properties of the dwmac/stmmac devices-described in the file net/stmmac.txt with the following changes.+described in the file stmmac.txt in the current directory with the+following changes.-Required properties:+Required properties on all platforms:-- compatible: should be "amlogic,meson6-dwmac" along with "snps,dwmac"- and any applicable more detailed version number- described in net/stmmac.txt+- compatible: Depending on the platform this should be one of:+ - "amlogic,meson6-dwmac"+ - "amlogic,meson8b-dwmac"+ - "amlogic,meson-gxbb-dwmac"+ Additionally "snps,dwmac" and any applicable more+ detailed version number described in net/stmmac.txt+ should be used.-- reg: should contain a register range for the dwmac controller and- another one for the Amlogic specific configuration+- reg: The first register range should be the one of the DWMAC+ controller. The second range is is for the Amlogic specific+ configuration (for example the PRG_ETHERNET register range+ on Meson8b and newer)-Example:+Required properties on Meson8b and newer:+- clock-names: Should contain the following:+ - "stmmaceth" - see stmmac.txt+ - "clkin0" - first parent clock of the internal mux+ - "clkin1" - second parent clock of the internal mux+++Example for Meson6: ethmac: ethernet@c9410000 { compatible = "amlogic,meson6-dwmac", "snps,dwmac";
From: Martin Blumenstingl <martin.blumenstingl@googlemail.com> Date: 2016-08-20 09:35:36
This exposes the MPLL2 clock as this is one of the input clocks of the
ethernet controller's internal mux.
Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
---
drivers/clk/meson/gxbb.h | 2 +-
include/dt-bindings/clock/gxbb-clkc.h | 1 +
2 files changed, 2 insertions(+), 1 deletion(-)
From: Martin Blumenstingl <martin.blumenstingl@googlemail.com> Date: 2016-08-20 09:35:37
The Ethernet controller available in Meson8b and GXBB SoCs is a Synopsys
DesignWare MAC IP core which is already supported by the stmmac driver.
In addition to the standard stmmac driver some Meson8b / GXBB specific
registers have to be configured for the PHY clocks. These SoC specific
registers are called PRG_ETHERNET_ADDR0 and PRG_ETHERNET_ADDR1 in the
datasheet.
These registers are not backwards compatible with those on Meson 6b,
which is why a new glue driver is introduced. This worked for many
boards because the bootloader programs the PRG_ETHERNET registers
correctly. Additionally the meson6-dwmac driver only sets bit 1 of
PRG_ETHERNET_ADDR0 which (according to the datasheet) is only used
during reset.
Currently all configuration values can be determined automatically,
based on the configured phy-mode (which is mandatory for the stmmac
driver). If required the tx-delay and the mux clock (so it supports
the MPLL2 clock as well) can be made configurable in the future.
Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
Tested-by: Kevin Hilman <khilman@baylibre.com>
---
drivers/net/ethernet/stmicro/stmmac/Makefile | 2 +-
.../net/ethernet/stmicro/stmmac/dwmac-meson8b.c | 329 +++++++++++++++++++++
2 files changed, 330 insertions(+), 1 deletion(-)
create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c
@@ -0,0 +1,329 @@+/*+*AmlogicMesonS805/S905DWMACgluelayer+*+*Copyright(C)20016MartinBlumenstingl<martin.blumenstingl@googlemail.com>+*+*Thisprogramisfreesoftware;youcanredistributeitand/ormodify+*itunderthetermsoftheGNUGeneralPublicLicenseversion2as+*publishedbytheFreeSoftwareFoundation.+*+*YoushouldhavereceivedacopyoftheGNUGeneralPublicLicense+*alongwiththisprogram.Ifnot,see<http://www.gnu.org/licenses/>.+*/++#include<linux/clk.h>+#include<linux/clk-provider.h>+#include<linux/device.h>+#include<linux/ethtool.h>+#include<linux/io.h>+#include<linux/ioport.h>+#include<linux/module.h>+#include<linux/of_net.h>+#include<linux/mfd/syscon.h>+#include<linux/platform_device.h>+#include<linux/stmmac.h>++#include"stmmac_platform.h"++#define PRG_ETH0 0x0++#define PRG_ETH0_RGMII_MODE BIT(0)++/* mux to choose between fclk_div2 (bit unset) and mpll2 (bit set) */+#define PRG_ETH0_CLK_M250_SEL_SHIFT 4+#define PRG_ETH0_CLK_M250_SEL_MASK GENMASK(4, 4)++#define PRG_ETH0_TXDLY_SHIFT 5+#define PRG_ETH0_TXDLY_MASK GENMASK(6, 5)+#define PRG_ETH0_TXDLY_OFF (0x0 << PRG_ETH0_TXDLY_SHIFT)+#define PRG_ETH0_TXDLY_QUARTER (0x1 << PRG_ETH0_TXDLY_SHIFT)+#define PRG_ETH0_TXDLY_HALF (0x2 << PRG_ETH0_TXDLY_SHIFT)+#define PRG_ETH0_TXDLY_THREE_QUARTERS (0x3 << PRG_ETH0_TXDLY_SHIFT)++/* divider for the result of m250_sel */+#define PRG_ETH0_CLK_M250_DIV_SHIFT 7+#define PRG_ETH0_CLK_M250_DIV_WIDTH 3++/* divides the result of m25_sel by either 5 (bit unset) or 10 (bit set) */+#define PRG_ETH0_CLK_M25_DIV_SHIFT 10+#define PRG_ETH0_CLK_M25_DIV_WIDTH 1++#define PRG_ETH0_INVERTED_RMII_CLK BIT(11)+#define PRG_ETH0_TX_AND_PHY_REF_CLK BIT(12)++#define MUX_CLK_NUM_PARENTS 2++structmeson8b_dwmac{+structplatform_device*pdev;++void__iomem*regs;++phy_interface_tphy_mode;++structclk_muxm250_mux;+structclk*m250_mux_clk;+structclk*m250_mux_parent[MUX_CLK_NUM_PARENTS];++structclk_dividerm250_div;+structclk*m250_div_clk;++structclk_dividerm25_div;+structclk*m25_div_clk;+};++staticvoidmeson8b_dwmac_mask_bits(structmeson8b_dwmac*dwmac,u32reg,+u32mask,u32value)+{+u32data;++data=readl(dwmac->regs+reg);+data&=~mask;+data|=(value&mask);++writel(data,dwmac->regs+reg);+}++staticintmeson8b_init_clk(structmeson8b_dwmac*dwmac)+{+structclk_init_datainit;+inti,ret;+structdevice*dev=&dwmac->pdev->dev;+charclk_name[32];+constchar*clk_div_parents[1];+constchar*mux_parent_names[MUX_CLK_NUM_PARENTS];+staticstructclk_div_tableclk_25m_div_table[]={+{.val=0,.div=5},+{.val=1,.div=10},+{/* sentinel */},+};++/* get the mux parents from DT */+for(i=0;i<MUX_CLK_NUM_PARENTS;i++){+charname[16];++snprintf(name,sizeof(name),"clkin%d",i);+dwmac->m250_mux_parent[i]=devm_clk_get(dev,name);+if(IS_ERR(dwmac->m250_mux_parent[i])){+ret=PTR_ERR(dwmac->m250_mux_parent[i]);+if(ret!=-EPROBE_DEFER)+dev_err(dev,"Missing clock %s\n",name);+returnret;+}++mux_parent_names[i]=+__clk_get_name(dwmac->m250_mux_parent[i]);+}++/* create the m250_mux */+snprintf(clk_name,sizeof(clk_name),"%s#m250_sel",dev_name(dev));+init.name=clk_name;+init.ops=&clk_mux_ops;+init.flags=CLK_IS_BASIC;+init.parent_names=mux_parent_names;+init.num_parents=MUX_CLK_NUM_PARENTS;++dwmac->m250_mux.reg=dwmac->regs+PRG_ETH0;+dwmac->m250_mux.shift=PRG_ETH0_CLK_M250_SEL_SHIFT;+dwmac->m250_mux.mask=PRG_ETH0_CLK_M250_SEL_MASK;+dwmac->m250_mux.flags=0;+dwmac->m250_mux.table=NULL;+dwmac->m250_mux.hw.init=&init;++dwmac->m250_mux_clk=devm_clk_register(dev,&dwmac->m250_mux.hw);+if(WARN_ON(PTR_ERR_OR_ZERO(dwmac->m250_mux_clk)))+returnPTR_ERR(dwmac->m250_mux_clk);++/* create the m250_div */+snprintf(clk_name,sizeof(clk_name),"%s#m250_div",dev_name(dev));+init.name=devm_kstrdup(dev,clk_name,GFP_KERNEL);+init.ops=&clk_divider_ops;+init.flags=CLK_IS_BASIC|CLK_SET_RATE_PARENT;+clk_div_parents[0]=__clk_get_name(dwmac->m250_mux_clk);+init.parent_names=clk_div_parents;+init.num_parents=ARRAY_SIZE(clk_div_parents);++dwmac->m250_div.reg=dwmac->regs+PRG_ETH0;+dwmac->m250_div.shift=PRG_ETH0_CLK_M250_DIV_SHIFT;+dwmac->m250_div.width=PRG_ETH0_CLK_M250_DIV_WIDTH;+dwmac->m250_div.hw.init=&init;+dwmac->m250_div.flags=CLK_DIVIDER_ONE_BASED|CLK_DIVIDER_ALLOW_ZERO;++dwmac->m250_div_clk=devm_clk_register(dev,&dwmac->m250_div.hw);+if(WARN_ON(PTR_ERR_OR_ZERO(dwmac->m250_div_clk)))+returnPTR_ERR(dwmac->m250_div_clk);++/* create the m25_div */+snprintf(clk_name,sizeof(clk_name),"%s#m25_div",dev_name(dev));+init.name=devm_kstrdup(dev,clk_name,GFP_KERNEL);+init.ops=&clk_divider_ops;+init.flags=CLK_IS_BASIC|CLK_SET_RATE_PARENT;+clk_div_parents[0]=__clk_get_name(dwmac->m250_div_clk);+init.parent_names=clk_div_parents;+init.num_parents=ARRAY_SIZE(clk_div_parents);++dwmac->m25_div.reg=dwmac->regs+PRG_ETH0;+dwmac->m25_div.shift=PRG_ETH0_CLK_M25_DIV_SHIFT;+dwmac->m25_div.width=PRG_ETH0_CLK_M25_DIV_WIDTH;+dwmac->m25_div.table=clk_25m_div_table;+dwmac->m25_div.hw.init=&init;+dwmac->m25_div.flags=CLK_DIVIDER_ALLOW_ZERO;++dwmac->m25_div_clk=devm_clk_register(dev,&dwmac->m25_div.hw);+if(WARN_ON(PTR_ERR_OR_ZERO(dwmac->m25_div_clk)))+returnPTR_ERR(dwmac->m25_div_clk);++return0;+}++staticintmeson8b_init_prg_eth(structmeson8b_dwmac*dwmac)+{+intret;+unsignedlongclk_rate;++switch(dwmac->phy_mode){+casePHY_INTERFACE_MODE_RGMII:+casePHY_INTERFACE_MODE_RGMII_ID:+casePHY_INTERFACE_MODE_RGMII_RXID:+casePHY_INTERFACE_MODE_RGMII_TXID:+/* Generate a 25MHz clock for the PHY */+clk_rate=25*1000*1000;++/* enable RGMII mode */+meson8b_dwmac_mask_bits(dwmac,PRG_ETH0,PRG_ETH0_RGMII_MODE,+PRG_ETH0_RGMII_MODE);++/* only relevant for RMII mode -> disable in RGMII mode */+meson8b_dwmac_mask_bits(dwmac,PRG_ETH0,+PRG_ETH0_INVERTED_RMII_CLK,0);++/* TX clock delay - all known boards use a 1/4 cycle delay */+meson8b_dwmac_mask_bits(dwmac,PRG_ETH0,PRG_ETH0_TXDLY_MASK,+PRG_ETH0_TXDLY_QUARTER);+break;++casePHY_INTERFACE_MODE_RMII:+/* Use the rate of the mux clock for the internal RMII PHY */+clk_rate=clk_get_rate(dwmac->m250_mux_clk);++/* disable RGMII mode -> enables RMII mode */+meson8b_dwmac_mask_bits(dwmac,PRG_ETH0,PRG_ETH0_RGMII_MODE,+0);++/* invert internal clk_rmii_i to generate 25/2.5 tx_rx_clk */+meson8b_dwmac_mask_bits(dwmac,PRG_ETH0,+PRG_ETH0_INVERTED_RMII_CLK,+PRG_ETH0_INVERTED_RMII_CLK);++/* TX clock delay cannot be configured in RMII mode */+meson8b_dwmac_mask_bits(dwmac,PRG_ETH0,PRG_ETH0_TXDLY_MASK,+0);++break;++default:+dev_err(&dwmac->pdev->dev,"unsupported phy-mode %s\n",+phy_modes(dwmac->phy_mode));+return-EINVAL;+}++ret=clk_prepare_enable(dwmac->m25_div_clk);+if(ret){+dev_err(&dwmac->pdev->dev,"failed to enable the PHY clock\n");+returnret;+}++ret=clk_set_rate(dwmac->m25_div_clk,clk_rate);+if(ret){+clk_disable_unprepare(dwmac->m25_div_clk);++dev_err(&dwmac->pdev->dev,"failed to set PHY clock\n");+returnret;+}++/* enable TX_CLK and PHY_REF_CLK generator */+meson8b_dwmac_mask_bits(dwmac,PRG_ETH0,PRG_ETH0_TX_AND_PHY_REF_CLK,+PRG_ETH0_TX_AND_PHY_REF_CLK);++return0;+}++staticintmeson8b_dwmac_probe(structplatform_device*pdev)+{+structplat_stmmacenet_data*plat_dat;+structstmmac_resourcesstmmac_res;+structresource*res;+structmeson8b_dwmac*dwmac;+intret;++ret=stmmac_get_platform_resources(pdev,&stmmac_res);+if(ret)+returnret;++plat_dat=stmmac_probe_config_dt(pdev,&stmmac_res.mac);+if(IS_ERR(plat_dat))+returnPTR_ERR(plat_dat);++dwmac=devm_kzalloc(&pdev->dev,sizeof(*dwmac),GFP_KERNEL);+if(!dwmac)+return-ENOMEM;++res=platform_get_resource(pdev,IORESOURCE_MEM,1);+if(!res)+return-ENODEV;++dwmac->regs=devm_ioremap_resource(&pdev->dev,res);+if(IS_ERR(dwmac->regs))+returnPTR_ERR(dwmac->regs);++dwmac->pdev=pdev;+dwmac->phy_mode=of_get_phy_mode(pdev->dev.of_node);+if(dwmac->phy_mode<0){+dev_err(&pdev->dev,"missing phy-mode property\n");+return-EINVAL;+}++ret=meson8b_init_clk(dwmac);+if(ret)+returnret;++ret=meson8b_init_prg_eth(dwmac);+if(ret)+returnret;++plat_dat->bsp_priv=dwmac;++platform_set_drvdata(pdev,dwmac);++returnstmmac_dvr_probe(&pdev->dev,plat_dat,&stmmac_res);+}++staticintmeson8b_dwmac_remove(structplatform_device*pdev)+{+structmeson8b_dwmac*dwmac=platform_get_drvdata(pdev);++clk_disable_unprepare(dwmac->m25_div_clk);++returnstmmac_pltfr_remove(pdev);+}++staticconststructof_device_idmeson8b_dwmac_match[]={+{.compatible="amlogic,meson8b-dwmac"},+{.compatible="amlogic,meson-gxbb-dwmac"},+{}+};+MODULE_DEVICE_TABLE(of,meson8b_dwmac_match);++staticstructplatform_drivermeson8b_dwmac_driver={+.probe=meson8b_dwmac_probe,+.remove=meson8b_dwmac_remove,+.driver={+.name="meson8b-dwmac",+.pm=&stmmac_pltfr_pm_ops,+.of_match_table=meson8b_dwmac_match,+},+};+module_platform_driver(meson8b_dwmac_driver);++MODULE_AUTHOR("Martin Blumenstingl <martin.blumenstingl@googlemail.com>");+MODULE_DESCRIPTION("Amlogic Meson S805/S905 DWMAC glue layer");+MODULE_LICENSE("GPL v2");
From: Joachim Eastwood <hidden> Date: 2016-08-20 21:29:08
Hi Martin,
On 20 August 2016 at 11:35, Martin Blumenstingl
[off-list ref] wrote:
The Ethernet controller available in Meson8b and GXBB SoCs is a Synopsys
DesignWare MAC IP core which is already supported by the stmmac driver.
In addition to the standard stmmac driver some Meson8b / GXBB specific
registers have to be configured for the PHY clocks. These SoC specific
registers are called PRG_ETHERNET_ADDR0 and PRG_ETHERNET_ADDR1 in the
datasheet.
These registers are not backwards compatible with those on Meson 6b,
which is why a new glue driver is introduced. This worked for many
boards because the bootloader programs the PRG_ETHERNET registers
correctly. Additionally the meson6-dwmac driver only sets bit 1 of
PRG_ETHERNET_ADDR0 which (according to the datasheet) is only used
during reset.
Currently all configuration values can be determined automatically,
based on the configured phy-mode (which is mandatory for the stmmac
driver). If required the tx-delay and the mux clock (so it supports
the MPLL2 clock as well) can be made configurable in the future.
Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
Tested-by: Kevin Hilman <khilman@baylibre.com>
---
drivers/net/ethernet/stmicro/stmmac/Makefile | 2 +-
.../net/ethernet/stmicro/stmmac/dwmac-meson8b.c | 329 +++++++++++++++++++++
2 files changed, 330 insertions(+), 1 deletion(-)
create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c
Did you test this code? I am pretty sure it will blow up given that
driver_data is not set to what you expect.
To get your meson8b_dwmac struct you must retrieve it from plat_dat->bsp_priv.
I have some code for a helper to retrieve bsp_priv that I have meant
to sent to the ML for a while now.
See: https://github.com/manabian/linux-lpc/commit/c3e155a6e38b9634e4e61aa4eeb4602ede7e44a6
Feel free to add it to your patch set if you want.
Alternatively take a look at the remove function from dwmac-stm32 here:
https://patchwork.ozlabs.org/patch/619816/
From: Martin Blumenstingl <martin.blumenstingl@googlemail.com> Date: 2016-08-28 16:16:32
This adds a DWMAC glue driver for the PRG_ETHERNET registers found in
Meson8b and GXBB SoCs. Based on the "old" meson6b-dwmac glue driver
the register layout is completely different.
Thus I introduced a separate driver.
Changes since v2:
- fixed unloading the glue driver when built as module. This pulls in a
patch from Joachim Eastwood (thanks) to get our private data structure
(bsp_priv).
Joachim Eastwood (1):
stmmac: introduce get_stmmac_bsp_priv() helper
Martin Blumenstingl (4):
net: dt-bindings: Document the new Meson8b and GXBB DWMAC bindings
clk: gxbb: expose MPLL2 clock for use by DT
net: stmmac: add a glue driver for the Amlogic Meson 8b / GXBB DWMAC
ARM64: dts: meson-gxbb: use the new GXBB DWMAC glue driver
.../devicetree/bindings/net/meson-dwmac.txt | 45 ++-
arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi | 8 +-
drivers/clk/meson/gxbb.h | 2 +-
drivers/net/ethernet/stmicro/stmmac/Makefile | 2 +-
.../net/ethernet/stmicro/stmmac/dwmac-meson8b.c | 327 +++++++++++++++++++++
.../net/ethernet/stmicro/stmmac/stmmac_platform.h | 8 +
include/dt-bindings/clock/gxbb-clkc.h | 1 +
7 files changed, 380 insertions(+), 13 deletions(-)
create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c
--
2.9.3
From: Martin Blumenstingl <martin.blumenstingl@googlemail.com> Date: 2016-08-28 16:16:34
This exposes the MPLL2 clock as this is one of the input clocks of the
ethernet controller's internal mux.
Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
---
drivers/clk/meson/gxbb.h | 2 +-
include/dt-bindings/clock/gxbb-clkc.h | 1 +
2 files changed, 2 insertions(+), 1 deletion(-)
From: Martin Blumenstingl <martin.blumenstingl@googlemail.com> Date: 2016-08-28 16:16:36
The Ethernet controller available in Meson8b and GXBB SoCs is a Synopsys
DesignWare MAC IP core which is already supported by the stmmac driver.
In addition to the standard stmmac driver some Meson8b / GXBB specific
registers have to be configured for the PHY clocks. These SoC specific
registers are called PRG_ETHERNET_ADDR0 and PRG_ETHERNET_ADDR1 in the
datasheet.
These registers are not backwards compatible with those on Meson 6b,
which is why a new glue driver is introduced. This worked for many
boards because the bootloader programs the PRG_ETHERNET registers
correctly. Additionally the meson6-dwmac driver only sets bit 1 of
PRG_ETHERNET_ADDR0 which (according to the datasheet) is only used
during reset.
Currently all configuration values can be determined automatically,
based on the configured phy-mode (which is mandatory for the stmmac
driver). If required the tx-delay and the mux clock (so it supports
the MPLL2 clock as well) can be made configurable in the future.
Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
Tested-by: Kevin Hilman <khilman@baylibre.com>
---
drivers/net/ethernet/stmicro/stmmac/Makefile | 2 +-
.../net/ethernet/stmicro/stmmac/dwmac-meson8b.c | 327 +++++++++++++++++++++
2 files changed, 328 insertions(+), 1 deletion(-)
create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c
@@ -0,0 +1,327 @@+/*+*AmlogicMesonS805/S905DWMACgluelayer+*+*Copyright(C)20016MartinBlumenstingl<martin.blumenstingl@googlemail.com>+*+*Thisprogramisfreesoftware;youcanredistributeitand/ormodify+*itunderthetermsoftheGNUGeneralPublicLicenseversion2as+*publishedbytheFreeSoftwareFoundation.+*+*YoushouldhavereceivedacopyoftheGNUGeneralPublicLicense+*alongwiththisprogram.Ifnot,see<http://www.gnu.org/licenses/>.+*/++#include<linux/clk.h>+#include<linux/clk-provider.h>+#include<linux/device.h>+#include<linux/ethtool.h>+#include<linux/io.h>+#include<linux/ioport.h>+#include<linux/module.h>+#include<linux/of_net.h>+#include<linux/mfd/syscon.h>+#include<linux/platform_device.h>+#include<linux/stmmac.h>++#include"stmmac_platform.h"++#define PRG_ETH0 0x0++#define PRG_ETH0_RGMII_MODE BIT(0)++/* mux to choose between fclk_div2 (bit unset) and mpll2 (bit set) */+#define PRG_ETH0_CLK_M250_SEL_SHIFT 4+#define PRG_ETH0_CLK_M250_SEL_MASK GENMASK(4, 4)++#define PRG_ETH0_TXDLY_SHIFT 5+#define PRG_ETH0_TXDLY_MASK GENMASK(6, 5)+#define PRG_ETH0_TXDLY_OFF (0x0 << PRG_ETH0_TXDLY_SHIFT)+#define PRG_ETH0_TXDLY_QUARTER (0x1 << PRG_ETH0_TXDLY_SHIFT)+#define PRG_ETH0_TXDLY_HALF (0x2 << PRG_ETH0_TXDLY_SHIFT)+#define PRG_ETH0_TXDLY_THREE_QUARTERS (0x3 << PRG_ETH0_TXDLY_SHIFT)++/* divider for the result of m250_sel */+#define PRG_ETH0_CLK_M250_DIV_SHIFT 7+#define PRG_ETH0_CLK_M250_DIV_WIDTH 3++/* divides the result of m25_sel by either 5 (bit unset) or 10 (bit set) */+#define PRG_ETH0_CLK_M25_DIV_SHIFT 10+#define PRG_ETH0_CLK_M25_DIV_WIDTH 1++#define PRG_ETH0_INVERTED_RMII_CLK BIT(11)+#define PRG_ETH0_TX_AND_PHY_REF_CLK BIT(12)++#define MUX_CLK_NUM_PARENTS 2++structmeson8b_dwmac{+structplatform_device*pdev;++void__iomem*regs;++phy_interface_tphy_mode;++structclk_muxm250_mux;+structclk*m250_mux_clk;+structclk*m250_mux_parent[MUX_CLK_NUM_PARENTS];++structclk_dividerm250_div;+structclk*m250_div_clk;++structclk_dividerm25_div;+structclk*m25_div_clk;+};++staticvoidmeson8b_dwmac_mask_bits(structmeson8b_dwmac*dwmac,u32reg,+u32mask,u32value)+{+u32data;++data=readl(dwmac->regs+reg);+data&=~mask;+data|=(value&mask);++writel(data,dwmac->regs+reg);+}++staticintmeson8b_init_clk(structmeson8b_dwmac*dwmac)+{+structclk_init_datainit;+inti,ret;+structdevice*dev=&dwmac->pdev->dev;+charclk_name[32];+constchar*clk_div_parents[1];+constchar*mux_parent_names[MUX_CLK_NUM_PARENTS];+staticstructclk_div_tableclk_25m_div_table[]={+{.val=0,.div=5},+{.val=1,.div=10},+{/* sentinel */},+};++/* get the mux parents from DT */+for(i=0;i<MUX_CLK_NUM_PARENTS;i++){+charname[16];++snprintf(name,sizeof(name),"clkin%d",i);+dwmac->m250_mux_parent[i]=devm_clk_get(dev,name);+if(IS_ERR(dwmac->m250_mux_parent[i])){+ret=PTR_ERR(dwmac->m250_mux_parent[i]);+if(ret!=-EPROBE_DEFER)+dev_err(dev,"Missing clock %s\n",name);+returnret;+}++mux_parent_names[i]=+__clk_get_name(dwmac->m250_mux_parent[i]);+}++/* create the m250_mux */+snprintf(clk_name,sizeof(clk_name),"%s#m250_sel",dev_name(dev));+init.name=clk_name;+init.ops=&clk_mux_ops;+init.flags=CLK_IS_BASIC;+init.parent_names=mux_parent_names;+init.num_parents=MUX_CLK_NUM_PARENTS;++dwmac->m250_mux.reg=dwmac->regs+PRG_ETH0;+dwmac->m250_mux.shift=PRG_ETH0_CLK_M250_SEL_SHIFT;+dwmac->m250_mux.mask=PRG_ETH0_CLK_M250_SEL_MASK;+dwmac->m250_mux.flags=0;+dwmac->m250_mux.table=NULL;+dwmac->m250_mux.hw.init=&init;++dwmac->m250_mux_clk=devm_clk_register(dev,&dwmac->m250_mux.hw);+if(WARN_ON(PTR_ERR_OR_ZERO(dwmac->m250_mux_clk)))+returnPTR_ERR(dwmac->m250_mux_clk);++/* create the m250_div */+snprintf(clk_name,sizeof(clk_name),"%s#m250_div",dev_name(dev));+init.name=devm_kstrdup(dev,clk_name,GFP_KERNEL);+init.ops=&clk_divider_ops;+init.flags=CLK_IS_BASIC|CLK_SET_RATE_PARENT;+clk_div_parents[0]=__clk_get_name(dwmac->m250_mux_clk);+init.parent_names=clk_div_parents;+init.num_parents=ARRAY_SIZE(clk_div_parents);++dwmac->m250_div.reg=dwmac->regs+PRG_ETH0;+dwmac->m250_div.shift=PRG_ETH0_CLK_M250_DIV_SHIFT;+dwmac->m250_div.width=PRG_ETH0_CLK_M250_DIV_WIDTH;+dwmac->m250_div.hw.init=&init;+dwmac->m250_div.flags=CLK_DIVIDER_ONE_BASED|CLK_DIVIDER_ALLOW_ZERO;++dwmac->m250_div_clk=devm_clk_register(dev,&dwmac->m250_div.hw);+if(WARN_ON(PTR_ERR_OR_ZERO(dwmac->m250_div_clk)))+returnPTR_ERR(dwmac->m250_div_clk);++/* create the m25_div */+snprintf(clk_name,sizeof(clk_name),"%s#m25_div",dev_name(dev));+init.name=devm_kstrdup(dev,clk_name,GFP_KERNEL);+init.ops=&clk_divider_ops;+init.flags=CLK_IS_BASIC|CLK_SET_RATE_PARENT;+clk_div_parents[0]=__clk_get_name(dwmac->m250_div_clk);+init.parent_names=clk_div_parents;+init.num_parents=ARRAY_SIZE(clk_div_parents);++dwmac->m25_div.reg=dwmac->regs+PRG_ETH0;+dwmac->m25_div.shift=PRG_ETH0_CLK_M25_DIV_SHIFT;+dwmac->m25_div.width=PRG_ETH0_CLK_M25_DIV_WIDTH;+dwmac->m25_div.table=clk_25m_div_table;+dwmac->m25_div.hw.init=&init;+dwmac->m25_div.flags=CLK_DIVIDER_ALLOW_ZERO;++dwmac->m25_div_clk=devm_clk_register(dev,&dwmac->m25_div.hw);+if(WARN_ON(PTR_ERR_OR_ZERO(dwmac->m25_div_clk)))+returnPTR_ERR(dwmac->m25_div_clk);++return0;+}++staticintmeson8b_init_prg_eth(structmeson8b_dwmac*dwmac)+{+intret;+unsignedlongclk_rate;++switch(dwmac->phy_mode){+casePHY_INTERFACE_MODE_RGMII:+casePHY_INTERFACE_MODE_RGMII_ID:+casePHY_INTERFACE_MODE_RGMII_RXID:+casePHY_INTERFACE_MODE_RGMII_TXID:+/* Generate a 25MHz clock for the PHY */+clk_rate=25*1000*1000;++/* enable RGMII mode */+meson8b_dwmac_mask_bits(dwmac,PRG_ETH0,PRG_ETH0_RGMII_MODE,+PRG_ETH0_RGMII_MODE);++/* only relevant for RMII mode -> disable in RGMII mode */+meson8b_dwmac_mask_bits(dwmac,PRG_ETH0,+PRG_ETH0_INVERTED_RMII_CLK,0);++/* TX clock delay - all known boards use a 1/4 cycle delay */+meson8b_dwmac_mask_bits(dwmac,PRG_ETH0,PRG_ETH0_TXDLY_MASK,+PRG_ETH0_TXDLY_QUARTER);+break;++casePHY_INTERFACE_MODE_RMII:+/* Use the rate of the mux clock for the internal RMII PHY */+clk_rate=clk_get_rate(dwmac->m250_mux_clk);++/* disable RGMII mode -> enables RMII mode */+meson8b_dwmac_mask_bits(dwmac,PRG_ETH0,PRG_ETH0_RGMII_MODE,+0);++/* invert internal clk_rmii_i to generate 25/2.5 tx_rx_clk */+meson8b_dwmac_mask_bits(dwmac,PRG_ETH0,+PRG_ETH0_INVERTED_RMII_CLK,+PRG_ETH0_INVERTED_RMII_CLK);++/* TX clock delay cannot be configured in RMII mode */+meson8b_dwmac_mask_bits(dwmac,PRG_ETH0,PRG_ETH0_TXDLY_MASK,+0);++break;++default:+dev_err(&dwmac->pdev->dev,"unsupported phy-mode %s\n",+phy_modes(dwmac->phy_mode));+return-EINVAL;+}++ret=clk_prepare_enable(dwmac->m25_div_clk);+if(ret){+dev_err(&dwmac->pdev->dev,"failed to enable the PHY clock\n");+returnret;+}++ret=clk_set_rate(dwmac->m25_div_clk,clk_rate);+if(ret){+clk_disable_unprepare(dwmac->m25_div_clk);++dev_err(&dwmac->pdev->dev,"failed to set PHY clock\n");+returnret;+}++/* enable TX_CLK and PHY_REF_CLK generator */+meson8b_dwmac_mask_bits(dwmac,PRG_ETH0,PRG_ETH0_TX_AND_PHY_REF_CLK,+PRG_ETH0_TX_AND_PHY_REF_CLK);++return0;+}++staticintmeson8b_dwmac_probe(structplatform_device*pdev)+{+structplat_stmmacenet_data*plat_dat;+structstmmac_resourcesstmmac_res;+structresource*res;+structmeson8b_dwmac*dwmac;+intret;++ret=stmmac_get_platform_resources(pdev,&stmmac_res);+if(ret)+returnret;++plat_dat=stmmac_probe_config_dt(pdev,&stmmac_res.mac);+if(IS_ERR(plat_dat))+returnPTR_ERR(plat_dat);++dwmac=devm_kzalloc(&pdev->dev,sizeof(*dwmac),GFP_KERNEL);+if(!dwmac)+return-ENOMEM;++res=platform_get_resource(pdev,IORESOURCE_MEM,1);+if(!res)+return-ENODEV;++dwmac->regs=devm_ioremap_resource(&pdev->dev,res);+if(IS_ERR(dwmac->regs))+returnPTR_ERR(dwmac->regs);++dwmac->pdev=pdev;+dwmac->phy_mode=of_get_phy_mode(pdev->dev.of_node);+if(dwmac->phy_mode<0){+dev_err(&pdev->dev,"missing phy-mode property\n");+return-EINVAL;+}++ret=meson8b_init_clk(dwmac);+if(ret)+returnret;++ret=meson8b_init_prg_eth(dwmac);+if(ret)+returnret;++plat_dat->bsp_priv=dwmac;++returnstmmac_dvr_probe(&pdev->dev,plat_dat,&stmmac_res);+}++staticintmeson8b_dwmac_remove(structplatform_device*pdev)+{+structmeson8b_dwmac*dwmac=get_stmmac_bsp_priv(&pdev->dev);++clk_disable_unprepare(dwmac->m25_div_clk);++returnstmmac_pltfr_remove(pdev);+}++staticconststructof_device_idmeson8b_dwmac_match[]={+{.compatible="amlogic,meson8b-dwmac"},+{.compatible="amlogic,meson-gxbb-dwmac"},+{}+};+MODULE_DEVICE_TABLE(of,meson8b_dwmac_match);++staticstructplatform_drivermeson8b_dwmac_driver={+.probe=meson8b_dwmac_probe,+.remove=meson8b_dwmac_remove,+.driver={+.name="meson8b-dwmac",+.pm=&stmmac_pltfr_pm_ops,+.of_match_table=meson8b_dwmac_match,+},+};+module_platform_driver(meson8b_dwmac_driver);++MODULE_AUTHOR("Martin Blumenstingl <martin.blumenstingl@googlemail.com>");+MODULE_DESCRIPTION("Amlogic Meson S805/S905 DWMAC glue layer");+MODULE_LICENSE("GPL v2");
From: Martin Blumenstingl <martin.blumenstingl@googlemail.com> Date: 2016-08-28 16:16:37
The Amlogic reference driver uses the "mc_val" devicetree property to
configure the PRG_ETHERNET_ADDR0 register. Unfortunately it uses magic
values for this configuration.
According to the datasheet the PRG_ETHERNET_ADDR0 register is at address
0xc8834108. However, the reference driver uses 0xc8834540 instead.
According to my tests, the value from the reference driver is correct.
No changes are required to the board dts files because the only
required configuration option is the phy-mode, which had to be
configured correctly before as well.
Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
---
arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
From: David Miller <davem@davemloft.net> Date: 2016-08-29 03:40:08
From: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
Date: Sun, 28 Aug 2016 18:16:32 +0200
This adds a DWMAC glue driver for the PRG_ETHERNET registers found in
Meson8b and GXBB SoCs. Based on the "old" meson6b-dwmac glue driver
the register layout is completely different.
Thus I introduced a separate driver.
Changes since v2:
- fixed unloading the glue driver when built as module. This pulls in a
patch from Joachim Eastwood (thanks) to get our private data structure
(bsp_priv).
This doesn't apply cleanly at all to the net-next tree, so I have
no idea where you expect these changes to be applied.
From: Martin Blumenstingl <martin.blumenstingl@googlemail.com> Date: 2016-08-30 18:49:28
On Mon, Aug 29, 2016 at 5:40 AM, David Miller [off-list ref] wrote:
From: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
Date: Sun, 28 Aug 2016 18:16:32 +0200
quoted
This adds a DWMAC glue driver for the PRG_ETHERNET registers found in
Meson8b and GXBB SoCs. Based on the "old" meson6b-dwmac glue driver
the register layout is completely different.
Thus I introduced a separate driver.
Changes since v2:
- fixed unloading the glue driver when built as module. This pulls in a
patch from Joachim Eastwood (thanks) to get our private data structure
(bsp_priv).
This doesn't apply cleanly at all to the net-next tree, so I have
no idea where you expect these changes to be applied.
OK, maybe Kevin can me help out here as I think the patches should go
to various trees.
I think patches 1, 3 and 4 should go through the net-next tree (as
these touch drivers/net/ethernet/stmicro/stmmac/ and the corresponding
documentation).
Patch 2 should probably go through clk-meson-gxbb / clk-next (just
like the other clk changes we had).
The last patch (patch 5) should probably go through the ARM SoC tree
(just like the other dts changes we had).
@David, Kevin: would this be fine for you?
We've been trying to move away from devm_clk_register() to
devm_clk_hw_register() so that clk providers aren't also clk
consumers. Obviously in this case this driver is a provider and a
consumer, so this isn't as important. Kevin did something similar
in the mmc driver, so I'll reiterate what I said on that patch.
Perhaps we should make __clk_create_clk() into a real clk
provider API so that we can use devm_clk_hw_register() here and
then generate a clk for this device. That would allow us to have
proper consumer tracking without relying on the clk that is
returned from clk_register() (the intent is to make that clk
instance internal to the framework).
From: Martin Blumenstingl <martin.blumenstingl@googlemail.com> Date: 2016-09-04 18:23:15
This adds a DWMAC glue driver for the PRG_ETHERNET registers found in
Meson8b and GXBB SoCs. Based on the "old" meson6b-dwmac glue driver
the register layout is completely different.
Thus I introduced a separate driver.
Changes since v3:
- remove (unnecessary) usage of CLK_IS_BASIC flag
- use WARN_ON(IS_ERR(...)) instead of WARN_ON(PTR_ERR_OR_ZERO(...))
- let devm_ioremap_resource() check the result returned by
platform_get_resource()
- added David Miller's ACKs to the patches which would be relevant for
the net-next tree (patches 1, 3 and 4) as per
http://lists.infradead.org/pipermail/linux-amlogic/2016-September/000995.html
- fixed typo in copyright year
Joachim Eastwood (1):
stmmac: introduce get_stmmac_bsp_priv() helper
Martin Blumenstingl (4):
net: dt-bindings: Document the new Meson8b and GXBB DWMAC bindings
clk: gxbb: expose MPLL2 clock for use by DT
net: stmmac: add a glue driver for the Amlogic Meson 8b / GXBB DWMAC
ARM64: dts: meson-gxbb: use the new GXBB DWMAC glue driver
.../devicetree/bindings/net/meson-dwmac.txt | 45 ++-
arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi | 8 +-
drivers/clk/meson/gxbb.h | 2 +-
drivers/net/ethernet/stmicro/stmmac/Makefile | 2 +-
.../net/ethernet/stmicro/stmmac/dwmac-meson8b.c | 324 +++++++++++++++++++++
.../net/ethernet/stmicro/stmmac/stmmac_platform.h | 8 +
include/dt-bindings/clock/gxbb-clkc.h | 1 +
7 files changed, 377 insertions(+), 13 deletions(-)
create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c
--
2.9.3
From: Martin Blumenstingl <martin.blumenstingl@googlemail.com> Date: 2016-09-04 18:23:16
This patch adds the documentation for the DWMAC ethernet controller
found in Amlogic Meson 8b (S805) and GXBB (S905) SoCs.
The main difference between the Meson6 glue is that different registers
(with different layout) are used.
Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
Acked-by: Rob Herring <robh@kernel.org>
Acked-by: David S. Miller <davem@davemloft.net>
---
.../devicetree/bindings/net/meson-dwmac.txt | 45 ++++++++++++++++++----
1 file changed, 37 insertions(+), 8 deletions(-)
@@ -1,18 +1,32 @@ * Amlogic Meson DWMAC Ethernet controller The device inherits all the properties of the dwmac/stmmac devices-described in the file net/stmmac.txt with the following changes.+described in the file stmmac.txt in the current directory with the+following changes.-Required properties:+Required properties on all platforms:-- compatible: should be "amlogic,meson6-dwmac" along with "snps,dwmac"- and any applicable more detailed version number- described in net/stmmac.txt+- compatible: Depending on the platform this should be one of:+ - "amlogic,meson6-dwmac"+ - "amlogic,meson8b-dwmac"+ - "amlogic,meson-gxbb-dwmac"+ Additionally "snps,dwmac" and any applicable more+ detailed version number described in net/stmmac.txt+ should be used.-- reg: should contain a register range for the dwmac controller and- another one for the Amlogic specific configuration+- reg: The first register range should be the one of the DWMAC+ controller. The second range is is for the Amlogic specific+ configuration (for example the PRG_ETHERNET register range+ on Meson8b and newer)-Example:+Required properties on Meson8b and newer:+- clock-names: Should contain the following:+ - "stmmaceth" - see stmmac.txt+ - "clkin0" - first parent clock of the internal mux+ - "clkin1" - second parent clock of the internal mux+++Example for Meson6: ethmac: ethernet@c9410000 { compatible = "amlogic,meson6-dwmac", "snps,dwmac";
From: Martin Blumenstingl <martin.blumenstingl@googlemail.com> Date: 2016-09-04 18:23:17
This exposes the MPLL2 clock as this is one of the input clocks of the
ethernet controller's internal mux.
Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
---
drivers/clk/meson/gxbb.h | 2 +-
include/dt-bindings/clock/gxbb-clkc.h | 1 +
2 files changed, 2 insertions(+), 1 deletion(-)
From: Martin Blumenstingl <martin.blumenstingl@googlemail.com> Date: 2016-09-04 18:23:18
From: Joachim Eastwood <redacted>
Create a helper to retrive dwmac private data from a dev
pointer. This is useful in PM callbacks and driver remove.
Signed-off-by: Joachim Eastwood <redacted>
Tested-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
Acked-by: David S. Miller <davem@davemloft.net>
---
drivers/net/ethernet/stmicro/stmmac/stmmac_platform.h | 8 ++++++++
1 file changed, 8 insertions(+)
From: Martin Blumenstingl <martin.blumenstingl@googlemail.com> Date: 2016-09-04 18:23:20
The Amlogic reference driver uses the "mc_val" devicetree property to
configure the PRG_ETHERNET_ADDR0 register. Unfortunately it uses magic
values for this configuration.
According to the datasheet the PRG_ETHERNET_ADDR0 register is at address
0xc8834108. However, the reference driver uses 0xc8834540 instead.
According to my tests, the value from the reference driver is correct.
No changes are required to the board dts files because the only
required configuration option is the phy-mode, which had to be
configured correctly before as well.
Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
---
arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)