* [PATCH v2 19/19] ARM: dts: aspeed-plametto: Add flash layout
From: Cédric Le Goater @ 2017-12-18 9:09 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20171215062443.23059-20-joel@jms.id.au>
On 12/15/2017 07:24 AM, Joel Stanley wrote:
> The OpenBMC flash layout is used by Palmetto systems.
>
> Signed-off-by: Joel Stanley <joel@jms.id.au>
Reviewed-by: C?dric Le Goater <clg@kaod.org>
> ---
> arch/arm/boot/dts/aspeed-bmc-opp-palmetto.dts | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/arch/arm/boot/dts/aspeed-bmc-opp-palmetto.dts b/arch/arm/boot/dts/aspeed-bmc-opp-palmetto.dts
> index a8f0c046e83e..cc18137386f2 100644
> --- a/arch/arm/boot/dts/aspeed-bmc-opp-palmetto.dts
> +++ b/arch/arm/boot/dts/aspeed-bmc-opp-palmetto.dts
> @@ -34,6 +34,7 @@
> status = "okay";
> m25p,fast-read;
> label = "bmc";
> +#include "openbmc-flash-layout.dtsi"
> };
> };
>
>
^ permalink raw reply
* [PATCH v2 10/19] ARM: dts: aspeed: Add LPC Snoop device
From: Cédric Le Goater @ 2017-12-18 9:16 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20171215062443.23059-11-joel@jms.id.au>
On 12/15/2017 07:24 AM, Joel Stanley wrote:
> LPC snoop hardware on the ASPEED BMC, used for monitoring
> host I/O port activity.
>
> Signed-off-by: Joel Stanley <joel@jms.id.au>
> ---
> arch/arm/boot/dts/aspeed-g4.dtsi | 7 +++++++
> arch/arm/boot/dts/aspeed-g5.dtsi | 6 ++++++
> 2 files changed, 13 insertions(+)
>
> diff --git a/arch/arm/boot/dts/aspeed-g4.dtsi b/arch/arm/boot/dts/aspeed-g4.dtsi
> index f6fee40c04c0..b3580f37f507 100644
> --- a/arch/arm/boot/dts/aspeed-g4.dtsi
> +++ b/arch/arm/boot/dts/aspeed-g4.dtsi
> @@ -236,6 +236,13 @@
> status = "disabled";
> };
>
> + lpc_snoop: lpc-snoop at 0 {
> + compatible = "aspeed,ast2500-lpc-snoop";
it should be :
aspeed,ast2400-lpc-snoop
a part from that :
Reviewed-by: C?dric Le Goater <clg@kaod.org>
> + reg = <0x0 0x80>;
> + interrupts = <8>;
> + status = "disabled";
> + };
> +
> lhc: lhc at 20 {
> compatible = "aspeed,ast2500-lhc";
> reg = <0x20 0x24 0x48 0x8>;
> diff --git a/arch/arm/boot/dts/aspeed-g5.dtsi b/arch/arm/boot/dts/aspeed-g5.dtsi
> index 96a9d2fe3f0d..50766f0629f8 100644
> --- a/arch/arm/boot/dts/aspeed-g5.dtsi
> +++ b/arch/arm/boot/dts/aspeed-g5.dtsi
> @@ -287,6 +287,12 @@
> status = "disabled";
> };
>
> + lpc_snoop: lpc-snoop at 0 {
> + compatible = "aspeed,ast2500-lpc-snoop";
> + reg = <0x0 0x80>;
> + interrupts = <8>;
> + status = "disabled";
> + };
>
> lhc: lhc at 20 {
> compatible = "aspeed,ast2500-lhc";
>
^ permalink raw reply
* [net-next: PATCH 0/8] Armada 7k/8k PP2 ACPI support
From: Marcin Wojtas @ 2017-12-18 9:17 UTC (permalink / raw)
To: linux-arm-kernel
Hi,
This patchset introduces ACPI support in mvpp2 and mvmdio drivers.
First three patches introduce fwnode helpers for obtaining PHY
information from nodes and also MDIO fwnode API for registering
the bus with its PHY/devices.
Following patches update code of the mvmdio and mvpp2 drivers
to support ACPI tables handling. The latter is done in 4 steps,
as can be seen in the commits. For the details, please
refer to the commit messages.
Drivers operation was tested on top of the net-next branch
with both DT and ACPI. Although for compatibility reasons
with older platforms, the mvmdio driver keeps using
of_ MDIO registering, new fwnode_ one proved to fully work
with DT as well (tested on MacchiatoBin board).
mvpp2/mvmdio driver can work with the ACPI representation, as exposed
on a public branch:
https://github.com/MarvellEmbeddedProcessors/edk2-open-platform/commits/marvell-armada-wip
It was compiled together with the most recent Tianocore EDK2 revision.
Please refer to the firmware build instruction on MacchiatoBin board:
http://wiki.macchiatobin.net/tiki-index.php?page=Build+from+source+-+UEFI+EDK+II
Above support configures 1G to use its PHY normally. 10G can work now
only with the link interrupt mode. Somehow reading of the
string property in fwnode_mdiobus_child_is_phy works only with
DT and cannot cope with 10G PHY nodes as in:
https://pastebin.com/3JnYpU0A
Above root cause will be further checked. In the meantime I will
appreciate any comments or remarks for the kernel patches.
Best regards,
Marcin
Marcin Wojtas (8):
device property: Introduce fwnode_get_mac_address()
device property: Introduce fwnode_get_phy_mode()
mdio_bus: Introduce fwnode MDIO helpers
net: mvmdio: add ACPI support
net: mvpp2: simplify maintaining enabled ports' list
net: mvpp2: use device_*/fwnode_* APIs instead of of_*
net: mvpp2: handle PHY with its fwnode
net: mvpp2: enable ACPI support in the driver
drivers/base/property.c | 52 +++--
drivers/net/ethernet/marvell/mvmdio.c | 42 +++-
drivers/net/ethernet/marvell/mvpp2.c | 246 ++++++++++++--------
drivers/net/phy/mdio_bus.c | 218 +++++++++++++++++
include/linux/mdio.h | 3 +
include/linux/property.h | 3 +
6 files changed, 454 insertions(+), 110 deletions(-)
--
2.7.4
^ permalink raw reply
* [net-next: PATCH 1/8] device property: Introduce fwnode_get_mac_address()
From: Marcin Wojtas @ 2017-12-18 9:17 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1513588684-15647-1-git-send-email-mw@semihalf.com>
Until now there were two almost identical functions for
obtaining MAC address - of_get_mac_address() and, more generic,
device_get_mac_address(). However it is not uncommon,
that the network interface is represented as a child
of the actual controller, hence it is not associated
directly to any struct device, required by the latter
routine.
This commit allows for getting the MAC address for
children nodes in the ACPI world by introducing a new function -
fwnode_get_mac_address(). This commit also changes
device_get_mac_address() routine to be its wrapper, in order
to prevent unnecessary duplication.
Signed-off-by: Marcin Wojtas <mw@semihalf.com>
---
drivers/base/property.c | 28 ++++++++++++++------
include/linux/property.h | 2 ++
2 files changed, 22 insertions(+), 8 deletions(-)
diff --git a/drivers/base/property.c b/drivers/base/property.c
index 851b1b6..f261d1a 100644
--- a/drivers/base/property.c
+++ b/drivers/base/property.c
@@ -1153,11 +1153,11 @@ int device_get_phy_mode(struct device *dev)
}
EXPORT_SYMBOL_GPL(device_get_phy_mode);
-static void *device_get_mac_addr(struct device *dev,
+static void *fwnode_get_mac_addr(struct fwnode_handle *fwnode,
const char *name, char *addr,
int alen)
{
- int ret = device_property_read_u8_array(dev, name, addr, alen);
+ int ret = fwnode_property_read_u8_array(fwnode, name, addr, alen);
if (ret == 0 && alen == ETH_ALEN && is_valid_ether_addr(addr))
return addr;
@@ -1165,8 +1165,8 @@ static void *device_get_mac_addr(struct device *dev,
}
/**
- * device_get_mac_address - Get the MAC for a given device
- * @dev: Pointer to the device
+ * fwnode_get_mac_address - Get the MAC from the firmware node
+ * @fwnode: Pointer to the firmware node
* @addr: Address of buffer to store the MAC in
* @alen: Length of the buffer pointed to by addr, should be ETH_ALEN
*
@@ -1187,19 +1187,31 @@ static void *device_get_mac_addr(struct device *dev,
* In this case, the real MAC is in 'local-mac-address', and 'mac-address'
* exists but is all zeros.
*/
-void *device_get_mac_address(struct device *dev, char *addr, int alen)
+void *fwnode_get_mac_address(struct fwnode_handle *fwnode, char *addr, int alen)
{
char *res;
- res = device_get_mac_addr(dev, "mac-address", addr, alen);
+ res = fwnode_get_mac_addr(fwnode, "mac-address", addr, alen);
if (res)
return res;
- res = device_get_mac_addr(dev, "local-mac-address", addr, alen);
+ res = fwnode_get_mac_addr(fwnode, "local-mac-address", addr, alen);
if (res)
return res;
- return device_get_mac_addr(dev, "address", addr, alen);
+ return fwnode_get_mac_addr(fwnode, "address", addr, alen);
+}
+EXPORT_SYMBOL(fwnode_get_mac_address);
+
+/**
+ * device_get_mac_address - Get the MAC for a given device
+ * @dev: Pointer to the device
+ * @addr: Address of buffer to store the MAC in
+ * @alen: Length of the buffer pointed to by addr, should be ETH_ALEN
+ */
+void *device_get_mac_address(struct device *dev, char *addr, int alen)
+{
+ return fwnode_get_mac_address(dev_fwnode(dev), addr, alen);
}
EXPORT_SYMBOL(device_get_mac_address);
diff --git a/include/linux/property.h b/include/linux/property.h
index f6189a3..35620e0 100644
--- a/include/linux/property.h
+++ b/include/linux/property.h
@@ -279,6 +279,8 @@ int device_get_phy_mode(struct device *dev);
void *device_get_mac_address(struct device *dev, char *addr, int alen);
+void *fwnode_get_mac_address(struct fwnode_handle *fwnode,
+ char *addr, int alen);
struct fwnode_handle *fwnode_graph_get_next_endpoint(
const struct fwnode_handle *fwnode, struct fwnode_handle *prev);
struct fwnode_handle *
--
2.7.4
^ permalink raw reply related
* [net-next: PATCH 2/8] device property: Introduce fwnode_get_phy_mode()
From: Marcin Wojtas @ 2017-12-18 9:17 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1513588684-15647-1-git-send-email-mw@semihalf.com>
Until now there were two almost identical functions for
obtaining network PHY mode - of_get_phy_mode() and,
more generic, device_get_phy_mode(). However it is not uncommon,
that the network interface is represented as a child
of the actual controller, hence it is not associated
directly to any struct device, required by the latter
routine.
This commit allows for getting the PHY mode for
children nodes in the ACPI world by introducing a new function -
fwnode_get_phy_mode(). This commit also changes
device_get_phy_mode() routine to be its wrapper, in order
to prevent unnecessary duplication.
Signed-off-by: Marcin Wojtas <mw@semihalf.com>
---
drivers/base/property.c | 24 ++++++++++++++++----
include/linux/property.h | 1 +
2 files changed, 20 insertions(+), 5 deletions(-)
diff --git a/drivers/base/property.c b/drivers/base/property.c
index f261d1a..7c4a53d 100644
--- a/drivers/base/property.c
+++ b/drivers/base/property.c
@@ -1126,21 +1126,21 @@ enum dev_dma_attr device_get_dma_attr(struct device *dev)
EXPORT_SYMBOL_GPL(device_get_dma_attr);
/**
- * device_get_phy_mode - Get phy mode for given device
- * @dev: Pointer to the given device
+ * fwnode_get_phy_mode - Get phy mode for given firmware node
+ * @fwnode: Pointer to the given node
*
* The function gets phy interface string from property 'phy-mode' or
* 'phy-connection-type', and return its index in phy_modes table, or errno in
* error case.
*/
-int device_get_phy_mode(struct device *dev)
+int fwnode_get_phy_mode(struct fwnode_handle *fwnode)
{
const char *pm;
int err, i;
- err = device_property_read_string(dev, "phy-mode", &pm);
+ err = fwnode_property_read_string(fwnode, "phy-mode", &pm);
if (err < 0)
- err = device_property_read_string(dev,
+ err = fwnode_property_read_string(fwnode,
"phy-connection-type", &pm);
if (err < 0)
return err;
@@ -1151,6 +1151,20 @@ int device_get_phy_mode(struct device *dev)
return -ENODEV;
}
+EXPORT_SYMBOL_GPL(fwnode_get_phy_mode);
+
+/**
+ * device_get_phy_mode - Get phy mode for given device
+ * @dev: Pointer to the given device
+ *
+ * The function gets phy interface string from property 'phy-mode' or
+ * 'phy-connection-type', and return its index in phy_modes table, or errno in
+ * error case.
+ */
+int device_get_phy_mode(struct device *dev)
+{
+ return fwnode_get_phy_mode(dev_fwnode(dev));
+}
EXPORT_SYMBOL_GPL(device_get_phy_mode);
static void *fwnode_get_mac_addr(struct fwnode_handle *fwnode,
diff --git a/include/linux/property.h b/include/linux/property.h
index 35620e0..9b13332 100644
--- a/include/linux/property.h
+++ b/include/linux/property.h
@@ -279,6 +279,7 @@ int device_get_phy_mode(struct device *dev);
void *device_get_mac_address(struct device *dev, char *addr, int alen);
+int fwnode_get_phy_mode(struct fwnode_handle *fwnode);
void *fwnode_get_mac_address(struct fwnode_handle *fwnode,
char *addr, int alen);
struct fwnode_handle *fwnode_graph_get_next_endpoint(
--
2.7.4
^ permalink raw reply related
* [net-next: PATCH 3/8] mdio_bus: Introduce fwnode MDIO helpers
From: Marcin Wojtas @ 2017-12-18 9:17 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1513588684-15647-1-git-send-email-mw@semihalf.com>
This patch introduces fwnode helper for registering MDIO
bus, as well as one for finding the PHY, basing on its
firmware node pointer. Comparing to existing OF equivalent,
fwnode_mdiobus_register() does not support:
* deprecated bindings (device whitelist, nor the PHY ID embedded
in the compatible string)
* MDIO bus auto scanning
Signed-off-by: Marcin Wojtas <mw@semihalf.com>
---
drivers/net/phy/mdio_bus.c | 218 ++++++++++++++++++++
include/linux/mdio.h | 3 +
2 files changed, 221 insertions(+)
diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c
index a0f34c3..f2b2a94 100644
--- a/drivers/net/phy/mdio_bus.c
+++ b/drivers/net/phy/mdio_bus.c
@@ -27,6 +27,7 @@
#include <linux/of_device.h>
#include <linux/of_mdio.h>
#include <linux/of_gpio.h>
+#include <linux/of_irq.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
@@ -662,6 +663,223 @@ static int mdio_uevent(struct device *dev, struct kobj_uevent_env *env)
return 0;
}
+static int fwnode_mdiobus_register_phy(struct mii_bus *bus,
+ struct fwnode_handle *child, u32 addr)
+{
+ struct phy_device *phy;
+ bool is_c45 = false;
+ int rc;
+
+ rc = fwnode_property_match_string(child, "compatible",
+ "ethernet-phy-ieee802.3-c45");
+ if (!rc)
+ is_c45 = true;
+
+ phy = get_phy_device(bus, addr, is_c45);
+ if (IS_ERR(phy))
+ return PTR_ERR(phy);
+
+ phy->irq = bus->irq[addr];
+
+ if (to_of_node(child)) {
+ rc = of_irq_get(to_of_node(child), 0);
+ if (rc == -EPROBE_DEFER) {
+ phy_device_free(phy);
+ return rc;
+ } else if (rc > 0) {
+ phy->irq = rc;
+ bus->irq[addr] = rc;
+ }
+ }
+
+ if (fwnode_property_read_bool(child, "broken-turn-around"))
+ bus->phy_ignore_ta_mask |= 1 << addr;
+
+ /* Associate the fwnode with the device structure so it
+ * can be looked up later.
+ */
+ phy->mdio.dev.fwnode = child;
+
+ /* All data is now stored in the phy struct, so register it */
+ rc = phy_device_register(phy);
+ if (rc) {
+ phy_device_free(phy);
+ fwnode_handle_put(child);
+ return rc;
+ }
+
+ dev_dbg(&bus->dev, "registered phy at address %i\n", addr);
+
+ return 0;
+}
+
+static int fwnode_mdiobus_register_device(struct mii_bus *bus,
+ struct fwnode_handle *child, u32 addr)
+{
+ struct mdio_device *mdiodev;
+ int rc;
+
+ mdiodev = mdio_device_create(bus, addr);
+ if (IS_ERR(mdiodev))
+ return PTR_ERR(mdiodev);
+
+ /* Associate the fwnode with the device structure so it
+ * can be looked up later.
+ */
+ mdiodev->dev.fwnode = child;
+
+ /* All data is now stored in the mdiodev struct; register it. */
+ rc = mdio_device_register(mdiodev);
+ if (rc) {
+ mdio_device_free(mdiodev);
+ fwnode_handle_put(child);
+ return rc;
+ }
+
+ dev_dbg(&bus->dev, "registered mdio device at address %i\n", addr);
+
+ return 0;
+}
+
+static int fwnode_mdio_parse_addr(struct device *dev,
+ const struct fwnode_handle *fwnode)
+{
+ u32 addr;
+ int ret;
+
+ ret = fwnode_property_read_u32(fwnode, "reg", &addr);
+ if (ret < 0) {
+ dev_err(dev, "PHY node has no 'reg' property\n");
+ return ret;
+ }
+
+ /* A PHY must have a reg property in the range [0-31] */
+ if (addr < 0 || addr >= PHY_MAX_ADDR) {
+ dev_err(dev, "PHY address %i is invalid\n", addr);
+ return -EINVAL;
+ }
+
+ return addr;
+}
+
+/**
+ * fwnode_mdiobus_child_is_phy - Return true if the child is a PHY node.
+ * It must either:
+ * o Compatible string of "ethernet-phy-ieee802.3-c45"
+ * o Compatible string of "ethernet-phy-ieee802.3-c22"
+ * Checking "compatible" property is done, in order to follow the DT binding.
+ */
+static bool fwnode_mdiobus_child_is_phy(struct fwnode_handle *child)
+{
+ int ret;
+
+ ret = fwnode_property_match_string(child, "compatible",
+ "ethernet-phy-ieee802.3-c45");
+ if (!ret)
+ return true;
+
+ ret = fwnode_property_match_string(child, "compatible",
+ "ethernet-phy-ieee802.3-c22");
+ if (!ret)
+ return true;
+
+ if (!fwnode_property_present(child, "compatible"))
+ return true;
+
+ return false;
+}
+
+/**
+ * fwnode_mdiobus_register - Register mii_bus and create PHYs from the fwnode
+ * @bus: pointer to mii_bus structure
+ * @fwnode: pointer to fwnode_handle of MDIO bus.
+ *
+ * This function registers the mii_bus structure and registers a phy_device
+ * for each child node of @fwnode.
+ */
+int fwnode_mdiobus_register(struct mii_bus *bus, struct fwnode_handle *fwnode)
+{
+ struct fwnode_handle *child;
+ int addr, rc;
+ int default_gpio_reset_delay_ms = 10;
+
+ /* Do not continue if the node is disabled */
+ if (!fwnode_device_is_available(fwnode))
+ return -ENODEV;
+
+ /* Mask out all PHYs from auto probing. Instead the PHYs listed in
+ * the firmware nodes are populated after the bus has been registered.
+ */
+ bus->phy_mask = ~0;
+
+ bus->dev.fwnode = fwnode;
+
+ /* Get bus level PHY reset GPIO details */
+ bus->reset_delay_us = default_gpio_reset_delay_ms;
+ fwnode_property_read_u32(fwnode, "reset-delay-us",
+ &bus->reset_delay_us);
+
+ /* Register the MDIO bus */
+ rc = mdiobus_register(bus);
+ if (rc)
+ return rc;
+
+ /* Loop over the child nodes and register a phy_device for each PHY */
+ fwnode_for_each_child_node(fwnode, child) {
+ addr = fwnode_mdio_parse_addr(&bus->dev, child);
+ if (addr < 0)
+ continue;
+
+ if (fwnode_mdiobus_child_is_phy(child))
+ rc = fwnode_mdiobus_register_phy(bus, child, addr);
+ else
+ rc = fwnode_mdiobus_register_device(bus, child, addr);
+ if (rc)
+ goto unregister;
+ }
+
+ return 0;
+
+unregister:
+ mdiobus_unregister(bus);
+
+ return rc;
+}
+EXPORT_SYMBOL(fwnode_mdiobus_register);
+
+/* Helper function for fwnode_phy_find_device */
+static int fwnode_phy_match(struct device *dev, void *phy_fwnode)
+{
+ return dev->fwnode == phy_fwnode;
+}
+
+/**
+ * fwnode_phy_find_device - find the phy_device associated to fwnode
+ * @phy_fwnode: Pointer to the PHY's fwnode
+ *
+ * If successful, returns a pointer to the phy_device with the embedded
+ * struct device refcount incremented by one, or NULL on failure.
+ */
+struct phy_device *fwnode_phy_find_device(struct fwnode_handle *phy_fwnode)
+{
+ struct device *d;
+ struct mdio_device *mdiodev;
+
+ if (!phy_fwnode)
+ return NULL;
+
+ d = bus_find_device(&mdio_bus_type, NULL, phy_fwnode, fwnode_phy_match);
+ if (d) {
+ mdiodev = to_mdio_device(d);
+ if (mdiodev->flags & MDIO_DEVICE_FLAG_PHY)
+ return to_phy_device(d);
+ put_device(d);
+ }
+
+ return NULL;
+}
+EXPORT_SYMBOL(fwnode_phy_find_device);
+
#ifdef CONFIG_PM
static int mdio_bus_suspend(struct device *dev)
{
diff --git a/include/linux/mdio.h b/include/linux/mdio.h
index e37c21d..286ec12 100644
--- a/include/linux/mdio.h
+++ b/include/linux/mdio.h
@@ -272,6 +272,9 @@ int mdiobus_unregister_device(struct mdio_device *mdiodev);
bool mdiobus_is_registered_device(struct mii_bus *bus, int addr);
struct phy_device *mdiobus_get_phy(struct mii_bus *bus, int addr);
+int fwnode_mdiobus_register(struct mii_bus *bus, struct fwnode_handle *fwnode);
+struct phy_device *fwnode_phy_find_device(struct fwnode_handle *phy_fwnode);
+
/**
* mdio_module_driver() - Helper macro for registering mdio drivers
*
--
2.7.4
^ permalink raw reply related
* [net-next: PATCH 4/8] net: mvmdio: add ACPI support
From: Marcin Wojtas @ 2017-12-18 9:18 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1513588684-15647-1-git-send-email-mw@semihalf.com>
This patch introducing ACPI support for the mvmdio driver by adding
acpi_match_table with two entries:
* "MRVL0100" for the SMI operation
* "MRVL0101" for the XSMI mode
Also clk enabling is skipped, because the tables do not contain
such data and clock maintenance relies on the firmware. The
MDIO bus is registered using newly introduced
fwnode_mdiobus_register().
Memory region used by mvmdio driver is usually placed in the middle
of the address space of the network controller (e.g. NETA or PP2).
The MDIO base address is obtained without requesting memory region
(by devm_ioremap() call), later overlapping resources are
requested by the network driver, where care is taken to avoid
concurrent access.
This way of solving problem occurred to be not sufficient with ACPI,
because resources declared in the table and used once, appear as
'in-use' in the OS. This patch also ensures releasing resources by
mvmdio driver prior to initializing the network controller driver.
Signed-off-by: Marcin Wojtas <mw@semihalf.com>
---
drivers/net/ethernet/marvell/mvmdio.c | 42 +++++++++++++++++++-
1 file changed, 40 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/marvell/mvmdio.c b/drivers/net/ethernet/marvell/mvmdio.c
index 0495487..31d758a 100644
--- a/drivers/net/ethernet/marvell/mvmdio.c
+++ b/drivers/net/ethernet/marvell/mvmdio.c
@@ -17,6 +17,7 @@
* warranty of any kind, whether express or implied.
*/
+#include <linux/acpi.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
@@ -279,9 +280,19 @@ static int orion_mdio_probe(struct platform_device *pdev)
struct resource *r;
struct mii_bus *bus;
struct orion_mdio_dev *dev;
+ const struct acpi_device_id *acpi_id;
+ bool use_acpi = false;
int i, ret;
- type = (enum orion_mdio_bus_type)of_device_get_match_data(&pdev->dev);
+ if (has_acpi_companion(&pdev->dev)) {
+ acpi_id = acpi_match_device(pdev->dev.driver->acpi_match_table,
+ &pdev->dev);
+ type = (enum orion_mdio_bus_type)acpi_id->driver_data;
+ use_acpi = true;
+ } else {
+ type =
+ (enum orion_mdio_bus_type)of_device_get_match_data(&pdev->dev);
+ }
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!r) {
@@ -319,7 +330,7 @@ static int orion_mdio_probe(struct platform_device *pdev)
init_waitqueue_head(&dev->smi_busy_wait);
- for (i = 0; i < ARRAY_SIZE(dev->clk); i++) {
+ for (i = 0; !use_acpi && i < ARRAY_SIZE(dev->clk); i++) {
dev->clk[i] = of_clk_get(pdev->dev.of_node, i);
if (IS_ERR(dev->clk[i]))
break;
@@ -350,6 +361,8 @@ static int orion_mdio_probe(struct platform_device *pdev)
if (pdev->dev.of_node)
ret = of_mdiobus_register(bus, pdev->dev.of_node);
+ else if (use_acpi)
+ ret = fwnode_mdiobus_register(bus, pdev->dev.fwnode);
else
ret = mdiobus_register(bus);
if (ret < 0) {
@@ -357,6 +370,15 @@ static int orion_mdio_probe(struct platform_device *pdev)
goto out_mdio;
}
+ /* In case of ACPI resources declared in the tables and used
+ * once, appear as 'in-use' in the OS. Make sure they are released,
+ * before the network driver possibly requests it again during
+ * its initialization. The care is taken there to avoid
+ * concurrent access to this memory region.
+ */
+ if (use_acpi)
+ release_resource(r);
+
platform_set_drvdata(pdev, bus);
return 0;
@@ -365,6 +387,11 @@ static int orion_mdio_probe(struct platform_device *pdev)
if (dev->err_interrupt > 0)
writel(0, dev->regs + MVMDIO_ERR_INT_MASK);
+ if (use_acpi) {
+ release_resource(r);
+ return ret;
+ }
+
for (i = 0; i < ARRAY_SIZE(dev->clk); i++) {
if (IS_ERR(dev->clk[i]))
break;
@@ -385,6 +412,9 @@ static int orion_mdio_remove(struct platform_device *pdev)
writel(0, dev->regs + MVMDIO_ERR_INT_MASK);
mdiobus_unregister(bus);
+ if (has_acpi_companion(&pdev->dev))
+ return 0;
+
for (i = 0; i < ARRAY_SIZE(dev->clk); i++) {
if (IS_ERR(dev->clk[i]))
break;
@@ -402,12 +432,20 @@ static const struct of_device_id orion_mdio_match[] = {
};
MODULE_DEVICE_TABLE(of, orion_mdio_match);
+static const struct acpi_device_id orion_mdio_acpi_match[] = {
+ { "MRVL0100", BUS_TYPE_SMI },
+ { "MRVL0101", BUS_TYPE_XSMI },
+ { },
+};
+MODULE_DEVICE_TABLE(acpi, orion_mdio_acpi_match);
+
static struct platform_driver orion_mdio_driver = {
.probe = orion_mdio_probe,
.remove = orion_mdio_remove,
.driver = {
.name = "orion-mdio",
.of_match_table = orion_mdio_match,
+ .acpi_match_table = ACPI_PTR(orion_mdio_acpi_match),
},
};
--
2.7.4
^ permalink raw reply related
* [net-next: PATCH 5/8] net: mvpp2: simplify maintaining enabled ports' list
From: Marcin Wojtas @ 2017-12-18 9:18 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1513588684-15647-1-git-send-email-mw@semihalf.com>
'port_count' field of the mvpp2 structure holds an overall amount
of available ports, based on DT nodes status. In order to be prepared
to support other HW description, obtain the value by incrementing it
upon each successful port initialization. This allowed for simplifying
port indexing in the controller's private array, whose size is now not
dynamically allocated, but fixed to MVPP2_MAX_PORTS.
This patch simplifies creating and filling list of enabled ports and
is a part of the preparation for adding ACPI support in the mvpp2 driver.
Signed-off-by: Marcin Wojtas <mw@semihalf.com>
---
drivers/net/ethernet/marvell/mvpp2.c | 32 +++++++-------------
1 file changed, 11 insertions(+), 21 deletions(-)
diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c
index a197607..7f42d90 100644
--- a/drivers/net/ethernet/marvell/mvpp2.c
+++ b/drivers/net/ethernet/marvell/mvpp2.c
@@ -865,7 +865,7 @@ struct mvpp2 {
/* List of pointers to port structures */
int port_count;
- struct mvpp2_port **port_list;
+ struct mvpp2_port *port_list[MVPP2_MAX_PORTS];
/* Aggregated TXQs */
struct mvpp2_tx_queue *aggr_txqs;
@@ -7741,7 +7741,7 @@ static void mvpp2_port_copy_mac_addr(struct net_device *dev, struct mvpp2 *priv,
/* Ports initialization */
static int mvpp2_port_probe(struct platform_device *pdev,
struct device_node *port_node,
- struct mvpp2 *priv, int index)
+ struct mvpp2 *priv)
{
struct device_node *phy_node;
struct phy *comphy;
@@ -7934,7 +7934,8 @@ static int mvpp2_port_probe(struct platform_device *pdev,
}
netdev_info(dev, "Using %s mac address %pM\n", mac_from, dev->dev_addr);
- priv->port_list[index] = port;
+ priv->port_list[priv->port_count++] = port;
+
return 0;
err_free_port_pcpu:
@@ -8313,28 +8314,17 @@ static int mvpp2_probe(struct platform_device *pdev)
goto err_mg_clk;
}
- priv->port_count = of_get_available_child_count(dn);
- if (priv->port_count == 0) {
- dev_err(&pdev->dev, "no ports enabled\n");
- err = -ENODEV;
- goto err_mg_clk;
- }
-
- priv->port_list = devm_kcalloc(&pdev->dev, priv->port_count,
- sizeof(*priv->port_list),
- GFP_KERNEL);
- if (!priv->port_list) {
- err = -ENOMEM;
- goto err_mg_clk;
- }
-
/* Initialize ports */
- i = 0;
for_each_available_child_of_node(dn, port_node) {
- err = mvpp2_port_probe(pdev, port_node, priv, i);
+ err = mvpp2_port_probe(pdev, port_node, priv);
if (err < 0)
goto err_port_probe;
- i++;
+ }
+
+ if (priv->port_count == 0) {
+ dev_err(&pdev->dev, "no ports enabled\n");
+ err = -ENODEV;
+ goto err_mg_clk;
}
/* Statistics must be gathered regularly because some of them (like
--
2.7.4
^ permalink raw reply related
* [net-next: PATCH 6/8] net: mvpp2: use device_*/fwnode_* APIs instead of of_*
From: Marcin Wojtas @ 2017-12-18 9:18 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1513588684-15647-1-git-send-email-mw@semihalf.com>
OF functions can be used only for the driver using DT.
As a preparation for introducing ACPI support in mvpp2
driver, use struct fwnode_handle in order to obtain
properties from the hardware description.
Because there is no equivalent for for_each_available_child_of_node(),
use device_for_each_child_node() and check the port availability
inside the mvpp2_port_probe() routine.
This patch replaces of_* function with device_*/fwnode_*
where possible in the mvpp2.
Signed-off-by: Marcin Wojtas <mw@semihalf.com>
---
drivers/net/ethernet/marvell/mvpp2.c | 47 +++++++++++---------
1 file changed, 26 insertions(+), 21 deletions(-)
diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c
index 7f42d90..537474f 100644
--- a/drivers/net/ethernet/marvell/mvpp2.c
+++ b/drivers/net/ethernet/marvell/mvpp2.c
@@ -932,6 +932,9 @@ struct mvpp2_port {
struct mvpp2 *priv;
+ /* Firmware node associated to the port */
+ struct fwnode_handle *fwnode;
+
/* Per-port registers' base address */
void __iomem *base;
void __iomem *stats_base;
@@ -7711,17 +7714,16 @@ static bool mvpp2_port_has_tx_irqs(struct mvpp2 *priv,
}
static void mvpp2_port_copy_mac_addr(struct net_device *dev, struct mvpp2 *priv,
- struct device_node *port_node,
+ struct fwnode_handle *fwnode,
char **mac_from)
{
struct mvpp2_port *port = netdev_priv(dev);
char hw_mac_addr[ETH_ALEN] = {0};
- const char *dt_mac_addr;
+ char fw_mac_addr[ETH_ALEN];
- dt_mac_addr = of_get_mac_address(port_node);
- if (dt_mac_addr && is_valid_ether_addr(dt_mac_addr)) {
- *mac_from = "device tree";
- ether_addr_copy(dev->dev_addr, dt_mac_addr);
+ if (fwnode_get_mac_address(fwnode, fw_mac_addr, ETH_ALEN)) {
+ *mac_from = "firmware node";
+ ether_addr_copy(dev->dev_addr, fw_mac_addr);
return;
}
@@ -7740,13 +7742,14 @@ static void mvpp2_port_copy_mac_addr(struct net_device *dev, struct mvpp2 *priv,
/* Ports initialization */
static int mvpp2_port_probe(struct platform_device *pdev,
- struct device_node *port_node,
+ struct fwnode_handle *port_fwnode,
struct mvpp2 *priv)
{
struct device_node *phy_node;
struct phy *comphy;
struct mvpp2_port *port;
struct mvpp2_port_pcpu *port_pcpu;
+ struct device_node *port_node = to_of_node(port_fwnode);
struct net_device *dev;
struct resource *res;
char *mac_from = "";
@@ -7757,6 +7760,10 @@ static int mvpp2_port_probe(struct platform_device *pdev,
int phy_mode;
int err, i, cpu;
+ /* Silently exit, if the port node turns out to be disabled. */
+ if (!fwnode_device_is_available(port_fwnode))
+ return 0;
+
has_tx_irqs = mvpp2_port_has_tx_irqs(priv, port_node);
if (!has_tx_irqs)
@@ -7773,7 +7780,7 @@ static int mvpp2_port_probe(struct platform_device *pdev,
return -ENOMEM;
phy_node = of_parse_phandle(port_node, "phy", 0);
- phy_mode = of_get_phy_mode(port_node);
+ phy_mode = fwnode_get_phy_mode(port_fwnode);
if (phy_mode < 0) {
dev_err(&pdev->dev, "incorrect phy mode\n");
err = phy_mode;
@@ -7789,7 +7796,7 @@ static int mvpp2_port_probe(struct platform_device *pdev,
comphy = NULL;
}
- if (of_property_read_u32(port_node, "port-id", &id)) {
+ if (fwnode_property_read_u32(port_fwnode, "port-id", &id)) {
err = -EINVAL;
dev_err(&pdev->dev, "missing port-id value\n");
goto err_free_netdev;
@@ -7820,7 +7827,7 @@ static int mvpp2_port_probe(struct platform_device *pdev,
/* the link irq is optional */
port->link_irq = 0;
- if (of_property_read_bool(port_node, "marvell,loopback"))
+ if (fwnode_property_read_bool(port_fwnode, "marvell,loopback"))
port->flags |= MVPP2_F_LOOPBACK;
port->id = id;
@@ -7845,8 +7852,8 @@ static int mvpp2_port_probe(struct platform_device *pdev,
MVPP21_MIB_COUNTERS_OFFSET +
port->gop_id * MVPP21_MIB_COUNTERS_PORT_SZ;
} else {
- if (of_property_read_u32(port_node, "gop-port-id",
- &port->gop_id)) {
+ if (fwnode_property_read_u32(port_fwnode, "gop-port-id",
+ &port->gop_id)) {
err = -EINVAL;
dev_err(&pdev->dev, "missing gop-port-id value\n");
goto err_deinit_qvecs;
@@ -7876,7 +7883,7 @@ static int mvpp2_port_probe(struct platform_device *pdev,
mutex_init(&port->gather_stats_lock);
INIT_DELAYED_WORK(&port->stats_work, mvpp2_gather_hw_statistics);
- mvpp2_port_copy_mac_addr(dev, priv, port_node, &mac_from);
+ mvpp2_port_copy_mac_addr(dev, priv, port_fwnode, &mac_from);
port->tx_ring_size = MVPP2_MAX_TXD_DFLT;
port->rx_ring_size = MVPP2_MAX_RXD_DFLT;
@@ -8194,8 +8201,7 @@ static int mvpp2_init(struct platform_device *pdev, struct mvpp2 *priv)
static int mvpp2_probe(struct platform_device *pdev)
{
- struct device_node *dn = pdev->dev.of_node;
- struct device_node *port_node;
+ struct fwnode_handle *port_fwnode;
struct mvpp2 *priv;
struct resource *res;
void __iomem *base;
@@ -8315,8 +8321,8 @@ static int mvpp2_probe(struct platform_device *pdev)
}
/* Initialize ports */
- for_each_available_child_of_node(dn, port_node) {
- err = mvpp2_port_probe(pdev, port_node, priv);
+ device_for_each_child_node(&pdev->dev, port_fwnode) {
+ err = mvpp2_port_probe(pdev, port_fwnode, priv);
if (err < 0)
goto err_port_probe;
}
@@ -8347,7 +8353,7 @@ static int mvpp2_probe(struct platform_device *pdev)
err_port_probe:
i = 0;
- for_each_available_child_of_node(dn, port_node) {
+ device_for_each_child_node(&pdev->dev, port_fwnode) {
if (priv->port_list[i])
mvpp2_port_remove(priv->port_list[i]);
i++;
@@ -8366,14 +8372,13 @@ static int mvpp2_probe(struct platform_device *pdev)
static int mvpp2_remove(struct platform_device *pdev)
{
struct mvpp2 *priv = platform_get_drvdata(pdev);
- struct device_node *dn = pdev->dev.of_node;
- struct device_node *port_node;
+ struct fwnode_handle *port_fwnode;
int i = 0;
flush_workqueue(priv->stats_queue);
destroy_workqueue(priv->stats_queue);
- for_each_available_child_of_node(dn, port_node) {
+ device_for_each_child_node(&pdev->dev, port_fwnode) {
if (priv->port_list[i]) {
mutex_destroy(&priv->port_list[i]->gather_stats_lock);
mvpp2_port_remove(priv->port_list[i]);
--
2.7.4
^ permalink raw reply related
* [net-next: PATCH 7/8] net: mvpp2: handle PHY with its fwnode
From: Marcin Wojtas @ 2017-12-18 9:18 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1513588684-15647-1-git-send-email-mw@semihalf.com>
Newly introduced mvmdio driver ACPI support and also fwnode
MDIO helpers allow for switching to PHY handling with its fwnode.
This patch replaces of_* related PHY handling function with
the fwnode_* equivalent and updates mvpp2_port structure
accordingly.
Signed-off-by: Marcin Wojtas <mw@semihalf.com>
---
drivers/net/ethernet/marvell/mvpp2.c | 41 ++++++++++++++------
1 file changed, 29 insertions(+), 12 deletions(-)
diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c
index 537474f..4e61ce7 100644
--- a/drivers/net/ethernet/marvell/mvpp2.c
+++ b/drivers/net/ethernet/marvell/mvpp2.c
@@ -963,7 +963,7 @@ struct mvpp2_port {
struct delayed_work stats_work;
phy_interface_t phy_interface;
- struct device_node *phy_node;
+ struct fwnode_handle *phy_fwnode;
struct phy *comphy;
unsigned int link;
unsigned int duplex;
@@ -6890,14 +6890,22 @@ static void mvpp21_get_mac_address(struct mvpp2_port *port, unsigned char *addr)
static int mvpp2_phy_connect(struct mvpp2_port *port)
{
struct phy_device *phy_dev;
+ int ret;
/* No PHY is attached */
- if (!port->phy_node)
+ if (!port->phy_fwnode)
return 0;
- phy_dev = of_phy_connect(port->dev, port->phy_node, mvpp2_link_event, 0,
+ phy_dev = fwnode_phy_find_device(port->phy_fwnode);
+ phy_dev->dev_flags = 0;
+
+ ret = phy_connect_direct(port->dev, phy_dev, mvpp2_link_event,
port->phy_interface);
- if (!phy_dev) {
+
+ /* Refcount is held by phy_connect_direct() on success */
+ put_device(&phy_dev->mdio.dev);
+
+ if (ret) {
netdev_err(port->dev, "cannot connect to phy\n");
return -ENODEV;
}
@@ -7047,7 +7055,7 @@ static int mvpp2_open(struct net_device *dev)
goto err_cleanup_txqs;
}
- if (priv->hw_version == MVPP22 && !port->phy_node && port->link_irq) {
+ if (priv->hw_version == MVPP22 && !port->phy_fwnode && port->link_irq) {
err = request_irq(port->link_irq, mvpp2_link_status_isr, 0,
dev->name, port);
if (err) {
@@ -7082,7 +7090,7 @@ static int mvpp2_open(struct net_device *dev)
return 0;
err_free_link_irq:
- if (priv->hw_version == MVPP22 && !port->phy_node && port->link_irq)
+ if (priv->hw_version == MVPP22 && !port->phy_fwnode && port->link_irq)
free_irq(port->link_irq, port);
err_free_irq:
mvpp2_irqs_deinit(port);
@@ -7107,7 +7115,7 @@ static int mvpp2_stop(struct net_device *dev)
on_each_cpu(mvpp2_interrupts_mask, port, 1);
mvpp2_shared_interrupt_mask_unmask(port, true);
- if (priv->hw_version == MVPP22 && !port->phy_node && port->link_irq)
+ if (priv->hw_version == MVPP22 && !port->phy_fwnode && port->link_irq)
free_irq(port->link_irq, port);
mvpp2_irqs_deinit(port);
@@ -7745,11 +7753,11 @@ static int mvpp2_port_probe(struct platform_device *pdev,
struct fwnode_handle *port_fwnode,
struct mvpp2 *priv)
{
- struct device_node *phy_node;
struct phy *comphy;
struct mvpp2_port *port;
struct mvpp2_port_pcpu *port_pcpu;
struct device_node *port_node = to_of_node(port_fwnode);
+ struct fwnode_reference_args args;
struct net_device *dev;
struct resource *res;
char *mac_from = "";
@@ -7779,7 +7787,6 @@ static int mvpp2_port_probe(struct platform_device *pdev,
if (!dev)
return -ENOMEM;
- phy_node = of_parse_phandle(port_node, "phy", 0);
phy_mode = fwnode_get_phy_mode(port_fwnode);
if (phy_mode < 0) {
dev_err(&pdev->dev, "incorrect phy mode\n");
@@ -7814,6 +7821,17 @@ static int mvpp2_port_probe(struct platform_device *pdev,
port->priv = priv;
port->has_tx_irqs = has_tx_irqs;
+ err = fwnode_property_get_reference_args(port_fwnode, "phy", NULL,
+ 0, 0, &args);
+ if (!err) {
+ port->phy_fwnode = args.fwnode;
+ } else if (err == -ENOENT) {
+ port->phy_fwnode = NULL;
+ } else {
+ dev_err(&pdev->dev, "unable to parse \"phy\" node\n");
+ goto err_free_netdev;
+ }
+
err = mvpp2_queue_vectors_init(port, port_node);
if (err)
goto err_free_netdev;
@@ -7836,7 +7854,6 @@ static int mvpp2_port_probe(struct platform_device *pdev,
else
port->first_rxq = port->id * priv->max_port_rxqs;
- port->phy_node = phy_node;
port->phy_interface = phy_mode;
port->comphy = comphy;
@@ -7958,7 +7975,7 @@ static int mvpp2_port_probe(struct platform_device *pdev,
err_deinit_qvecs:
mvpp2_queue_vectors_deinit(port);
err_free_netdev:
- of_node_put(phy_node);
+ fwnode_handle_put(args.fwnode);
free_netdev(dev);
return err;
}
@@ -7969,7 +7986,7 @@ static void mvpp2_port_remove(struct mvpp2_port *port)
int i;
unregister_netdev(port->dev);
- of_node_put(port->phy_node);
+ fwnode_handle_put(port->phy_fwnode);
free_percpu(port->pcpu);
free_percpu(port->stats);
for (i = 0; i < port->ntxqs; i++)
--
2.7.4
^ permalink raw reply related
* [net-next: PATCH 8/8] net: mvpp2: enable ACPI support in the driver
From: Marcin Wojtas @ 2017-12-18 9:18 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1513588684-15647-1-git-send-email-mw@semihalf.com>
This patch introduces an alternative way of obtaining resources - via
ACPI tables provided by firmware. Enabling coexistence with the DT
support, in addition to the OF_*->device_*/fwnode_* API replacement,
required following steps to be taken:
* Add mvpp2_acpi_match table
* Omit clock configuration and obtain tclk from the property - in ACPI
world, the firmware is responsible for clock maintenance.
* Disable comphy and syscon handling as they are not available for ACPI.
* Modify way of obtaining interrupts - with ACPI they are resources
bound to struct platform_device and it's not possible to obtain
them directly from the child node. Hence a formula is used, depending
on the port_id and number of possible CPUs.
Moreover when booting with ACPI MVPP2_QDIST_MULTI_MODE is picked by
default, as there is no need to keep any kind of the backward
compatibility.
Signed-off-by: Marcin Wojtas <mw@semihalf.com>
---
drivers/net/ethernet/marvell/mvpp2.c | 130 +++++++++++++-------
1 file changed, 87 insertions(+), 43 deletions(-)
diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c
index 4e61ce7..762a44e 100644
--- a/drivers/net/ethernet/marvell/mvpp2.c
+++ b/drivers/net/ethernet/marvell/mvpp2.c
@@ -10,6 +10,7 @@
* warranty of any kind, whether express or implied.
*/
+#include <linux/acpi.h>
#include <linux/kernel.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
@@ -7477,7 +7478,8 @@ static int mvpp2_simple_queue_vectors_init(struct mvpp2_port *port,
return 0;
}
-static int mvpp2_multi_queue_vectors_init(struct mvpp2_port *port,
+static int mvpp2_multi_queue_vectors_init(struct platform_device *pdev,
+ struct mvpp2_port *port,
struct device_node *port_node)
{
struct mvpp2_queue_vector *v;
@@ -7510,7 +7512,11 @@ static int mvpp2_multi_queue_vectors_init(struct mvpp2_port *port,
strncpy(irqname, "rx-shared", sizeof(irqname));
}
- v->irq = of_irq_get_byname(port_node, irqname);
+ if (port_node)
+ v->irq = of_irq_get_byname(port_node, irqname);
+ else
+ v->irq = platform_get_irq(pdev, port->id *
+ (port->nqvecs + 2) + i);
if (v->irq <= 0) {
ret = -EINVAL;
goto err;
@@ -7528,11 +7534,12 @@ static int mvpp2_multi_queue_vectors_init(struct mvpp2_port *port,
return ret;
}
-static int mvpp2_queue_vectors_init(struct mvpp2_port *port,
+static int mvpp2_queue_vectors_init(struct platform_device *pdev,
+ struct mvpp2_port *port,
struct device_node *port_node)
{
if (port->has_tx_irqs)
- return mvpp2_multi_queue_vectors_init(port, port_node);
+ return mvpp2_multi_queue_vectors_init(pdev, port, port_node);
else
return mvpp2_simple_queue_vectors_init(port, port_node);
}
@@ -7753,7 +7760,7 @@ static int mvpp2_port_probe(struct platform_device *pdev,
struct fwnode_handle *port_fwnode,
struct mvpp2 *priv)
{
- struct phy *comphy;
+ struct phy *comphy = NULL;
struct mvpp2_port *port;
struct mvpp2_port_pcpu *port_pcpu;
struct device_node *port_node = to_of_node(port_fwnode);
@@ -7772,7 +7779,12 @@ static int mvpp2_port_probe(struct platform_device *pdev,
if (!fwnode_device_is_available(port_fwnode))
return 0;
- has_tx_irqs = mvpp2_port_has_tx_irqs(priv, port_node);
+ if (port_node) {
+ has_tx_irqs = mvpp2_port_has_tx_irqs(priv, port_node);
+ } else {
+ has_tx_irqs = true;
+ queue_mode = MVPP2_QDIST_MULTI_MODE;
+ }
if (!has_tx_irqs)
queue_mode = MVPP2_QDIST_SINGLE_MODE;
@@ -7794,13 +7806,15 @@ static int mvpp2_port_probe(struct platform_device *pdev,
goto err_free_netdev;
}
- comphy = devm_of_phy_get(&pdev->dev, port_node, NULL);
- if (IS_ERR(comphy)) {
- if (PTR_ERR(comphy) == -EPROBE_DEFER) {
- err = -EPROBE_DEFER;
- goto err_free_netdev;
+ if (port_node) {
+ comphy = devm_of_phy_get(&pdev->dev, port_node, NULL);
+ if (IS_ERR(comphy)) {
+ if (PTR_ERR(comphy) == -EPROBE_DEFER) {
+ err = -EPROBE_DEFER;
+ goto err_free_netdev;
+ }
+ comphy = NULL;
}
- comphy = NULL;
}
if (fwnode_property_read_u32(port_fwnode, "port-id", &id)) {
@@ -7820,6 +7834,7 @@ static int mvpp2_port_probe(struct platform_device *pdev,
port->nrxqs = nrxqs;
port->priv = priv;
port->has_tx_irqs = has_tx_irqs;
+ port->id = id;
err = fwnode_property_get_reference_args(port_fwnode, "phy", NULL,
0, 0, &args);
@@ -7832,11 +7847,16 @@ static int mvpp2_port_probe(struct platform_device *pdev,
goto err_free_netdev;
}
- err = mvpp2_queue_vectors_init(port, port_node);
+ err = mvpp2_queue_vectors_init(pdev, port, port_node);
if (err)
goto err_free_netdev;
- port->link_irq = of_irq_get_byname(port_node, "link");
+ if (port_node)
+ port->link_irq = of_irq_get_byname(port_node, "link");
+ else
+ port->link_irq = platform_get_irq(pdev, port->id *
+ (port->nqvecs + 2) +
+ port->nqvecs + 1);
if (port->link_irq == -EPROBE_DEFER) {
err = -EPROBE_DEFER;
goto err_deinit_qvecs;
@@ -7848,7 +7868,6 @@ static int mvpp2_port_probe(struct platform_device *pdev,
if (fwnode_property_read_bool(port_fwnode, "marvell,loopback"))
port->flags |= MVPP2_F_LOOPBACK;
- port->id = id;
if (priv->hw_version == MVPP21)
port->first_rxq = port->id * port->nrxqs;
else
@@ -8218,6 +8237,7 @@ static int mvpp2_init(struct platform_device *pdev, struct mvpp2 *priv)
static int mvpp2_probe(struct platform_device *pdev)
{
+ const struct acpi_device_id *acpi_id;
struct fwnode_handle *port_fwnode;
struct mvpp2 *priv;
struct resource *res;
@@ -8229,8 +8249,14 @@ static int mvpp2_probe(struct platform_device *pdev)
if (!priv)
return -ENOMEM;
- priv->hw_version =
- (unsigned long)of_device_get_match_data(&pdev->dev);
+ if (has_acpi_companion(&pdev->dev)) {
+ acpi_id = acpi_match_device(pdev->dev.driver->acpi_match_table,
+ &pdev->dev);
+ priv->hw_version = (unsigned long)acpi_id->driver_data;
+ } else {
+ priv->hw_version =
+ (unsigned long)of_device_get_match_data(&pdev->dev);
+ }
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
base = devm_ioremap_resource(&pdev->dev, res);
@@ -8247,7 +8273,9 @@ static int mvpp2_probe(struct platform_device *pdev)
priv->iface_base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(priv->iface_base))
return PTR_ERR(priv->iface_base);
+ }
+ if (priv->hw_version == MVPP22 && dev_of_node(&pdev->dev)) {
priv->sysctrl_base =
syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
"marvell,system-controller");
@@ -8273,32 +8301,34 @@ static int mvpp2_probe(struct platform_device *pdev)
else
priv->max_port_rxqs = 32;
- priv->pp_clk = devm_clk_get(&pdev->dev, "pp_clk");
- if (IS_ERR(priv->pp_clk))
- return PTR_ERR(priv->pp_clk);
- err = clk_prepare_enable(priv->pp_clk);
- if (err < 0)
- return err;
-
- priv->gop_clk = devm_clk_get(&pdev->dev, "gop_clk");
- if (IS_ERR(priv->gop_clk)) {
- err = PTR_ERR(priv->gop_clk);
- goto err_pp_clk;
- }
- err = clk_prepare_enable(priv->gop_clk);
- if (err < 0)
- goto err_pp_clk;
+ if (dev_of_node(&pdev->dev)) {
+ priv->pp_clk = devm_clk_get(&pdev->dev, "pp_clk");
+ if (IS_ERR(priv->pp_clk))
+ return PTR_ERR(priv->pp_clk);
+ err = clk_prepare_enable(priv->pp_clk);
+ if (err < 0)
+ return err;
- if (priv->hw_version == MVPP22) {
- priv->mg_clk = devm_clk_get(&pdev->dev, "mg_clk");
- if (IS_ERR(priv->mg_clk)) {
- err = PTR_ERR(priv->mg_clk);
- goto err_gop_clk;
+ priv->gop_clk = devm_clk_get(&pdev->dev, "gop_clk");
+ if (IS_ERR(priv->gop_clk)) {
+ err = PTR_ERR(priv->gop_clk);
+ goto err_pp_clk;
}
-
- err = clk_prepare_enable(priv->mg_clk);
+ err = clk_prepare_enable(priv->gop_clk);
if (err < 0)
- goto err_gop_clk;
+ goto err_pp_clk;
+
+ if (priv->hw_version == MVPP22) {
+ priv->mg_clk = devm_clk_get(&pdev->dev, "mg_clk");
+ if (IS_ERR(priv->mg_clk)) {
+ err = PTR_ERR(priv->mg_clk);
+ goto err_gop_clk;
+ }
+
+ err = clk_prepare_enable(priv->mg_clk);
+ if (err < 0)
+ goto err_gop_clk;
+ }
priv->axi_clk = devm_clk_get(&pdev->dev, "axi_clk");
if (IS_ERR(priv->axi_clk)) {
@@ -8311,10 +8341,14 @@ static int mvpp2_probe(struct platform_device *pdev)
if (err < 0)
goto err_gop_clk;
}
- }
- /* Get system's tclk rate */
- priv->tclk = clk_get_rate(priv->pp_clk);
+ /* Get system's tclk rate */
+ priv->tclk = clk_get_rate(priv->pp_clk);
+ } else if (device_property_read_u32(&pdev->dev, "clock-frequency",
+ &priv->tclk)) {
+ dev_err(&pdev->dev, "missing clock-frequency value\n");
+ return -EINVAL;
+ }
if (priv->hw_version == MVPP22) {
err = dma_set_mask(&pdev->dev, DMA_BIT_MASK(40));
@@ -8418,6 +8452,9 @@ static int mvpp2_remove(struct platform_device *pdev)
aggr_txq->descs_dma);
}
+ if (is_acpi_node(port_fwnode))
+ return 0;
+
clk_disable_unprepare(priv->axi_clk);
clk_disable_unprepare(priv->mg_clk);
clk_disable_unprepare(priv->pp_clk);
@@ -8439,12 +8476,19 @@ static const struct of_device_id mvpp2_match[] = {
};
MODULE_DEVICE_TABLE(of, mvpp2_match);
+static const struct acpi_device_id mvpp2_acpi_match[] = {
+ { "MRVL0110", MVPP22 },
+ { },
+};
+MODULE_DEVICE_TABLE(acpi, mvpp2_acpi_match);
+
static struct platform_driver mvpp2_driver = {
.probe = mvpp2_probe,
.remove = mvpp2_remove,
.driver = {
.name = MVPP2_DRIVER_NAME,
.of_match_table = mvpp2_match,
+ .acpi_match_table = ACPI_PTR(mvpp2_acpi_match),
},
};
--
2.7.4
^ permalink raw reply related
* [linux-sunxi] [PATCH v3 2/3] dt-bindings: media: Add Allwinner V3s Camera Sensor Interface (CSI)
From: Maxime Ripard @ 2017-12-18 9:24 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20171218164921.227b82349c778283f5e5eba8@magewell.com>
Hi,
On Mon, Dec 18, 2017 at 04:49:21PM +0800, Yong wrote:
> > > + compatible = "allwinner,sun8i-v3s-csi";
> > > + reg = <0x01cb4000 0x1000>;
> > > + interrupts = <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>;
> > > + clocks = <&ccu CLK_BUS_CSI>,
> > > + <&ccu CLK_CSI1_SCLK>,
> >
> > CSI also has an MCLK. Do you need that one?
>
> MCLK is not needed if the front end is not a sensor (like adv7611).
> I will add it as an option.
I guess this should always be needed then. And the driver will make
the decision to enable it or not.
Maxime
--
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20171218/010dbb66/attachment-0001.sig>
^ permalink raw reply
* [PATCH v2 03/19] ARM: dts: aspeed: Add LPC and child devices
From: Cédric Le Goater @ 2017-12-18 9:25 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20171215062443.23059-4-joel@jms.id.au>
On 12/15/2017 07:24 AM, Joel Stanley wrote:
> From: Andrew Jeffery <andrew@aj.id.au>
>
> Ensure the ordering is correct and add all of the children in the SoC
> device trees for the ast2400 and ast2500.
>
> Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
> Signed-off-by: Joel Stanley <joel@jms.id.au>
> ---
> arch/arm/boot/dts/aspeed-g4.dtsi | 35 +++++++++++++++++++++++++++++++++++
> arch/arm/boot/dts/aspeed-g5.dtsi | 27 +++++++++++++++++----------
> 2 files changed, 52 insertions(+), 10 deletions(-)
>
> diff --git a/arch/arm/boot/dts/aspeed-g4.dtsi b/arch/arm/boot/dts/aspeed-g4.dtsi
> index 100d092e6c07..a3bc5da7d42c 100644
> --- a/arch/arm/boot/dts/aspeed-g4.dtsi
> +++ b/arch/arm/boot/dts/aspeed-g4.dtsi
> @@ -226,6 +226,41 @@
> status = "disabled";
> };
>
> + lpc: lpc at 1e789000 {
> + compatible = "aspeed,ast2400-lpc", "simple-mfd";
> + reg = <0x1e789000 0x1000>;
> +
> + #address-cells = <1>;
> + #size-cells = <1>;
> + ranges = <0x0 0x1e789000 0x1000>;
> +
> + lpc_bmc: lpc-bmc at 0 {
> + compatible = "aspeed,ast2400-lpc-bmc";
> + reg = <0x0 0x80>;
> + };
> +
> + lpc_host: lpc-host at 80 {
> + compatible = "aspeed,ast2400-lpc-host", "simple-mfd", "syscon";
> + reg = <0x80 0x1e0>;
> + reg-io-width = <4>;
> +
> + #address-cells = <1>;
> + #size-cells = <1>;
> + ranges = <0x0 0x80 0x1e0>;
> +
> + lpc_ctrl: lpc-ctrl at 0 {
> + compatible = "aspeed,ast2400-lpc-ctrl";
> + reg = <0x0 0x80>;
> + status = "disabled";
> + };
> +
> + lhc: lhc at 20 {
> + compatible = "aspeed,ast2500-lhc";
aspeed,ast2400-lhc
The layout of the registers are the same but there a couple of differences
in the bit definitions between the two SoCs.
a part from that :
Reviewed-by: C?dric Le Goater <clg@kaod.org>
C.
> + reg = <0x20 0x24 0x48 0x8>;
> + };
> + };
> + };
> +
> uart2: serial at 1e78d000 {
> compatible = "ns16550a";
> reg = <0x1e78d000 0x20>;
> diff --git a/arch/arm/boot/dts/aspeed-g5.dtsi b/arch/arm/boot/dts/aspeed-g5.dtsi
> index 1f9d28313f82..7861631940fe 100644
> --- a/arch/arm/boot/dts/aspeed-g5.dtsi
> +++ b/arch/arm/boot/dts/aspeed-g5.dtsi
> @@ -266,6 +266,16 @@
> status = "disabled";
> };
>
> + vuart: serial at 1e787000 {
> + compatible = "aspeed,ast2500-vuart";
> + reg = <0x1e787000 0x40>;
> + reg-shift = <2>;
> + interrupts = <10>;
> + clocks = <&clk_uart>;
> + no-loopback-test;
> + status = "disabled";
> + };
> +
> lpc: lpc at 1e789000 {
> compatible = "aspeed,ast2500-lpc", "simple-mfd";
> reg = <0x1e789000 0x1000>;
> @@ -289,6 +299,13 @@
>
> reg-io-width = <4>;
>
> + lpc_ctrl: lpc-ctrl at 0 {
> + compatible = "aspeed,ast2500-lpc-ctrl";
> + reg = <0x0 0x80>;
> + status = "disabled";
> + };
> +
> +
> lhc: lhc at 20 {
> compatible = "aspeed,ast2500-lhc";
> reg = <0x20 0x24 0x48 0x8>;
> @@ -296,16 +313,6 @@
> };
> };
>
> - vuart: serial at 1e787000 {
> - compatible = "aspeed,ast2500-vuart";
> - reg = <0x1e787000 0x40>;
> - reg-shift = <2>;
> - interrupts = <10>;
> - clocks = <&clk_uart>;
> - no-loopback-test;
> - status = "disabled";
> - };
> -
> uart2: serial at 1e78d000 {
> compatible = "ns16550a";
> reg = <0x1e78d000 0x20>;
>
^ permalink raw reply
* [PATCH 2/4] clocksource: stm32: use prescaler to adjust the resolution
From: Daniel Lezcano @ 2017-12-18 9:26 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20171215085247.14946-3-benjamin.gaignard@st.com>
On 15/12/2017 09:52, Benjamin Gaignard wrote:
> Rather than use fixed prescaler values compute it to get a clock
> as close as possible of 10KHz and a resolution of 0.1ms.
>
> Signed-off-by: Benjamin Gaignard <benjamin.gaignard@st.com>
> ---
> drivers/clocksource/timer-stm32.c | 23 ++++++++++++++++-------
> 1 file changed, 16 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/clocksource/timer-stm32.c b/drivers/clocksource/timer-stm32.c
> index 23a321cca45b..de721d318065 100644
> --- a/drivers/clocksource/timer-stm32.c
> +++ b/drivers/clocksource/timer-stm32.c
> @@ -37,6 +37,11 @@
>
> #define TIM_EGR_UG BIT(0)
>
> +#define MAX_TIM_PSC 0xFFFF
> +
> +/* Target a 10KHz clock to get a resolution of 0.1 ms */
> +#define TARGETED_CLK_RATE 10000
> +
> static int stm32_clock_event_shutdown(struct clock_event_device *evt)
> {
> struct timer_of *to = to_timer_of(evt);
> @@ -83,7 +88,7 @@ static irqreturn_t stm32_clock_event_handler(int irq, void *dev_id)
> static void __init stm32_clockevent_init(struct timer_of *to)
> {
> unsigned long max_delta;
> - int prescaler;
> + unsigned long prescaler;
>
> to->clkevt.name = "stm32_clockevent";
> to->clkevt.features = CLOCK_EVT_FEAT_PERIODIC;
> @@ -96,13 +101,17 @@ static void __init stm32_clockevent_init(struct timer_of *to)
> /* Detect whether the timer is 16 or 32 bits */
> writel_relaxed(~0U, timer_of_base(to) + TIM_ARR);
> max_delta = readl_relaxed(timer_of_base(to) + TIM_ARR);
> - if (max_delta == ~0U) {
> - prescaler = 1;
> + to->clkevt.rating = 50;
> + if (max_delta == ~0U)
> to->clkevt.rating = 250;
> - } else {
> - prescaler = 1024;
> - to->clkevt.rating = 50;
> - }
> +
> + /*
> + * Get the highest possible prescaler value to be as close
> + * as possible of TARGETED_CLK_RATE
> + */
> + prescaler = DIV_ROUND_CLOSEST(timer_of_rate(to), TARGETED_CLK_RATE);
With a 90MHz or 125MHz, the prescaler will be 9000 or 12500, so much
more than the 1024 we have today for 16b, and 1 for 32b.
Shouldn't the computation be weighted with the bits width ?
Otherwise the timer will wrap like:
32bits:
before: (2^32 / 90e6) x 1 = 47.72 seconds
after: (2^32 / 90e6) x 9000 = 119.3 *hours* ~= 5days
16bits:
before: (2^16 / 90e6) x 1024 = 0.745 seconds
after: (2^16 / 90e6) x 9000 = 6.55 seconds
The patch is ok to target the 10KHz timer rate for 16b with a 1ms
resolution wrapping up after 6.55 seconds. But not for the 32bits timer.
Furthermore, we can't tell anymore the 32bits timers have a rating of
250 after this patch.
Leave the 32bits part as it is and compute the prescaler only in case of
16bits with the target rate, which sounds a reasonable approach.
> + if (prescaler > MAX_TIM_PSC)
> + prescaler = MAX_TIM_PSC;
That can happen only if the clock rate is greater than ~655MHz, that
could not happen today as far as I can tell regarding the DT. So if we
hit this condition, we should speak up in the log (pr_warn).
> writel_relaxed(0, timer_of_base(to) + TIM_ARR);
> writel_relaxed(prescaler - 1, timer_of_base(to) + TIM_PSC);
Can you fix this prescaler - 1 in order to be consistent with the
computation with 16b ? (32b prescaler = 0, 16b prescaler = clk_rate /
target ).
Thanks.
-- Daniel
--
<http://www.linaro.org/> Linaro.org ? Open source software for ARM SoCs
Follow Linaro: <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog
^ permalink raw reply
* [PATCH 1/1] arm: sunxi: Add alternative pins for spi0
From: Maxime Ripard @ 2017-12-18 9:28 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <ca648552-cefb-e19d-72cf-8b56e97b013d@gmail.com>
On Mon, Dec 18, 2017 at 08:24:21AM +0200, Stefan Mavrodiev wrote:
> On 12/15/2017 05:08 PM, Maxime Ripard wrote:
> > Hi,
> >
> > On Thu, Dec 14, 2017 at 08:24:54AM +0200, Stefan Mavrodiev wrote:
> > > On 12/13/2017 05:40 PM, Maxime Ripard wrote:
> > > > Hi,
> > > >
> > > > On Wed, Dec 13, 2017 at 09:44:34AM +0200, Stefan Mavrodiev wrote:
> > > > > Allwinner A10/A13/A20 SoCs have pinmux for spi0
> > > > > on port C. The patch adds these pins in the respective
> > > > > dts includes.
> > > > >
> > > > > Signed-off-by: Stefan Mavrodiev <stefan@olimex.com>
> > > > Do you have any boards that are using these?
> > > >
> > > > We won't merge that patch if there's no users for it.
> > > A20-OLinuXino-Lime/Lime2 and A10-OLinuXino-Lime with spi flash.
> > > For A13 we still doesn't have that option.
> > If this bus is exposed on the headers, you can add those to the DT but
> > leave them disabled if you want. Buf if there's no users of those
> > nodes, our policy is not to merge them.
>
> So basically I should resend the patch, enabling the those pins only for
> sun4i and sun7i platform?
I'm not quite sure what you mean, but you should do something like
77df9d66b0b1ad01c685fd6341ce501493899658
Maxime
--
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20171218/717315d0/attachment.sig>
^ permalink raw reply
* [PATCH v5 7/8] pwm: pwm-omap-dmtimer: Adapt driver to utilize dmtimer pdata ops
From: Ladislav Michl @ 2017-12-18 9:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1513059137-21593-8-git-send-email-j-keerthy@ti.com>
Keerthy,
On Tue, Dec 12, 2017 at 11:42:16AM +0530, Keerthy wrote:
> Adapt driver to utilize dmtimer pdata ops instead of pdata-quirks.
>
> Signed-off-by: Keerthy <j-keerthy@ti.com>
> ---
>
> Changes in v4:
>
> * Switched to dev_get_platdata.
Where do you expect dev.platform_data to be set? PWM driver is failing
with:
omap-dmtimer-pwm dmtimer-pwm: dmtimer pdata structure NULL
omap-dmtimer-pwm: probe of dmtimer-pwm failed with error -22
Which I fixed with patch bellow, to be able to test your patchset.
Also I'm running a bit out of time, so I'll send few clean up
patches and event capture code to get some feedback early.
Regards,
ladis
diff --git a/drivers/clocksource/timer-dm.c b/drivers/clocksource/timer-dm.c
index 39be39e6a8dd..d3d8a49cae0d 100644
--- a/drivers/clocksource/timer-dm.c
+++ b/drivers/clocksource/timer-dm.c
@@ -773,6 +773,7 @@ static int omap_dm_timer_probe(struct platform_device *pdev)
dev_err(dev, "%s: no platform data.\n", __func__);
return -ENODEV;
}
+ dev->platform_data = pdata;
irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if (unlikely(!irq)) {
>
> Changes in v3:
>
> * Used of_find_platdata_by_node function to fetch platform
> data for timer node.
>
> drivers/pwm/pwm-omap-dmtimer.c | 39 ++++++++++++++++++++++-----------------
> 1 file changed, 22 insertions(+), 17 deletions(-)
^ permalink raw reply related
* [PATCH v2 18/19] ARM: dts: aspeed-romulus: Update Romulus system
From: Cédric Le Goater @ 2017-12-18 9:32 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20171215062443.23059-19-joel@jms.id.au>
Some comments below,
On 12/15/2017 07:24 AM, Joel Stanley wrote:
> - Fix incorrect RAM size
> - Remove alias; these are now specified in the dtsi
> - Add newly upstreamed devices
> - Include OpenBMC flash layout
>
> Signed-off-by: Joel Stanley <joel@jms.id.au>
> ---
> arch/arm/boot/dts/aspeed-bmc-opp-romulus.dts | 153 ++++++++++++++++++++++++++-
> 1 file changed, 148 insertions(+), 5 deletions(-)
>
> diff --git a/arch/arm/boot/dts/aspeed-bmc-opp-romulus.dts b/arch/arm/boot/dts/aspeed-bmc-opp-romulus.dts
> index a7a9386f964d..bfdf643584df 100644
> --- a/arch/arm/boot/dts/aspeed-bmc-opp-romulus.dts
> +++ b/arch/arm/boot/dts/aspeed-bmc-opp-romulus.dts
> @@ -7,17 +7,13 @@
> model = "Romulus BMC";
> compatible = "ibm,romulus-bmc", "aspeed,ast2500";
>
> - aliases {
> - serial4 = &uart5;
> - };
> -
> chosen {
> stdout-path = &uart5;
> bootargs = "console=ttyS4,115200 earlyprintk";
> };
>
> memory {
> - reg = <0x80000000 0x40000000>;
> + reg = <0x80000000 0x20000000>;
> };
>
> reserved-memory {
> @@ -29,6 +25,73 @@
> no-map;
> reg = <0xbf000000 0x01000000>; /* 16M */
> };
> +
> + flash_memory: region at 98000000 {
> + no-map;
> + reg = <0x98000000 0x04000000>; /* 64M */
> + };
> + };
> +
> + leds {
> + compatible = "gpio-leds";
> +
> + fault {
> + gpios = <&gpio ASPEED_GPIO(N, 2) GPIO_ACTIVE_LOW>;
> + };
> +
> + identify {
> + gpios = <&gpio ASPEED_GPIO(N, 4) GPIO_ACTIVE_HIGH>;
> + };
> +
> + power {
> + gpios = <&gpio ASPEED_GPIO(R, 5) GPIO_ACTIVE_LOW>;
> + };
> + };
> +
> + fsi: gpio-fsi {
> + compatible = "fsi-master-gpio", "fsi-master";
> + #address-cells = <2>;
> + #size-cells = <0>;
> +
> + clock-gpios = <&gpio ASPEED_GPIO(AA, 0) GPIO_ACTIVE_HIGH>;
> + data-gpios = <&gpio ASPEED_GPIO(AA, 2) GPIO_ACTIVE_HIGH>;
> + mux-gpios = <&gpio ASPEED_GPIO(A, 6) GPIO_ACTIVE_HIGH>;
> + enable-gpios = <&gpio ASPEED_GPIO(D, 0) GPIO_ACTIVE_HIGH>;
> + trans-gpios = <&gpio ASPEED_GPIO(R, 2) GPIO_ACTIVE_HIGH>;
> + };
> +
> + gpio-keys {
> + compatible = "gpio-keys";
> +
> + checkstop {
> + label = "checkstop";
> + gpios = <&gpio ASPEED_GPIO(J, 2) GPIO_ACTIVE_LOW>;
> + linux,code = <ASPEED_GPIO(J, 2)>;
> + };
> + };
> +};
> +
> +&fmc {
> + status = "okay";
> +
> + flash at 0 {
> + status = "okay";
> + label = "pnor";
> + m25p,fast-read;
> +#include "openbmc-flash-layout.dtsi"
> + };
> +};
> +
> +&spi1 {
> + status = "okay";
> +
> + pinctrl-names = "default";
> + pinctrl-0 = <&pinctrl_spi1_default>;
> +
> + flash at 0 {
> + status = "okay";
> + label = "pnor";
> + m25p,fast-read;
> };
> };
hmm, the fmc and spi1 bindings were already added in commit 1142aea9ff9d.
> @@ -38,6 +101,7 @@
> status = "okay";
> m25p,fast-read;
> label = "bmc";
> +#include "openbmc-flash-layout.dtsi"
This looks like an extra "fmc" node ?
> };
> };
>
> @@ -53,6 +117,12 @@
> };
> };
>
> +&lpc_ctrl {
> + status = "okay";
> + memory-region = <&flash_memory>;
> + flash = <&spi1>;
> +};
> +
> &uart1 {
> /* Rear RS-232 connector */
> status = "okay";
> @@ -81,6 +151,10 @@
> pinctrl-0 = <&pinctrl_rmii1_default>;
> };
>
> +&i2c1 {
> + status = "okay";
> +};
> +
> &i2c2 {
> status = "okay";
> };
> @@ -133,8 +207,77 @@
>
> &i2c12 {
> status = "okay";
> +
> + max31785 at 52 {
> + compatible = "maxim,max31785";
> + reg = <0x52>;
> + };
> +};
> +
> +&gpio {
> + nic_func_mode0 {
> + gpio-hog;
> + gpios = <ASPEED_GPIO(D, 3) GPIO_ACTIVE_HIGH>;
> + output-low;
> + line-name = "nic_func_mode0";
> + };
> + nic_func_mode1 {
> + gpio-hog;
> + gpios = <ASPEED_GPIO(D, 4) GPIO_ACTIVE_HIGH>;
> + output-low;
> + line-name = "nic_func_mode1";
> + };
> };
>
> &vuart {
> status = "okay";
> };
> +
> +&gfx {
> + status = "okay";
> +};
> +
> +&pinctrl {
> + aspeed,external-nodes = <&gfx &lhc>;
> +};
> +
> +&pwm_tacho {
> + status = "okay";
> + pinctrl-names = "default";
> + pinctrl-0 = <&pinctrl_pwm0_default &pinctrl_pwm1_default>;
> +
> + fan at 0 {
> + reg = <0x00>;
> + aspeed,fan-tach-ch = /bits/ 8 <0x08>;
> + };
> +
> + fan at 1 {
> + reg = <0x00>;
> + aspeed,fan-tach-ch = /bits/ 8 <0x09>;
> + };
> +
> + fan at 2 {
> + reg = <0x01>;
> + aspeed,fan-tach-ch = /bits/ 8 <0x0a>;
> + };
> +
> + fan at 3 {
> + reg = <0x01>;
> + aspeed,fan-tach-ch = /bits/ 8 <0x0b>;
> + };
> +
> + fan at 4 {
> + reg = <0x00>;
> + aspeed,fan-tach-ch = /bits/ 8 <0x0c>;
> + };
> +
> + fan at 5 {
> + reg = <0x00>;
> + aspeed,fan-tach-ch = /bits/ 8 <0x0d>;
> + };
> +
> + fan at 6 {
> + reg = <0x01>;
> + aspeed,fan-tach-ch = /bits/ 8 <0x0e>;
> + };
> +};
>
^ permalink raw reply
* [PATCH] ARM: mediatek: use more generic prompts for SoCs with ARMv7
From: sean.wang at mediatek.com @ 2017-12-18 9:39 UTC (permalink / raw)
To: linux-arm-kernel
From: Sean Wang <sean.wang@mediatek.com>
Supported MediaTek SoCs with ARMv7 are not limited within MT65xx or MT81xx
and thus use more generic words to prompt users as the other vendors
usually use.
Signed-off-by: Sean Wang <sean.wang@mediatek.com>
---
arch/arm/mach-mediatek/Kconfig | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm/mach-mediatek/Kconfig b/arch/arm/mach-mediatek/Kconfig
index 70e49d5..91cc461 100644
--- a/arch/arm/mach-mediatek/Kconfig
+++ b/arch/arm/mach-mediatek/Kconfig
@@ -1,5 +1,5 @@
menuconfig ARCH_MEDIATEK
- bool "Mediatek MT65xx & MT81xx SoC"
+ bool "MediaTek SoC Support"
depends on ARCH_MULTI_V7
select ARM_GIC
select PINCTRL
--
2.7.4
^ permalink raw reply related
* [PATCH 04/25] arm: exynos/s3c: dts: Remove leading 0x and 0s from bindings notation
From: Krzysztof Kozlowski @ 2017-12-18 9:40 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20171215124630.30082-1-malat@debian.org>
On Fri, Dec 15, 2017 at 1:46 PM, Mathieu Malaterre <malat@debian.org> wrote:
> Improve the DTS files by removing all the leading "0x" and zeros to fix the
> following dtc warnings:
>
> Warning (unit_address_format): Node /XXX unit name should not have leading "0x"
>
> and
>
> Warning (unit_address_format): Node /XXX unit name should not have leading 0s
>
> Converted using the following command:
>
> find . -type f \( -iname *.dts -o -iname *.dtsi \) -exec sed -i -e "s/@\([0-9a-fA-FxX\.;:#]+\)\s*{/@\L\1 {/g" -e "s/@0x\(.*\) {/@\1 {/g" -e "s/@0+\(.*\) {/@\1 {/g" {} +^C
>
> For simplicity, two sed expressions were used to solve each warnings separately.
>
> To make the regex expression more robust a few other issues were resolved,
> namely setting unit-address to lower case, and adding a whitespace before the
> the opening curly brace:
>
> https://elinux.org/Device_Tree_Linux#Linux_conventions
>
> This will solve as a side effect warning:
>
> Warning (simple_bus_reg): Node /XXX@<UPPER> simple-bus unit address format error, expected "<lower>"
>
> This is a follow up to commit 4c9847b7375a ("dt-bindings: Remove leading 0x from bindings notation")
>
> Reported-by: David Daney <ddaney@caviumnetworks.com>
> Suggested-by: Rob Herring <robh@kernel.org>
> Acked-by: Krzysztof Kozlowski <krzk@kernel.org>
Ack was for different patchset, touching only three files...
> Signed-off-by: Mathieu Malaterre <malat@debian.org>
> ---
> arch/arm/boot/dts/exynos3250.dtsi | 34 ++++++------
> arch/arm/boot/dts/exynos4.dtsi | 56 +++++++++----------
> arch/arm/boot/dts/exynos4210.dtsi | 8 +--
> arch/arm/boot/dts/exynos4412-pinctrl.dtsi | 2 +-
> arch/arm/boot/dts/exynos4412.dtsi | 22 ++++----
> arch/arm/boot/dts/exynos5.dtsi | 22 ++++----
> arch/arm/boot/dts/exynos5250.dtsi | 64 +++++++++++-----------
> arch/arm/boot/dts/exynos5260.dtsi | 26 ++++-----
> arch/arm/boot/dts/exynos5420.dtsi | 78 +++++++++++++--------------
> arch/arm/boot/dts/exynos5422-odroid-core.dtsi | 2 +-
> arch/arm/boot/dts/exynos5440.dtsi | 14 ++---
> arch/arm/boot/dts/s3c2416.dtsi | 8 +--
> 12 files changed, 168 insertions(+), 168 deletions(-)
>
> diff --git a/arch/arm/boot/dts/exynos3250.dtsi b/arch/arm/boot/dts/exynos3250.dtsi
> index 2bd3872221a1..8d47571b3984 100644
> --- a/arch/arm/boot/dts/exynos3250.dtsi
> +++ b/arch/arm/boot/dts/exynos3250.dtsi
> @@ -164,31 +164,31 @@
> syscon = <&pmu_system_controller>;
> };
>
> - pd_cam: cam-power-domain at 10023C00 {
> + pd_cam: cam-power-domain at 10023c00 {
This is not related to this patch and it was not present in the
version I acked. I also already fixed this here:
https://patchwork.kernel.org/patch/10113323/
There is no changelog explaining the difference in patches. Original
patch was okay, why changing it?
Best regards,
Krzysztof
^ permalink raw reply
* [net-next: PATCH 0/8] Armada 7k/8k PP2 ACPI support
From: Ard Biesheuvel @ 2017-12-18 9:40 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1513588684-15647-1-git-send-email-mw@semihalf.com>
On 18 December 2017 at 10:17, Marcin Wojtas <mw@semihalf.com> wrote:
> Hi,
>
> This patchset introduces ACPI support in mvpp2 and mvmdio drivers.
> First three patches introduce fwnode helpers for obtaining PHY
> information from nodes and also MDIO fwnode API for registering
> the bus with its PHY/devices.
>
> Following patches update code of the mvmdio and mvpp2 drivers
> to support ACPI tables handling. The latter is done in 4 steps,
> as can be seen in the commits. For the details, please
> refer to the commit messages.
>
> Drivers operation was tested on top of the net-next branch
> with both DT and ACPI. Although for compatibility reasons
> with older platforms, the mvmdio driver keeps using
> of_ MDIO registering, new fwnode_ one proved to fully work
> with DT as well (tested on MacchiatoBin board).
>
> mvpp2/mvmdio driver can work with the ACPI representation, as exposed
> on a public branch:
> https://github.com/MarvellEmbeddedProcessors/edk2-open-platform/commits/marvell-armada-wip
> It was compiled together with the most recent Tianocore EDK2 revision.
> Please refer to the firmware build instruction on MacchiatoBin board:
> http://wiki.macchiatobin.net/tiki-index.php?page=Build+from+source+-+UEFI+EDK+II
>
> Above support configures 1G to use its PHY normally. 10G can work now
> only with the link interrupt mode. Somehow reading of the
> string property in fwnode_mdiobus_child_is_phy works only with
> DT and cannot cope with 10G PHY nodes as in:
> https://pastebin.com/3JnYpU0A
>
> Above root cause will be further checked. In the meantime I will
> appreciate any comments or remarks for the kernel patches.
>
Hi Marcin,
I have added linux-acpi and Graeme to cc. I think it makes sense to
discuss the way you describe the device topology before looking at the
patches in more detail.
In particular, I would like to request feedback on the use of
[redundant] 'reg' properties and the use of _DSD + compatible to
describe PHYs. Usually, we try to avoid this, given that it is
essentially a ACPI encapsulated DT dialect that is difficult to
support in drivers unless they are based on DT to begin with. Also,
non-standard _DSD properties require a vendor prefix, it is not
freeform.
For reference, the ACPI description is here (starting at line 175)
https://github.com/MarvellEmbeddedProcessors/edk2-open-platform/blob/72d5ac23b20dd74d479daa5e40ba443264b31261/Platforms/Marvell/Armada/AcpiTables/Armada80x0McBin/Dsdt.asl
--
Ard.
^ permalink raw reply
* [PATCH v3 05/11] thermal: armada: Add support for Armada AP806
From: Miquel RAYNAL @ 2017-12-18 9:41 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <87y3m5o9h4.fsf@free-electrons.com>
Hello Gregory & Baruch,
On Thu, 14 Dec 2017 12:05:43 +0100
Gregory CLEMENT <gregory.clement@free-electrons.com> wrote:
> > @@ -184,9 +214,9 @@ static int armada_get_temp(struct
> > thermal_zone_device *thermal, div = priv->data->coef_div;
> >
> > if (priv->data->inverted)
> > - *temp = ((m * reg) - b) / div;
> > + *temp = ((m * sample) - b) / div;
> > else
> > - *temp = (b - (m * reg)) / div;
> > + *temp = (b - (m * sample)) / div;
> > return 0;
> > }
> >
> > @@ -237,6 +267,19 @@ static const struct armada_thermal_data
> > armada380_data = { .inverted = true,
> > };
> >
> > +static const struct armada_thermal_data armada_ap806_data = {
> > + .is_valid = armada_is_valid,
> > + .init_sensor = armada_ap806_init_sensor,
> > + .is_valid_bit = BIT(16),
> > + .temp_shift = 0,
> > + .temp_mask = 0x3ff,
> > + .coef_b = -150000,
>
> Don't you expect any side effect by storing a negative value in a
> unsigned variable?
That is a fair question, I did not spot that.
As other values are really close to 2^32 I don't know what is the best
option for us in this case. Should I:
- don't care?
- use signed values? (dangerous IMHO)
- use a union with a signed and an unsigned value? (problem moved to
->get_temp())
Thanks for your input.
Miqu?l
^ permalink raw reply
* [linux-sunxi] [PATCH v3 2/3] dt-bindings: media: Add Allwinner V3s Camera Sensor Interface (CSI)
From: Yong @ 2017-12-18 9:43 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20171218092437.ksczam5h7hirmpcv@flea.lan>
Hi,
On Mon, 18 Dec 2017 10:24:37 +0100
Maxime Ripard <maxime.ripard@free-electrons.com> wrote:
> Hi,
>
> On Mon, Dec 18, 2017 at 04:49:21PM +0800, Yong wrote:
> > > > + compatible = "allwinner,sun8i-v3s-csi";
> > > > + reg = <0x01cb4000 0x1000>;
> > > > + interrupts = <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>;
> > > > + clocks = <&ccu CLK_BUS_CSI>,
> > > > + <&ccu CLK_CSI1_SCLK>,
> > >
> > > CSI also has an MCLK. Do you need that one?
> >
> > MCLK is not needed if the front end is not a sensor (like adv7611).
> > I will add it as an option.
>
> I guess this should always be needed then. And the driver will make
> the decision to enable it or not.
But how the driver to know if it should be enabled?
I think MCLK should be added in DT just if the subdev need it.
>
> Maxime
>
> --
> Maxime Ripard, Free Electrons
> Embedded Linux and Kernel engineering
> http://free-electrons.com
Thanks,
Yong
^ permalink raw reply
* [PATCH 2/4] clocksource: stm32: use prescaler to adjust the resolution
From: Benjamin Gaignard @ 2017-12-18 9:44 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <4e57bec8-a52b-9574-5f6e-985457d44147@linaro.org>
2017-12-18 10:26 GMT+01:00 Daniel Lezcano <daniel.lezcano@linaro.org>:
> On 15/12/2017 09:52, Benjamin Gaignard wrote:
>> Rather than use fixed prescaler values compute it to get a clock
>> as close as possible of 10KHz and a resolution of 0.1ms.
>>
>> Signed-off-by: Benjamin Gaignard <benjamin.gaignard@st.com>
>> ---
>> drivers/clocksource/timer-stm32.c | 23 ++++++++++++++++-------
>> 1 file changed, 16 insertions(+), 7 deletions(-)
>>
>> diff --git a/drivers/clocksource/timer-stm32.c b/drivers/clocksource/timer-stm32.c
>> index 23a321cca45b..de721d318065 100644
>> --- a/drivers/clocksource/timer-stm32.c
>> +++ b/drivers/clocksource/timer-stm32.c
>> @@ -37,6 +37,11 @@
>>
>> #define TIM_EGR_UG BIT(0)
>>
>> +#define MAX_TIM_PSC 0xFFFF
>> +
>> +/* Target a 10KHz clock to get a resolution of 0.1 ms */
>> +#define TARGETED_CLK_RATE 10000
>> +
>> static int stm32_clock_event_shutdown(struct clock_event_device *evt)
>> {
>> struct timer_of *to = to_timer_of(evt);
>> @@ -83,7 +88,7 @@ static irqreturn_t stm32_clock_event_handler(int irq, void *dev_id)
>> static void __init stm32_clockevent_init(struct timer_of *to)
>> {
>> unsigned long max_delta;
>> - int prescaler;
>> + unsigned long prescaler;
>>
>> to->clkevt.name = "stm32_clockevent";
>> to->clkevt.features = CLOCK_EVT_FEAT_PERIODIC;
>> @@ -96,13 +101,17 @@ static void __init stm32_clockevent_init(struct timer_of *to)
>> /* Detect whether the timer is 16 or 32 bits */
>> writel_relaxed(~0U, timer_of_base(to) + TIM_ARR);
>> max_delta = readl_relaxed(timer_of_base(to) + TIM_ARR);
>> - if (max_delta == ~0U) {
>> - prescaler = 1;
>> + to->clkevt.rating = 50;
>> + if (max_delta == ~0U)
>> to->clkevt.rating = 250;
>> - } else {
>> - prescaler = 1024;
>> - to->clkevt.rating = 50;
>> - }
>> +
>> + /*
>> + * Get the highest possible prescaler value to be as close
>> + * as possible of TARGETED_CLK_RATE
>> + */
>> + prescaler = DIV_ROUND_CLOSEST(timer_of_rate(to), TARGETED_CLK_RATE);
>
> With a 90MHz or 125MHz, the prescaler will be 9000 or 12500, so much
> more than the 1024 we have today for 16b, and 1 for 32b.
>
> Shouldn't the computation be weighted with the bits width ?
My goal was to get the same resolution (0.1ms) for all the timers so
the wrap will depend of the number of bits like you describe below.
>
> Otherwise the timer will wrap like:
>
> 32bits:
>
> before: (2^32 / 90e6) x 1 = 47.72 seconds
> after: (2^32 / 90e6) x 9000 = 119.3 *hours* ~= 5days
>
> 16bits:
>
> before: (2^16 / 90e6) x 1024 = 0.745 seconds
> after: (2^16 / 90e6) x 9000 = 6.55 seconds
>
> The patch is ok to target the 10KHz timer rate for 16b with a 1ms
> resolution wrapping up after 6.55 seconds. But not for the 32bits timer.
> Furthermore, we can't tell anymore the 32bits timers have a rating of
> 250 after this patch.
What is the link between rating and resolution (or wrap) ?
Is it a problem to get a long wrap ?
>
> Leave the 32bits part as it is and compute the prescaler only in case of
> 16bits with the target rate, which sounds a reasonable approach.
>
>> + if (prescaler > MAX_TIM_PSC)
>> + prescaler = MAX_TIM_PSC;
>
> That can happen only if the clock rate is greater than ~655MHz, that
> could not happen today as far as I can tell regarding the DT. So if we
> hit this condition, we should speak up in the log (pr_warn).
It is to be futur proof for next possible SoC but even if prescaler
reach this limit
it is not a problem the only consequence would be that resolution and
wrap change.
>
>> writel_relaxed(0, timer_of_base(to) + TIM_ARR);
>> writel_relaxed(prescaler - 1, timer_of_base(to) + TIM_PSC);
>
> Can you fix this prescaler - 1 in order to be consistent with the
> computation with 16b ? (32b prescaler = 0, 16b prescaler = clk_rate /
> target ).
In the hardware the clock is divise by " TIM_PSC value 1" so to be coherent
with that I need to do prescaler -1.
Benjamin
>
> Thanks.
>
> -- Daniel
>
> --
> <http://www.linaro.org/> Linaro.org ? Open source software for ARM SoCs
>
> Follow Linaro: <http://www.facebook.com/pages/Linaro> Facebook |
> <http://twitter.com/#!/linaroorg> Twitter |
> <http://www.linaro.org/linaro-blog/> Blog
>
^ permalink raw reply
* [PATCH net-next v3 0/7] net: phy: meson-gxl: clean-up and improvements
From: Jerome Brunet @ 2017-12-18 9:44 UTC (permalink / raw)
To: linux-arm-kernel
This patchset adds defines for the control registers and helpers to access
the banked registers. The goal being to make it easier to understand what
the driver actually does.
Then CONFIG_A6 settings is removed since this statement was without effect
Finally interrupt support is added, speeding things up a little
This series has been tested on the libretech-cc and khadas VIM
Changes since v2 [0]:
Drop LPA corruption fix which has been merged through net. Apart from this,
series remains the same.
[0]: https://lkml.kernel.org/r/20171207142715.32578-1-jbrunet at baylibre.com
Jerome Brunet (7):
net: phy: meson-gxl: check phy_write return value
net: phy: meson-gxl: define control registers
net: phy: meson-gxl: add read and write helpers for banked registers
net: phy: meson-gxl: use genphy_config_init
net: phy: meson-gxl: leave CONFIG_A6 untouched
net: phy: meson-gxl: add interrupt support
net: phy: meson-gxl: join the authors
drivers/net/phy/meson-gxl.c | 185 ++++++++++++++++++++++++++++++++++----------
1 file changed, 146 insertions(+), 39 deletions(-)
--
2.14.3
^ permalink raw reply
* [PATCH net-next v3 1/7] net: phy: meson-gxl: check phy_write return value
From: Jerome Brunet @ 2017-12-18 9:44 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20171218094446.31912-1-jbrunet@baylibre.com>
Always check phy_write return values. Better to be safe than sorry
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
---
drivers/net/phy/meson-gxl.c | 50 ++++++++++++++++++++++++++++++++++-----------
1 file changed, 38 insertions(+), 12 deletions(-)
diff --git a/drivers/net/phy/meson-gxl.c b/drivers/net/phy/meson-gxl.c
index 4ee630afe43a..900606204c0a 100644
--- a/drivers/net/phy/meson-gxl.c
+++ b/drivers/net/phy/meson-gxl.c
@@ -26,27 +26,53 @@
static int meson_gxl_config_init(struct phy_device *phydev)
{
+ int ret;
+
/* Enable Analog and DSP register Bank access by */
- phy_write(phydev, 0x14, 0x0000);
- phy_write(phydev, 0x14, 0x0400);
- phy_write(phydev, 0x14, 0x0000);
- phy_write(phydev, 0x14, 0x0400);
+ ret = phy_write(phydev, 0x14, 0x0000);
+ if (ret)
+ return ret;
+ ret = phy_write(phydev, 0x14, 0x0400);
+ if (ret)
+ return ret;
+ ret = phy_write(phydev, 0x14, 0x0000);
+ if (ret)
+ return ret;
+ ret = phy_write(phydev, 0x14, 0x0400);
+ if (ret)
+ return ret;
/* Write Analog register 23 */
- phy_write(phydev, 0x17, 0x8E0D);
- phy_write(phydev, 0x14, 0x4417);
+ ret = phy_write(phydev, 0x17, 0x8E0D);
+ if (ret)
+ return ret;
+ ret = phy_write(phydev, 0x14, 0x4417);
+ if (ret)
+ return ret;
/* Enable fractional PLL */
- phy_write(phydev, 0x17, 0x0005);
- phy_write(phydev, 0x14, 0x5C1B);
+ ret = phy_write(phydev, 0x17, 0x0005);
+ if (ret)
+ return ret;
+ ret = phy_write(phydev, 0x14, 0x5C1B);
+ if (ret)
+ return ret;
/* Program fraction FR_PLL_DIV1 */
- phy_write(phydev, 0x17, 0x029A);
- phy_write(phydev, 0x14, 0x5C1D);
+ ret = phy_write(phydev, 0x17, 0x029A);
+ if (ret)
+ return ret;
+ ret = phy_write(phydev, 0x14, 0x5C1D);
+ if (ret)
+ return ret;
/* Program fraction FR_PLL_DIV1 */
- phy_write(phydev, 0x17, 0xAAAA);
- phy_write(phydev, 0x14, 0x5C1C);
+ ret = phy_write(phydev, 0x17, 0xAAAA);
+ if (ret)
+ return ret;
+ ret = phy_write(phydev, 0x14, 0x5C1C);
+ if (ret)
+ return ret;
return 0;
}
--
2.14.3
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox