From b59889bf344dd261b50d69a5eacfa2874573c7cd Mon Sep 17 00:00:00 2001 From: Pratyush Yadav Date: Tue, 26 May 2020 17:35:57 +0530 Subject: regmap: Check for out-of-range offsets before mapping them In regmap_raw_{read,write}_range(), offsets are checked to make sure they aren't out of range. But this check happens _after_ the address is mapped from physical memory. Input should be sanity-checked before using it. Mapping the address before validating it leaves the door open to passing an invalid address to map_physmem(). So check for out of range offsets _before_ mapping them. This fixes a segmentation fault in sandbox when -1 is used as an offset to regmap_{read,write}(). Signed-off-by: Pratyush Yadav --- drivers/core/regmap.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/core/regmap.c b/drivers/core/regmap.c index 4a214ef..a67a237 100644 --- a/drivers/core/regmap.c +++ b/drivers/core/regmap.c @@ -310,13 +310,13 @@ int regmap_raw_read_range(struct regmap *map, uint range_num, uint offset, } range = &map->ranges[range_num]; - ptr = map_physmem(range->start + offset, val_len, MAP_NOCACHE); - if (offset + val_len > range->size) { debug("%s: offset/size combination invalid\n", __func__); return -ERANGE; } + ptr = map_physmem(range->start + offset, val_len, MAP_NOCACHE); + switch (val_len) { case REGMAP_SIZE_8: *((u8 *)valp) = __read_8(ptr, map->endianness); @@ -419,13 +419,13 @@ int regmap_raw_write_range(struct regmap *map, uint range_num, uint offset, } range = &map->ranges[range_num]; - ptr = map_physmem(range->start + offset, val_len, MAP_NOCACHE); - if (offset + val_len > range->size) { debug("%s: offset/size combination invalid\n", __func__); return -ERANGE; } + ptr = map_physmem(range->start + offset, val_len, MAP_NOCACHE); + switch (val_len) { case REGMAP_SIZE_8: __write_8(ptr, val, map->endianness); -- cgit v1.1 From c03b7612ea346ad7454086d1623fb57098faf315 Mon Sep 17 00:00:00 2001 From: Michael Walle Date: Tue, 2 Jun 2020 01:47:07 +0200 Subject: usb: provide a device tree node to USB devices It is possible to specify a device tree node for an USB device. This is useful if you have a static USB setup and want to use aliases which point to these nodes, like on the Raspberry Pi. The nodes are matched against their hub port number, the compatible strings are not matched for now. Signed-off-by: Michael Walle Reviewed-by: Marek Vasut Reviewed-by: Simon Glass --- drivers/usb/host/usb-uclass.c | 41 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 36 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/usb-uclass.c b/drivers/usb/host/usb-uclass.c index cb79dfb..f42c062 100644 --- a/drivers/usb/host/usb-uclass.c +++ b/drivers/usb/host/usb-uclass.c @@ -494,6 +494,35 @@ static int usb_match_one_id(struct usb_device_descriptor *desc, return usb_match_one_id_intf(desc, int_desc, id); } +static ofnode usb_get_ofnode(struct udevice *hub, int port) +{ + ofnode node; + u32 reg; + + if (!dev_has_of_node(hub)) + return ofnode_null(); + + /* + * The USB controller and its USB hub are two different udevices, + * but the device tree has only one node for both. Thus we are + * assigning this node to both udevices. + * If port is zero, the controller scans its root hub, thus we + * are using the same ofnode as the controller here. + */ + if (!port) + return dev_ofnode(hub); + + ofnode_for_each_subnode(node, dev_ofnode(hub)) { + if (ofnode_read_u32(node, "reg", ®)) + continue; + + if (reg == port) + return node; + } + + return ofnode_null(); +} + /** * usb_find_and_bind_driver() - Find and bind the right USB driver * @@ -502,13 +531,14 @@ static int usb_match_one_id(struct usb_device_descriptor *desc, static int usb_find_and_bind_driver(struct udevice *parent, struct usb_device_descriptor *desc, struct usb_interface_descriptor *iface, - int bus_seq, int devnum, + int bus_seq, int devnum, int port, struct udevice **devp) { struct usb_driver_entry *start, *entry; int n_ents; int ret; char name[30], *str; + ofnode node = usb_get_ofnode(parent, port); *devp = NULL; debug("%s: Searching for driver\n", __func__); @@ -533,8 +563,8 @@ static int usb_find_and_bind_driver(struct udevice *parent, * find another driver. For now this doesn't seem * necesssary, so just bind the first match. */ - ret = device_bind(parent, drv, drv->name, NULL, -1, - &dev); + ret = device_bind_ofnode(parent, drv, drv->name, NULL, + node, &dev); if (ret) goto error; debug("%s: Match found: %s\n", __func__, drv->name); @@ -651,9 +681,10 @@ int usb_scan_device(struct udevice *parent, int port, if (ret) { if (ret != -ENOENT) return ret; - ret = usb_find_and_bind_driver(parent, &udev->descriptor, iface, + ret = usb_find_and_bind_driver(parent, &udev->descriptor, + iface, udev->controller_dev->seq, - udev->devnum, &dev); + udev->devnum, port, &dev); if (ret) return ret; created = true; -- cgit v1.1 From be1a6e94254af205bd67d69e3bdb26b161ccd72f Mon Sep 17 00:00:00 2001 From: Michael Walle Date: Tue, 2 Jun 2020 01:47:09 +0200 Subject: dm: uclass: don't assign aliased seq numbers If there are aliases for an uclass, set the base for the "dynamically" allocated numbers next to the highest alias. Please note, that this might lead to holes in the sequences, depending on the device tree. For example if there is only an alias "ethernet1", the next device seq number would be 2. In particular this fixes a problem with boards which are using ethernet aliases but also might have network add-in cards like the E1000. If the board is started with the add-in card and depending on the order of the drivers, the E1000 might occupy the first ethernet device and mess up all the hardware addresses, because the devices are now shifted by one. Also adapt the test cases to the new handling and add test cases checking the holes in the seq numbers. Signed-off-by: Michael Walle Reviewed-by: Alex Marginean Tested-by: Alex Marginean Acked-by: Vladimir Oltean Reviewed-by: Simon Glass Tested-by: Michal Simek [on zcu102-revA] --- drivers/core/uclass.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/core/uclass.c b/drivers/core/uclass.c index 2ab419c..c3f1b73 100644 --- a/drivers/core/uclass.c +++ b/drivers/core/uclass.c @@ -689,13 +689,14 @@ int uclass_unbind_device(struct udevice *dev) int uclass_resolve_seq(struct udevice *dev) { + struct uclass *uc = dev->uclass; + struct uclass_driver *uc_drv = uc->uc_drv; struct udevice *dup; - int seq; + int seq = 0; int ret; assert(dev->seq == -1); - ret = uclass_find_device_by_seq(dev->uclass->uc_drv->id, dev->req_seq, - false, &dup); + ret = uclass_find_device_by_seq(uc_drv->id, dev->req_seq, false, &dup); if (!ret) { dm_warn("Device '%s': seq %d is in use by '%s'\n", dev->name, dev->req_seq, dup->name); @@ -707,9 +708,17 @@ int uclass_resolve_seq(struct udevice *dev) return ret; } - for (seq = 0; seq < DM_MAX_SEQ; seq++) { - ret = uclass_find_device_by_seq(dev->uclass->uc_drv->id, seq, - false, &dup); + if (CONFIG_IS_ENABLED(OF_CONTROL) && CONFIG_IS_ENABLED(DM_SEQ_ALIAS) && + (uc_drv->flags & DM_UC_FLAG_SEQ_ALIAS)) { + /* + * dev_read_alias_highest_id() will return -1 if there no + * alias. Thus we can always add one. + */ + seq = dev_read_alias_highest_id(uc_drv->name) + 1; + } + + for (; seq < DM_MAX_SEQ; seq++) { + ret = uclass_find_device_by_seq(uc_drv->id, seq, false, &dup); if (ret == -ENODEV) break; if (ret) -- cgit v1.1 From baafd99d13931312ff3e2c1c75922d8a46222f7f Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Thu, 26 Mar 2020 03:54:01 +0000 Subject: net: phy: micrel: ksz8061 implement errata 80000688A fix Linux commit 232ba3a51cc2 ('net: phy: Micrel KSZ8061: link failure after cable connect') implements a fix for the above errata. This patch replicates that errata fix in an ksz8061 specific init routine. Signed-off-by: Bryan O'Donoghue Acked-by: Joe Hershberger --- drivers/net/phy/micrel_ksz8xxx.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'drivers') diff --git a/drivers/net/phy/micrel_ksz8xxx.c b/drivers/net/phy/micrel_ksz8xxx.c index 98a0c83..60d42fe 100644 --- a/drivers/net/phy/micrel_ksz8xxx.c +++ b/drivers/net/phy/micrel_ksz8xxx.c @@ -82,6 +82,21 @@ static struct phy_driver KSZ8051_driver = { .shutdown = &genphy_shutdown, }; +static int ksz8061_config(struct phy_device *phydev) +{ + return phy_write(phydev, MDIO_MMD_PMAPMD, MDIO_DEVID1, 0xB61A); +} + +static struct phy_driver KSZ8061_driver = { + .name = "Micrel KSZ8061", + .uid = 0x00221570, + .mask = 0xfffff0, + .features = PHY_BASIC_FEATURES, + .config = &ksz8061_config, + .startup = &genphy_startup, + .shutdown = &genphy_shutdown, +}; + static int ksz8081_config(struct phy_device *phydev) { int ret; @@ -210,6 +225,7 @@ int phy_micrel_ksz8xxx_init(void) phy_register(&KSZ804_driver); phy_register(&KSZ8031_driver); phy_register(&KSZ8051_driver); + phy_register(&KSZ8061_driver); phy_register(&KSZ8081_driver); phy_register(&KS8721_driver); phy_register(&ksz8895_driver); -- cgit v1.1 From a7a435e7d41db6a611427b4cc5fd506a18fb2c2f Mon Sep 17 00:00:00 2001 From: Tom Warren Date: Thu, 26 Mar 2020 15:59:13 -0700 Subject: net: rt8169: WAR for DHCP not getting IP after kernel boot/reboot This is a WAR for DHCP failure after rebooting from the L4T kernel. The r8169.c kernel driver is setting bit 19 of the rt816x HW register 0xF0, which goes by FuncEvent and MISC in various driver source/datasheets. That bit is called RxDv_Gated_En in the r8169.c kernel driver. Clear it here at the end of probe to ensure that U-Boot can get an IP assigned via DHCP. Signed-off-by: Tom Warren --- drivers/net/rtl8169.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'drivers') diff --git a/drivers/net/rtl8169.c b/drivers/net/rtl8169.c index 75058fd..fb4fae2 100644 --- a/drivers/net/rtl8169.c +++ b/drivers/net/rtl8169.c @@ -240,6 +240,9 @@ enum RTL8169_register_content { /*_TBICSRBit*/ TBILinkOK = 0x02000000, + + /* FuncEvent/Misc */ + RxDv_Gated_En = 0x80000, }; static struct { @@ -1210,6 +1213,19 @@ static int rtl8169_eth_probe(struct udevice *dev) return ret; } + /* + * WAR for DHCP failure after rebooting from kernel. + * Clear RxDv_Gated_En bit which was set by kernel driver. + * Without this, U-Boot can't get an IP via DHCP. + * Register (FuncEvent, aka MISC) and RXDV_GATED_EN bit are from + * the r8169.c kernel driver. + */ + + u32 val = RTL_R32(FuncEvent); + debug("%s: FuncEvent/Misc (0xF0) = 0x%08X\n", __func__, val); + val &= ~RxDv_Gated_En; + RTL_W32(FuncEvent, val); + return 0; } -- cgit v1.1 From 9c6de508a6362a3ddd4067e90f07ae613f312aa4 Mon Sep 17 00:00:00 2001 From: Florin Chiculita Date: Wed, 29 Apr 2020 14:25:48 +0300 Subject: net: phy: add phyid search in vendor specific space There are devices accesible through mdio clause-45, such as retimers, that do not have PMA or PCS blocks. This patch adds MDIO_MMD_VEND1 on the list of device addresses where phyid is searched. Previous order of devices was kept. Signed-off-by: Florin Chiculita Reviewed-by: Madalin Bucur --- drivers/net/phy/phy.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index cce09c4..6778989 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -786,17 +786,27 @@ static struct phy_device *get_phy_device_by_mask(struct mii_dev *bus, uint phy_mask, phy_interface_t interface) { - int i; struct phy_device *phydev; - + int devad[] = { + /* Clause-22 */ + MDIO_DEVAD_NONE, + /* Clause-45 */ + MDIO_MMD_PMAPMD, + MDIO_MMD_WIS, + MDIO_MMD_PCS, + MDIO_MMD_PHYXS, + MDIO_MMD_VEND1, + }; + int i, devad_cnt; + + devad_cnt = sizeof(devad)/sizeof(int); phydev = search_for_existing_phy(bus, phy_mask, interface); if (phydev) return phydev; - /* Try Standard (ie Clause 22) access */ - /* Otherwise we have to try Clause 45 */ - for (i = 0; i < 5; i++) { + /* try different access clauses */ + for (i = 0; i < devad_cnt; i++) { phydev = create_phy_by_mask(bus, phy_mask, - i ? i : MDIO_DEVAD_NONE, interface); + devad[i], interface); if (IS_ERR(phydev)) return NULL; if (phydev) -- cgit v1.1 From bc0e578f903d24b5291d34959ad534138ced0780 Mon Sep 17 00:00:00 2001 From: Dan Murphy Date: Mon, 4 May 2020 16:14:39 -0500 Subject: net: phy: Add support for TI PHY init ti_phy_init function was allocated to the DP83867 PHY. This function name is to generic for a specific PHY. The function can be moved to a TI specific file that can register all TI PHYs that are defined in the defconfig. The ti_phy_init file will contain all TI PHYs initialization so that only phy_ti_init can be called from the framework. In addition to the above the config flag for the DP83867 needs to be changed in the Kconfig and dependent defconfig files. The config flag that was used for the DP83867 was also generic in nature so a more specific config flag for the DP83867 was created. Acked-by: Michal Simek Signed-off-by: Dan Murphy --- drivers/net/phy/Kconfig | 8 ++++++++ drivers/net/phy/Makefile | 3 ++- drivers/net/phy/dp83867.c | 3 ++- drivers/net/phy/ti_phy_init.c | 18 ++++++++++++++++++ drivers/net/phy/ti_phy_init.h | 15 +++++++++++++++ 5 files changed, 45 insertions(+), 2 deletions(-) create mode 100644 drivers/net/phy/ti_phy_init.c create mode 100644 drivers/net/phy/ti_phy_init.h (limited to 'drivers') diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index d1f049e..a5a1ff2 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig @@ -243,6 +243,14 @@ config PHY_TERANETICS config PHY_TI bool "Texas Instruments Ethernet PHYs support" + ---help--- + Adds PHY registration support for TI PHYs. + +config PHY_TI_DP83867 + select PHY_TI + bool "Texas Instruments Ethernet DP83867 PHY support" + ---help--- + Adds support for the TI DP83867 1Gbit PHY. config PHY_VITESSE bool "Vitesse Ethernet PHYs support" diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile index 1d81516..6e72233 100644 --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile @@ -25,7 +25,8 @@ obj-$(CONFIG_PHY_NATSEMI) += natsemi.o obj-$(CONFIG_PHY_REALTEK) += realtek.o obj-$(CONFIG_PHY_SMSC) += smsc.o obj-$(CONFIG_PHY_TERANETICS) += teranetics.o -obj-$(CONFIG_PHY_TI) += dp83867.o +obj-$(CONFIG_PHY_TI) += ti_phy_init.o +obj-$(CONFIG_PHY_TI_DP83867) += dp83867.o obj-$(CONFIG_PHY_XILINX) += xilinx_phy.o obj-$(CONFIG_PHY_XILINX_GMII2RGMII) += xilinx_gmii2rgmii.o obj-$(CONFIG_PHY_VITESSE) += vitesse.o diff --git a/drivers/net/phy/dp83867.c b/drivers/net/phy/dp83867.c index d435cc1..eada454 100644 --- a/drivers/net/phy/dp83867.c +++ b/drivers/net/phy/dp83867.c @@ -14,6 +14,7 @@ #include #include +#include "ti_phy_init.h" /* TI DP83867 */ #define DP83867_DEVADDR 0x1f @@ -430,7 +431,7 @@ static struct phy_driver DP83867_driver = { .shutdown = &genphy_shutdown, }; -int phy_ti_init(void) +int phy_dp83867_init(void) { phy_register(&DP83867_driver); return 0; diff --git a/drivers/net/phy/ti_phy_init.c b/drivers/net/phy/ti_phy_init.c new file mode 100644 index 0000000..277b29a --- /dev/null +++ b/drivers/net/phy/ti_phy_init.c @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * TI Generic PHY Init to register any TI Ethernet PHYs + * + * Author: Dan Murphy + * + * Copyright (C) 2019-20 Texas Instruments Inc. + */ + +#include "ti_phy_init.h" + +int phy_ti_init(void) +{ +#ifdef CONFIG_PHY_TI_DP83867 + phy_dp83867_init(); +#endif + return 0; +} diff --git a/drivers/net/phy/ti_phy_init.h b/drivers/net/phy/ti_phy_init.h new file mode 100644 index 0000000..6c7f6c6 --- /dev/null +++ b/drivers/net/phy/ti_phy_init.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * TI Generic Ethernet PHY + * + * Author: Dan Murphy + * + * Copyright (C) 2019-20 Texas Instruments Inc. + */ + +#ifndef _TI_GEN_PHY_H +#define _TI_GEN_PHY_H + +int phy_dp83867_init(void); + +#endif /* _TI_GEN_PHY_H */ -- cgit v1.1 From 8882238cc4c1276629c989ea1fe71b15358a5040 Mon Sep 17 00:00:00 2001 From: Dan Murphy Date: Mon, 4 May 2020 16:14:40 -0500 Subject: net: phy: Add DP8382x phy registration to TI PHY init Add the DP8382X generic PHY registration to the TI PHY init file. Acked-by: Michal Simek Signed-off-by: Dan Murphy --- drivers/net/phy/Kconfig | 7 ++++ drivers/net/phy/ti_phy_init.c | 83 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 90 insertions(+) (limited to 'drivers') diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index a5a1ff2..b0bd762 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig @@ -252,6 +252,13 @@ config PHY_TI_DP83867 ---help--- Adds support for the TI DP83867 1Gbit PHY. +config PHY_TI_GENERIC + select PHY_TI + bool "Texas Instruments Generic Ethernet PHYs support" + ---help--- + Adds support for Generic TI PHYs that don't need special handling but + the PHY name is associated with a PHY ID. + config PHY_VITESSE bool "Vitesse Ethernet PHYs support" diff --git a/drivers/net/phy/ti_phy_init.c b/drivers/net/phy/ti_phy_init.c index 277b29a..50eff77 100644 --- a/drivers/net/phy/ti_phy_init.c +++ b/drivers/net/phy/ti_phy_init.c @@ -7,12 +7,95 @@ * Copyright (C) 2019-20 Texas Instruments Inc. */ +#include #include "ti_phy_init.h" +#ifdef CONFIG_PHY_TI_GENERIC +static struct phy_driver dp83822_driver = { + .name = "TI DP83822", + .uid = 0x2000a240, + .mask = 0xfffffff0, + .features = PHY_BASIC_FEATURES, + .config = &genphy_config_aneg, + .startup = &genphy_startup, + .shutdown = &genphy_shutdown, +}; + +static struct phy_driver dp83826nc_driver = { + .name = "TI DP83826NC", + .uid = 0x2000a110, + .mask = 0xfffffff0, + .features = PHY_BASIC_FEATURES, + .config = &genphy_config_aneg, + .startup = &genphy_startup, + .shutdown = &genphy_shutdown, +}; + +static struct phy_driver dp83826c_driver = { + .name = "TI DP83826C", + .uid = 0x2000a130, + .mask = 0xfffffff0, + .features = PHY_BASIC_FEATURES, + .config = &genphy_config_aneg, + .startup = &genphy_startup, + .shutdown = &genphy_shutdown, +}; + +static struct phy_driver dp83825s_driver = { + .name = "TI DP83825S", + .uid = 0x2000a140, + .mask = 0xfffffff0, + .features = PHY_BASIC_FEATURES, + .config = &genphy_config_aneg, + .startup = &genphy_startup, + .shutdown = &genphy_shutdown, +}; + +static struct phy_driver dp83825i_driver = { + .name = "TI DP83825I", + .uid = 0x2000a150, + .mask = 0xfffffff0, + .features = PHY_BASIC_FEATURES, + .config = &genphy_config_aneg, + .startup = &genphy_startup, + .shutdown = &genphy_shutdown, +}; + +static struct phy_driver dp83825m_driver = { + .name = "TI DP83825M", + .uid = 0x2000a160, + .mask = 0xfffffff0, + .features = PHY_BASIC_FEATURES, + .config = &genphy_config_aneg, + .startup = &genphy_startup, + .shutdown = &genphy_shutdown, +}; + +static struct phy_driver dp83825cs_driver = { + .name = "TI DP83825CS", + .uid = 0x2000a170, + .mask = 0xfffffff0, + .features = PHY_BASIC_FEATURES, + .config = &genphy_config_aneg, + .startup = &genphy_startup, + .shutdown = &genphy_shutdown, +}; +#endif /* CONFIG_PHY_TI_GENERIC */ + int phy_ti_init(void) { #ifdef CONFIG_PHY_TI_DP83867 phy_dp83867_init(); #endif + +#ifdef CONFIG_PHY_TI_GENERIC + phy_register(&dp83822_driver); + phy_register(&dp83825s_driver); + phy_register(&dp83825i_driver); + phy_register(&dp83825m_driver); + phy_register(&dp83825cs_driver); + phy_register(&dp83826c_driver); + phy_register(&dp83826nc_driver); +#endif return 0; } -- cgit v1.1 From 9962dd25b1e228c5c8f0b33ef89c48093ca2a311 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sat, 9 May 2020 22:34:35 +0200 Subject: net: rtl8139: Factor out device name assignment Pull the device name setting into a separate function, as this will be shared between DM/non-DM variants. Signed-off-by: Marek Vasut Cc: Joe Hershberger --- drivers/net/rtl8139.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/rtl8139.c b/drivers/net/rtl8139.c index 0daeefa..cc7fcdf 100644 --- a/drivers/net/rtl8139.c +++ b/drivers/net/rtl8139.c @@ -524,6 +524,11 @@ static int rtl8139_bcast_addr(struct eth_device *dev, const u8 *bcast_mac, return 0; } +static void rtl8139_name(char *str, int card_number) +{ + sprintf(str, "RTL8139#%u", card_number); +} + static struct pci_device_id supported[] = { { PCI_VENDOR_ID_REALTEK, PCI_DEVICE_ID_REALTEK_8139 }, { PCI_VENDOR_ID_DLINK, PCI_DEVICE_ID_DLINK_8139 }, @@ -556,7 +561,7 @@ int rtl8139_initialize(bd_t *bis) } memset(dev, 0, sizeof(*dev)); - sprintf(dev->name, "RTL8139#%d", card_number); + rtl8139_name(dev->name, card_number); dev->priv = (void *)devno; dev->iobase = (int)bus_to_phys(iobase); -- cgit v1.1 From 1ba8d9844562c74f0d80423d5dac658291d6d2f1 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sat, 9 May 2020 22:34:36 +0200 Subject: net: rtl8139: Switch from malloc()+memset() to calloc() Replace malloc()+memset() combination with calloc(), no functional change. Signed-off-by: Marek Vasut Cc: Joe Hershberger --- drivers/net/rtl8139.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/rtl8139.c b/drivers/net/rtl8139.c index cc7fcdf..4874c1a 100644 --- a/drivers/net/rtl8139.c +++ b/drivers/net/rtl8139.c @@ -554,12 +554,11 @@ int rtl8139_initialize(bd_t *bis) debug("rtl8139: REALTEK RTL8139 @0x%x\n", iobase); - dev = (struct eth_device *)malloc(sizeof(*dev)); + dev = calloc(1, sizeof(*dev)); if (!dev) { printf("Can not allocate memory of rtl8139\n"); break; } - memset(dev, 0, sizeof(*dev)); rtl8139_name(dev->name, card_number); -- cgit v1.1 From f4385539f1a6b4def6bf74091a2bc11f574d3bd1 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sat, 9 May 2020 22:34:37 +0200 Subject: net: rtl8139: Use dev->iobase instead of custom ioaddr Replace the use of custom static ioaddr variable with common dev->iobase, no functional change. Signed-off-by: Marek Vasut Cc: Joe Hershberger --- drivers/net/rtl8139.c | 84 +++++++++++++++++++++++---------------------------- 1 file changed, 38 insertions(+), 46 deletions(-) (limited to 'drivers') diff --git a/drivers/net/rtl8139.c b/drivers/net/rtl8139.c index 4874c1a..f829e52 100644 --- a/drivers/net/rtl8139.c +++ b/drivers/net/rtl8139.c @@ -192,7 +192,6 @@ #define RTL_STS_RXSTATUSOK BIT(0) static unsigned int cur_rx, cur_tx; -static int ioaddr; /* The RTL8139 can only transmit from a contiguous, aligned memory block. */ static unsigned char tx_buffer[TX_BUF_SIZE] __aligned(4); @@ -223,42 +222,43 @@ static void rtl8139_eeprom_delay(uintptr_t regbase) inl(regbase + RTL_REG_CFG9346); } -static int rtl8139_read_eeprom(unsigned int location, unsigned int addr_len) +static int rtl8139_read_eeprom(struct eth_device *dev, + unsigned int location, unsigned int addr_len) { unsigned int read_cmd = location | (EE_READ_CMD << addr_len); - uintptr_t ee_addr = ioaddr + RTL_REG_CFG9346; + uintptr_t ee_addr = dev->iobase + RTL_REG_CFG9346; unsigned int retval = 0; u8 dataval; int i; outb(EE_ENB & ~EE_CS, ee_addr); outb(EE_ENB, ee_addr); - rtl8139_eeprom_delay(ioaddr); + rtl8139_eeprom_delay(dev->iobase); /* Shift the read command bits out. */ for (i = 4 + addr_len; i >= 0; i--) { dataval = (read_cmd & BIT(i)) ? EE_DATA_WRITE : 0; outb(EE_ENB | dataval, ee_addr); - rtl8139_eeprom_delay(ioaddr); + rtl8139_eeprom_delay(dev->iobase); outb(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr); - rtl8139_eeprom_delay(ioaddr); + rtl8139_eeprom_delay(dev->iobase); } outb(EE_ENB, ee_addr); - rtl8139_eeprom_delay(ioaddr); + rtl8139_eeprom_delay(dev->iobase); for (i = 16; i > 0; i--) { outb(EE_ENB | EE_SHIFT_CLK, ee_addr); - rtl8139_eeprom_delay(ioaddr); + rtl8139_eeprom_delay(dev->iobase); retval <<= 1; retval |= inb(ee_addr) & EE_DATA_READ; outb(EE_ENB, ee_addr); - rtl8139_eeprom_delay(ioaddr); + rtl8139_eeprom_delay(dev->iobase); } /* Terminate the EEPROM access. */ outb(~EE_CS, ee_addr); - rtl8139_eeprom_delay(ioaddr); + rtl8139_eeprom_delay(dev->iobase); return retval; } @@ -275,10 +275,10 @@ static void rtl8139_set_rx_mode(struct eth_device *dev) RTL_REG_RXCONFIG_ACCEPTMULTICAST | RTL_REG_RXCONFIG_ACCEPTMYPHYS; - outl(rtl8139_rx_config | rx_mode, ioaddr + RTL_REG_RXCONFIG); + outl(rtl8139_rx_config | rx_mode, dev->iobase + RTL_REG_RXCONFIG); - outl(0xffffffff, ioaddr + RTL_REG_MAR0 + 0); - outl(0xffffffff, ioaddr + RTL_REG_MAR0 + 4); + outl(0xffffffff, dev->iobase + RTL_REG_MAR0 + 0); + outl(0xffffffff, dev->iobase + RTL_REG_MAR0 + 4); } static void rtl8139_hw_reset(struct eth_device *dev) @@ -286,11 +286,11 @@ static void rtl8139_hw_reset(struct eth_device *dev) u8 reg; int i; - outb(RTL_REG_CHIPCMD_CMDRESET, ioaddr + RTL_REG_CHIPCMD); + outb(RTL_REG_CHIPCMD_CMDRESET, dev->iobase + RTL_REG_CHIPCMD); /* Give the chip 10ms to finish the reset. */ for (i = 0; i < 100; i++) { - reg = inb(ioaddr + RTL_REG_CHIPCMD); + reg = inb(dev->iobase + RTL_REG_CHIPCMD); if (!(reg & RTL_REG_CHIPCMD_CMDRESET)) break; @@ -308,15 +308,15 @@ static void rtl8139_reset(struct eth_device *dev) rtl8139_hw_reset(dev); for (i = 0; i < ETH_ALEN; i++) - outb(dev->enetaddr[i], ioaddr + RTL_REG_MAC0 + i); + outb(dev->enetaddr[i], dev->iobase + RTL_REG_MAC0 + i); /* Must enable Tx/Rx before setting transfer thresholds! */ outb(RTL_REG_CHIPCMD_CMDRXENB | RTL_REG_CHIPCMD_CMDTXENB, - ioaddr + RTL_REG_CHIPCMD); + dev->iobase + RTL_REG_CHIPCMD); /* accept no frames yet! */ - outl(rtl8139_rx_config, ioaddr + RTL_REG_RXCONFIG); - outl((TX_DMA_BURST << 8) | 0x03000000, ioaddr + RTL_REG_TXCONFIG); + outl(rtl8139_rx_config, dev->iobase + RTL_REG_RXCONFIG); + outl((TX_DMA_BURST << 8) | 0x03000000, dev->iobase + RTL_REG_TXCONFIG); /* * The Linux driver changes RTL_REG_CONFIG1 here to use a different @@ -331,7 +331,7 @@ static void rtl8139_reset(struct eth_device *dev) debug_cond(DEBUG_RX, "rx ring address is %p\n", rx_ring); flush_cache((unsigned long)rx_ring, RX_BUF_LEN); - outl(phys_to_bus((int)rx_ring), ioaddr + RTL_REG_RXBUF); + outl(phys_to_bus((int)rx_ring), dev->iobase + RTL_REG_RXBUF); /* * If we add multicast support, the RTL_REG_MAR0 register would have @@ -340,17 +340,17 @@ static void rtl8139_reset(struct eth_device *dev) * unicast. */ outb(RTL_REG_CHIPCMD_CMDRXENB | RTL_REG_CHIPCMD_CMDTXENB, - ioaddr + RTL_REG_CHIPCMD); + dev->iobase + RTL_REG_CHIPCMD); - outl(rtl8139_rx_config, ioaddr + RTL_REG_RXCONFIG); + outl(rtl8139_rx_config, dev->iobase + RTL_REG_RXCONFIG); /* Start the chip's Tx and Rx process. */ - outl(0, ioaddr + RTL_REG_RXMISSED); + outl(0, dev->iobase + RTL_REG_RXMISSED); rtl8139_set_rx_mode(dev); /* Disable all known interrupts by setting the interrupt mask. */ - outw(0, ioaddr + RTL_REG_INTRMASK); + outw(0, dev->iobase + RTL_REG_INTRMASK); } static int rtl8139_send(struct eth_device *dev, void *packet, int length) @@ -360,8 +360,6 @@ static int rtl8139_send(struct eth_device *dev, void *packet, int length) unsigned int status; int i = 0; - ioaddr = dev->iobase; - memcpy(tx_buffer, packet, length); debug_cond(DEBUG_TX, "sending %d bytes\n", len); @@ -375,12 +373,12 @@ static int rtl8139_send(struct eth_device *dev, void *packet, int length) flush_cache((unsigned long)tx_buffer, length); outl(phys_to_bus((unsigned long)tx_buffer), - ioaddr + RTL_REG_TXADDR0 + cur_tx * 4); + dev->iobase + RTL_REG_TXADDR0 + cur_tx * 4); outl(((TX_FIFO_THRESH << 11) & 0x003f0000) | len, - ioaddr + RTL_REG_TXSTATUS0 + cur_tx * 4); + dev->iobase + RTL_REG_TXSTATUS0 + cur_tx * 4); do { - status = inw(ioaddr + RTL_REG_INTRSTATUS); + status = inw(dev->iobase + RTL_REG_INTRSTATUS); /* * Only acknlowledge interrupt sources we can properly * handle here - the RTL_REG_INTRSTATUS_RXOVERFLOW/ @@ -389,14 +387,14 @@ static int rtl8139_send(struct eth_device *dev, void *packet, int length) */ status &= RTL_REG_INTRSTATUS_TXOK | RTL_REG_INTRSTATUS_TXERR | RTL_REG_INTRSTATUS_PCIERR; - outw(status, ioaddr + RTL_REG_INTRSTATUS); + outw(status, dev->iobase + RTL_REG_INTRSTATUS); if (status) break; udelay(10); } while (i++ < RTL_TIMEOUT); - txstatus = inl(ioaddr + RTL_REG_TXSTATUS0 + cur_tx * 4); + txstatus = inl(dev->iobase + RTL_REG_TXSTATUS0 + cur_tx * 4); if (!(status & RTL_REG_INTRSTATUS_TXOK)) { debug_cond(DEBUG_TX, @@ -426,14 +424,12 @@ static int rtl8139_recv(struct eth_device *dev) unsigned int status; int length = 0; - ioaddr = dev->iobase; - - if (inb(ioaddr + RTL_REG_CHIPCMD) & RTL_REG_CHIPCMD_RXBUFEMPTY) + if (inb(dev->iobase + RTL_REG_CHIPCMD) & RTL_REG_CHIPCMD_RXBUFEMPTY) return 0; - status = inw(ioaddr + RTL_REG_INTRSTATUS); + status = inw(dev->iobase + RTL_REG_INTRSTATUS); /* See below for the rest of the interrupt acknowledges. */ - outw(status & ~rxstat, ioaddr + RTL_REG_INTRSTATUS); + outw(status & ~rxstat, dev->iobase + RTL_REG_INTRSTATUS); debug_cond(DEBUG_RX, "%s: int %hX ", __func__, status); @@ -474,13 +470,13 @@ static int rtl8139_recv(struct eth_device *dev) flush_cache((unsigned long)rx_ring, RX_BUF_LEN); cur_rx = ROUND(cur_rx + rx_size + 4, 4); - outw(cur_rx - 16, ioaddr + RTL_REG_RXBUFPTR); + outw(cur_rx - 16, dev->iobase + RTL_REG_RXBUFPTR); /* * See RTL8139 Programming Guide V0.1 for the official handling of * Rx overflow situations. The document itself contains basically * no usable information, except for a few exception handling rules. */ - outw(status & rxstat, ioaddr + RTL_REG_INTRSTATUS); + outw(status & rxstat, dev->iobase + RTL_REG_INTRSTATUS); return length; } @@ -491,18 +487,16 @@ static int rtl8139_init(struct eth_device *dev, bd_t *bis) int addr_len, i; u8 reg; - ioaddr = dev->iobase; - /* Bring the chip out of low-power mode. */ - outb(0x00, ioaddr + RTL_REG_CONFIG1); + outb(0x00, dev->iobase + RTL_REG_CONFIG1); - addr_len = rtl8139_read_eeprom(0, 8) == 0x8129 ? 8 : 6; + addr_len = rtl8139_read_eeprom(dev, 0, 8) == 0x8129 ? 8 : 6; for (i = 0; i < 3; i++) - *ap++ = le16_to_cpu(rtl8139_read_eeprom(i + 7, addr_len)); + *ap++ = le16_to_cpu(rtl8139_read_eeprom(dev, i + 7, addr_len)); rtl8139_reset(dev); - reg = inb(ioaddr + RTL_REG_MEDIASTATUS); + reg = inb(dev->iobase + RTL_REG_MEDIASTATUS); if (reg & RTL_REG_MEDIASTATUS_MSRLINKFAIL) { printf("Cable not connected or other link failure\n"); return -1; @@ -513,8 +507,6 @@ static int rtl8139_init(struct eth_device *dev, bd_t *bis) static void rtl8139_stop(struct eth_device *dev) { - ioaddr = dev->iobase; - rtl8139_hw_reset(dev); } -- cgit v1.1 From 8ff1d4a9c8e629253e43d9d04eccbfa773f81e83 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sat, 9 May 2020 22:34:38 +0200 Subject: net: rtl8139: Clean up bus_to_phys()/phys_to_bus() macros These macros depended on the dev variable being declared wherever they were used. This is wrong and will not work with DM anyway, so pass only the PCI BFD into these macros, which fixes the dependency and prepares them for DM support as well. Signed-off-by: Marek Vasut Cc: Joe Hershberger --- drivers/net/rtl8139.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/rtl8139.c b/drivers/net/rtl8139.c index f829e52..aa13740 100644 --- a/drivers/net/rtl8139.c +++ b/drivers/net/rtl8139.c @@ -96,8 +96,8 @@ #define DEBUG_TX 0 /* set to 1 to enable debug code */ #define DEBUG_RX 0 /* set to 1 to enable debug code */ -#define bus_to_phys(a) pci_mem_to_phys((pci_dev_t)dev->priv, a) -#define phys_to_bus(a) pci_phys_to_mem((pci_dev_t)dev->priv, a) +#define bus_to_phys(devno, a) pci_mem_to_phys((pci_dev_t)(devno), (a)) +#define phys_to_bus(devno, a) pci_phys_to_mem((pci_dev_t)(devno), (a)) /* Symbolic offsets to registers. */ /* Ethernet hardware address. */ @@ -331,7 +331,7 @@ static void rtl8139_reset(struct eth_device *dev) debug_cond(DEBUG_RX, "rx ring address is %p\n", rx_ring); flush_cache((unsigned long)rx_ring, RX_BUF_LEN); - outl(phys_to_bus((int)rx_ring), dev->iobase + RTL_REG_RXBUF); + outl(phys_to_bus(dev->priv, (int)rx_ring), dev->iobase + RTL_REG_RXBUF); /* * If we add multicast support, the RTL_REG_MAR0 register would have @@ -372,7 +372,7 @@ static int rtl8139_send(struct eth_device *dev, void *packet, int length) tx_buffer[len++] = '\0'; flush_cache((unsigned long)tx_buffer, length); - outl(phys_to_bus((unsigned long)tx_buffer), + outl(phys_to_bus(dev->priv, (unsigned long)tx_buffer), dev->iobase + RTL_REG_TXADDR0 + cur_tx * 4); outl(((TX_FIFO_THRESH << 11) & 0x003f0000) | len, dev->iobase + RTL_REG_TXSTATUS0 + cur_tx * 4); @@ -555,7 +555,7 @@ int rtl8139_initialize(bd_t *bis) rtl8139_name(dev->name, card_number); dev->priv = (void *)devno; - dev->iobase = (int)bus_to_phys(iobase); + dev->iobase = (unsigned long)bus_to_phys(devno, iobase); dev->init = rtl8139_init; dev->halt = rtl8139_stop; dev->send = rtl8139_send; -- cgit v1.1 From 3feb6f7ff6856e1e903e5a62f6252d37731b6592 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sat, 9 May 2020 22:34:39 +0200 Subject: net: rtl8139: Introduce device private data Introduce rtl8139_pdata, which is a super-structure around eth_device and tracks per-device state, here the device IO address, PCI BDF, RX and TX ring position. Pass this structure around instead of the old non-DM eth_device in preparation for DM conversion. Signed-off-by: Marek Vasut Cc: Joe Hershberger --- drivers/net/rtl8139.c | 136 +++++++++++++++++++++++++++++--------------------- 1 file changed, 78 insertions(+), 58 deletions(-) (limited to 'drivers') diff --git a/drivers/net/rtl8139.c b/drivers/net/rtl8139.c index aa13740..dff77de 100644 --- a/drivers/net/rtl8139.c +++ b/drivers/net/rtl8139.c @@ -191,7 +191,14 @@ #define RTL_STS_RXBADALIGN BIT(1) #define RTL_STS_RXSTATUSOK BIT(0) -static unsigned int cur_rx, cur_tx; +struct rtl8139_priv { + struct eth_device dev; + unsigned int cur_rx; + unsigned int cur_tx; + unsigned long ioaddr; + pci_dev_t devno; + unsigned char enetaddr[6]; +}; /* The RTL8139 can only transmit from a contiguous, aligned memory block. */ static unsigned char tx_buffer[TX_BUF_SIZE] __aligned(4); @@ -222,43 +229,43 @@ static void rtl8139_eeprom_delay(uintptr_t regbase) inl(regbase + RTL_REG_CFG9346); } -static int rtl8139_read_eeprom(struct eth_device *dev, +static int rtl8139_read_eeprom(struct rtl8139_priv *priv, unsigned int location, unsigned int addr_len) { unsigned int read_cmd = location | (EE_READ_CMD << addr_len); - uintptr_t ee_addr = dev->iobase + RTL_REG_CFG9346; + uintptr_t ee_addr = priv->ioaddr + RTL_REG_CFG9346; unsigned int retval = 0; u8 dataval; int i; outb(EE_ENB & ~EE_CS, ee_addr); outb(EE_ENB, ee_addr); - rtl8139_eeprom_delay(dev->iobase); + rtl8139_eeprom_delay(priv->ioaddr); /* Shift the read command bits out. */ for (i = 4 + addr_len; i >= 0; i--) { dataval = (read_cmd & BIT(i)) ? EE_DATA_WRITE : 0; outb(EE_ENB | dataval, ee_addr); - rtl8139_eeprom_delay(dev->iobase); + rtl8139_eeprom_delay(priv->ioaddr); outb(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr); - rtl8139_eeprom_delay(dev->iobase); + rtl8139_eeprom_delay(priv->ioaddr); } outb(EE_ENB, ee_addr); - rtl8139_eeprom_delay(dev->iobase); + rtl8139_eeprom_delay(priv->ioaddr); for (i = 16; i > 0; i--) { outb(EE_ENB | EE_SHIFT_CLK, ee_addr); - rtl8139_eeprom_delay(dev->iobase); + rtl8139_eeprom_delay(priv->ioaddr); retval <<= 1; retval |= inb(ee_addr) & EE_DATA_READ; outb(EE_ENB, ee_addr); - rtl8139_eeprom_delay(dev->iobase); + rtl8139_eeprom_delay(priv->ioaddr); } /* Terminate the EEPROM access. */ outb(~EE_CS, ee_addr); - rtl8139_eeprom_delay(dev->iobase); + rtl8139_eeprom_delay(priv->ioaddr); return retval; } @@ -268,29 +275,29 @@ static const unsigned int rtl8139_rx_config = (RX_FIFO_THRESH << 13) | (RX_DMA_BURST << 8); -static void rtl8139_set_rx_mode(struct eth_device *dev) +static void rtl8139_set_rx_mode(struct rtl8139_priv *priv) { /* !IFF_PROMISC */ unsigned int rx_mode = RTL_REG_RXCONFIG_ACCEPTBROADCAST | RTL_REG_RXCONFIG_ACCEPTMULTICAST | RTL_REG_RXCONFIG_ACCEPTMYPHYS; - outl(rtl8139_rx_config | rx_mode, dev->iobase + RTL_REG_RXCONFIG); + outl(rtl8139_rx_config | rx_mode, priv->ioaddr + RTL_REG_RXCONFIG); - outl(0xffffffff, dev->iobase + RTL_REG_MAR0 + 0); - outl(0xffffffff, dev->iobase + RTL_REG_MAR0 + 4); + outl(0xffffffff, priv->ioaddr + RTL_REG_MAR0 + 0); + outl(0xffffffff, priv->ioaddr + RTL_REG_MAR0 + 4); } -static void rtl8139_hw_reset(struct eth_device *dev) +static void rtl8139_hw_reset(struct rtl8139_priv *priv) { u8 reg; int i; - outb(RTL_REG_CHIPCMD_CMDRESET, dev->iobase + RTL_REG_CHIPCMD); + outb(RTL_REG_CHIPCMD_CMDRESET, priv->ioaddr + RTL_REG_CHIPCMD); /* Give the chip 10ms to finish the reset. */ for (i = 0; i < 100; i++) { - reg = inb(dev->iobase + RTL_REG_CHIPCMD); + reg = inb(priv->ioaddr + RTL_REG_CHIPCMD); if (!(reg & RTL_REG_CHIPCMD_CMDRESET)) break; @@ -298,25 +305,25 @@ static void rtl8139_hw_reset(struct eth_device *dev) } } -static void rtl8139_reset(struct eth_device *dev) +static void rtl8139_reset(struct rtl8139_priv *priv) { int i; - cur_rx = 0; - cur_tx = 0; + priv->cur_rx = 0; + priv->cur_tx = 0; - rtl8139_hw_reset(dev); + rtl8139_hw_reset(priv); for (i = 0; i < ETH_ALEN; i++) - outb(dev->enetaddr[i], dev->iobase + RTL_REG_MAC0 + i); + outb(priv->enetaddr[i], priv->ioaddr + RTL_REG_MAC0 + i); /* Must enable Tx/Rx before setting transfer thresholds! */ outb(RTL_REG_CHIPCMD_CMDRXENB | RTL_REG_CHIPCMD_CMDTXENB, - dev->iobase + RTL_REG_CHIPCMD); + priv->ioaddr + RTL_REG_CHIPCMD); /* accept no frames yet! */ - outl(rtl8139_rx_config, dev->iobase + RTL_REG_RXCONFIG); - outl((TX_DMA_BURST << 8) | 0x03000000, dev->iobase + RTL_REG_TXCONFIG); + outl(rtl8139_rx_config, priv->ioaddr + RTL_REG_RXCONFIG); + outl((TX_DMA_BURST << 8) | 0x03000000, priv->ioaddr + RTL_REG_TXCONFIG); /* * The Linux driver changes RTL_REG_CONFIG1 here to use a different @@ -331,7 +338,7 @@ static void rtl8139_reset(struct eth_device *dev) debug_cond(DEBUG_RX, "rx ring address is %p\n", rx_ring); flush_cache((unsigned long)rx_ring, RX_BUF_LEN); - outl(phys_to_bus(dev->priv, (int)rx_ring), dev->iobase + RTL_REG_RXBUF); + outl(phys_to_bus(priv->devno, (int)rx_ring), priv->ioaddr + RTL_REG_RXBUF); /* * If we add multicast support, the RTL_REG_MAR0 register would have @@ -340,21 +347,22 @@ static void rtl8139_reset(struct eth_device *dev) * unicast. */ outb(RTL_REG_CHIPCMD_CMDRXENB | RTL_REG_CHIPCMD_CMDTXENB, - dev->iobase + RTL_REG_CHIPCMD); + priv->ioaddr + RTL_REG_CHIPCMD); - outl(rtl8139_rx_config, dev->iobase + RTL_REG_RXCONFIG); + outl(rtl8139_rx_config, priv->ioaddr + RTL_REG_RXCONFIG); /* Start the chip's Tx and Rx process. */ - outl(0, dev->iobase + RTL_REG_RXMISSED); + outl(0, priv->ioaddr + RTL_REG_RXMISSED); - rtl8139_set_rx_mode(dev); + rtl8139_set_rx_mode(priv); /* Disable all known interrupts by setting the interrupt mask. */ - outw(0, dev->iobase + RTL_REG_INTRMASK); + outw(0, priv->ioaddr + RTL_REG_INTRMASK); } static int rtl8139_send(struct eth_device *dev, void *packet, int length) { + struct rtl8139_priv *priv = container_of(dev, struct rtl8139_priv, dev); unsigned int len = length; unsigned long txstatus; unsigned int status; @@ -372,13 +380,13 @@ static int rtl8139_send(struct eth_device *dev, void *packet, int length) tx_buffer[len++] = '\0'; flush_cache((unsigned long)tx_buffer, length); - outl(phys_to_bus(dev->priv, (unsigned long)tx_buffer), - dev->iobase + RTL_REG_TXADDR0 + cur_tx * 4); + outl(phys_to_bus(priv->devno, (unsigned long)tx_buffer), + priv->ioaddr + RTL_REG_TXADDR0 + priv->cur_tx * 4); outl(((TX_FIFO_THRESH << 11) & 0x003f0000) | len, - dev->iobase + RTL_REG_TXSTATUS0 + cur_tx * 4); + priv->ioaddr + RTL_REG_TXSTATUS0 + priv->cur_tx * 4); do { - status = inw(dev->iobase + RTL_REG_INTRSTATUS); + status = inw(priv->ioaddr + RTL_REG_INTRSTATUS); /* * Only acknlowledge interrupt sources we can properly * handle here - the RTL_REG_INTRSTATUS_RXOVERFLOW/ @@ -387,26 +395,26 @@ static int rtl8139_send(struct eth_device *dev, void *packet, int length) */ status &= RTL_REG_INTRSTATUS_TXOK | RTL_REG_INTRSTATUS_TXERR | RTL_REG_INTRSTATUS_PCIERR; - outw(status, dev->iobase + RTL_REG_INTRSTATUS); + outw(status, priv->ioaddr + RTL_REG_INTRSTATUS); if (status) break; udelay(10); } while (i++ < RTL_TIMEOUT); - txstatus = inl(dev->iobase + RTL_REG_TXSTATUS0 + cur_tx * 4); + txstatus = inl(priv->ioaddr + RTL_REG_TXSTATUS0 + priv->cur_tx * 4); if (!(status & RTL_REG_INTRSTATUS_TXOK)) { debug_cond(DEBUG_TX, "tx timeout/error (%d usecs), status %hX txstatus %lX\n", 10 * i, status, txstatus); - rtl8139_reset(dev); + rtl8139_reset(priv); return 0; } - cur_tx = (cur_tx + 1) % NUM_TX_DESC; + priv->cur_tx = (priv->cur_tx + 1) % NUM_TX_DESC; debug_cond(DEBUG_TX, "tx done, status %hX txstatus %lX\n", status, txstatus); @@ -416,6 +424,7 @@ static int rtl8139_send(struct eth_device *dev, void *packet, int length) static int rtl8139_recv(struct eth_device *dev) { + struct rtl8139_priv *priv = container_of(dev, struct rtl8139_priv, dev); const unsigned int rxstat = RTL_REG_INTRSTATUS_RXFIFOOVER | RTL_REG_INTRSTATUS_RXOVERFLOW | RTL_REG_INTRSTATUS_RXOK; @@ -424,16 +433,16 @@ static int rtl8139_recv(struct eth_device *dev) unsigned int status; int length = 0; - if (inb(dev->iobase + RTL_REG_CHIPCMD) & RTL_REG_CHIPCMD_RXBUFEMPTY) + if (inb(priv->ioaddr + RTL_REG_CHIPCMD) & RTL_REG_CHIPCMD_RXBUFEMPTY) return 0; - status = inw(dev->iobase + RTL_REG_INTRSTATUS); + status = inw(priv->ioaddr + RTL_REG_INTRSTATUS); /* See below for the rest of the interrupt acknowledges. */ - outw(status & ~rxstat, dev->iobase + RTL_REG_INTRSTATUS); + outw(status & ~rxstat, priv->ioaddr + RTL_REG_INTRSTATUS); debug_cond(DEBUG_RX, "%s: int %hX ", __func__, status); - ring_offs = cur_rx % RX_BUF_LEN; + ring_offs = priv->cur_rx % RX_BUF_LEN; /* ring_offs is guaranteed being 4-byte aligned */ rx_status = le32_to_cpu(*(unsigned int *)(rx_ring + ring_offs)); rx_size = rx_status >> 16; @@ -446,7 +455,7 @@ static int rtl8139_recv(struct eth_device *dev) (rx_size > ETH_FRAME_LEN + 4)) { printf("rx error %hX\n", rx_status); /* this clears all interrupts still pending */ - rtl8139_reset(dev); + rtl8139_reset(priv); return 0; } @@ -469,45 +478,51 @@ static int rtl8139_recv(struct eth_device *dev) } flush_cache((unsigned long)rx_ring, RX_BUF_LEN); - cur_rx = ROUND(cur_rx + rx_size + 4, 4); - outw(cur_rx - 16, dev->iobase + RTL_REG_RXBUFPTR); + priv->cur_rx = ROUND(priv->cur_rx + rx_size + 4, 4); + outw(priv->cur_rx - 16, priv->ioaddr + RTL_REG_RXBUFPTR); /* * See RTL8139 Programming Guide V0.1 for the official handling of * Rx overflow situations. The document itself contains basically * no usable information, except for a few exception handling rules. */ - outw(status & rxstat, dev->iobase + RTL_REG_INTRSTATUS); + outw(status & rxstat, priv->ioaddr + RTL_REG_INTRSTATUS); return length; } static int rtl8139_init(struct eth_device *dev, bd_t *bis) { - unsigned short *ap = (unsigned short *)dev->enetaddr; + struct rtl8139_priv *priv = container_of(dev, struct rtl8139_priv, dev); + unsigned short *ap = (unsigned short *)priv->enetaddr; int addr_len, i; u8 reg; /* Bring the chip out of low-power mode. */ - outb(0x00, dev->iobase + RTL_REG_CONFIG1); + outb(0x00, priv->ioaddr + RTL_REG_CONFIG1); - addr_len = rtl8139_read_eeprom(dev, 0, 8) == 0x8129 ? 8 : 6; + addr_len = rtl8139_read_eeprom(priv, 0, 8) == 0x8129 ? 8 : 6; for (i = 0; i < 3; i++) - *ap++ = le16_to_cpu(rtl8139_read_eeprom(dev, i + 7, addr_len)); + *ap++ = le16_to_cpu(rtl8139_read_eeprom(priv, i + 7, addr_len)); - rtl8139_reset(dev); + rtl8139_reset(priv); - reg = inb(dev->iobase + RTL_REG_MEDIASTATUS); + reg = inb(priv->ioaddr + RTL_REG_MEDIASTATUS); if (reg & RTL_REG_MEDIASTATUS_MSRLINKFAIL) { printf("Cable not connected or other link failure\n"); return -1; } + /* Non-DM compatibility */ + memcpy(priv->dev.enetaddr, priv->enetaddr, 6); + return 0; } static void rtl8139_stop(struct eth_device *dev) { - rtl8139_hw_reset(dev); + struct rtl8139_priv *priv = container_of(dev, struct rtl8139_priv, dev); + + rtl8139_hw_reset(priv); } static int rtl8139_bcast_addr(struct eth_device *dev, const u8 *bcast_mac, @@ -529,6 +544,7 @@ static struct pci_device_id supported[] = { int rtl8139_initialize(bd_t *bis) { + struct rtl8139_priv *priv; struct eth_device *dev; int card_number = 0; pci_dev_t devno; @@ -546,16 +562,20 @@ int rtl8139_initialize(bd_t *bis) debug("rtl8139: REALTEK RTL8139 @0x%x\n", iobase); - dev = calloc(1, sizeof(*dev)); - if (!dev) { + priv = calloc(1, sizeof(*priv)); + if (!priv) { printf("Can not allocate memory of rtl8139\n"); break; } + priv->devno = devno; + priv->ioaddr = (unsigned long)bus_to_phys(devno, iobase); + + dev = &priv->dev; + rtl8139_name(dev->name, card_number); - dev->priv = (void *)devno; - dev->iobase = (unsigned long)bus_to_phys(devno, iobase); + dev->iobase = priv->ioaddr; /* Non-DM compatibility */ dev->init = rtl8139_init; dev->halt = rtl8139_stop; dev->send = rtl8139_send; -- cgit v1.1 From 26f59c28bdea91617b3acfd132d5affc55e1ef4a Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sat, 9 May 2020 22:34:40 +0200 Subject: net: rtl8139: Pass private data into rtl8139_eeprom_delay() Instead of always calling rtl8139_eeprom_delay() with priv->ioaddr, call it with priv and let the function access priv->ioaddr. This reduces code duplication and has no impact, since the compiler will inline this as needed anyway. Signed-off-by: Marek Vasut Cc: Joe Hershberger --- drivers/net/rtl8139.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/net/rtl8139.c b/drivers/net/rtl8139.c index dff77de..ae5d125 100644 --- a/drivers/net/rtl8139.c +++ b/drivers/net/rtl8139.c @@ -220,13 +220,13 @@ static unsigned char rx_ring[RX_BUF_LEN + 16] __aligned(4); #define EE_READ_CMD 6 #define EE_ERASE_CMD 7 -static void rtl8139_eeprom_delay(uintptr_t regbase) +static void rtl8139_eeprom_delay(struct rtl8139_priv *priv) { /* * Delay between EEPROM clock transitions. * No extra delay is needed with 33MHz PCI, but 66MHz may change this. */ - inl(regbase + RTL_REG_CFG9346); + inl(priv->ioaddr + RTL_REG_CFG9346); } static int rtl8139_read_eeprom(struct rtl8139_priv *priv, @@ -240,32 +240,32 @@ static int rtl8139_read_eeprom(struct rtl8139_priv *priv, outb(EE_ENB & ~EE_CS, ee_addr); outb(EE_ENB, ee_addr); - rtl8139_eeprom_delay(priv->ioaddr); + rtl8139_eeprom_delay(priv); /* Shift the read command bits out. */ for (i = 4 + addr_len; i >= 0; i--) { dataval = (read_cmd & BIT(i)) ? EE_DATA_WRITE : 0; outb(EE_ENB | dataval, ee_addr); - rtl8139_eeprom_delay(priv->ioaddr); + rtl8139_eeprom_delay(priv); outb(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr); - rtl8139_eeprom_delay(priv->ioaddr); + rtl8139_eeprom_delay(priv); } outb(EE_ENB, ee_addr); - rtl8139_eeprom_delay(priv->ioaddr); + rtl8139_eeprom_delay(priv); for (i = 16; i > 0; i--) { outb(EE_ENB | EE_SHIFT_CLK, ee_addr); - rtl8139_eeprom_delay(priv->ioaddr); + rtl8139_eeprom_delay(priv); retval <<= 1; retval |= inb(ee_addr) & EE_DATA_READ; outb(EE_ENB, ee_addr); - rtl8139_eeprom_delay(priv->ioaddr); + rtl8139_eeprom_delay(priv); } /* Terminate the EEPROM access. */ outb(~EE_CS, ee_addr); - rtl8139_eeprom_delay(priv->ioaddr); + rtl8139_eeprom_delay(priv); return retval; } -- cgit v1.1 From 6a4a5c194df8af25390f4ba30250a76fc0256643 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sat, 9 May 2020 22:34:41 +0200 Subject: net: rtl8139: Split out common and non-DM functions Split the driver into common and non-DM functionality, so that the DM support can later re-use the common code, while we retain the non-DM code until all the platforms are converted. Signed-off-by: Marek Vasut Cc: Joe Hershberger --- drivers/net/rtl8139.c | 92 +++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 68 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/net/rtl8139.c b/drivers/net/rtl8139.c index ae5d125..70b09fb 100644 --- a/drivers/net/rtl8139.c +++ b/drivers/net/rtl8139.c @@ -193,6 +193,7 @@ struct rtl8139_priv { struct eth_device dev; + unsigned int rxstatus; unsigned int cur_rx; unsigned int cur_tx; unsigned long ioaddr; @@ -360,9 +361,9 @@ static void rtl8139_reset(struct rtl8139_priv *priv) outw(0, priv->ioaddr + RTL_REG_INTRMASK); } -static int rtl8139_send(struct eth_device *dev, void *packet, int length) +static int rtl8139_send_common(struct rtl8139_priv *priv, + void *packet, int length) { - struct rtl8139_priv *priv = container_of(dev, struct rtl8139_priv, dev); unsigned int len = length; unsigned long txstatus; unsigned int status; @@ -422,25 +423,24 @@ static int rtl8139_send(struct eth_device *dev, void *packet, int length) return length; } -static int rtl8139_recv(struct eth_device *dev) +static int rtl8139_recv_common(struct rtl8139_priv *priv, unsigned char *rxdata, + uchar **packetp) { - struct rtl8139_priv *priv = container_of(dev, struct rtl8139_priv, dev); const unsigned int rxstat = RTL_REG_INTRSTATUS_RXFIFOOVER | RTL_REG_INTRSTATUS_RXOVERFLOW | RTL_REG_INTRSTATUS_RXOK; unsigned int rx_size, rx_status; unsigned int ring_offs; - unsigned int status; int length = 0; if (inb(priv->ioaddr + RTL_REG_CHIPCMD) & RTL_REG_CHIPCMD_RXBUFEMPTY) return 0; - status = inw(priv->ioaddr + RTL_REG_INTRSTATUS); + priv->rxstatus = inw(priv->ioaddr + RTL_REG_INTRSTATUS); /* See below for the rest of the interrupt acknowledges. */ - outw(status & ~rxstat, priv->ioaddr + RTL_REG_INTRSTATUS); + outw(priv->rxstatus & ~rxstat, priv->ioaddr + RTL_REG_INTRSTATUS); - debug_cond(DEBUG_RX, "%s: int %hX ", __func__, status); + debug_cond(DEBUG_RX, "%s: int %hX ", __func__, priv->rxstatus); ring_offs = priv->cur_rx % RX_BUF_LEN; /* ring_offs is guaranteed being 4-byte aligned */ @@ -462,20 +462,30 @@ static int rtl8139_recv(struct eth_device *dev) /* Received a good packet */ length = rx_size - 4; /* no one cares about the FCS */ if (ring_offs + 4 + rx_size - 4 > RX_BUF_LEN) { - unsigned char rxdata[RX_BUF_LEN]; int semi_count = RX_BUF_LEN - ring_offs - 4; memcpy(rxdata, rx_ring + ring_offs + 4, semi_count); memcpy(&rxdata[semi_count], rx_ring, rx_size - 4 - semi_count); - net_process_received_packet(rxdata, length); + *packetp = rxdata; debug_cond(DEBUG_RX, "rx packet %d+%d bytes", semi_count, rx_size - 4 - semi_count); } else { - net_process_received_packet(rx_ring + ring_offs + 4, length); + *packetp = rx_ring + ring_offs + 4; debug_cond(DEBUG_RX, "rx packet %d bytes", rx_size - 4); } + + return length; +} + +static int rtl8139_free_pkt_common(struct rtl8139_priv *priv, unsigned int len) +{ + const unsigned int rxstat = RTL_REG_INTRSTATUS_RXFIFOOVER | + RTL_REG_INTRSTATUS_RXOVERFLOW | + RTL_REG_INTRSTATUS_RXOK; + unsigned int rx_size = len + 4; + flush_cache((unsigned long)rx_ring, RX_BUF_LEN); priv->cur_rx = ROUND(priv->cur_rx + rx_size + 4, 4); @@ -485,14 +495,13 @@ static int rtl8139_recv(struct eth_device *dev) * Rx overflow situations. The document itself contains basically * no usable information, except for a few exception handling rules. */ - outw(status & rxstat, priv->ioaddr + RTL_REG_INTRSTATUS); + outw(priv->rxstatus & rxstat, priv->ioaddr + RTL_REG_INTRSTATUS); - return length; + return 0; } -static int rtl8139_init(struct eth_device *dev, bd_t *bis) +static int rtl8139_init_common(struct rtl8139_priv *priv) { - struct rtl8139_priv *priv = container_of(dev, struct rtl8139_priv, dev); unsigned short *ap = (unsigned short *)priv->enetaddr; int addr_len, i; u8 reg; @@ -518,19 +527,11 @@ static int rtl8139_init(struct eth_device *dev, bd_t *bis) return 0; } -static void rtl8139_stop(struct eth_device *dev) +static void rtl8139_stop_common(struct rtl8139_priv *priv) { - struct rtl8139_priv *priv = container_of(dev, struct rtl8139_priv, dev); - rtl8139_hw_reset(priv); } -static int rtl8139_bcast_addr(struct eth_device *dev, const u8 *bcast_mac, - int join) -{ - return 0; -} - static void rtl8139_name(char *str, int card_number) { sprintf(str, "RTL8139#%u", card_number); @@ -542,6 +543,49 @@ static struct pci_device_id supported[] = { { } }; +static int rtl8139_bcast_addr(struct eth_device *dev, const u8 *bcast_mac, + int join) +{ + return 0; +} + +static int rtl8139_init(struct eth_device *dev, bd_t *bis) +{ + struct rtl8139_priv *priv = container_of(dev, struct rtl8139_priv, dev); + + return rtl8139_init_common(priv); +} + +static void rtl8139_stop(struct eth_device *dev) +{ + struct rtl8139_priv *priv = container_of(dev, struct rtl8139_priv, dev); + + return rtl8139_stop_common(priv); +} + +static int rtl8139_send(struct eth_device *dev, void *packet, int length) +{ + struct rtl8139_priv *priv = container_of(dev, struct rtl8139_priv, dev); + + return rtl8139_send_common(priv, packet, length); +} + +static int rtl8139_recv(struct eth_device *dev) +{ + struct rtl8139_priv *priv = container_of(dev, struct rtl8139_priv, dev); + unsigned char rxdata[RX_BUF_LEN]; + uchar *packet; + int ret; + + ret = rtl8139_recv_common(priv, rxdata, &packet); + if (ret) { + net_process_received_packet(packet, ret); + rtl8139_free_pkt_common(priv, ret); + } + + return ret; +} + int rtl8139_initialize(bd_t *bis) { struct rtl8139_priv *priv; -- cgit v1.1 From 2df3a51510758dc6208ecf36f5e4b929d01f2dd1 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sat, 9 May 2020 22:34:42 +0200 Subject: net: rtl8139: Use PCI_DEVICE() to define PCI device compat list Use this macro to fully fill the PCI device ID table. This is mandatory for the DM PCI support, which checks all the fields. Signed-off-by: Marek Vasut Cc: Joe Hershberger --- drivers/net/rtl8139.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/rtl8139.c b/drivers/net/rtl8139.c index 70b09fb..f319017 100644 --- a/drivers/net/rtl8139.c +++ b/drivers/net/rtl8139.c @@ -538,8 +538,8 @@ static void rtl8139_name(char *str, int card_number) } static struct pci_device_id supported[] = { - { PCI_VENDOR_ID_REALTEK, PCI_DEVICE_ID_REALTEK_8139 }, - { PCI_VENDOR_ID_DLINK, PCI_DEVICE_ID_DLINK_8139 }, + { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, PCI_DEVICE_ID_REALTEK_8139) }, + { PCI_DEVICE(PCI_VENDOR_ID_DLINK, PCI_DEVICE_ID_DLINK_8139) }, { } }; -- cgit v1.1 From d8afb8b28efb5af640d693e7f848732141482cfb Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sat, 9 May 2020 22:34:43 +0200 Subject: net: rtl8139: Read HW address from EEPROM only on probe Do not re-read the HW address from the EEPROM on every start of transfer, otherwise the user will not be able to adjust ethaddr as needed. Read the address only once, when the card is detected. Signed-off-by: Marek Vasut Cc: Joe Hershberger --- drivers/net/rtl8139.c | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/net/rtl8139.c b/drivers/net/rtl8139.c index f319017..d7fabdb 100644 --- a/drivers/net/rtl8139.c +++ b/drivers/net/rtl8139.c @@ -502,17 +502,11 @@ static int rtl8139_free_pkt_common(struct rtl8139_priv *priv, unsigned int len) static int rtl8139_init_common(struct rtl8139_priv *priv) { - unsigned short *ap = (unsigned short *)priv->enetaddr; - int addr_len, i; u8 reg; /* Bring the chip out of low-power mode. */ outb(0x00, priv->ioaddr + RTL_REG_CONFIG1); - addr_len = rtl8139_read_eeprom(priv, 0, 8) == 0x8129 ? 8 : 6; - for (i = 0; i < 3; i++) - *ap++ = le16_to_cpu(rtl8139_read_eeprom(priv, i + 7, addr_len)); - rtl8139_reset(priv); reg = inb(priv->ioaddr + RTL_REG_MEDIASTATUS); @@ -521,9 +515,6 @@ static int rtl8139_init_common(struct rtl8139_priv *priv) return -1; } - /* Non-DM compatibility */ - memcpy(priv->dev.enetaddr, priv->enetaddr, 6); - return 0; } @@ -532,6 +523,19 @@ static void rtl8139_stop_common(struct rtl8139_priv *priv) rtl8139_hw_reset(priv); } +static void rtl8139_get_hwaddr(struct rtl8139_priv *priv) +{ + unsigned short *ap = (unsigned short *)priv->enetaddr; + int i, addr_len; + + /* Bring the chip out of low-power mode. */ + outb(0x00, priv->ioaddr + RTL_REG_CONFIG1); + + addr_len = rtl8139_read_eeprom(priv, 0, 8) == 0x8129 ? 8 : 6; + for (i = 0; i < 3; i++) + *ap++ = le16_to_cpu(rtl8139_read_eeprom(priv, i + 7, addr_len)); +} + static void rtl8139_name(char *str, int card_number) { sprintf(str, "RTL8139#%u", card_number); @@ -626,6 +630,11 @@ int rtl8139_initialize(bd_t *bis) dev->recv = rtl8139_recv; dev->mcast = rtl8139_bcast_addr; + rtl8139_get_hwaddr(priv); + + /* Non-DM compatibility */ + memcpy(priv->dev.enetaddr, priv->enetaddr, 6); + eth_register(dev); card_number++; -- cgit v1.1 From 46c8b18734d273619174006eef498639c06000d3 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sat, 9 May 2020 22:34:44 +0200 Subject: net: rtl8139: Add DM support Add support for driver model to the driver. Signed-off-by: Marek Vasut Cc: Joe Hershberger --- drivers/net/rtl8139.c | 133 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 132 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/rtl8139.c b/drivers/net/rtl8139.c index d7fabdb..8a6f305 100644 --- a/drivers/net/rtl8139.c +++ b/drivers/net/rtl8139.c @@ -70,6 +70,7 @@ #include #include +#include #include #include #include @@ -96,8 +97,13 @@ #define DEBUG_TX 0 /* set to 1 to enable debug code */ #define DEBUG_RX 0 /* set to 1 to enable debug code */ +#ifdef CONFIG_DM_ETH +#define bus_to_phys(devno, a) dm_pci_mem_to_phys((devno), (a)) +#define phys_to_bus(devno, a) dm_pci_phys_to_mem((devno), (a)) +#else #define bus_to_phys(devno, a) pci_mem_to_phys((pci_dev_t)(devno), (a)) #define phys_to_bus(devno, a) pci_phys_to_mem((pci_dev_t)(devno), (a)) +#endif /* Symbolic offsets to registers. */ /* Ethernet hardware address. */ @@ -192,12 +198,16 @@ #define RTL_STS_RXSTATUSOK BIT(0) struct rtl8139_priv { +#ifndef CONFIG_DM_ETH struct eth_device dev; + pci_dev_t devno; +#else + struct udevice *devno; +#endif unsigned int rxstatus; unsigned int cur_rx; unsigned int cur_tx; unsigned long ioaddr; - pci_dev_t devno; unsigned char enetaddr[6]; }; @@ -547,6 +557,7 @@ static struct pci_device_id supported[] = { { } }; +#ifndef CONFIG_DM_ETH static int rtl8139_bcast_addr(struct eth_device *dev, const u8 *bcast_mac, int join) { @@ -646,3 +657,123 @@ int rtl8139_initialize(bd_t *bis) return card_number; } +#else /* DM_ETH */ +static int rtl8139_start(struct udevice *dev) +{ + struct eth_pdata *plat = dev_get_platdata(dev); + struct rtl8139_priv *priv = dev_get_priv(dev); + + memcpy(priv->enetaddr, plat->enetaddr, sizeof(plat->enetaddr)); + + return rtl8139_init_common(priv); +} + +static void rtl8139_stop(struct udevice *dev) +{ + struct rtl8139_priv *priv = dev_get_priv(dev); + + rtl8139_stop_common(priv); +} + +static int rtl8139_send(struct udevice *dev, void *packet, int length) +{ + struct rtl8139_priv *priv = dev_get_priv(dev); + int ret; + + ret = rtl8139_send_common(priv, packet, length); + + return ret ? 0 : -ETIMEDOUT; +} + +static int rtl8139_recv(struct udevice *dev, int flags, uchar **packetp) +{ + struct rtl8139_priv *priv = dev_get_priv(dev); + static unsigned char rxdata[RX_BUF_LEN]; + + return rtl8139_recv_common(priv, rxdata, packetp); +} + +static int rtl8139_free_pkt(struct udevice *dev, uchar *packet, int length) +{ + struct rtl8139_priv *priv = dev_get_priv(dev); + + rtl8139_free_pkt_common(priv, length); + + return 0; +} + +static int rtl8139_write_hwaddr(struct udevice *dev) +{ + struct eth_pdata *plat = dev_get_platdata(dev); + struct rtl8139_priv *priv = dev_get_priv(dev); + + memcpy(priv->enetaddr, plat->enetaddr, sizeof(plat->enetaddr)); + + rtl8139_reset(priv); + + return 0; +} + +static int rtl8139_read_rom_hwaddr(struct udevice *dev) +{ + struct rtl8139_priv *priv = dev_get_priv(dev); + + rtl8139_get_hwaddr(priv); + + return 0; +} + +static int rtl8139_bind(struct udevice *dev) +{ + static int card_number; + char name[16]; + + rtl8139_name(name, card_number++); + + return device_set_name(dev, name); +} + +static int rtl8139_probe(struct udevice *dev) +{ + struct eth_pdata *plat = dev_get_platdata(dev); + struct rtl8139_priv *priv = dev_get_priv(dev); + u32 iobase; + + dm_pci_read_config32(dev, PCI_BASE_ADDRESS_1, &iobase); + iobase &= ~0xf; + + debug("rtl8139: REALTEK RTL8139 @0x%x\n", iobase); + + priv->devno = dev; + priv->ioaddr = (unsigned long)bus_to_phys(dev, iobase); + + rtl8139_get_hwaddr(priv); + memcpy(plat->enetaddr, priv->enetaddr, sizeof(priv->enetaddr)); + + dm_pci_write_config8(dev, PCI_LATENCY_TIMER, 0x20); + + return 0; +} + +static const struct eth_ops rtl8139_ops = { + .start = rtl8139_start, + .send = rtl8139_send, + .recv = rtl8139_recv, + .stop = rtl8139_stop, + .free_pkt = rtl8139_free_pkt, + .write_hwaddr = rtl8139_write_hwaddr, + .read_rom_hwaddr = rtl8139_read_rom_hwaddr, +}; + +U_BOOT_DRIVER(eth_rtl8139) = { + .name = "eth_rtl8139", + .id = UCLASS_ETH, + .bind = rtl8139_bind, + .probe = rtl8139_probe, + .ops = &rtl8139_ops, + .priv_auto_alloc_size = sizeof(struct rtl8139_priv), + .platdata_auto_alloc_size = sizeof(struct eth_pdata), +}; + +U_BOOT_PCI_DEVICE(eth_rtl8139, supported); +#endif -- cgit v1.1 From c78ae11e07d84c10ad5ee91593e49fcf20b07359 Mon Sep 17 00:00:00 2001 From: Faiz Abbas Date: Fri, 22 May 2020 07:32:28 +0530 Subject: mmc: davinci_mmc: Cleanup to use dt in U-boot and static platdata in SPL Cleanup this driver to use dt in U-boot and static platdata in SPL. This requires the following steps: 1. Move all platdata assignment from probe() to ofdata_to_platdata(). This function is only called in U-boot. 2. Replicate all the platdata assignment being done in ofdata_to_platdata() in the omapl138 board file. This data is used in the SPL case where SPL_OF_CONTROL is not enabled. 3. Remove SPL_OF_CONTROL and related configs from omapl138_lcdk_defconfig This cleanup effectively reverts 3ef94715cc ('mmc: davinci: fix mmc boot in SPL') Signed-off-by: Faiz Abbas Tested-by: Bartosz Golaszewski --- drivers/mmc/davinci_mmc.c | 63 +++++++++++++++++++---------------------------- 1 file changed, 26 insertions(+), 37 deletions(-) (limited to 'drivers') diff --git a/drivers/mmc/davinci_mmc.c b/drivers/mmc/davinci_mmc.c index 2408a68..4ef9f7c 100644 --- a/drivers/mmc/davinci_mmc.c +++ b/drivers/mmc/davinci_mmc.c @@ -18,7 +18,6 @@ #include #include -#define DAVINCI_MAX_BLOCKS (32) #define WATCHDOG_COUNT (100000) #define get_val(addr) REG(addr) @@ -34,12 +33,6 @@ struct davinci_mmc_priv { struct gpio_desc cd_gpio; /* Card Detect GPIO */ struct gpio_desc wp_gpio; /* Write Protect GPIO */ }; - -struct davinci_mmc_plat -{ - struct mmc_config cfg; - struct mmc mmc; -}; #endif /* Set davinci clock prescalar value based on the required clock in HZ */ @@ -487,43 +480,16 @@ static int davinci_mmc_probe(struct udevice *dev) struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); struct davinci_mmc_plat *plat = dev_get_platdata(dev); struct davinci_mmc_priv *priv = dev_get_priv(dev); - struct mmc_config *cfg = &plat->cfg; -#ifdef CONFIG_SPL_BUILD - int ret; -#endif - - cfg->f_min = 200000; - cfg->f_max = 25000000; - cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34, - cfg->host_caps = MMC_MODE_4BIT, /* DA850 supports only 4-bit SD/MMC */ - cfg->b_max = DAVINCI_MAX_BLOCKS; - cfg->name = "da830-mmc"; - priv->reg_base = (struct davinci_mmc_regs *)dev_read_addr(dev); + priv->reg_base = plat->reg_base; priv->input_clk = clk_get(DAVINCI_MMCSD_CLKID); - #if CONFIG_IS_ENABLED(DM_GPIO) /* These GPIOs are optional */ gpio_request_by_name(dev, "cd-gpios", 0, &priv->cd_gpio, GPIOD_IS_IN); gpio_request_by_name(dev, "wp-gpios", 0, &priv->wp_gpio, GPIOD_IS_IN); #endif - upriv->mmc = &plat->mmc; -#ifdef CONFIG_SPL_BUILD - /* - * FIXME This is a temporary workaround to enable the driver model in - * SPL on omapl138-lcdk. For some reason the bind() callback is not - * being called in SPL for MMC which breaks the mmc boot - the hack - * is to call mmc_bind() from probe(). We also don't have full DT - * support in SPL, hence the hard-coded base register address. - */ - priv->reg_base = (struct davinci_mmc_regs *)DAVINCI_MMC_SD0_BASE; - ret = mmc_bind(dev, &plat->mmc, &plat->cfg); - if (ret) - return ret; -#endif - return davinci_dm_mmc_init(dev); } @@ -534,21 +500,44 @@ static int davinci_mmc_bind(struct udevice *dev) return mmc_bind(dev, &plat->mmc, &plat->cfg); } +#if CONFIG_IS_ENABLED(OF_CONTROL) +static int davinci_mmc_ofdata_to_platdata(struct udevice *dev) +{ + struct davinci_mmc_plat *plat = dev_get_platdata(dev); + struct mmc_config *cfg = &plat->cfg; + + plat->reg_base = (struct davinci_mmc_regs *)dev_read_addr(dev); + cfg->f_min = 200000; + cfg->f_max = 25000000; + cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34, + cfg->host_caps = MMC_MODE_4BIT, /* DA850 supports only 4-bit SD/MMC */ + cfg->b_max = DAVINCI_MAX_BLOCKS; + cfg->name = "da830-mmc"; + + return 0; +} + static const struct udevice_id davinci_mmc_ids[] = { { .compatible = "ti,da830-mmc" }, {}, }; - +#endif U_BOOT_DRIVER(davinci_mmc_drv) = { .name = "davinci_mmc", .id = UCLASS_MMC, +#if CONFIG_IS_ENABLED(OF_CONTROL) .of_match = davinci_mmc_ids, + .platdata_auto_alloc_size = sizeof(struct davinci_mmc_plat), + .ofdata_to_platdata = davinci_mmc_ofdata_to_platdata, +#endif #if CONFIG_BLK .bind = davinci_mmc_bind, #endif .probe = davinci_mmc_probe, .ops = &davinci_mmc_ops, - .platdata_auto_alloc_size = sizeof(struct davinci_mmc_plat), .priv_auto_alloc_size = sizeof(struct davinci_mmc_priv), +#if !CONFIG_IS_ENABLED(OF_CONTROL) + .flags = DM_FLAG_PRE_RELOC, +#endif }; #endif -- cgit v1.1 From 5b9ee0fc6f9adb05eefa457a752626cb22cca958 Mon Sep 17 00:00:00 2001 From: Bin Liu Date: Wed, 3 Jun 2020 14:46:22 +0300 Subject: phy: omap-usb2-phy: disable phy charger detect AM654x PG1.0 has a silicon bug that D+ is pulled high after POR, which could cause enumeration failure with some USB hubs. Disabling the USB2_PHY Charger Detect function will put D+ into the normal state. Using property "ti,dis-chg-det-quirk" in the DT usb2-phy node to enable this workaround for AM654x PG1.0. Signed-off-by: Bin Liu Signed-off-by: Vignesh Raghavendra Signed-off-by: Roger Quadros --- drivers/phy/omap-usb2-phy.c | 33 ++++++++++++++++++++++++++++----- 1 file changed, 28 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/phy/omap-usb2-phy.c b/drivers/phy/omap-usb2-phy.c index 0793b97..adc454d 100644 --- a/drivers/phy/omap-usb2-phy.c +++ b/drivers/phy/omap-usb2-phy.c @@ -17,6 +17,7 @@ #include #define OMAP_USB2_CALIBRATE_FALSE_DISCONNECT BIT(0) +#define OMAP_USB2_DISABLE_CHG_DET BIT(1) #define OMAP_DEV_PHY_PD BIT(0) #define OMAP_USB2_PHY_PD BIT(28) @@ -33,6 +34,10 @@ #define AM654_USB2_VBUS_DET_EN BIT(5) #define AM654_USB2_VBUSVALID_DET_EN BIT(4) +#define USB2PHY_CHRG_DET 0x14 +#define USB2PHY_USE_CHG_DET_REG BIT(29) +#define USB2PHY_DIS_CHG_DET BIT(28) + DECLARE_GLOBAL_DATA_PTR; struct omap_usb2_phy { @@ -160,6 +165,12 @@ static int omap_usb2_phy_init(struct phy *usb_phy) writel(val, priv->phy_base + USB2PHY_ANA_CONFIG1); } + if (priv->flags & OMAP_USB2_DISABLE_CHG_DET) { + val = readl(priv->phy_base + USB2PHY_CHRG_DET); + val |= USB2PHY_USE_CHG_DET_REG | USB2PHY_DIS_CHG_DET; + writel(val, priv->phy_base + USB2PHY_CHRG_DET); + } + return 0; } @@ -197,13 +208,25 @@ int omap_usb2_phy_probe(struct udevice *dev) if (!data) return -EINVAL; - if (data->flags & OMAP_USB2_CALIBRATE_FALSE_DISCONNECT) { - priv->phy_base = dev_read_addr_ptr(dev); + priv->phy_base = dev_read_addr_ptr(dev); - if (!priv->phy_base) - return -EINVAL; + if (!priv->phy_base) + return -EINVAL; + + if (data->flags & OMAP_USB2_CALIBRATE_FALSE_DISCONNECT) priv->flags |= OMAP_USB2_CALIBRATE_FALSE_DISCONNECT; - } + + /* + * AM654x PG1.0 has a silicon bug that D+ is pulled high after + * POR, which could cause enumeration failure with some USB hubs. + * Disabling the USB2_PHY Charger Detect function will put D+ + * into the normal state. + * + * Using property "ti,dis-chg-det-quirk" in the DT usb2-phy node + * to enable this workaround for AM654x PG1.0. + */ + if (dev_read_bool(dev, "ti,dis-chg-det-quirk")) + priv->flags |= OMAP_USB2_DISABLE_CHG_DET; regmap = syscon_regmap_lookup_by_phandle(dev, "syscon-phy-power"); if (!IS_ERR(regmap)) { -- cgit v1.1 From a37f765219870e4cb4ed9590dff77ed8a380a462 Mon Sep 17 00:00:00 2001 From: Tom Rini Date: Thu, 4 Jun 2020 16:01:39 -0400 Subject: gpio: omap_gpio: Fix unused function warning in non-DM case In the case of non-DM_GPIO the function get_gpio_index() will never be called, and clang will warn about this. Move this to be with the other non-DM code for easier removal later. Cc: Lokesh Vutla Signed-off-by: Tom Rini Reviewed-by: Lokesh Vutla --- drivers/gpio/omap_gpio.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpio/omap_gpio.c b/drivers/gpio/omap_gpio.c index 4249850..c986ef0 100644 --- a/drivers/gpio/omap_gpio.c +++ b/drivers/gpio/omap_gpio.c @@ -41,11 +41,6 @@ struct gpio_bank { #endif -static inline int get_gpio_index(int gpio) -{ - return gpio & 0x1f; -} - int gpio_is_valid(int gpio) { return (gpio >= 0) && (gpio < OMAP_MAX_GPIO); @@ -122,6 +117,10 @@ static int _get_gpio_value(const struct gpio_bank *bank, int gpio) } #if !CONFIG_IS_ENABLED(DM_GPIO) +static inline int get_gpio_index(int gpio) +{ + return gpio & 0x1f; +} static inline const struct gpio_bank *get_gpio_bank(int gpio) { -- cgit v1.1 From 2af17e2573e8f4b949658ac45cad2e825e5aedc0 Mon Sep 17 00:00:00 2001 From: Tom Rini Date: Thu, 4 Jun 2020 16:03:55 -0400 Subject: mmc: omap_hsmmc: Add guards around omap_hsmmc_get_cfg() We only call the function omap_hsmmc_get_cfg in the case of OMAP34XX or when we have to iodelay recalibration. Add guards for these checks as clang will otherwise warn. Cc: Peng Fan Cc: Lokesh Vutla Signed-off-by: Tom Rini Reviewed-by: Peng Fan Reviewed-by: Lokesh Vutla --- drivers/mmc/omap_hsmmc.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/mmc/omap_hsmmc.c b/drivers/mmc/omap_hsmmc.c index 8636cd7..0e05fe4 100644 --- a/drivers/mmc/omap_hsmmc.c +++ b/drivers/mmc/omap_hsmmc.c @@ -175,6 +175,8 @@ static inline struct omap_hsmmc_data *omap_hsmmc_get_data(struct mmc *mmc) return (struct omap_hsmmc_data *)mmc->priv; #endif } + +#if defined(CONFIG_OMAP34XX) || defined(CONFIG_IODELAY_RECALIBRATION) static inline struct mmc_config *omap_hsmmc_get_cfg(struct mmc *mmc) { #if CONFIG_IS_ENABLED(DM_MMC) @@ -184,6 +186,7 @@ static inline struct mmc_config *omap_hsmmc_get_cfg(struct mmc *mmc) return &((struct omap_hsmmc_data *)mmc->priv)->cfg; #endif } +#endif #if defined(OMAP_HSMMC_USE_GPIO) && !CONFIG_IS_ENABLED(DM_MMC) static int omap_mmc_setup_gpio_in(int gpio, const char *label) -- cgit v1.1 From eab48865f93a19e2a196a6c4e3480f16df4027d9 Mon Sep 17 00:00:00 2001 From: Tom Rini Date: Thu, 4 Jun 2020 16:05:32 -0400 Subject: net: cpsw: Add __maybe_unused to generated inlines We generate a number of helper inline functions to make accesses easier. However not all permutations of each function will be used and clang will warn about unused ones. Decorate all of them with __maybe_unused because of this. Cc: Lokesh Vutla Signed-off-by: Tom Rini Reviewed-by: Grygorii Strashko --- drivers/net/ti/cpsw.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ti/cpsw.c b/drivers/net/ti/cpsw.c index 95761ff..9d4332f 100644 --- a/drivers/net/ti/cpsw.c +++ b/drivers/net/ti/cpsw.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -247,11 +248,11 @@ static inline void cpsw_ale_set_field(u32 *ale_entry, u32 start, u32 bits, } #define DEFINE_ALE_FIELD(name, start, bits) \ -static inline int cpsw_ale_get_##name(u32 *ale_entry) \ +static inline int __maybe_unused cpsw_ale_get_##name(u32 *ale_entry) \ { \ return cpsw_ale_get_field(ale_entry, start, bits); \ } \ -static inline void cpsw_ale_set_##name(u32 *ale_entry, u32 value) \ +static inline void __maybe_unused cpsw_ale_set_##name(u32 *ale_entry, u32 value) \ { \ cpsw_ale_set_field(ale_entry, start, bits, value); \ } -- cgit v1.1 From 8d50551dc77bc87dc6c6b3474e094d9203a24144 Mon Sep 17 00:00:00 2001 From: Chuanhua Han Date: Thu, 4 Jun 2020 23:16:30 +0800 Subject: dm: spi: Convert Freescale ESPI driver to driver model Modify the Freescale ESPI driver to support the driver model. Also resolved the following problems: ===================== WARNING ====================== This board does not use CONFIG_DM_SPI. Please update the board before v2019.04 for no dm conversion and v2019.07 for partially dm converted drivers. Failure to update can lead to driver/board removal See doc/driver-model/MIGRATION.txt for more info. ==================================================== ===================== WARNING ====================== This board does not use CONFIG_DM_SPI_FLASH. Please update the board to use CONFIG_SPI_FLASH before the v2019.07 release. Failure to update by the deadline may result in board removal. See doc/driver-model/MIGRATION.txt for more info. ==================================================== Signed-off-by: Chuanhua Han Signed-off-by: Xiaowei Bao Signed-off-by: Hou Zhiqiang Reviewed-by: Jagan Teki --- drivers/spi/fsl_espi.c | 444 +++++++++++++++++++++++++++++++++++-------------- 1 file changed, 321 insertions(+), 123 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/fsl_espi.c b/drivers/spi/fsl_espi.c index 50d194f..5c76fd9 100644 --- a/drivers/spi/fsl_espi.c +++ b/drivers/spi/fsl_espi.c @@ -3,7 +3,9 @@ * eSPI controller driver. * * Copyright 2010-2011 Freescale Semiconductor, Inc. + * Copyright 2020 NXP * Author: Mingkai Hu (Mingkai.hu@freescale.com) + * Chuanhua Han (chuanhua.han@nxp.com) */ #include @@ -14,10 +16,16 @@ #include #include #include +#include +#include +#include +#include struct fsl_spi_slave { struct spi_slave slave; ccsr_espi_t *espi; + u32 speed_hz; + unsigned int cs; unsigned int div16; unsigned int pm; int tx_timeout; @@ -31,6 +39,9 @@ struct fsl_spi_slave { #define to_fsl_spi_slave(s) container_of(s, struct fsl_spi_slave, slave) #define US_PER_SECOND 1000000UL +/* default SCK frequency, unit: HZ */ +#define FSL_ESPI_DEFAULT_SCK_FREQ 10000000 + #define ESPI_MAX_CS_NUM 4 #define ESPI_FIFO_WIDTH_BIT 32 @@ -65,116 +76,27 @@ struct fsl_spi_slave { #define ESPI_MAX_DATA_TRANSFER_LEN 0xFFF0 -struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, - unsigned int max_hz, unsigned int mode) -{ - struct fsl_spi_slave *fsl; - sys_info_t sysinfo; - unsigned long spibrg = 0; - unsigned long spi_freq = 0; - unsigned char pm = 0; - - if (!spi_cs_is_valid(bus, cs)) - return NULL; - - fsl = spi_alloc_slave(struct fsl_spi_slave, bus, cs); - if (!fsl) - return NULL; - - fsl->espi = (void *)(CONFIG_SYS_MPC85xx_ESPI_ADDR); - fsl->mode = mode; - fsl->max_transfer_length = ESPI_MAX_DATA_TRANSFER_LEN; - - /* Set eSPI BRG clock source */ - get_sys_info(&sysinfo); - spibrg = sysinfo.freq_systembus / 2; - fsl->div16 = 0; - if ((spibrg / max_hz) > 32) { - fsl->div16 = ESPI_CSMODE_DIV16; - pm = spibrg / (max_hz * 16 * 2); - if (pm > 16) { - pm = 16; - debug("Requested speed is too low: %d Hz, %ld Hz " - "is used.\n", max_hz, spibrg / (32 * 16)); - } - } else - pm = spibrg / (max_hz * 2); - if (pm) - pm--; - fsl->pm = pm; - - if (fsl->div16) - spi_freq = spibrg / ((pm + 1) * 2 * 16); - else - spi_freq = spibrg / ((pm + 1) * 2); - - /* set tx_timeout to 10 times of one espi FIFO entry go out */ - fsl->tx_timeout = DIV_ROUND_UP((US_PER_SECOND * ESPI_FIFO_WIDTH_BIT - * 10), spi_freq); - - return &fsl->slave; -} - -void spi_free_slave(struct spi_slave *slave) -{ - struct fsl_spi_slave *fsl = to_fsl_spi_slave(slave); - free(fsl); -} - -int spi_claim_bus(struct spi_slave *slave) +void fsl_spi_cs_activate(struct spi_slave *slave, uint cs) { struct fsl_spi_slave *fsl = to_fsl_spi_slave(slave); ccsr_espi_t *espi = fsl->espi; - unsigned char pm = fsl->pm; - unsigned int cs = slave->cs; - unsigned int mode = fsl->mode; - unsigned int div16 = fsl->div16; - int i; - - debug("%s: bus:%i cs:%i\n", __func__, slave->bus, cs); - - /* Enable eSPI interface */ - out_be32(&espi->mode, ESPI_MODE_RXTHR(3) - | ESPI_MODE_TXTHR(4) | ESPI_MODE_EN); - - out_be32(&espi->event, 0xffffffff); /* Clear all eSPI events */ - out_be32(&espi->mask, 0x00000000); /* Mask all eSPI interrupts */ - - /* Init CS mode interface */ - for (i = 0; i < ESPI_MAX_CS_NUM; i++) - out_be32(&espi->csmode[i], ESPI_CSMODE_INIT_VAL); - - out_be32(&espi->csmode[cs], in_be32(&espi->csmode[cs]) & - ~(ESPI_CSMODE_PM(0xF) | ESPI_CSMODE_DIV16 - | ESPI_CSMODE_CI_INACTIVEHIGH | ESPI_CSMODE_CP_BEGIN_EDGCLK - | ESPI_CSMODE_REV_MSB_FIRST | ESPI_CSMODE_LEN(0xF))); - - /* Set eSPI BRG clock source */ - out_be32(&espi->csmode[cs], in_be32(&espi->csmode[cs]) - | ESPI_CSMODE_PM(pm) | div16); - - /* Set eSPI mode */ - if (mode & SPI_CPHA) - out_be32(&espi->csmode[cs], in_be32(&espi->csmode[cs]) - | ESPI_CSMODE_CP_BEGIN_EDGCLK); - if (mode & SPI_CPOL) - out_be32(&espi->csmode[cs], in_be32(&espi->csmode[cs]) - | ESPI_CSMODE_CI_INACTIVEHIGH); - - /* Character bit order: msb first */ - out_be32(&espi->csmode[cs], in_be32(&espi->csmode[cs]) - | ESPI_CSMODE_REV_MSB_FIRST); - - /* Character length in bits, between 0x3~0xf, i.e. 4bits~16bits */ - out_be32(&espi->csmode[cs], in_be32(&espi->csmode[cs]) - | ESPI_CSMODE_LEN(7)); + unsigned int com = 0; + size_t data_len = fsl->data_len; - return 0; + com &= ~(ESPI_COM_CS(0x3) | ESPI_COM_TRANLEN(0xFFFF)); + com |= ESPI_COM_CS(cs); + com |= ESPI_COM_TRANLEN(data_len - 1); + out_be32(&espi->com, com); } -void spi_release_bus(struct spi_slave *slave) +void fsl_spi_cs_deactivate(struct spi_slave *slave) { + struct fsl_spi_slave *fsl = to_fsl_spi_slave(slave); + ccsr_espi_t *espi = fsl->espi; + /* clear the RXCNT and TXCNT */ + out_be32(&espi->mode, in_be32(&espi->mode) & (~ESPI_MODE_EN)); + out_be32(&espi->mode, in_be32(&espi->mode) | ESPI_MODE_EN); } static void fsl_espi_tx(struct fsl_spi_slave *fsl, const void *dout) @@ -207,7 +129,8 @@ static void fsl_espi_tx(struct fsl_spi_slave *fsl, const void *dout) debug("***spi_xfer:...Tx timeout! event = %08x\n", event); } -static int fsl_espi_rx(struct fsl_spi_slave *fsl, void *din, unsigned int bytes) +static int fsl_espi_rx(struct fsl_spi_slave *fsl, void *din, + unsigned int bytes) { ccsr_espi_t *espi = fsl->espi; unsigned int tmpdin, rx_times; @@ -239,10 +162,17 @@ static int fsl_espi_rx(struct fsl_spi_slave *fsl, void *din, unsigned int bytes) return bytes; } -int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *data_out, - void *data_in, unsigned long flags) +void espi_release_bus(struct fsl_spi_slave *fsl) { - struct fsl_spi_slave *fsl = to_fsl_spi_slave(slave); + /* Disable the SPI hardware */ + out_be32(&fsl->espi->mode, + in_be32(&fsl->espi->mode) & (~ESPI_MODE_EN)); +} + +int espi_xfer(struct fsl_spi_slave *fsl, uint cs, unsigned int bitlen, + const void *data_out, void *data_in, unsigned long flags) +{ + struct spi_slave *slave = &fsl->slave; ccsr_espi_t *espi = fsl->espi; unsigned int event, rx_bytes; const void *dout = NULL; @@ -261,13 +191,14 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *data_out, max_tran_len = fsl->max_transfer_length; switch (flags) { case SPI_XFER_BEGIN: - cmd_len = fsl->cmd_len = data_len; + cmd_len = data_len; + fsl->cmd_len = cmd_len; memcpy(cmd_buf, data_out, cmd_len); return 0; case 0: case SPI_XFER_END: if (bitlen == 0) { - spi_cs_deactivate(slave); + fsl_spi_cs_deactivate(slave); return 0; } buf_len = 2 * cmd_len + min(data_len, (size_t)max_tran_len); @@ -307,7 +238,7 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *data_out, num_blks = DIV_ROUND_UP(tran_len + cmd_len, 4); num_bytes = (tran_len + cmd_len) % 4; fsl->data_len = tran_len + cmd_len; - spi_cs_activate(slave); + fsl_spi_cs_activate(slave, cs); /* Clear all eSPI events */ out_be32(&espi->event , 0xffffffff); @@ -350,37 +281,304 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *data_out, *(int *)buffer += tran_len; } } - spi_cs_deactivate(slave); + fsl_spi_cs_deactivate(slave); } free(buffer); return 0; } +void espi_claim_bus(struct fsl_spi_slave *fsl, unsigned int cs) +{ + ccsr_espi_t *espi = fsl->espi; + unsigned char pm = fsl->pm; + unsigned int mode = fsl->mode; + unsigned int div16 = fsl->div16; + int i; + + /* Enable eSPI interface */ + out_be32(&espi->mode, ESPI_MODE_RXTHR(3) + | ESPI_MODE_TXTHR(4) | ESPI_MODE_EN); + + out_be32(&espi->event, 0xffffffff); /* Clear all eSPI events */ + out_be32(&espi->mask, 0x00000000); /* Mask all eSPI interrupts */ + + /* Init CS mode interface */ + for (i = 0; i < ESPI_MAX_CS_NUM; i++) + out_be32(&espi->csmode[i], ESPI_CSMODE_INIT_VAL); + + out_be32(&espi->csmode[cs], in_be32(&espi->csmode[cs]) & + ~(ESPI_CSMODE_PM(0xF) | ESPI_CSMODE_DIV16 + | ESPI_CSMODE_CI_INACTIVEHIGH | ESPI_CSMODE_CP_BEGIN_EDGCLK + | ESPI_CSMODE_REV_MSB_FIRST | ESPI_CSMODE_LEN(0xF))); + + /* Set eSPI BRG clock source */ + out_be32(&espi->csmode[cs], in_be32(&espi->csmode[cs]) + | ESPI_CSMODE_PM(pm) | div16); + + /* Set eSPI mode */ + if (mode & SPI_CPHA) + out_be32(&espi->csmode[cs], in_be32(&espi->csmode[cs]) + | ESPI_CSMODE_CP_BEGIN_EDGCLK); + if (mode & SPI_CPOL) + out_be32(&espi->csmode[cs], in_be32(&espi->csmode[cs]) + | ESPI_CSMODE_CI_INACTIVEHIGH); + + /* Character bit order: msb first */ + out_be32(&espi->csmode[cs], in_be32(&espi->csmode[cs]) + | ESPI_CSMODE_REV_MSB_FIRST); + + /* Character length in bits, between 0x3~0xf, i.e. 4bits~16bits */ + out_be32(&espi->csmode[cs], in_be32(&espi->csmode[cs]) + | ESPI_CSMODE_LEN(7)); +} + +void espi_setup_slave(struct fsl_spi_slave *fsl) +{ + unsigned int max_hz; + sys_info_t sysinfo; + unsigned long spibrg = 0; + unsigned long spi_freq = 0; + unsigned char pm = 0; + + max_hz = fsl->speed_hz; + + get_sys_info(&sysinfo); + spibrg = sysinfo.freq_systembus / 2; + fsl->div16 = 0; + if ((spibrg / max_hz) > 32) { + fsl->div16 = ESPI_CSMODE_DIV16; + pm = spibrg / (max_hz * 16 * 2); + if (pm > 16) { + pm = 16; + debug("max_hz is too low: %d Hz, %ld Hz is used.\n", + max_hz, spibrg / (32 * 16)); + } + } else { + pm = spibrg / (max_hz * 2); + } + if (pm) + pm--; + fsl->pm = pm; + + if (fsl->div16) + spi_freq = spibrg / ((pm + 1) * 2 * 16); + else + spi_freq = spibrg / ((pm + 1) * 2); + + /* set tx_timeout to 10 times of one espi FIFO entry go out */ + fsl->tx_timeout = DIV_ROUND_UP((US_PER_SECOND * ESPI_FIFO_WIDTH_BIT + * 10), spi_freq);/* Set eSPI BRG clock source */ +} + +#if !CONFIG_IS_ENABLED(DM_SPI) int spi_cs_is_valid(unsigned int bus, unsigned int cs) { return bus == 0 && cs < ESPI_MAX_CS_NUM; } -void spi_cs_activate(struct spi_slave *slave) +struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, + unsigned int max_hz, unsigned int mode) +{ + struct fsl_spi_slave *fsl; + + if (!spi_cs_is_valid(bus, cs)) + return NULL; + + fsl = spi_alloc_slave(struct fsl_spi_slave, bus, cs); + if (!fsl) + return NULL; + + fsl->espi = (void *)(CONFIG_SYS_MPC85xx_ESPI_ADDR); + fsl->mode = mode; + fsl->max_transfer_length = ESPI_MAX_DATA_TRANSFER_LEN; + fsl->speed_hz = max_hz; + + espi_setup_slave(fsl); + + return &fsl->slave; +} + +void spi_free_slave(struct spi_slave *slave) { struct fsl_spi_slave *fsl = to_fsl_spi_slave(slave); - ccsr_espi_t *espi = fsl->espi; - unsigned int com = 0; - size_t data_len = fsl->data_len; - com &= ~(ESPI_COM_CS(0x3) | ESPI_COM_TRANLEN(0xFFFF)); - com |= ESPI_COM_CS(slave->cs); - com |= ESPI_COM_TRANLEN(data_len - 1); - out_be32(&espi->com, com); + free(fsl); } -void spi_cs_deactivate(struct spi_slave *slave) +int spi_claim_bus(struct spi_slave *slave) { struct fsl_spi_slave *fsl = to_fsl_spi_slave(slave); - ccsr_espi_t *espi = fsl->espi; - /* clear the RXCNT and TXCNT */ - out_be32(&espi->mode, in_be32(&espi->mode) & (~ESPI_MODE_EN)); - out_be32(&espi->mode, in_be32(&espi->mode) | ESPI_MODE_EN); + espi_claim_bus(fsl, slave->cs); + + return 0; } + +void spi_release_bus(struct spi_slave *slave) +{ + struct fsl_spi_slave *fsl = to_fsl_spi_slave(slave); + + espi_release_bus(fsl); +} + +int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout, + void *din, unsigned long flags) +{ + struct fsl_spi_slave *fsl = (struct fsl_spi_slave *)slave; + + return espi_xfer(fsl, slave->cs, bitlen, dout, din, flags); +} +#else +static void __espi_set_speed(struct fsl_spi_slave *fsl) +{ + espi_setup_slave(fsl); + + /* Set eSPI BRG clock source */ + out_be32(&fsl->espi->csmode[fsl->cs], + in_be32(&fsl->espi->csmode[fsl->cs]) + | ESPI_CSMODE_PM(fsl->pm) | fsl->div16); +} + +static void __espi_set_mode(struct fsl_spi_slave *fsl) +{ + /* Set eSPI mode */ + if (fsl->mode & SPI_CPHA) + out_be32(&fsl->espi->csmode[fsl->cs], + in_be32(&fsl->espi->csmode[fsl->cs]) + | ESPI_CSMODE_CP_BEGIN_EDGCLK); + if (fsl->mode & SPI_CPOL) + out_be32(&fsl->espi->csmode[fsl->cs], + in_be32(&fsl->espi->csmode[fsl->cs]) + | ESPI_CSMODE_CI_INACTIVEHIGH); +} + +static int fsl_espi_claim_bus(struct udevice *dev) +{ + struct udevice *bus = dev->parent; + struct fsl_spi_slave *fsl = dev_get_priv(bus); + + espi_claim_bus(fsl, fsl->cs); + + return 0; +} + +static int fsl_espi_release_bus(struct udevice *dev) +{ + struct udevice *bus = dev->parent; + struct fsl_spi_slave *fsl = dev_get_priv(bus); + + espi_release_bus(fsl); + + return 0; +} + +static int fsl_espi_xfer(struct udevice *dev, unsigned int bitlen, + const void *dout, void *din, unsigned long flags) +{ + struct udevice *bus = dev->parent; + struct fsl_spi_slave *fsl = dev_get_priv(bus); + + return espi_xfer(fsl, fsl->cs, bitlen, dout, din, flags); +} + +static int fsl_espi_set_speed(struct udevice *bus, uint speed) +{ + struct fsl_spi_slave *fsl = dev_get_priv(bus); + + debug("%s speed %u\n", __func__, speed); + fsl->speed_hz = speed; + + __espi_set_speed(fsl); + + return 0; +} + +static int fsl_espi_set_mode(struct udevice *bus, uint mode) +{ + struct fsl_spi_slave *fsl = dev_get_priv(bus); + + debug("%s mode %u\n", __func__, mode); + fsl->mode = mode; + + __espi_set_mode(fsl); + + return 0; +} + +static int fsl_espi_child_pre_probe(struct udevice *dev) +{ + struct dm_spi_slave_platdata *slave_plat = dev_get_parent_platdata(dev); + struct udevice *bus = dev->parent; + struct fsl_spi_slave *fsl = dev_get_priv(bus); + + debug("%s cs %u\n", __func__, slave_plat->cs); + fsl->cs = slave_plat->cs; + + return 0; +} + +static int fsl_espi_probe(struct udevice *bus) +{ + struct fsl_espi_platdata *plat = dev_get_platdata(bus); + struct fsl_spi_slave *fsl = dev_get_priv(bus); + + fsl->espi = (ccsr_espi_t *)((u32)plat->regs_addr); + fsl->max_transfer_length = ESPI_MAX_DATA_TRANSFER_LEN; + fsl->speed_hz = plat->speed_hz; + + debug("%s probe done, bus-num %d.\n", bus->name, bus->seq); + + return 0; +} + +static const struct dm_spi_ops fsl_espi_ops = { + .claim_bus = fsl_espi_claim_bus, + .release_bus = fsl_espi_release_bus, + .xfer = fsl_espi_xfer, + .set_speed = fsl_espi_set_speed, + .set_mode = fsl_espi_set_mode, +}; + +#if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA) +static int fsl_espi_ofdata_to_platdata(struct udevice *bus) +{ + fdt_addr_t addr; + struct fsl_espi_platdata *plat = bus->platdata; + const void *blob = gd->fdt_blob; + int node = dev_of_offset(bus); + + addr = dev_read_addr(bus); + if (addr == FDT_ADDR_T_NONE) + return -EINVAL; + + plat->regs_addr = lower_32_bits(addr); + plat->speed_hz = fdtdec_get_int(blob, node, "spi-max-frequency", + FSL_ESPI_DEFAULT_SCK_FREQ); + + debug("ESPI: regs=%p, max-frequency=%d\n", + &plat->regs_addr, plat->speed_hz); + + return 0; +} + +static const struct udevice_id fsl_espi_ids[] = { + { .compatible = "fsl,mpc8536-espi" }, + { } +}; +#endif + +U_BOOT_DRIVER(fsl_espi) = { + .name = "fsl_espi", + .id = UCLASS_SPI, +#if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA) + .of_match = fsl_espi_ids, + .ofdata_to_platdata = fsl_espi_ofdata_to_platdata, +#endif + .ops = &fsl_espi_ops, + .platdata_auto_alloc_size = sizeof(struct fsl_espi_platdata), + .priv_auto_alloc_size = sizeof(struct fsl_spi_slave), + .probe = fsl_espi_probe, + .child_pre_probe = fsl_espi_child_pre_probe, +}; +#endif -- cgit v1.1 From 39b95556f9b97b0fa824871aef53647d6ea0b44e Mon Sep 17 00:00:00 2001 From: Anatolij Gustschin Date: Mon, 25 May 2020 21:47:19 +0200 Subject: video: make vidconsole commands optional Converting some boards to DM_VIDEO results in build breakage due to increased code size. Make video console specific commands optional to reduce binary size. Signed-off-by: Anatolij Gustschin Reviewed-by: Simon Glass --- drivers/video/Kconfig | 8 ++++++++ drivers/video/vidconsole-uclass.c | 2 ++ 2 files changed, 10 insertions(+) (limited to 'drivers') diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 3812354..d0e9563 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -35,6 +35,14 @@ config BACKLIGHT_GPIO it understands the standard device tree (leds/backlight/gpio-backlight.txt) +config CMD_VIDCONSOLE + bool "Enable vidconsole commands lcdputs and setcurs" + depends on DM_VIDEO + default y + help + Enabling this will provide 'setcurs' and 'lcdputs' commands which + support cursor positioning and drawing strings on video framebuffer. + config VIDEO_BPP8 bool "Support 8-bit-per-pixel displays" depends on DM_VIDEO diff --git a/drivers/video/vidconsole-uclass.c b/drivers/video/vidconsole-uclass.c index d30e6db..901347c 100644 --- a/drivers/video/vidconsole-uclass.c +++ b/drivers/video/vidconsole-uclass.c @@ -613,6 +613,7 @@ UCLASS_DRIVER(vidconsole) = { .per_device_auto_alloc_size = sizeof(struct vidconsole_priv), }; +#if CONFIG_IS_ENABLED(CMD_VIDCONSOLE) void vidconsole_position_cursor(struct udevice *dev, unsigned col, unsigned row) { struct vidconsole_priv *priv = dev_get_uclass_priv(dev); @@ -673,3 +674,4 @@ U_BOOT_CMD( "print string on video framebuffer", " " ); +#endif /* CONFIG_IS_ENABLED(CMD_VIDCONSOLE) */ -- cgit v1.1 From 0b12f76f7241cb22d4a41ab048b64c8c3a88199d Mon Sep 17 00:00:00 2001 From: Anatolij Gustschin Date: Tue, 26 May 2020 00:09:22 +0200 Subject: video: ipuv3: fix building with disabled panel driver Panel code might be disabled for some boards, make this driver code optional. Signed-off-by: Anatolij Gustschin --- drivers/video/imx/mxc_ipuv3_fb.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/video/imx/mxc_ipuv3_fb.c b/drivers/video/imx/mxc_ipuv3_fb.c index 4044473..cdef84a 100644 --- a/drivers/video/imx/mxc_ipuv3_fb.c +++ b/drivers/video/imx/mxc_ipuv3_fb.c @@ -645,7 +645,6 @@ static int ipuv3_video_probe(struct udevice *dev) #if defined(CONFIG_DISPLAY) struct udevice *disp_dev; #endif - struct udevice *panel_dev; u32 fb_start, fb_end; int ret; @@ -672,9 +671,13 @@ static int ipuv3_video_probe(struct udevice *dev) return ret; } #endif - ret = uclass_get_device(UCLASS_PANEL, 0, &panel_dev); - if (panel_dev) - panel_enable_backlight(panel_dev); + if (CONFIG_IS_ENABLED(PANEL)) { + struct udevice *panel_dev; + + ret = uclass_get_device(UCLASS_PANEL, 0, &panel_dev); + if (panel_dev) + panel_enable_backlight(panel_dev); + } uc_priv->xsize = gmode->xres; uc_priv->ysize = gmode->yres; -- cgit v1.1 From e26e520046a1b551f25acf3d7b6705a37c808deb Mon Sep 17 00:00:00 2001 From: Anatolij Gustschin Date: Tue, 26 May 2020 00:20:49 +0200 Subject: video: make backlight and panel drivers optional Not all boards use these drivers, so allow to disable them to fix building boards with U-Boot binary image size restrictions. Signed-off-by: Anatolij Gustschin Reviewed-by: Simon Glass --- drivers/video/Kconfig | 27 +++++++++++++++++++++++++-- drivers/video/Makefile | 5 +++-- 2 files changed, 28 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index d0e9563..aaea7ce 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -14,9 +14,17 @@ config DM_VIDEO option compiles in the video uclass and routes all LCD/video access through this. +config BACKLIGHT + bool "Enable panel backlight uclass support" + depends on DM_VIDEO + default y + help + This provides backlight uclass driver that enables basic panel + backlight support. + config BACKLIGHT_PWM bool "Generic PWM based Backlight Driver" - depends on DM_VIDEO && DM_PWM + depends on BACKLIGHT && DM_PWM default y help If you have a LCD backlight adjustable by PWM, say Y to enable @@ -27,7 +35,7 @@ config BACKLIGHT_PWM config BACKLIGHT_GPIO bool "Generic GPIO based Backlight Driver" - depends on DM_VIDEO + depends on BACKLIGHT help If you have a LCD backlight adjustable by GPIO, say Y to enable this driver. @@ -151,6 +159,21 @@ config NO_FB_CLEAR loads takes over the screen. This, for example, can be used to keep splash image on screen until grub graphical boot menu starts. +config PANEL + bool "Enable panel uclass support" + depends on DM_VIDEO + default y + help + This provides panel uclass driver that enables basic panel support. + +config SIMPLE_PANEL + bool "Enable simple panel support" + depends on PANEL + default y + help + This turns on a simple panel driver that enables a compatible + video panel. + source "drivers/video/fonts/Kconfig" config VIDCONSOLE_AS_LCD diff --git a/drivers/video/Makefile b/drivers/video/Makefile index df7119d..1dbd09a 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -4,17 +4,18 @@ # Wolfgang Denk, DENX Software Engineering, wd@denx.de. ifdef CONFIG_DM +obj-$(CONFIG_BACKLIGHT) += backlight-uclass.o obj-$(CONFIG_BACKLIGHT_GPIO) += backlight_gpio.o obj-$(CONFIG_BACKLIGHT_PWM) += pwm_backlight.o obj-$(CONFIG_CONSOLE_NORMAL) += console_normal.o obj-$(CONFIG_CONSOLE_ROTATION) += console_rotate.o obj-$(CONFIG_CONSOLE_TRUETYPE) += console_truetype.o fonts/ obj-$(CONFIG_DISPLAY) += display-uclass.o -obj-$(CONFIG_DM_VIDEO) += backlight-uclass.o obj-$(CONFIG_VIDEO_MIPI_DSI) += dsi-host-uclass.o -obj-$(CONFIG_DM_VIDEO) += panel-uclass.o simple_panel.o obj-$(CONFIG_DM_VIDEO) += video-uclass.o vidconsole-uclass.o obj-$(CONFIG_DM_VIDEO) += video_bmp.o +obj-$(CONFIG_PANEL) += panel-uclass.o +obj-$(CONFIG_SIMPLE_PANEL) += simple_panel.o endif obj-${CONFIG_EXYNOS_FB} += exynos/ -- cgit v1.1 From db755b36d2ee240cae30de9cccada8fe398b3eef Mon Sep 17 00:00:00 2001 From: Anatolij Gustschin Date: Mon, 25 May 2020 14:34:17 +0200 Subject: video: ipuv3: remove some useless code to reduce binary size To enable DM_VIDEO we must decrease binary size to fix build breakage for some boards, so drop not needed code. Also add !DM_VIDEO guards which can be later removed when last non DM users will be converted. Signed-off-by: Anatolij Gustschin --- drivers/video/imx/ipu_disp.c | 12 --------- drivers/video/imx/mxc_ipuv3_fb.c | 57 ++++++++++++++++------------------------ 2 files changed, 22 insertions(+), 47 deletions(-) (limited to 'drivers') diff --git a/drivers/video/imx/ipu_disp.c b/drivers/video/imx/ipu_disp.c index c2f00bf..4506989 100644 --- a/drivers/video/imx/ipu_disp.c +++ b/drivers/video/imx/ipu_disp.c @@ -1191,9 +1191,6 @@ int32_t ipu_disp_set_global_alpha(ipu_channel_t channel, unsigned char enable, else bg_chan = 0; - if (!g_ipu_clk_enabled) - clk_enable(g_ipu_clk); - if (bg_chan) { reg = __raw_readl(DP_COM_CONF()); __raw_writel(reg & ~DP_COM_CONF_GWSEL, DP_COM_CONF()); @@ -1217,9 +1214,6 @@ int32_t ipu_disp_set_global_alpha(ipu_channel_t channel, unsigned char enable, reg = __raw_readl(IPU_SRM_PRI2) | 0x8; __raw_writel(reg, IPU_SRM_PRI2); - if (!g_ipu_clk_enabled) - clk_disable(g_ipu_clk); - return 0; } @@ -1246,9 +1240,6 @@ int32_t ipu_disp_set_color_key(ipu_channel_t channel, unsigned char enable, (channel == MEM_BG_ASYNC1 || channel == MEM_FG_ASYNC1))) return -EINVAL; - if (!g_ipu_clk_enabled) - clk_enable(g_ipu_clk); - color_key_4rgb = 1; /* Transform color key from rgb to yuv if CSC is enabled */ if (((fg_csc_type == RGB2YUV) && (bg_csc_type == YUV2YUV)) || @@ -1286,8 +1277,5 @@ int32_t ipu_disp_set_color_key(ipu_channel_t channel, unsigned char enable, reg = __raw_readl(IPU_SRM_PRI2) | 0x8; __raw_writel(reg, IPU_SRM_PRI2); - if (!g_ipu_clk_enabled) - clk_disable(g_ipu_clk); - return 0; } diff --git a/drivers/video/imx/mxc_ipuv3_fb.c b/drivers/video/imx/mxc_ipuv3_fb.c index cdef84a..6787201 100644 --- a/drivers/video/imx/mxc_ipuv3_fb.c +++ b/drivers/video/imx/mxc_ipuv3_fb.c @@ -38,8 +38,10 @@ DECLARE_GLOBAL_DATA_PTR; static int mxcfb_map_video_memory(struct fb_info *fbi); static int mxcfb_unmap_video_memory(struct fb_info *fbi); +#if !CONFIG_IS_ENABLED(DM_VIDEO) /* graphics setup */ static GraphicDevice panel; +#endif static struct fb_videomode const *gmode; static uint8_t gdisp; static uint32_t gpixfmt; @@ -120,27 +122,6 @@ static uint32_t bpp_to_pixfmt(struct fb_info *fbi) return pixfmt; } -/* - * Set fixed framebuffer parameters based on variable settings. - * - * @param info framebuffer information pointer - */ -static int mxcfb_set_fix(struct fb_info *info) -{ - struct fb_fix_screeninfo *fix = &info->fix; - struct fb_var_screeninfo *var = &info->var; - - fix->line_length = var->xres_virtual * var->bits_per_pixel / 8; - - fix->type = FB_TYPE_PACKED_PIXELS; - fix->accel = FB_ACCEL_NONE; - fix->visual = FB_VISUAL_TRUECOLOR; - fix->xpanstep = 1; - fix->ypanstep = 1; - - return 0; -} - static int setup_disp_channel1(struct fb_info *fbi) { ipu_channel_params_t params; @@ -226,7 +207,6 @@ static int mxcfb_set_par(struct fb_info *fbi) ipu_disable_channel(mxc_fbi->ipu_ch); ipu_uninit_channel(mxc_fbi->ipu_ch); - mxcfb_set_fix(fbi); mem_len = fbi->var.yres_virtual * fbi->fix.line_length; if (!fbi->fix.smem_start || (mem_len > fbi->fix.smem_len)) { @@ -499,6 +479,8 @@ static struct fb_info *mxcfb_init_fbinfo(void) return fbi; } +extern struct clk *g_ipu_clk; + /* * Probe routine for the framebuffer driver. It is called during the * driver binding process. The following functions are performed in @@ -512,16 +494,14 @@ static int mxcfb_probe(u32 interface_pix_fmt, uint8_t disp, { struct fb_info *fbi; struct mxcfb_info *mxcfbi; - int ret = 0; /* * Initialize FB structures */ fbi = mxcfb_init_fbinfo(); - if (!fbi) { - ret = -ENOMEM; - goto err0; - } + if (!fbi) + return -ENOMEM; + mxcfbi = (struct mxcfb_info *)fbi->par; if (!g_dp_in_use) { @@ -534,9 +514,11 @@ static int mxcfb_probe(u32 interface_pix_fmt, uint8_t disp, mxcfbi->ipu_di = disp; + if (!ipu_clk_enabled()) + clk_enable(g_ipu_clk); + ipu_disp_set_global_alpha(mxcfbi->ipu_ch, 1, 0x80); ipu_disp_set_color_key(mxcfbi->ipu_ch, 0, 0); - strcpy(fbi->fix.id, "DISP3 BG"); g_dp_in_use = 1; @@ -547,7 +529,8 @@ static int mxcfb_probe(u32 interface_pix_fmt, uint8_t disp, mxcfbi->ipu_di_pix_fmt = interface_pix_fmt; fb_videomode_to_var(&fbi->var, mode); fbi->var.bits_per_pixel = 16; - fbi->fix.line_length = fbi->var.xres * (fbi->var.bits_per_pixel / 8); + fbi->fix.line_length = fbi->var.xres_virtual * + (fbi->var.bits_per_pixel / 8); fbi->fix.smem_len = fbi->var.yres_virtual * fbi->fix.line_length; mxcfb_check_var(&fbi->var, fbi); @@ -555,14 +538,13 @@ static int mxcfb_probe(u32 interface_pix_fmt, uint8_t disp, /* Default Y virtual size is 2x panel size */ fbi->var.yres_virtual = fbi->var.yres * 2; - mxcfb_set_fix(fbi); - /* allocate fb first */ if (mxcfb_map_video_memory(fbi) < 0) return -ENOMEM; mxcfb_set_par(fbi); +#if !CONFIG_IS_ENABLED(DM_VIDEO) panel.winSizeX = mode->xres; panel.winSizeY = mode->yres; panel.plnSizeX = mode->xres; @@ -573,13 +555,12 @@ static int mxcfb_probe(u32 interface_pix_fmt, uint8_t disp, panel.gdfBytesPP = 2; panel.gdfIndex = GDF_16BIT_565RGB; - +#endif +#ifdef DEBUG ipu_dump_registers(); +#endif return 0; - -err0: - return ret; } void ipuv3_fb_shutdown(void) @@ -604,6 +585,7 @@ void ipuv3_fb_shutdown(void) } } +#if !CONFIG_IS_ENABLED(DM_VIDEO) void *video_hw_init(void) { int ret; @@ -618,6 +600,7 @@ void *video_hw_init(void) return (void *)&panel; } +#endif int ipuv3_fb_init(struct fb_videomode const *mode, uint8_t disp, @@ -710,8 +693,12 @@ static int ipuv3_video_bind(struct udevice *dev) } static const struct udevice_id ipuv3_video_ids[] = { +#ifdef CONFIG_ARCH_MX6 { .compatible = "fsl,imx6q-ipu" }, +#endif +#ifdef CONFIG_ARCH_MX5 { .compatible = "fsl,imx53-ipu" }, +#endif { } }; -- cgit v1.1 From 22b897a12323364c584b1ff31fe9f5250e0d3481 Mon Sep 17 00:00:00 2001 From: Anatolij Gustschin Date: Sat, 23 May 2020 17:11:20 +0200 Subject: video: extend stdout video console work-around for 'vga' cfb_console driver uses 'vga' console name and we still have board environments defining this name. Re-use existing DM_VIDEO work- around for console name to support 'vga' name in stdout environment. Signed-off-by: Anatolij Gustschin Tested-by: Soeren Moch Reviewed-by: Simon Glass Reviewed-by: Tom Rini --- drivers/video/Kconfig | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index aaea7ce..01e8dbf 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -177,14 +177,16 @@ config SIMPLE_PANEL source "drivers/video/fonts/Kconfig" config VIDCONSOLE_AS_LCD - bool "Use 'vidconsole' when 'lcd' is seen in stdout" + string "Use 'vidconsole' when string defined here is seen in stdout" depends on DM_VIDEO - help - This is a work-around for boards which have 'lcd' in their stdout - environment variable, but have moved to use driver model for video. - In this case the console will no-longer work. While it is possible - to update the environment, the breakage may be confusing for users. - This option will be removed around the end of 2016. + default "lcd" if LCD || TEGRA_COMMON + default "vga" if !LCD + help + This is a work-around for boards which have 'lcd' or 'vga' in their + stdout environment variable, but have moved to use driver model for + video. In this case the console will no-longer work. While it is + possible to update the environment, the breakage may be confusing for + users. This option will be removed around the end of 2020. config VIDEO_COREBOOT bool "Enable coreboot framebuffer driver support" -- cgit v1.1 From 0a5be6c5fd031fbdcd499500ad02608008329b29 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sat, 23 May 2020 13:06:48 +0200 Subject: net: eepro100: Remove EEPRO100_SROM_WRITE This code is never enabled, last board that used it was ELPPC which was removed some 5 years ago, so just remove this code altogether. Signed-off-by: Marek Vasut --- drivers/net/eepro100.c | 87 -------------------------------------------------- 1 file changed, 87 deletions(-) (limited to 'drivers') diff --git a/drivers/net/eepro100.c b/drivers/net/eepro100.c index e186ab4..62a0dc7 100644 --- a/drivers/net/eepro100.c +++ b/drivers/net/eepro100.c @@ -781,93 +781,6 @@ static int read_eeprom (struct eth_device *dev, int location, int addr_len) return retval; } -#ifdef CONFIG_EEPRO100_SROM_WRITE -int eepro100_write_eeprom (struct eth_device* dev, int location, int addr_len, unsigned short data) -{ - unsigned short dataval; - int enable_cmd = 0x3f | EE_EWENB_CMD; - int write_cmd = location | EE_WRITE_CMD; - int i; - unsigned long datalong, tmplong; - - OUTW(dev, EE_ENB & ~EE_CS, SCBeeprom); - udelay(1); - OUTW(dev, EE_ENB, SCBeeprom); - - /* Shift the enable command bits out. */ - for (i = (addr_len+EE_CMD_BITS-1); i >= 0; i--) - { - dataval = (enable_cmd & (1 << i)) ? EE_DATA_WRITE : 0; - OUTW(dev, EE_ENB | dataval, SCBeeprom); - udelay(1); - OUTW(dev, EE_ENB | dataval | EE_SHIFT_CLK, SCBeeprom); - udelay(1); - } - - OUTW(dev, EE_ENB, SCBeeprom); - udelay(1); - OUTW(dev, EE_ENB & ~EE_CS, SCBeeprom); - udelay(1); - OUTW(dev, EE_ENB, SCBeeprom); - - - /* Shift the write command bits out. */ - for (i = (addr_len+EE_CMD_BITS-1); i >= 0; i--) - { - dataval = (write_cmd & (1 << i)) ? EE_DATA_WRITE : 0; - OUTW(dev, EE_ENB | dataval, SCBeeprom); - udelay(1); - OUTW(dev, EE_ENB | dataval | EE_SHIFT_CLK, SCBeeprom); - udelay(1); - } - - /* Write the data */ - datalong= (unsigned long) ((((data) & 0x00ff) << 8) | ( (data) >> 8)); - - for (i = 0; i< EE_DATA_BITS; i++) - { - /* Extract and move data bit to bit DI */ - dataval = ((datalong & 0x8000)>>13) ? EE_DATA_WRITE : 0; - - OUTW(dev, EE_ENB | dataval, SCBeeprom); - udelay(1); - OUTW(dev, EE_ENB | dataval | EE_SHIFT_CLK, SCBeeprom); - udelay(1); - OUTW(dev, EE_ENB | dataval, SCBeeprom); - udelay(1); - - datalong = datalong << 1; /* Adjust significant data bit*/ - } - - /* Finish up command (toggle CS) */ - OUTW(dev, EE_ENB & ~EE_CS, SCBeeprom); - udelay(1); /* delay for more than 250 ns */ - OUTW(dev, EE_ENB, SCBeeprom); - - /* Wait for programming ready (D0 = 1) */ - tmplong = 10; - do - { - dataval = INW(dev, SCBeeprom); - if (dataval & EE_DATA_READ) - break; - udelay(10000); - } - while (-- tmplong); - - if (tmplong == 0) - { - printf ("Write i82559 eeprom timed out (100 ms waiting for data ready.\n"); - return -1; - } - - /* Terminate the EEPROM access. */ - OUTW(dev, EE_ENB & ~EE_CS, SCBeeprom); - - return 0; -} -#endif - static void init_rx_ring (struct eth_device *dev) { int i; -- cgit v1.1 From aba283d838bf5e5c227f2b779feba583c3964c90 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sat, 23 May 2020 12:49:16 +0200 Subject: net: eepro100: Clean up comments Clean the comments up to they trigger fewer checkpatch warnings, no functional change. Signed-off-by: Marek Vasut --- drivers/net/eepro100.c | 100 ++++++++++++++++++------------------------------- 1 file changed, 36 insertions(+), 64 deletions(-) (limited to 'drivers') diff --git a/drivers/net/eepro100.c b/drivers/net/eepro100.c index 62a0dc7..503c44a 100644 --- a/drivers/net/eepro100.c +++ b/drivers/net/eepro100.c @@ -15,8 +15,7 @@ #undef DEBUG - /* Ethernet chip registers. - */ +/* Ethernet chip registers. */ #define SCBStatus 0 /* Rx/Command Unit Status *Word* */ #define SCBIntAckByte 1 /* Rx/Command Unit STAT/ACK byte */ #define SCBCmd 2 /* Rx/Command Unit Command *Word* */ @@ -30,8 +29,7 @@ #define SCBGenControl 28 /* 82559 General Control Register */ #define SCBGenStatus 29 /* 82559 General Status register */ - /* 82559 SCB status word defnitions - */ +/* 82559 SCB status word defnitions */ #define SCB_STATUS_CX 0x8000 /* CU finished command (transmit) */ #define SCB_STATUS_FR 0x4000 /* frame received */ #define SCB_STATUS_CNA 0x2000 /* CU left active state */ @@ -45,8 +43,7 @@ #define SCB_INTACK_TX (SCB_STATUS_CX | SCB_STATUS_CNA) #define SCB_INTACK_RX (SCB_STATUS_FR | SCB_STATUS_RNR) - /* System control block commands - */ +/* System control block commands */ /* CU Commands */ #define CU_NOP 0x0000 #define CU_START 0x0010 @@ -81,16 +78,14 @@ #define RU_STATUS_NO_RBDS_NORES ((2<<2)|(8<<2)) #define RU_STATUS_NO_RBDS_READY ((4<<2)|(8<<2)) - /* 82559 Port interface commands. - */ +/* 82559 Port interface commands. */ #define I82559_RESET 0x00000000 /* Software reset */ #define I82559_SELFTEST 0x00000001 /* 82559 Selftest command */ #define I82559_SELECTIVE_RESET 0x00000002 #define I82559_DUMP 0x00000003 #define I82559_DUMP_WAKEUP 0x00000007 - /* 82559 Eeprom interface. - */ +/* 82559 Eeprom interface. */ #define EE_SHIFT_CLK 0x01 /* EEPROM shift clock. */ #define EE_CS 0x02 /* EEPROM chip select. */ #define EE_DATA_WRITE 0x04 /* EEPROM chip data in. */ @@ -101,15 +96,13 @@ #define EE_CMD_BITS 3 #define EE_DATA_BITS 16 - /* The EEPROM commands include the alway-set leading bit. - */ +/* The EEPROM commands include the alway-set leading bit. */ #define EE_EWENB_CMD (4 << addr_len) #define EE_WRITE_CMD (5 << addr_len) #define EE_READ_CMD (6 << addr_len) #define EE_ERASE_CMD (7 << addr_len) - /* Receive frame descriptors. - */ +/* Receive frame descriptors. */ struct RxFD { volatile u16 status; volatile u16 control; @@ -143,8 +136,7 @@ struct RxFD { #define RFD_RX_IA_MATCH 0x0002 /* individual address does not match */ #define RFD_RX_TCO 0x0001 /* TCO indication */ - /* Transmit frame descriptors - */ +/* Transmit frame descriptors */ struct TxFD { /* Transmit frame descriptor set. */ volatile u16 status; volatile u16 command; @@ -152,9 +144,9 @@ struct TxFD { /* Transmit frame descriptor set. */ volatile u32 tx_desc_addr; /* Always points to the tx_buf_addr element. */ volatile s32 count; - volatile u32 tx_buf_addr0; /* void *, frame to be transmitted. */ + volatile u32 tx_buf_addr0; /* void *, frame to be transmitted. */ volatile s32 tx_buf_size0; /* Length of Tx frame. */ - volatile u32 tx_buf_addr1; /* void *, frame to be transmitted. */ + volatile u32 tx_buf_addr1; /* void *, frame to be transmitted. */ volatile s32 tx_buf_size1; /* Length of Tx frame. */ }; @@ -168,12 +160,11 @@ struct TxFD { /* Transmit frame descriptor set. */ #define TxCB_COUNT_MASK 0x3fff #define TxCB_COUNT_EOF 0x8000 - /* The Speedo3 Rx and Tx frame/buffer descriptors. - */ +/* The Speedo3 Rx and Tx frame/buffer descriptors. */ struct descriptor { /* A generic descriptor. */ volatile u16 status; volatile u16 command; - volatile u32 link; /* struct descriptor * */ + volatile u32 link; /* struct descriptor * */ unsigned char params[0]; }; @@ -187,15 +178,14 @@ struct descriptor { /* A generic descriptor. */ #define CONFIG_SYS_STATUS_C 0x8000 #define CONFIG_SYS_STATUS_OK 0x2000 - /* Misc. - */ +/* Misc. */ #define NUM_RX_DESC PKTBUFSRX -#define NUM_TX_DESC 1 /* Number of TX descriptors */ +#define NUM_TX_DESC 1 /* Number of TX descriptors */ #define TOUT_LOOP 1000000 -static struct RxFD rx_ring[NUM_RX_DESC]; /* RX descriptor ring */ -static struct TxFD tx_ring[NUM_TX_DESC]; /* TX descriptor ring */ +static struct RxFD rx_ring[NUM_RX_DESC]; /* RX descriptor ring */ +static struct TxFD tx_ring[NUM_TX_DESC]; /* TX descriptor ring */ static int rx_next; /* RX descriptor ring pointer */ static int tx_next; /* TX descriptor ring pointer */ static int tx_threshold; @@ -293,7 +283,8 @@ static int set_phyreg (struct eth_device *dev, unsigned char addr, return 0; } -/* Check if given phyaddr is valid, i.e. there is a PHY connected. +/* + * Check if given phyaddr is valid, i.e. there is a PHY connected. * Do this by checking model value field from ID2 register. */ static struct eth_device* verify_phyaddr (const char *devname, @@ -363,8 +354,7 @@ static int eepro100_miiphy_write(struct mii_dev *bus, int addr, int devad, #endif -/* Wait for the chip get the command. -*/ +/* Wait for the chip get the command. */ static int wait_for_eepro100 (struct eth_device *dev) { int i; @@ -394,8 +384,7 @@ int eepro100_initialize (bd_t * bis) int idx = 0; while (1) { - /* Find PCI device - */ + /* Find PCI device */ if ((devno = pci_find_devices (supported, idx++)) < 0) { break; } @@ -412,8 +401,7 @@ int eepro100_initialize (bd_t * bis) PCI_COMMAND, PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); - /* Check if I/O accesses and Bus Mastering are enabled. - */ + /* Check if I/O accesses and Bus Mastering are enabled. */ pci_read_config_dword (devno, PCI_COMMAND, &status); if (!(status & PCI_COMMAND_MEMORY)) { printf ("Error: Can not enable MEM access.\n"); @@ -459,8 +447,7 @@ int eepro100_initialize (bd_t * bis) card_number++; - /* Set the latency timer for value. - */ + /* Set the latency timer for value. */ pci_write_config_byte (devno, PCI_LATENCY_TIMER, 0x20); udelay(10 * 1000); @@ -478,8 +465,7 @@ static int eepro100_init (struct eth_device *dev, bd_t * bis) int tx_cur; struct descriptor *ias_cmd, *cfg_cmd; - /* Reset the ethernet controller - */ + /* Reset the ethernet controller */ OUTL (dev, I82559_SELECTIVE_RESET, SCBPort); udelay(20); @@ -500,13 +486,11 @@ static int eepro100_init (struct eth_device *dev, bd_t * bis) OUTL (dev, 0, SCBPointer); OUTW (dev, SCB_M | CU_ADDR_LOAD, SCBCmd); - /* Initialize Rx and Tx rings. - */ + /* Initialize Rx and Tx rings. */ init_rx_ring (dev); purge_tx_ring (dev); - /* Tell the adapter where the RX ring is located. - */ + /* Tell the adapter where the RX ring is located. */ if (!wait_for_eepro100 (dev)) { printf ("Error: Can not reset ethernet controller.\n"); goto Done; @@ -550,8 +534,7 @@ static int eepro100_init (struct eth_device *dev, bd_t * bis) goto Done; } - /* Send the Individual Address Setup frame - */ + /* Send the Individual Address Setup frame */ tx_cur = tx_next; tx_next = ((tx_next + 1) % NUM_TX_DESC); @@ -562,8 +545,7 @@ static int eepro100_init (struct eth_device *dev, bd_t * bis) memcpy (ias_cmd->params, dev->enetaddr, 6); - /* Tell the adapter where the TX ring is located. - */ + /* Tell the adapter where the TX ring is located. */ if (!wait_for_eepro100 (dev)) { printf ("Error: Can not reset ethernet controller.\n"); goto Done; @@ -626,8 +608,7 @@ static int eepro100_send(struct eth_device *dev, void *packet, int length) goto Done; } - /* Send the packet. - */ + /* Send the packet. */ OUTL (dev, phys_to_bus ((u32) & tx_ring[tx_cur]), SCBPointer); OUTW (dev, SCB_M | CU_START, SCBCmd); @@ -666,21 +647,16 @@ static int eepro100_recv (struct eth_device *dev) break; } - /* Valid frame status. - */ + /* Valid frame status. */ if ((status & RFD_STATUS_OK)) { - /* A valid frame received. - */ + /* A valid frame received. */ length = le32_to_cpu (rx_ring[rx_next].count) & 0x3fff; - /* Pass the packet up to the protocol - * layers. - */ + /* Pass the packet up to the protocol layers. */ net_process_received_packet((u8 *)rx_ring[rx_next].data, length); } else { - /* There was an error. - */ + /* There was an error. */ printf ("RX error status = 0x%08X\n", status); } @@ -691,8 +667,7 @@ static int eepro100_recv (struct eth_device *dev) rx_prev = (rx_next + NUM_RX_DESC - 1) % NUM_RX_DESC; rx_ring[rx_prev].control = 0; - /* Update entry information. - */ + /* Update entry information. */ rx_next = (rx_next + 1) % NUM_RX_DESC; } @@ -700,8 +675,7 @@ static int eepro100_recv (struct eth_device *dev) printf ("%s: Receiver is not ready, restart it !\n", dev->name); - /* Reinitialize Rx ring. - */ + /* Reinitialize Rx ring. */ init_rx_ring (dev); if (!wait_for_eepro100 (dev)) { @@ -719,8 +693,7 @@ static int eepro100_recv (struct eth_device *dev) static void eepro100_halt (struct eth_device *dev) { - /* Reset the ethernet controller - */ + /* Reset the ethernet controller */ OUTL (dev, I82559_SELECTIVE_RESET, SCBPort); udelay(20); @@ -745,8 +718,7 @@ static void eepro100_halt (struct eth_device *dev) return; } - /* SROM Read. - */ +/* SROM Read. */ static int read_eeprom (struct eth_device *dev, int location, int addr_len) { unsigned short retval = 0; -- cgit v1.1 From e5352c6bbe1606b4e2e9845dba54a83af14f3da0 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sat, 23 May 2020 13:11:48 +0200 Subject: net: eepro100: Use plain debug() Convert all the ifdef DEBUG to plain debug(), no functional change. Signed-off-by: Marek Vasut --- drivers/net/eepro100.c | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/net/eepro100.c b/drivers/net/eepro100.c index 503c44a..dd90238 100644 --- a/drivers/net/eepro100.c +++ b/drivers/net/eepro100.c @@ -13,8 +13,6 @@ #include #include -#undef DEBUG - /* Ethernet chip registers. */ #define SCBStatus 0 /* Rx/Command Unit Status *Word* */ #define SCBIntAckByte 1 /* Rx/Command Unit STAT/ACK byte */ @@ -392,10 +390,8 @@ int eepro100_initialize (bd_t * bis) pci_read_config_dword (devno, PCI_BASE_ADDRESS_0, &iobase); iobase &= ~0xf; -#ifdef DEBUG - printf ("eepro100: Intel i82559 PCI EtherExpressPro @0x%x\n", - iobase); -#endif + debug("eepro100: Intel i82559 PCI EtherExpressPro @0x%x\n", + iobase); pci_write_config_dword (devno, PCI_COMMAND, @@ -810,10 +806,7 @@ static void read_hw_addr (struct eth_device *dev, bd_t * bis) if (sum != 0xBABA) { memset (dev->enetaddr, 0, ETH_ALEN); -#ifdef DEBUG - printf ("%s: Invalid EEPROM checksum %#4.4x, " - "check settings before activating this device!\n", - dev->name, sum); -#endif + debug("%s: Invalid EEPROM checksum %#4.4x, check settings before activating this device!\n", + dev->name, sum); } } -- cgit v1.1 From db9f1818bfc79fd96301b8b4eae1db8b136e7570 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sat, 23 May 2020 13:17:03 +0200 Subject: net: eepro100: Fix spacing This is automated cleanup via checkpatch, no functional change. ./scripts/checkpatch.pl --show-types -f drivers/net/eepro100.c ./scripts/checkpatch.pl --types SPACING -f --fix --fix-inplace drivers/net/eepro100.c Signed-off-by: Marek Vasut --- drivers/net/eepro100.c | 278 ++++++++++++++++++++++++------------------------- 1 file changed, 139 insertions(+), 139 deletions(-) (limited to 'drivers') diff --git a/drivers/net/eepro100.c b/drivers/net/eepro100.c index dd90238..1b6d537 100644 --- a/drivers/net/eepro100.c +++ b/drivers/net/eepro100.c @@ -68,13 +68,13 @@ #define CU_STATUS_MASK 0x00C0 #define RU_STATUS_MASK 0x003C -#define RU_STATUS_IDLE (0<<2) -#define RU_STATUS_SUS (1<<2) -#define RU_STATUS_NORES (2<<2) -#define RU_STATUS_READY (4<<2) -#define RU_STATUS_NO_RBDS_SUS ((1<<2)|(8<<2)) -#define RU_STATUS_NO_RBDS_NORES ((2<<2)|(8<<2)) -#define RU_STATUS_NO_RBDS_READY ((4<<2)|(8<<2)) +#define RU_STATUS_IDLE (0 << 2) +#define RU_STATUS_SUS (1 << 2) +#define RU_STATUS_NORES (2 << 2) +#define RU_STATUS_READY (4 << 2) +#define RU_STATUS_NO_RBDS_SUS ((1 << 2) | (8 << 2)) +#define RU_STATUS_NO_RBDS_NORES ((2 << 2) | (8 << 2)) +#define RU_STATUS_NO_RBDS_READY ((4 << 2) | (8 << 2)) /* 82559 Port interface commands. */ #define I82559_RESET 0x00000000 /* Software reset */ @@ -200,15 +200,15 @@ static const char i82558_config_cmd[] = { 0x31, 0x05, }; -static void init_rx_ring (struct eth_device *dev); -static void purge_tx_ring (struct eth_device *dev); +static void init_rx_ring(struct eth_device *dev); +static void purge_tx_ring(struct eth_device *dev); -static void read_hw_addr (struct eth_device *dev, bd_t * bis); +static void read_hw_addr(struct eth_device *dev, bd_t * bis); -static int eepro100_init (struct eth_device *dev, bd_t * bis); +static int eepro100_init(struct eth_device *dev, bd_t * bis); static int eepro100_send(struct eth_device *dev, void *packet, int length); -static int eepro100_recv (struct eth_device *dev); -static void eepro100_halt (struct eth_device *dev); +static int eepro100_recv(struct eth_device *dev); +static void eepro100_halt(struct eth_device *dev); #if defined(CONFIG_E500) #define bus_to_phys(a) (a) @@ -218,28 +218,28 @@ static void eepro100_halt (struct eth_device *dev); #define phys_to_bus(a) pci_phys_to_mem((pci_dev_t)dev->priv, a) #endif -static inline int INW (struct eth_device *dev, u_long addr) +static inline int INW(struct eth_device *dev, u_long addr) { return le16_to_cpu(*(volatile u16 *)(addr + (u_long)dev->iobase)); } -static inline void OUTW (struct eth_device *dev, int command, u_long addr) +static inline void OUTW(struct eth_device *dev, int command, u_long addr) { *(volatile u16 *)((addr + (u_long)dev->iobase)) = cpu_to_le16(command); } -static inline void OUTL (struct eth_device *dev, int command, u_long addr) +static inline void OUTL(struct eth_device *dev, int command, u_long addr) { *(volatile u32 *)((addr + (u_long)dev->iobase)) = cpu_to_le32(command); } #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) -static inline int INL (struct eth_device *dev, u_long addr) +static inline int INL(struct eth_device *dev, u_long addr) { return le32_to_cpu(*(volatile u32 *)(addr + (u_long)dev->iobase)); } -static int get_phyreg (struct eth_device *dev, unsigned char addr, +static int get_phyreg(struct eth_device *dev, unsigned char addr, unsigned char reg, unsigned short *value) { int cmd; @@ -247,22 +247,22 @@ static int get_phyreg (struct eth_device *dev, unsigned char addr, /* read requested data */ cmd = (2 << 26) | ((addr & 0x1f) << 21) | ((reg & 0x1f) << 16); - OUTL (dev, cmd, SCBCtrlMDI); + OUTL(dev, cmd, SCBCtrlMDI); do { udelay(1000); - cmd = INL (dev, SCBCtrlMDI); + cmd = INL(dev, SCBCtrlMDI); } while (!(cmd & (1 << 28)) && (--timeout)); if (timeout == 0) return -1; - *value = (unsigned short) (cmd & 0xffff); + *value = (unsigned short)(cmd & 0xffff); return 0; } -static int set_phyreg (struct eth_device *dev, unsigned char addr, +static int set_phyreg(struct eth_device *dev, unsigned char addr, unsigned char reg, unsigned short value) { int cmd; @@ -270,9 +270,9 @@ static int set_phyreg (struct eth_device *dev, unsigned char addr, /* write requested data */ cmd = (1 << 26) | ((addr & 0x1f) << 21) | ((reg & 0x1f) << 16); - OUTL (dev, cmd | value, SCBCtrlMDI); + OUTL(dev, cmd | value, SCBCtrlMDI); - while (!(INL (dev, SCBCtrlMDI) & (1 << 28)) && (--timeout)) + while (!(INL(dev, SCBCtrlMDI) & (1 << 28)) && (--timeout)) udelay(1000); if (timeout == 0) @@ -285,7 +285,7 @@ static int set_phyreg (struct eth_device *dev, unsigned char addr, * Check if given phyaddr is valid, i.e. there is a PHY connected. * Do this by checking model value field from ID2 register. */ -static struct eth_device* verify_phyaddr (const char *devname, +static struct eth_device* verify_phyaddr(const char *devname, unsigned char addr) { struct eth_device *dev; @@ -353,11 +353,11 @@ static int eepro100_miiphy_write(struct mii_dev *bus, int addr, int devad, #endif /* Wait for the chip get the command. */ -static int wait_for_eepro100 (struct eth_device *dev) +static int wait_for_eepro100(struct eth_device *dev) { int i; - for (i = 0; INW (dev, SCBCmd) & (CU_CMD_MASK | RU_CMD_MASK); i++) { + for (i = 0; INW(dev, SCBCmd) & (CU_CMD_MASK | RU_CMD_MASK); i++) { if (i >= TOUT_LOOP) { return 0; } @@ -373,7 +373,7 @@ static struct pci_device_id supported[] = { {} }; -int eepro100_initialize (bd_t * bis) +int eepro100_initialize(bd_t * bis) { pci_dev_t devno; int card_number = 0; @@ -383,50 +383,50 @@ int eepro100_initialize (bd_t * bis) while (1) { /* Find PCI device */ - if ((devno = pci_find_devices (supported, idx++)) < 0) { + if ((devno = pci_find_devices(supported, idx++)) < 0) { break; } - pci_read_config_dword (devno, PCI_BASE_ADDRESS_0, &iobase); + pci_read_config_dword(devno, PCI_BASE_ADDRESS_0, &iobase); iobase &= ~0xf; debug("eepro100: Intel i82559 PCI EtherExpressPro @0x%x\n", iobase); - pci_write_config_dword (devno, + pci_write_config_dword(devno, PCI_COMMAND, PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); /* Check if I/O accesses and Bus Mastering are enabled. */ - pci_read_config_dword (devno, PCI_COMMAND, &status); + pci_read_config_dword(devno, PCI_COMMAND, &status); if (!(status & PCI_COMMAND_MEMORY)) { - printf ("Error: Can not enable MEM access.\n"); + printf("Error: Can not enable MEM access.\n"); continue; } if (!(status & PCI_COMMAND_MASTER)) { - printf ("Error: Can not enable Bus Mastering.\n"); + printf("Error: Can not enable Bus Mastering.\n"); continue; } - dev = (struct eth_device *) malloc (sizeof *dev); + dev = (struct eth_device *)malloc(sizeof *dev); if (!dev) { printf("eepro100: Can not allocate memory\n"); break; } memset(dev, 0, sizeof(*dev)); - sprintf (dev->name, "i82559#%d", card_number); - dev->priv = (void *) devno; /* this have to come before bus_to_phys() */ - dev->iobase = bus_to_phys (iobase); + sprintf(dev->name, "i82559#%d", card_number); + dev->priv = (void *)devno; /* this have to come before bus_to_phys() */ + dev->iobase = bus_to_phys(iobase); dev->init = eepro100_init; dev->halt = eepro100_halt; dev->send = eepro100_send; dev->recv = eepro100_recv; - eth_register (dev); + eth_register(dev); -#if defined (CONFIG_MII) || defined(CONFIG_CMD_MII) +#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) /* register mii command access routines */ int retval; struct mii_dev *mdiodev = mdio_alloc(); @@ -444,89 +444,89 @@ int eepro100_initialize (bd_t * bis) card_number++; /* Set the latency timer for value. */ - pci_write_config_byte (devno, PCI_LATENCY_TIMER, 0x20); + pci_write_config_byte(devno, PCI_LATENCY_TIMER, 0x20); udelay(10 * 1000); - read_hw_addr (dev, bis); + read_hw_addr(dev, bis); } return card_number; } -static int eepro100_init (struct eth_device *dev, bd_t * bis) +static int eepro100_init(struct eth_device *dev, bd_t * bis) { int i, status = -1; int tx_cur; struct descriptor *ias_cmd, *cfg_cmd; /* Reset the ethernet controller */ - OUTL (dev, I82559_SELECTIVE_RESET, SCBPort); + OUTL(dev, I82559_SELECTIVE_RESET, SCBPort); udelay(20); - OUTL (dev, I82559_RESET, SCBPort); + OUTL(dev, I82559_RESET, SCBPort); udelay(20); - if (!wait_for_eepro100 (dev)) { - printf ("Error: Can not reset ethernet controller.\n"); + if (!wait_for_eepro100(dev)) { + printf("Error: Can not reset ethernet controller.\n"); goto Done; } - OUTL (dev, 0, SCBPointer); - OUTW (dev, SCB_M | RUC_ADDR_LOAD, SCBCmd); + OUTL(dev, 0, SCBPointer); + OUTW(dev, SCB_M | RUC_ADDR_LOAD, SCBCmd); - if (!wait_for_eepro100 (dev)) { - printf ("Error: Can not reset ethernet controller.\n"); + if (!wait_for_eepro100(dev)) { + printf("Error: Can not reset ethernet controller.\n"); goto Done; } - OUTL (dev, 0, SCBPointer); - OUTW (dev, SCB_M | CU_ADDR_LOAD, SCBCmd); + OUTL(dev, 0, SCBPointer); + OUTW(dev, SCB_M | CU_ADDR_LOAD, SCBCmd); /* Initialize Rx and Tx rings. */ - init_rx_ring (dev); - purge_tx_ring (dev); + init_rx_ring(dev); + purge_tx_ring(dev); /* Tell the adapter where the RX ring is located. */ - if (!wait_for_eepro100 (dev)) { - printf ("Error: Can not reset ethernet controller.\n"); + if (!wait_for_eepro100(dev)) { + printf("Error: Can not reset ethernet controller.\n"); goto Done; } - OUTL (dev, phys_to_bus ((u32) & rx_ring[rx_next]), SCBPointer); - OUTW (dev, SCB_M | RUC_START, SCBCmd); + OUTL(dev, phys_to_bus((u32)&rx_ring[rx_next]), SCBPointer); + OUTW(dev, SCB_M | RUC_START, SCBCmd); /* Send the Configure frame */ tx_cur = tx_next; tx_next = ((tx_next + 1) % NUM_TX_DESC); - cfg_cmd = (struct descriptor *) &tx_ring[tx_cur]; + cfg_cmd = (struct descriptor *)&tx_ring[tx_cur]; cfg_cmd->command = cpu_to_le16 ((CONFIG_SYS_CMD_SUSPEND | CONFIG_SYS_CMD_CONFIGURE)); cfg_cmd->status = 0; - cfg_cmd->link = cpu_to_le32 (phys_to_bus ((u32) & tx_ring[tx_next])); + cfg_cmd->link = cpu_to_le32 (phys_to_bus((u32)&tx_ring[tx_next])); - memcpy (cfg_cmd->params, i82558_config_cmd, - sizeof (i82558_config_cmd)); + memcpy(cfg_cmd->params, i82558_config_cmd, + sizeof(i82558_config_cmd)); - if (!wait_for_eepro100 (dev)) { - printf ("Error---CONFIG_SYS_CMD_CONFIGURE: Can not reset ethernet controller.\n"); + if (!wait_for_eepro100(dev)) { + printf("Error---CONFIG_SYS_CMD_CONFIGURE: Can not reset ethernet controller.\n"); goto Done; } - OUTL (dev, phys_to_bus ((u32) & tx_ring[tx_cur]), SCBPointer); - OUTW (dev, SCB_M | CU_START, SCBCmd); + OUTL(dev, phys_to_bus((u32)&tx_ring[tx_cur]), SCBPointer); + OUTW(dev, SCB_M | CU_START, SCBCmd); for (i = 0; - !(le16_to_cpu (tx_ring[tx_cur].status) & CONFIG_SYS_STATUS_C); + !(le16_to_cpu(tx_ring[tx_cur].status) & CONFIG_SYS_STATUS_C); i++) { if (i >= TOUT_LOOP) { - printf ("%s: Tx error buffer not ready\n", dev->name); + printf("%s: Tx error buffer not ready\n", dev->name); goto Done; } } - if (!(le16_to_cpu (tx_ring[tx_cur].status) & CONFIG_SYS_STATUS_OK)) { - printf ("TX error status = 0x%08X\n", - le16_to_cpu (tx_ring[tx_cur].status)); + if (!(le16_to_cpu(tx_ring[tx_cur].status) & CONFIG_SYS_STATUS_OK)) { + printf("TX error status = 0x%08X\n", + le16_to_cpu(tx_ring[tx_cur].status)); goto Done; } @@ -534,34 +534,34 @@ static int eepro100_init (struct eth_device *dev, bd_t * bis) tx_cur = tx_next; tx_next = ((tx_next + 1) % NUM_TX_DESC); - ias_cmd = (struct descriptor *) &tx_ring[tx_cur]; + ias_cmd = (struct descriptor *)&tx_ring[tx_cur]; ias_cmd->command = cpu_to_le16 ((CONFIG_SYS_CMD_SUSPEND | CONFIG_SYS_CMD_IAS)); ias_cmd->status = 0; - ias_cmd->link = cpu_to_le32 (phys_to_bus ((u32) & tx_ring[tx_next])); + ias_cmd->link = cpu_to_le32 (phys_to_bus((u32)&tx_ring[tx_next])); - memcpy (ias_cmd->params, dev->enetaddr, 6); + memcpy(ias_cmd->params, dev->enetaddr, 6); /* Tell the adapter where the TX ring is located. */ - if (!wait_for_eepro100 (dev)) { - printf ("Error: Can not reset ethernet controller.\n"); + if (!wait_for_eepro100(dev)) { + printf("Error: Can not reset ethernet controller.\n"); goto Done; } - OUTL (dev, phys_to_bus ((u32) & tx_ring[tx_cur]), SCBPointer); - OUTW (dev, SCB_M | CU_START, SCBCmd); + OUTL(dev, phys_to_bus((u32)&tx_ring[tx_cur]), SCBPointer); + OUTW(dev, SCB_M | CU_START, SCBCmd); - for (i = 0; !(le16_to_cpu (tx_ring[tx_cur].status) & CONFIG_SYS_STATUS_C); + for (i = 0; !(le16_to_cpu(tx_ring[tx_cur].status) & CONFIG_SYS_STATUS_C); i++) { if (i >= TOUT_LOOP) { - printf ("%s: Tx error buffer not ready\n", + printf("%s: Tx error buffer not ready\n", dev->name); goto Done; } } - if (!(le16_to_cpu (tx_ring[tx_cur].status) & CONFIG_SYS_STATUS_OK)) { - printf ("TX error status = 0x%08X\n", - le16_to_cpu (tx_ring[tx_cur].status)); + if (!(le16_to_cpu(tx_ring[tx_cur].status) & CONFIG_SYS_STATUS_OK)) { + printf("TX error status = 0x%08X\n", + le16_to_cpu(tx_ring[tx_cur].status)); goto Done; } @@ -577,48 +577,48 @@ static int eepro100_send(struct eth_device *dev, void *packet, int length) int tx_cur; if (length <= 0) { - printf ("%s: bad packet size: %d\n", dev->name, length); + printf("%s: bad packet size: %d\n", dev->name, length); goto Done; } tx_cur = tx_next; tx_next = (tx_next + 1) % NUM_TX_DESC; - tx_ring[tx_cur].command = cpu_to_le16 ( TxCB_CMD_TRANSMIT | + tx_ring[tx_cur].command = cpu_to_le16 (TxCB_CMD_TRANSMIT | TxCB_CMD_SF | TxCB_CMD_S | - TxCB_CMD_EL ); + TxCB_CMD_EL); tx_ring[tx_cur].status = 0; tx_ring[tx_cur].count = cpu_to_le32 (tx_threshold); tx_ring[tx_cur].link = - cpu_to_le32 (phys_to_bus ((u32) & tx_ring[tx_next])); + cpu_to_le32 (phys_to_bus((u32)&tx_ring[tx_next])); tx_ring[tx_cur].tx_desc_addr = - cpu_to_le32 (phys_to_bus ((u32) & tx_ring[tx_cur].tx_buf_addr0)); + cpu_to_le32 (phys_to_bus((u32)&tx_ring[tx_cur].tx_buf_addr0)); tx_ring[tx_cur].tx_buf_addr0 = - cpu_to_le32 (phys_to_bus ((u_long) packet)); + cpu_to_le32 (phys_to_bus((u_long)packet)); tx_ring[tx_cur].tx_buf_size0 = cpu_to_le32 (length); - if (!wait_for_eepro100 (dev)) { - printf ("%s: Tx error ethernet controller not ready.\n", + if (!wait_for_eepro100(dev)) { + printf("%s: Tx error ethernet controller not ready.\n", dev->name); goto Done; } /* Send the packet. */ - OUTL (dev, phys_to_bus ((u32) & tx_ring[tx_cur]), SCBPointer); - OUTW (dev, SCB_M | CU_START, SCBCmd); + OUTL(dev, phys_to_bus((u32)&tx_ring[tx_cur]), SCBPointer); + OUTW(dev, SCB_M | CU_START, SCBCmd); - for (i = 0; !(le16_to_cpu (tx_ring[tx_cur].status) & CONFIG_SYS_STATUS_C); + for (i = 0; !(le16_to_cpu(tx_ring[tx_cur].status) & CONFIG_SYS_STATUS_C); i++) { if (i >= TOUT_LOOP) { - printf ("%s: Tx error buffer not ready\n", dev->name); + printf("%s: Tx error buffer not ready\n", dev->name); goto Done; } } - if (!(le16_to_cpu (tx_ring[tx_cur].status) & CONFIG_SYS_STATUS_OK)) { - printf ("TX error status = 0x%08X\n", - le16_to_cpu (tx_ring[tx_cur].status)); + if (!(le16_to_cpu(tx_ring[tx_cur].status) & CONFIG_SYS_STATUS_OK)) { + printf("TX error status = 0x%08X\n", + le16_to_cpu(tx_ring[tx_cur].status)); goto Done; } @@ -628,16 +628,16 @@ static int eepro100_send(struct eth_device *dev, void *packet, int length) return status; } -static int eepro100_recv (struct eth_device *dev) +static int eepro100_recv(struct eth_device *dev) { u16 status, stat; int rx_prev, length = 0; - stat = INW (dev, SCBStatus); - OUTW (dev, stat & SCB_STATUS_RNR, SCBStatus); + stat = INW(dev, SCBStatus); + OUTW(dev, stat & SCB_STATUS_RNR, SCBStatus); for (;;) { - status = le16_to_cpu (rx_ring[rx_next].status); + status = le16_to_cpu(rx_ring[rx_next].status); if (!(status & RFD_STATUS_C)) { break; @@ -646,14 +646,14 @@ static int eepro100_recv (struct eth_device *dev) /* Valid frame status. */ if ((status & RFD_STATUS_OK)) { /* A valid frame received. */ - length = le32_to_cpu (rx_ring[rx_next].count) & 0x3fff; + length = le32_to_cpu(rx_ring[rx_next].count) & 0x3fff; /* Pass the packet up to the protocol layers. */ net_process_received_packet((u8 *)rx_ring[rx_next].data, length); } else { /* There was an error. */ - printf ("RX error status = 0x%08X\n", status); + printf("RX error status = 0x%08X\n", status); } rx_ring[rx_next].control = cpu_to_le16 (RFD_CONTROL_S); @@ -669,87 +669,87 @@ static int eepro100_recv (struct eth_device *dev) if (stat & SCB_STATUS_RNR) { - printf ("%s: Receiver is not ready, restart it !\n", dev->name); + printf("%s: Receiver is not ready, restart it !\n", dev->name); /* Reinitialize Rx ring. */ - init_rx_ring (dev); + init_rx_ring(dev); - if (!wait_for_eepro100 (dev)) { - printf ("Error: Can not restart ethernet controller.\n"); + if (!wait_for_eepro100(dev)) { + printf("Error: Can not restart ethernet controller.\n"); goto Done; } - OUTL (dev, phys_to_bus ((u32) & rx_ring[rx_next]), SCBPointer); - OUTW (dev, SCB_M | RUC_START, SCBCmd); + OUTL(dev, phys_to_bus((u32)&rx_ring[rx_next]), SCBPointer); + OUTW(dev, SCB_M | RUC_START, SCBCmd); } Done: return length; } -static void eepro100_halt (struct eth_device *dev) +static void eepro100_halt(struct eth_device *dev) { /* Reset the ethernet controller */ - OUTL (dev, I82559_SELECTIVE_RESET, SCBPort); + OUTL(dev, I82559_SELECTIVE_RESET, SCBPort); udelay(20); - OUTL (dev, I82559_RESET, SCBPort); + OUTL(dev, I82559_RESET, SCBPort); udelay(20); - if (!wait_for_eepro100 (dev)) { - printf ("Error: Can not reset ethernet controller.\n"); + if (!wait_for_eepro100(dev)) { + printf("Error: Can not reset ethernet controller.\n"); goto Done; } - OUTL (dev, 0, SCBPointer); - OUTW (dev, SCB_M | RUC_ADDR_LOAD, SCBCmd); + OUTL(dev, 0, SCBPointer); + OUTW(dev, SCB_M | RUC_ADDR_LOAD, SCBCmd); - if (!wait_for_eepro100 (dev)) { - printf ("Error: Can not reset ethernet controller.\n"); + if (!wait_for_eepro100(dev)) { + printf("Error: Can not reset ethernet controller.\n"); goto Done; } - OUTL (dev, 0, SCBPointer); - OUTW (dev, SCB_M | CU_ADDR_LOAD, SCBCmd); + OUTL(dev, 0, SCBPointer); + OUTW(dev, SCB_M | CU_ADDR_LOAD, SCBCmd); Done: return; } /* SROM Read. */ -static int read_eeprom (struct eth_device *dev, int location, int addr_len) +static int read_eeprom(struct eth_device *dev, int location, int addr_len) { unsigned short retval = 0; int read_cmd = location | EE_READ_CMD; int i; - OUTW (dev, EE_ENB & ~EE_CS, SCBeeprom); - OUTW (dev, EE_ENB, SCBeeprom); + OUTW(dev, EE_ENB & ~EE_CS, SCBeeprom); + OUTW(dev, EE_ENB, SCBeeprom); /* Shift the read command bits out. */ for (i = 12; i >= 0; i--) { short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0; - OUTW (dev, EE_ENB | dataval, SCBeeprom); + OUTW(dev, EE_ENB | dataval, SCBeeprom); udelay(1); - OUTW (dev, EE_ENB | dataval | EE_SHIFT_CLK, SCBeeprom); + OUTW(dev, EE_ENB | dataval | EE_SHIFT_CLK, SCBeeprom); udelay(1); } - OUTW (dev, EE_ENB, SCBeeprom); + OUTW(dev, EE_ENB, SCBeeprom); for (i = 15; i >= 0; i--) { - OUTW (dev, EE_ENB | EE_SHIFT_CLK, SCBeeprom); + OUTW(dev, EE_ENB | EE_SHIFT_CLK, SCBeeprom); udelay(1); retval = (retval << 1) | - ((INW (dev, SCBeeprom) & EE_DATA_READ) ? 1 : 0); - OUTW (dev, EE_ENB, SCBeeprom); + ((INW(dev, SCBeeprom) & EE_DATA_READ) ? 1 : 0); + OUTW(dev, EE_ENB, SCBeeprom); udelay(1); } /* Terminate the EEPROM access. */ - OUTW (dev, EE_ENB & ~EE_CS, SCBeeprom); + OUTW(dev, EE_ENB & ~EE_CS, SCBeeprom); return retval; } -static void init_rx_ring (struct eth_device *dev) +static void init_rx_ring(struct eth_device *dev) { int i; @@ -759,7 +759,7 @@ static void init_rx_ring (struct eth_device *dev) (i == NUM_RX_DESC - 1) ? cpu_to_le16 (RFD_CONTROL_S) : 0; rx_ring[i].link = cpu_to_le32 (phys_to_bus - ((u32) & rx_ring[(i + 1) % NUM_RX_DESC])); + ((u32)&rx_ring[(i + 1) % NUM_RX_DESC])); rx_ring[i].rx_buf_addr = 0xffffffff; rx_ring[i].count = cpu_to_le32 (PKTSIZE_ALIGN << 16); } @@ -767,7 +767,7 @@ static void init_rx_ring (struct eth_device *dev) rx_next = 0; } -static void purge_tx_ring (struct eth_device *dev) +static void purge_tx_ring(struct eth_device *dev) { int i; @@ -788,14 +788,14 @@ static void purge_tx_ring (struct eth_device *dev) } } -static void read_hw_addr (struct eth_device *dev, bd_t * bis) +static void read_hw_addr(struct eth_device *dev, bd_t * bis) { u16 sum = 0; int i, j; - int addr_len = read_eeprom (dev, 0, 6) == 0xffff ? 8 : 6; + int addr_len = read_eeprom(dev, 0, 6) == 0xffff ? 8 : 6; for (j = 0, i = 0; i < 0x40; i++) { - u16 value = read_eeprom (dev, i, addr_len); + u16 value = read_eeprom(dev, i, addr_len); sum += value; if (i < 3) { @@ -805,7 +805,7 @@ static void read_hw_addr (struct eth_device *dev, bd_t * bis) } if (sum != 0xBABA) { - memset (dev->enetaddr, 0, ETH_ALEN); + memset(dev->enetaddr, 0, ETH_ALEN); debug("%s: Invalid EEPROM checksum %#4.4x, check settings before activating this device!\n", dev->name, sum); } -- cgit v1.1 From 9b12ff9911ec1a3b89648e0753e1d20d4d0ba2b0 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sat, 23 May 2020 13:20:14 +0200 Subject: net: eepro100: Fix braces This is automated cleanup via checkpatch, no functional change. ./scripts/checkpatch.pl --show-types -f drivers/net/eepro100.c ./scripts/checkpatch.pl --types BRACES -f --fix --fix-inplace drivers/net/eepro100.c Signed-off-by: Marek Vasut --- drivers/net/eepro100.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/net/eepro100.c b/drivers/net/eepro100.c index 1b6d537..6dccd59 100644 --- a/drivers/net/eepro100.c +++ b/drivers/net/eepro100.c @@ -358,9 +358,8 @@ static int wait_for_eepro100(struct eth_device *dev) int i; for (i = 0; INW(dev, SCBCmd) & (CU_CMD_MASK | RU_CMD_MASK); i++) { - if (i >= TOUT_LOOP) { + if (i >= TOUT_LOOP) return 0; - } } return 1; @@ -383,9 +382,9 @@ int eepro100_initialize(bd_t * bis) while (1) { /* Find PCI device */ - if ((devno = pci_find_devices(supported, idx++)) < 0) { + devno = pci_find_devices(supported, idx++); + if (devno < 0) break; - } pci_read_config_dword(devno, PCI_BASE_ADDRESS_0, &iobase); iobase &= ~0xf; @@ -639,9 +638,8 @@ static int eepro100_recv(struct eth_device *dev) for (;;) { status = le16_to_cpu(rx_ring[rx_next].status); - if (!(status & RFD_STATUS_C)) { + if (!(status & RFD_STATUS_C)) break; - } /* Valid frame status. */ if ((status & RFD_STATUS_OK)) { @@ -668,7 +666,6 @@ static int eepro100_recv(struct eth_device *dev) } if (stat & SCB_STATUS_RNR) { - printf("%s: Receiver is not ready, restart it !\n", dev->name); /* Reinitialize Rx ring. */ -- cgit v1.1 From 773af836daee64743a51450ee25d758283d4281f Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sat, 23 May 2020 13:21:43 +0200 Subject: net: eepro100: Fix parenthesis alignment This is automated cleanup via checkpatch, no functional change. ./scripts/checkpatch.pl --show-types -f drivers/net/eepro100.c ./scripts/checkpatch.pl --types PARENTHESIS_ALIGNMENT -f --fix --fix-inplace drivers/net/eepro100.c Signed-off-by: Marek Vasut --- drivers/net/eepro100.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/net/eepro100.c b/drivers/net/eepro100.c index 6dccd59..d367052 100644 --- a/drivers/net/eepro100.c +++ b/drivers/net/eepro100.c @@ -240,7 +240,7 @@ static inline int INL(struct eth_device *dev, u_long addr) } static int get_phyreg(struct eth_device *dev, unsigned char addr, - unsigned char reg, unsigned short *value) + unsigned char reg, unsigned short *value) { int cmd; int timeout = 50; @@ -263,7 +263,7 @@ static int get_phyreg(struct eth_device *dev, unsigned char addr, } static int set_phyreg(struct eth_device *dev, unsigned char addr, - unsigned char reg, unsigned short value) + unsigned char reg, unsigned short value) { int cmd; int timeout = 50; @@ -286,7 +286,7 @@ static int set_phyreg(struct eth_device *dev, unsigned char addr, * Do this by checking model value field from ID2 register. */ static struct eth_device* verify_phyaddr(const char *devname, - unsigned char addr) + unsigned char addr) { struct eth_device *dev; unsigned short value; @@ -393,7 +393,7 @@ int eepro100_initialize(bd_t * bis) iobase); pci_write_config_dword(devno, - PCI_COMMAND, + PCI_COMMAND, PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); /* Check if I/O accesses and Bus Mastering are enabled. */ @@ -504,7 +504,7 @@ static int eepro100_init(struct eth_device *dev, bd_t * bis) cfg_cmd->link = cpu_to_le32 (phys_to_bus((u32)&tx_ring[tx_next])); memcpy(cfg_cmd->params, i82558_config_cmd, - sizeof(i82558_config_cmd)); + sizeof(i82558_config_cmd)); if (!wait_for_eepro100(dev)) { printf("Error---CONFIG_SYS_CMD_CONFIGURE: Can not reset ethernet controller.\n"); @@ -525,7 +525,7 @@ static int eepro100_init(struct eth_device *dev, bd_t * bis) if (!(le16_to_cpu(tx_ring[tx_cur].status) & CONFIG_SYS_STATUS_OK)) { printf("TX error status = 0x%08X\n", - le16_to_cpu(tx_ring[tx_cur].status)); + le16_to_cpu(tx_ring[tx_cur].status)); goto Done; } @@ -553,14 +553,14 @@ static int eepro100_init(struct eth_device *dev, bd_t * bis) i++) { if (i >= TOUT_LOOP) { printf("%s: Tx error buffer not ready\n", - dev->name); + dev->name); goto Done; } } if (!(le16_to_cpu(tx_ring[tx_cur].status) & CONFIG_SYS_STATUS_OK)) { printf("TX error status = 0x%08X\n", - le16_to_cpu(tx_ring[tx_cur].status)); + le16_to_cpu(tx_ring[tx_cur].status)); goto Done; } @@ -599,7 +599,7 @@ static int eepro100_send(struct eth_device *dev, void *packet, int length) if (!wait_for_eepro100(dev)) { printf("%s: Tx error ethernet controller not ready.\n", - dev->name); + dev->name); goto Done; } @@ -617,7 +617,7 @@ static int eepro100_send(struct eth_device *dev, void *packet, int length) if (!(le16_to_cpu(tx_ring[tx_cur].status) & CONFIG_SYS_STATUS_OK)) { printf("TX error status = 0x%08X\n", - le16_to_cpu(tx_ring[tx_cur].status)); + le16_to_cpu(tx_ring[tx_cur].status)); goto Done; } -- cgit v1.1 From 7a30873585c9da2221f652c091bab5e66d5d6653 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sat, 23 May 2020 13:23:13 +0200 Subject: net: eepro100: Fix pointer location This is automated cleanup via checkpatch, no functional change. ./scripts/checkpatch.pl --show-types -f drivers/net/eepro100.c ./scripts/checkpatch.pl --types POINTER_LOCATION -f --fix --fix-inplace drivers/net/eepro100.c Signed-off-by: Marek Vasut --- drivers/net/eepro100.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/eepro100.c b/drivers/net/eepro100.c index d367052..2aad124 100644 --- a/drivers/net/eepro100.c +++ b/drivers/net/eepro100.c @@ -203,9 +203,9 @@ static const char i82558_config_cmd[] = { static void init_rx_ring(struct eth_device *dev); static void purge_tx_ring(struct eth_device *dev); -static void read_hw_addr(struct eth_device *dev, bd_t * bis); +static void read_hw_addr(struct eth_device *dev, bd_t *bis); -static int eepro100_init(struct eth_device *dev, bd_t * bis); +static int eepro100_init(struct eth_device *dev, bd_t *bis); static int eepro100_send(struct eth_device *dev, void *packet, int length); static int eepro100_recv(struct eth_device *dev); static void eepro100_halt(struct eth_device *dev); @@ -285,7 +285,7 @@ static int set_phyreg(struct eth_device *dev, unsigned char addr, * Check if given phyaddr is valid, i.e. there is a PHY connected. * Do this by checking model value field from ID2 register. */ -static struct eth_device* verify_phyaddr(const char *devname, +static struct eth_device *verify_phyaddr(const char *devname, unsigned char addr) { struct eth_device *dev; @@ -372,7 +372,7 @@ static struct pci_device_id supported[] = { {} }; -int eepro100_initialize(bd_t * bis) +int eepro100_initialize(bd_t *bis) { pci_dev_t devno; int card_number = 0; @@ -454,7 +454,7 @@ int eepro100_initialize(bd_t * bis) } -static int eepro100_init(struct eth_device *dev, bd_t * bis) +static int eepro100_init(struct eth_device *dev, bd_t *bis) { int i, status = -1; int tx_cur; @@ -785,7 +785,7 @@ static void purge_tx_ring(struct eth_device *dev) } } -static void read_hw_addr(struct eth_device *dev, bd_t * bis) +static void read_hw_addr(struct eth_device *dev, bd_t *bis) { u16 sum = 0; int i, j; -- cgit v1.1 From 614e95152dd63ac5259cd99c5c90949dcc466123 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sat, 23 May 2020 13:26:50 +0200 Subject: net: eepro100: Fix indented label This is automated cleanup via checkpatch, no functional change. ./scripts/checkpatch.pl --show-types -f drivers/net/eepro100.c ./scripts/checkpatch.pl --types INDENTED_LABEL -f --fix --fix-inplace drivers/net/eepro100.c Signed-off-by: Marek Vasut --- drivers/net/eepro100.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/eepro100.c b/drivers/net/eepro100.c index 2aad124..e5bc90f 100644 --- a/drivers/net/eepro100.c +++ b/drivers/net/eepro100.c @@ -566,7 +566,7 @@ static int eepro100_init(struct eth_device *dev, bd_t *bis) status = 0; - Done: +Done: return status; } @@ -623,7 +623,7 @@ static int eepro100_send(struct eth_device *dev, void *packet, int length) status = length; - Done: +Done: return status; } @@ -680,7 +680,7 @@ static int eepro100_recv(struct eth_device *dev) OUTW(dev, SCB_M | RUC_START, SCBCmd); } - Done: +Done: return length; } @@ -707,7 +707,7 @@ static void eepro100_halt(struct eth_device *dev) OUTL(dev, 0, SCBPointer); OUTW(dev, SCB_M | CU_ADDR_LOAD, SCBCmd); - Done: +Done: return; } -- cgit v1.1 From b0131730795c1ff7994a008d1c68b3b9b200d213 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sat, 23 May 2020 13:45:41 +0200 Subject: net: eepro100: Fix remaining checkpatch issues This is automated cleanup via checkpatch, no functional change. ./scripts/checkpatch.pl --show-types -f drivers/net/eepro100.c ./scripts/checkpatch.pl -f --fix --fix-inplace drivers/net/eepro100.c This fixes all the remaining errors except a couple of comments which are longer than 80 characters, all the volatile misuse and all the camelcase, that needs a separate patch. Signed-off-by: Marek Vasut --- drivers/net/eepro100.c | 45 ++++++++++++++++++++++++--------------------- 1 file changed, 24 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/net/eepro100.c b/drivers/net/eepro100.c index e5bc90f..45c0136 100644 --- a/drivers/net/eepro100.c +++ b/drivers/net/eepro100.c @@ -293,7 +293,7 @@ static struct eth_device *verify_phyaddr(const char *devname, unsigned char model; dev = eth_get_dev_by_name(devname); - if (dev == NULL) { + if (!dev) { printf("%s: no such device\n", devname); return NULL; } @@ -322,7 +322,7 @@ static int eepro100_miiphy_read(struct mii_dev *bus, int addr, int devad, struct eth_device *dev; dev = verify_phyaddr(bus->name, addr); - if (dev == NULL) + if (!dev) return -1; if (get_phyreg(dev, addr, reg, &value) != 0) { @@ -339,7 +339,7 @@ static int eepro100_miiphy_write(struct mii_dev *bus, int addr, int devad, struct eth_device *dev; dev = verify_phyaddr(bus->name, addr); - if (dev == NULL) + if (!dev) return -1; if (set_phyreg(dev, addr, reg, value) != 0) { @@ -392,9 +392,8 @@ int eepro100_initialize(bd_t *bis) debug("eepro100: Intel i82559 PCI EtherExpressPro @0x%x\n", iobase); - pci_write_config_dword(devno, - PCI_COMMAND, - PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); + pci_write_config_dword(devno, PCI_COMMAND, + PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); /* Check if I/O accesses and Bus Mastering are enabled. */ pci_read_config_dword(devno, PCI_COMMAND, &status); @@ -408,7 +407,7 @@ int eepro100_initialize(bd_t *bis) continue; } - dev = (struct eth_device *)malloc(sizeof *dev); + dev = (struct eth_device *)malloc(sizeof(*dev)); if (!dev) { printf("eepro100: Can not allocate memory\n"); break; @@ -429,6 +428,7 @@ int eepro100_initialize(bd_t *bis) /* register mii command access routines */ int retval; struct mii_dev *mdiodev = mdio_alloc(); + if (!mdiodev) return -ENOMEM; strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN); @@ -453,7 +453,6 @@ int eepro100_initialize(bd_t *bis) return card_number; } - static int eepro100_init(struct eth_device *dev, bd_t *bis) { int i, status = -1; @@ -499,9 +498,10 @@ static int eepro100_init(struct eth_device *dev, bd_t *bis) tx_next = ((tx_next + 1) % NUM_TX_DESC); cfg_cmd = (struct descriptor *)&tx_ring[tx_cur]; - cfg_cmd->command = cpu_to_le16 ((CONFIG_SYS_CMD_SUSPEND | CONFIG_SYS_CMD_CONFIGURE)); + cfg_cmd->command = cpu_to_le16(CONFIG_SYS_CMD_SUSPEND | + CONFIG_SYS_CMD_CONFIGURE); cfg_cmd->status = 0; - cfg_cmd->link = cpu_to_le32 (phys_to_bus((u32)&tx_ring[tx_next])); + cfg_cmd->link = cpu_to_le32(phys_to_bus((u32)&tx_ring[tx_next])); memcpy(cfg_cmd->params, i82558_config_cmd, sizeof(i82558_config_cmd)); @@ -534,9 +534,10 @@ static int eepro100_init(struct eth_device *dev, bd_t *bis) tx_next = ((tx_next + 1) % NUM_TX_DESC); ias_cmd = (struct descriptor *)&tx_ring[tx_cur]; - ias_cmd->command = cpu_to_le16 ((CONFIG_SYS_CMD_SUSPEND | CONFIG_SYS_CMD_IAS)); + ias_cmd->command = cpu_to_le16(CONFIG_SYS_CMD_SUSPEND | + CONFIG_SYS_CMD_IAS); ias_cmd->status = 0; - ias_cmd->link = cpu_to_le32 (phys_to_bus((u32)&tx_ring[tx_next])); + ias_cmd->link = cpu_to_le32(phys_to_bus((u32)&tx_ring[tx_next])); memcpy(ias_cmd->params, dev->enetaddr, 6); @@ -549,8 +550,9 @@ static int eepro100_init(struct eth_device *dev, bd_t *bis) OUTL(dev, phys_to_bus((u32)&tx_ring[tx_cur]), SCBPointer); OUTW(dev, SCB_M | CU_START, SCBCmd); - for (i = 0; !(le16_to_cpu(tx_ring[tx_cur].status) & CONFIG_SYS_STATUS_C); - i++) { + for (i = 0; + !(le16_to_cpu(tx_ring[tx_cur].status) & CONFIG_SYS_STATUS_C); + i++) { if (i >= TOUT_LOOP) { printf("%s: Tx error buffer not ready\n", dev->name); @@ -607,8 +609,9 @@ static int eepro100_send(struct eth_device *dev, void *packet, int length) OUTL(dev, phys_to_bus((u32)&tx_ring[tx_cur]), SCBPointer); OUTW(dev, SCB_M | CU_START, SCBCmd); - for (i = 0; !(le16_to_cpu(tx_ring[tx_cur].status) & CONFIG_SYS_STATUS_C); - i++) { + for (i = 0; + !(le16_to_cpu(tx_ring[tx_cur].status) & CONFIG_SYS_STATUS_C); + i++) { if (i >= TOUT_LOOP) { printf("%s: Tx error buffer not ready\n", dev->name); goto Done; @@ -752,13 +755,13 @@ static void init_rx_ring(struct eth_device *dev) for (i = 0; i < NUM_RX_DESC; i++) { rx_ring[i].status = 0; - rx_ring[i].control = - (i == NUM_RX_DESC - 1) ? cpu_to_le16 (RFD_CONTROL_S) : 0; + rx_ring[i].control = (i == NUM_RX_DESC - 1) ? + cpu_to_le16 (RFD_CONTROL_S) : 0; rx_ring[i].link = - cpu_to_le32 (phys_to_bus - ((u32)&rx_ring[(i + 1) % NUM_RX_DESC])); + cpu_to_le32(phys_to_bus((u32)&rx_ring[(i + 1) % + NUM_RX_DESC])); rx_ring[i].rx_buf_addr = 0xffffffff; - rx_ring[i].count = cpu_to_le32 (PKTSIZE_ALIGN << 16); + rx_ring[i].count = cpu_to_le32(PKTSIZE_ALIGN << 16); } rx_next = 0; -- cgit v1.1 From f3878f5c2821cca2c2587adf522319578ed0c1da Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sat, 23 May 2020 13:52:50 +0200 Subject: net: eepro100: Fix camelcase This is automated cleanup via checkpatch, no functional change. ./scripts/checkpatch.pl --show-types -f drivers/net/eepro100.c ./scripts/checkpatch.pl --types INDENTED_LABEL -f --fix --fix-inplace drivers/net/eepro100.c Signed-off-by: Marek Vasut --- drivers/net/eepro100.c | 172 ++++++++++++++++++++++++------------------------- 1 file changed, 85 insertions(+), 87 deletions(-) (limited to 'drivers') diff --git a/drivers/net/eepro100.c b/drivers/net/eepro100.c index 45c0136..d3ced08 100644 --- a/drivers/net/eepro100.c +++ b/drivers/net/eepro100.c @@ -14,18 +14,18 @@ #include /* Ethernet chip registers. */ -#define SCBStatus 0 /* Rx/Command Unit Status *Word* */ -#define SCBIntAckByte 1 /* Rx/Command Unit STAT/ACK byte */ -#define SCBCmd 2 /* Rx/Command Unit Command *Word* */ -#define SCBIntrCtlByte 3 /* Rx/Command Unit Intr.Control Byte */ -#define SCBPointer 4 /* General purpose pointer. */ -#define SCBPort 8 /* Misc. commands and operands. */ -#define SCBflash 12 /* Flash memory control. */ -#define SCBeeprom 14 /* EEPROM memory control. */ -#define SCBCtrlMDI 16 /* MDI interface control. */ -#define SCBEarlyRx 20 /* Early receive byte count. */ -#define SCBGenControl 28 /* 82559 General Control Register */ -#define SCBGenStatus 29 /* 82559 General Status register */ +#define SCB_STATUS 0 /* Rx/Command Unit Status *Word* */ +#define SCB_INT_ACK_BYTE 1 /* Rx/Command Unit STAT/ACK byte */ +#define SCB_CMD 2 /* Rx/Command Unit Command *Word* */ +#define SCB_INTR_CTL_BYTE 3 /* Rx/Command Unit Intr.Control Byte */ +#define SCB_POINTER 4 /* General purpose pointer. */ +#define SCB_PORT 8 /* Misc. commands and operands. */ +#define SCB_FLASH 12 /* Flash memory control. */ +#define SCB_EEPROM 14 /* EEPROM memory control. */ +#define SCB_CTRL_MDI 16 /* MDI interface control. */ +#define SCB_EARLY_RX 20 /* Early receive byte count. */ +#define SCB_GEN_CONTROL 28 /* 82559 General Control Register */ +#define SCB_GEN_STATUS 29 /* 82559 General Status register */ /* 82559 SCB status word defnitions */ #define SCB_STATUS_CX 0x8000 /* CU finished command (transmit) */ @@ -101,10 +101,10 @@ #define EE_ERASE_CMD (7 << addr_len) /* Receive frame descriptors. */ -struct RxFD { +struct eepro100_rxfd { volatile u16 status; volatile u16 control; - volatile u32 link; /* struct RxFD * */ + volatile u32 link; /* struct eepro100_rxfd * */ volatile u32 rx_buf_addr; /* void * */ volatile u32 count; @@ -135,7 +135,7 @@ struct RxFD { #define RFD_RX_TCO 0x0001 /* TCO indication */ /* Transmit frame descriptors */ -struct TxFD { /* Transmit frame descriptor set. */ +struct eepro100_txfd { /* Transmit frame descriptor set. */ volatile u16 status; volatile u16 command; volatile u32 link; /* void * */ @@ -148,15 +148,15 @@ struct TxFD { /* Transmit frame descriptor set. */ volatile s32 tx_buf_size1; /* Length of Tx frame. */ }; -#define TxCB_CMD_TRANSMIT 0x0004 /* transmit command */ -#define TxCB_CMD_SF 0x0008 /* 0=simplified, 1=flexible mode */ -#define TxCB_CMD_NC 0x0010 /* 0=CRC insert by controller */ -#define TxCB_CMD_I 0x2000 /* generate interrupt on completion */ -#define TxCB_CMD_S 0x4000 /* suspend on completion */ -#define TxCB_CMD_EL 0x8000 /* last command block in CBL */ +#define TXCB_CMD_TRANSMIT 0x0004 /* transmit command */ +#define TXCB_CMD_SF 0x0008 /* 0=simplified, 1=flexible mode */ +#define TXCB_CMD_NC 0x0010 /* 0=CRC insert by controller */ +#define TXCB_CMD_I 0x2000 /* generate interrupt on completion */ +#define TXCB_CMD_S 0x4000 /* suspend on completion */ +#define TXCB_CMD_EL 0x8000 /* last command block in CBL */ -#define TxCB_COUNT_MASK 0x3fff -#define TxCB_COUNT_EOF 0x8000 +#define TXCB_COUNT_MASK 0x3fff +#define TXCB_COUNT_EOF 0x8000 /* The Speedo3 Rx and Tx frame/buffer descriptors. */ struct descriptor { /* A generic descriptor. */ @@ -182,8 +182,8 @@ struct descriptor { /* A generic descriptor. */ #define TOUT_LOOP 1000000 -static struct RxFD rx_ring[NUM_RX_DESC]; /* RX descriptor ring */ -static struct TxFD tx_ring[NUM_TX_DESC]; /* TX descriptor ring */ +static struct eepro100_rxfd rx_ring[NUM_RX_DESC]; /* RX descriptor ring */ +static struct eepro100_txfd tx_ring[NUM_TX_DESC]; /* TX descriptor ring */ static int rx_next; /* RX descriptor ring pointer */ static int tx_next; /* TX descriptor ring pointer */ static int tx_threshold; @@ -247,11 +247,11 @@ static int get_phyreg(struct eth_device *dev, unsigned char addr, /* read requested data */ cmd = (2 << 26) | ((addr & 0x1f) << 21) | ((reg & 0x1f) << 16); - OUTL(dev, cmd, SCBCtrlMDI); + OUTL(dev, cmd, SCB_CTRL_MDI); do { udelay(1000); - cmd = INL(dev, SCBCtrlMDI); + cmd = INL(dev, SCB_CTRL_MDI); } while (!(cmd & (1 << 28)) && (--timeout)); if (timeout == 0) @@ -270,9 +270,9 @@ static int set_phyreg(struct eth_device *dev, unsigned char addr, /* write requested data */ cmd = (1 << 26) | ((addr & 0x1f) << 21) | ((reg & 0x1f) << 16); - OUTL(dev, cmd | value, SCBCtrlMDI); + OUTL(dev, cmd | value, SCB_CTRL_MDI); - while (!(INL(dev, SCBCtrlMDI) & (1 << 28)) && (--timeout)) + while (!(INL(dev, SCB_CTRL_MDI) & (1 << 28)) && (--timeout)) udelay(1000); if (timeout == 0) @@ -357,7 +357,7 @@ static int wait_for_eepro100(struct eth_device *dev) { int i; - for (i = 0; INW(dev, SCBCmd) & (CU_CMD_MASK | RU_CMD_MASK); i++) { + for (i = 0; INW(dev, SCB_CMD) & (CU_CMD_MASK | RU_CMD_MASK); i++) { if (i >= TOUT_LOOP) return 0; } @@ -460,25 +460,25 @@ static int eepro100_init(struct eth_device *dev, bd_t *bis) struct descriptor *ias_cmd, *cfg_cmd; /* Reset the ethernet controller */ - OUTL(dev, I82559_SELECTIVE_RESET, SCBPort); + OUTL(dev, I82559_SELECTIVE_RESET, SCB_PORT); udelay(20); - OUTL(dev, I82559_RESET, SCBPort); + OUTL(dev, I82559_RESET, SCB_PORT); udelay(20); if (!wait_for_eepro100(dev)) { printf("Error: Can not reset ethernet controller.\n"); - goto Done; + goto done; } - OUTL(dev, 0, SCBPointer); - OUTW(dev, SCB_M | RUC_ADDR_LOAD, SCBCmd); + OUTL(dev, 0, SCB_POINTER); + OUTW(dev, SCB_M | RUC_ADDR_LOAD, SCB_CMD); if (!wait_for_eepro100(dev)) { printf("Error: Can not reset ethernet controller.\n"); - goto Done; + goto done; } - OUTL(dev, 0, SCBPointer); - OUTW(dev, SCB_M | CU_ADDR_LOAD, SCBCmd); + OUTL(dev, 0, SCB_POINTER); + OUTW(dev, SCB_M | CU_ADDR_LOAD, SCB_CMD); /* Initialize Rx and Tx rings. */ init_rx_ring(dev); @@ -487,11 +487,11 @@ static int eepro100_init(struct eth_device *dev, bd_t *bis) /* Tell the adapter where the RX ring is located. */ if (!wait_for_eepro100(dev)) { printf("Error: Can not reset ethernet controller.\n"); - goto Done; + goto done; } - OUTL(dev, phys_to_bus((u32)&rx_ring[rx_next]), SCBPointer); - OUTW(dev, SCB_M | RUC_START, SCBCmd); + OUTL(dev, phys_to_bus((u32)&rx_ring[rx_next]), SCB_POINTER); + OUTW(dev, SCB_M | RUC_START, SCB_CMD); /* Send the Configure frame */ tx_cur = tx_next; @@ -508,25 +508,25 @@ static int eepro100_init(struct eth_device *dev, bd_t *bis) if (!wait_for_eepro100(dev)) { printf("Error---CONFIG_SYS_CMD_CONFIGURE: Can not reset ethernet controller.\n"); - goto Done; + goto done; } - OUTL(dev, phys_to_bus((u32)&tx_ring[tx_cur]), SCBPointer); - OUTW(dev, SCB_M | CU_START, SCBCmd); + OUTL(dev, phys_to_bus((u32)&tx_ring[tx_cur]), SCB_POINTER); + OUTW(dev, SCB_M | CU_START, SCB_CMD); for (i = 0; !(le16_to_cpu(tx_ring[tx_cur].status) & CONFIG_SYS_STATUS_C); i++) { if (i >= TOUT_LOOP) { printf("%s: Tx error buffer not ready\n", dev->name); - goto Done; + goto done; } } if (!(le16_to_cpu(tx_ring[tx_cur].status) & CONFIG_SYS_STATUS_OK)) { printf("TX error status = 0x%08X\n", le16_to_cpu(tx_ring[tx_cur].status)); - goto Done; + goto done; } /* Send the Individual Address Setup frame */ @@ -544,11 +544,11 @@ static int eepro100_init(struct eth_device *dev, bd_t *bis) /* Tell the adapter where the TX ring is located. */ if (!wait_for_eepro100(dev)) { printf("Error: Can not reset ethernet controller.\n"); - goto Done; + goto done; } - OUTL(dev, phys_to_bus((u32)&tx_ring[tx_cur]), SCBPointer); - OUTW(dev, SCB_M | CU_START, SCBCmd); + OUTL(dev, phys_to_bus((u32)&tx_ring[tx_cur]), SCB_POINTER); + OUTW(dev, SCB_M | CU_START, SCB_CMD); for (i = 0; !(le16_to_cpu(tx_ring[tx_cur].status) & CONFIG_SYS_STATUS_C); @@ -556,19 +556,19 @@ static int eepro100_init(struct eth_device *dev, bd_t *bis) if (i >= TOUT_LOOP) { printf("%s: Tx error buffer not ready\n", dev->name); - goto Done; + goto done; } } if (!(le16_to_cpu(tx_ring[tx_cur].status) & CONFIG_SYS_STATUS_OK)) { printf("TX error status = 0x%08X\n", le16_to_cpu(tx_ring[tx_cur].status)); - goto Done; + goto done; } status = 0; -Done: +done: return status; } @@ -579,16 +579,14 @@ static int eepro100_send(struct eth_device *dev, void *packet, int length) if (length <= 0) { printf("%s: bad packet size: %d\n", dev->name, length); - goto Done; + goto done; } tx_cur = tx_next; tx_next = (tx_next + 1) % NUM_TX_DESC; - tx_ring[tx_cur].command = cpu_to_le16 (TxCB_CMD_TRANSMIT | - TxCB_CMD_SF | - TxCB_CMD_S | - TxCB_CMD_EL); + tx_ring[tx_cur].command = cpu_to_le16(TXCB_CMD_TRANSMIT | TXCB_CMD_SF | + TXCB_CMD_S | TXCB_CMD_EL); tx_ring[tx_cur].status = 0; tx_ring[tx_cur].count = cpu_to_le32 (tx_threshold); tx_ring[tx_cur].link = @@ -602,31 +600,31 @@ static int eepro100_send(struct eth_device *dev, void *packet, int length) if (!wait_for_eepro100(dev)) { printf("%s: Tx error ethernet controller not ready.\n", dev->name); - goto Done; + goto done; } /* Send the packet. */ - OUTL(dev, phys_to_bus((u32)&tx_ring[tx_cur]), SCBPointer); - OUTW(dev, SCB_M | CU_START, SCBCmd); + OUTL(dev, phys_to_bus((u32)&tx_ring[tx_cur]), SCB_POINTER); + OUTW(dev, SCB_M | CU_START, SCB_CMD); for (i = 0; !(le16_to_cpu(tx_ring[tx_cur].status) & CONFIG_SYS_STATUS_C); i++) { if (i >= TOUT_LOOP) { printf("%s: Tx error buffer not ready\n", dev->name); - goto Done; + goto done; } } if (!(le16_to_cpu(tx_ring[tx_cur].status) & CONFIG_SYS_STATUS_OK)) { printf("TX error status = 0x%08X\n", le16_to_cpu(tx_ring[tx_cur].status)); - goto Done; + goto done; } status = length; -Done: +done: return status; } @@ -635,8 +633,8 @@ static int eepro100_recv(struct eth_device *dev) u16 status, stat; int rx_prev, length = 0; - stat = INW(dev, SCBStatus); - OUTW(dev, stat & SCB_STATUS_RNR, SCBStatus); + stat = INW(dev, SCB_STATUS); + OUTW(dev, stat & SCB_STATUS_RNR, SCB_STATUS); for (;;) { status = le16_to_cpu(rx_ring[rx_next].status); @@ -676,41 +674,41 @@ static int eepro100_recv(struct eth_device *dev) if (!wait_for_eepro100(dev)) { printf("Error: Can not restart ethernet controller.\n"); - goto Done; + goto done; } - OUTL(dev, phys_to_bus((u32)&rx_ring[rx_next]), SCBPointer); - OUTW(dev, SCB_M | RUC_START, SCBCmd); + OUTL(dev, phys_to_bus((u32)&rx_ring[rx_next]), SCB_POINTER); + OUTW(dev, SCB_M | RUC_START, SCB_CMD); } -Done: +done: return length; } static void eepro100_halt(struct eth_device *dev) { /* Reset the ethernet controller */ - OUTL(dev, I82559_SELECTIVE_RESET, SCBPort); + OUTL(dev, I82559_SELECTIVE_RESET, SCB_PORT); udelay(20); - OUTL(dev, I82559_RESET, SCBPort); + OUTL(dev, I82559_RESET, SCB_PORT); udelay(20); if (!wait_for_eepro100(dev)) { printf("Error: Can not reset ethernet controller.\n"); - goto Done; + goto done; } - OUTL(dev, 0, SCBPointer); - OUTW(dev, SCB_M | RUC_ADDR_LOAD, SCBCmd); + OUTL(dev, 0, SCB_POINTER); + OUTW(dev, SCB_M | RUC_ADDR_LOAD, SCB_CMD); if (!wait_for_eepro100(dev)) { printf("Error: Can not reset ethernet controller.\n"); - goto Done; + goto done; } - OUTL(dev, 0, SCBPointer); - OUTW(dev, SCB_M | CU_ADDR_LOAD, SCBCmd); + OUTL(dev, 0, SCB_POINTER); + OUTW(dev, SCB_M | CU_ADDR_LOAD, SCB_CMD); -Done: +done: return; } @@ -721,31 +719,31 @@ static int read_eeprom(struct eth_device *dev, int location, int addr_len) int read_cmd = location | EE_READ_CMD; int i; - OUTW(dev, EE_ENB & ~EE_CS, SCBeeprom); - OUTW(dev, EE_ENB, SCBeeprom); + OUTW(dev, EE_ENB & ~EE_CS, SCB_EEPROM); + OUTW(dev, EE_ENB, SCB_EEPROM); /* Shift the read command bits out. */ for (i = 12; i >= 0; i--) { short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0; - OUTW(dev, EE_ENB | dataval, SCBeeprom); + OUTW(dev, EE_ENB | dataval, SCB_EEPROM); udelay(1); - OUTW(dev, EE_ENB | dataval | EE_SHIFT_CLK, SCBeeprom); + OUTW(dev, EE_ENB | dataval | EE_SHIFT_CLK, SCB_EEPROM); udelay(1); } - OUTW(dev, EE_ENB, SCBeeprom); + OUTW(dev, EE_ENB, SCB_EEPROM); for (i = 15; i >= 0; i--) { - OUTW(dev, EE_ENB | EE_SHIFT_CLK, SCBeeprom); + OUTW(dev, EE_ENB | EE_SHIFT_CLK, SCB_EEPROM); udelay(1); retval = (retval << 1) | - ((INW(dev, SCBeeprom) & EE_DATA_READ) ? 1 : 0); - OUTW(dev, EE_ENB, SCBeeprom); + ((INW(dev, SCB_EEPROM) & EE_DATA_READ) ? 1 : 0); + OUTW(dev, EE_ENB, SCB_EEPROM); udelay(1); } /* Terminate the EEPROM access. */ - OUTW(dev, EE_ENB & ~EE_CS, SCBeeprom); + OUTW(dev, EE_ENB & ~EE_CS, SCB_EEPROM); return retval; } -- cgit v1.1 From 81bdeea2fe62277922a6bd735f936b168352a49d Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sat, 23 May 2020 14:14:45 +0200 Subject: net: eepro100: Use standard I/O accessors The current eepro100 driver accesses its memory mapped registers directly instead of using the standard I/O accessors. This can cause problems on some systems as the accesses can get out of order. So convert the direct volatile dereferences to use the normal in/out macros. Signed-off-by: Marek Vasut --- drivers/net/eepro100.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/eepro100.c b/drivers/net/eepro100.c index d3ced08..5d11665 100644 --- a/drivers/net/eepro100.c +++ b/drivers/net/eepro100.c @@ -220,23 +220,23 @@ static void eepro100_halt(struct eth_device *dev); static inline int INW(struct eth_device *dev, u_long addr) { - return le16_to_cpu(*(volatile u16 *)(addr + (u_long)dev->iobase)); + return le16_to_cpu(readw(addr + (void *)dev->iobase)); } static inline void OUTW(struct eth_device *dev, int command, u_long addr) { - *(volatile u16 *)((addr + (u_long)dev->iobase)) = cpu_to_le16(command); + writew(cpu_to_le16(command), addr + (void *)dev->iobase); } static inline void OUTL(struct eth_device *dev, int command, u_long addr) { - *(volatile u32 *)((addr + (u_long)dev->iobase)) = cpu_to_le32(command); + writel(cpu_to_le32(command), addr + (void *)dev->iobase); } #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) static inline int INL(struct eth_device *dev, u_long addr) { - return le32_to_cpu(*(volatile u32 *)(addr + (u_long)dev->iobase)); + return le32_to_cpu(readl(addr + (void *)dev->iobase)); } static int get_phyreg(struct eth_device *dev, unsigned char addr, -- cgit v1.1 From 46df32ef2f8226434b06b43c51cbd94268b343d9 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sat, 23 May 2020 14:26:16 +0200 Subject: net: eepro100: Replace purge_tx_ring() with memset() This function zeroes-out all the descriptors in the TX ring, use memset() instead. Signed-off-by: Marek Vasut --- drivers/net/eepro100.c | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/net/eepro100.c b/drivers/net/eepro100.c index 5d11665..6fb9192 100644 --- a/drivers/net/eepro100.c +++ b/drivers/net/eepro100.c @@ -767,23 +767,9 @@ static void init_rx_ring(struct eth_device *dev) static void purge_tx_ring(struct eth_device *dev) { - int i; - tx_next = 0; tx_threshold = 0x01208000; - - for (i = 0; i < NUM_TX_DESC; i++) { - tx_ring[i].status = 0; - tx_ring[i].command = 0; - tx_ring[i].link = 0; - tx_ring[i].tx_desc_addr = 0; - tx_ring[i].count = 0; - - tx_ring[i].tx_buf_addr0 = 0; - tx_ring[i].tx_buf_size0 = 0; - tx_ring[i].tx_buf_addr1 = 0; - tx_ring[i].tx_buf_size1 = 0; - } + memset(tx_ring, 0, sizeof(*tx_ring) * NUM_TX_DESC); } static void read_hw_addr(struct eth_device *dev, bd_t *bis) -- cgit v1.1 From 95655b921bdb39aa23a345be13140ab221776705 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sat, 23 May 2020 14:30:31 +0200 Subject: net: eepro100: Factor out tx_ring command issuing This code is replicated in the driver thrice almost verbatim, factor it out into a separate function and clean it up. No functional change. Signed-off-by: Marek Vasut --- drivers/net/eepro100.c | 124 +++++++++++++++++++++---------------------------- 1 file changed, 53 insertions(+), 71 deletions(-) (limited to 'drivers') diff --git a/drivers/net/eepro100.c b/drivers/net/eepro100.c index 6fb9192..03ba9a4 100644 --- a/drivers/net/eepro100.c +++ b/drivers/net/eepro100.c @@ -453,11 +453,44 @@ int eepro100_initialize(bd_t *bis) return card_number; } +static int eepro100_txcmd_send(struct eth_device *dev, + struct eepro100_txfd *desc) +{ + u16 rstat; + int i = 0; + + if (!wait_for_eepro100(dev)) + return -ETIMEDOUT; + + OUTL(dev, phys_to_bus((u32)desc), SCB_POINTER); + OUTW(dev, SCB_M | CU_START, SCB_CMD); + + while (true) { + rstat = le16_to_cpu(desc->status); + if (rstat & CONFIG_SYS_STATUS_C) + break; + + if (i++ >= TOUT_LOOP) { + printf("%s: Tx error buffer not ready\n", dev->name); + return -EINVAL; + } + } + + rstat = le16_to_cpu(desc->status); + + if (!(rstat & CONFIG_SYS_STATUS_OK)) { + printf("TX error status = 0x%08X\n", rstat); + return -EIO; + } + + return 0; +} + static int eepro100_init(struct eth_device *dev, bd_t *bis) { - int i, status = -1; + struct eepro100_txfd *ias_cmd, *cfg_cmd; + int ret, status = -1; int tx_cur; - struct descriptor *ias_cmd, *cfg_cmd; /* Reset the ethernet controller */ OUTL(dev, I82559_SELECTIVE_RESET, SCB_PORT); @@ -497,35 +530,19 @@ static int eepro100_init(struct eth_device *dev, bd_t *bis) tx_cur = tx_next; tx_next = ((tx_next + 1) % NUM_TX_DESC); - cfg_cmd = (struct descriptor *)&tx_ring[tx_cur]; + cfg_cmd = &tx_ring[tx_cur]; cfg_cmd->command = cpu_to_le16(CONFIG_SYS_CMD_SUSPEND | CONFIG_SYS_CMD_CONFIGURE); cfg_cmd->status = 0; cfg_cmd->link = cpu_to_le32(phys_to_bus((u32)&tx_ring[tx_next])); - memcpy(cfg_cmd->params, i82558_config_cmd, + memcpy(((struct descriptor *)cfg_cmd)->params, i82558_config_cmd, sizeof(i82558_config_cmd)); - if (!wait_for_eepro100(dev)) { - printf("Error---CONFIG_SYS_CMD_CONFIGURE: Can not reset ethernet controller.\n"); - goto done; - } - - OUTL(dev, phys_to_bus((u32)&tx_ring[tx_cur]), SCB_POINTER); - OUTW(dev, SCB_M | CU_START, SCB_CMD); - - for (i = 0; - !(le16_to_cpu(tx_ring[tx_cur].status) & CONFIG_SYS_STATUS_C); - i++) { - if (i >= TOUT_LOOP) { - printf("%s: Tx error buffer not ready\n", dev->name); - goto done; - } - } - - if (!(le16_to_cpu(tx_ring[tx_cur].status) & CONFIG_SYS_STATUS_OK)) { - printf("TX error status = 0x%08X\n", - le16_to_cpu(tx_ring[tx_cur].status)); + ret = eepro100_txcmd_send(dev, cfg_cmd); + if (ret) { + if (ret == -ETIMEDOUT) + printf("Error---CONFIG_SYS_CMD_CONFIGURE: Can not reset ethernet controller.\n"); goto done; } @@ -533,36 +550,18 @@ static int eepro100_init(struct eth_device *dev, bd_t *bis) tx_cur = tx_next; tx_next = ((tx_next + 1) % NUM_TX_DESC); - ias_cmd = (struct descriptor *)&tx_ring[tx_cur]; + ias_cmd = &tx_ring[tx_cur]; ias_cmd->command = cpu_to_le16(CONFIG_SYS_CMD_SUSPEND | CONFIG_SYS_CMD_IAS); ias_cmd->status = 0; ias_cmd->link = cpu_to_le32(phys_to_bus((u32)&tx_ring[tx_next])); - memcpy(ias_cmd->params, dev->enetaddr, 6); - - /* Tell the adapter where the TX ring is located. */ - if (!wait_for_eepro100(dev)) { - printf("Error: Can not reset ethernet controller.\n"); - goto done; - } - - OUTL(dev, phys_to_bus((u32)&tx_ring[tx_cur]), SCB_POINTER); - OUTW(dev, SCB_M | CU_START, SCB_CMD); - - for (i = 0; - !(le16_to_cpu(tx_ring[tx_cur].status) & CONFIG_SYS_STATUS_C); - i++) { - if (i >= TOUT_LOOP) { - printf("%s: Tx error buffer not ready\n", - dev->name); - goto done; - } - } + memcpy(((struct descriptor *)ias_cmd)->params, dev->enetaddr, 6); - if (!(le16_to_cpu(tx_ring[tx_cur].status) & CONFIG_SYS_STATUS_OK)) { - printf("TX error status = 0x%08X\n", - le16_to_cpu(tx_ring[tx_cur].status)); + ret = eepro100_txcmd_send(dev, ias_cmd); + if (ret) { + if (ret == -ETIMEDOUT) + printf("Error: Can not reset ethernet controller.\n"); goto done; } @@ -574,7 +573,7 @@ done: static int eepro100_send(struct eth_device *dev, void *packet, int length) { - int i, status = -1; + int ret, status = -1; int tx_cur; if (length <= 0) { @@ -597,28 +596,11 @@ static int eepro100_send(struct eth_device *dev, void *packet, int length) cpu_to_le32 (phys_to_bus((u_long)packet)); tx_ring[tx_cur].tx_buf_size0 = cpu_to_le32 (length); - if (!wait_for_eepro100(dev)) { - printf("%s: Tx error ethernet controller not ready.\n", - dev->name); - goto done; - } - - /* Send the packet. */ - OUTL(dev, phys_to_bus((u32)&tx_ring[tx_cur]), SCB_POINTER); - OUTW(dev, SCB_M | CU_START, SCB_CMD); - - for (i = 0; - !(le16_to_cpu(tx_ring[tx_cur].status) & CONFIG_SYS_STATUS_C); - i++) { - if (i >= TOUT_LOOP) { - printf("%s: Tx error buffer not ready\n", dev->name); - goto done; - } - } - - if (!(le16_to_cpu(tx_ring[tx_cur].status) & CONFIG_SYS_STATUS_OK)) { - printf("TX error status = 0x%08X\n", - le16_to_cpu(tx_ring[tx_cur].status)); + ret = eepro100_txcmd_send(dev, &tx_ring[tx_cur]); + if (ret) { + if (ret == -ETIMEDOUT) + printf("%s: Tx error ethernet controller not ready.\n", + dev->name); goto done; } -- cgit v1.1 From 5116aae111b317e82c023af911082aa8d3526a4f Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sat, 23 May 2020 14:55:26 +0200 Subject: net: eepro100: Add cache management Add cache invalidation and flushes wherever the DMA descriptors are written or read, otherwise this driver cannot work reliably on any systems where caches are enabled. Signed-off-by: Marek Vasut --- drivers/net/eepro100.c | 65 ++++++++++++++++++++++++++++++++++---------------- 1 file changed, 45 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/net/eepro100.c b/drivers/net/eepro100.c index 03ba9a4..89bfcfb 100644 --- a/drivers/net/eepro100.c +++ b/drivers/net/eepro100.c @@ -5,6 +5,7 @@ */ #include +#include #include #include #include @@ -459,6 +460,9 @@ static int eepro100_txcmd_send(struct eth_device *dev, u16 rstat; int i = 0; + flush_dcache_range((unsigned long)desc, + (unsigned long)desc + sizeof(*desc)); + if (!wait_for_eepro100(dev)) return -ETIMEDOUT; @@ -466,6 +470,8 @@ static int eepro100_txcmd_send(struct eth_device *dev, OUTW(dev, SCB_M | CU_START, SCB_CMD); while (true) { + invalidate_dcache_range((unsigned long)desc, + (unsigned long)desc + sizeof(*desc)); rstat = le16_to_cpu(desc->status); if (rstat & CONFIG_SYS_STATUS_C) break; @@ -476,6 +482,8 @@ static int eepro100_txcmd_send(struct eth_device *dev, } } + invalidate_dcache_range((unsigned long)desc, + (unsigned long)desc + sizeof(*desc)); rstat = le16_to_cpu(desc->status); if (!(rstat & CONFIG_SYS_STATUS_OK)) { @@ -523,6 +531,7 @@ static int eepro100_init(struct eth_device *dev, bd_t *bis) goto done; } + /* RX ring cache was already flushed in init_rx_ring() */ OUTL(dev, phys_to_bus((u32)&rx_ring[rx_next]), SCB_POINTER); OUTW(dev, SCB_M | RUC_START, SCB_CMD); @@ -573,6 +582,7 @@ done: static int eepro100_send(struct eth_device *dev, void *packet, int length) { + struct eepro100_txfd *desc; int ret, status = -1; int tx_cur; @@ -584,17 +594,15 @@ static int eepro100_send(struct eth_device *dev, void *packet, int length) tx_cur = tx_next; tx_next = (tx_next + 1) % NUM_TX_DESC; - tx_ring[tx_cur].command = cpu_to_le16(TXCB_CMD_TRANSMIT | TXCB_CMD_SF | - TXCB_CMD_S | TXCB_CMD_EL); - tx_ring[tx_cur].status = 0; - tx_ring[tx_cur].count = cpu_to_le32 (tx_threshold); - tx_ring[tx_cur].link = - cpu_to_le32 (phys_to_bus((u32)&tx_ring[tx_next])); - tx_ring[tx_cur].tx_desc_addr = - cpu_to_le32 (phys_to_bus((u32)&tx_ring[tx_cur].tx_buf_addr0)); - tx_ring[tx_cur].tx_buf_addr0 = - cpu_to_le32 (phys_to_bus((u_long)packet)); - tx_ring[tx_cur].tx_buf_size0 = cpu_to_le32 (length); + desc = &tx_ring[tx_cur]; + desc->command = cpu_to_le16(TXCB_CMD_TRANSMIT | TXCB_CMD_SF | + TXCB_CMD_S | TXCB_CMD_EL); + desc->status = 0; + desc->count = cpu_to_le32(tx_threshold); + desc->link = cpu_to_le32(phys_to_bus((u32)&tx_ring[tx_next])); + desc->tx_desc_addr = cpu_to_le32(phys_to_bus((u32)&desc->tx_buf_addr0)); + desc->tx_buf_addr0 = cpu_to_le32(phys_to_bus((u_long)packet)); + desc->tx_buf_size0 = cpu_to_le32(length); ret = eepro100_txcmd_send(dev, &tx_ring[tx_cur]); if (ret) { @@ -612,14 +620,18 @@ done: static int eepro100_recv(struct eth_device *dev) { - u16 status, stat; + struct eepro100_rxfd *desc; int rx_prev, length = 0; + u16 status, stat; stat = INW(dev, SCB_STATUS); OUTW(dev, stat & SCB_STATUS_RNR, SCB_STATUS); for (;;) { - status = le16_to_cpu(rx_ring[rx_next].status); + desc = &rx_ring[rx_next]; + invalidate_dcache_range((unsigned long)desc, + (unsigned long)desc + sizeof(*desc)); + status = le16_to_cpu(desc->status); if (!(status & RFD_STATUS_C)) break; @@ -627,22 +639,26 @@ static int eepro100_recv(struct eth_device *dev) /* Valid frame status. */ if ((status & RFD_STATUS_OK)) { /* A valid frame received. */ - length = le32_to_cpu(rx_ring[rx_next].count) & 0x3fff; + length = le32_to_cpu(desc->count) & 0x3fff; /* Pass the packet up to the protocol layers. */ - net_process_received_packet((u8 *)rx_ring[rx_next].data, - length); + net_process_received_packet((u8 *)desc->data, length); } else { /* There was an error. */ printf("RX error status = 0x%08X\n", status); } - rx_ring[rx_next].control = cpu_to_le16 (RFD_CONTROL_S); - rx_ring[rx_next].status = 0; - rx_ring[rx_next].count = cpu_to_le32 (PKTSIZE_ALIGN << 16); + desc->control = cpu_to_le16(RFD_CONTROL_S); + desc->status = 0; + desc->count = cpu_to_le32(PKTSIZE_ALIGN << 16); + flush_dcache_range((unsigned long)desc, + (unsigned long)desc + sizeof(*desc)); rx_prev = (rx_next + NUM_RX_DESC - 1) % NUM_RX_DESC; - rx_ring[rx_prev].control = 0; + desc = &rx_ring[rx_prev]; + desc->control = 0; + flush_dcache_range((unsigned long)desc, + (unsigned long)desc + sizeof(*desc)); /* Update entry information. */ rx_next = (rx_next + 1) % NUM_RX_DESC; @@ -659,6 +675,7 @@ static int eepro100_recv(struct eth_device *dev) goto done; } + /* RX ring cache was already flushed in init_rx_ring() */ OUTL(dev, phys_to_bus((u32)&rx_ring[rx_next]), SCB_POINTER); OUTW(dev, SCB_M | RUC_START, SCB_CMD); } @@ -744,6 +761,10 @@ static void init_rx_ring(struct eth_device *dev) rx_ring[i].count = cpu_to_le32(PKTSIZE_ALIGN << 16); } + flush_dcache_range((unsigned long)rx_ring, + (unsigned long)rx_ring + + (sizeof(*rx_ring) * NUM_RX_DESC)); + rx_next = 0; } @@ -752,6 +773,10 @@ static void purge_tx_ring(struct eth_device *dev) tx_next = 0; tx_threshold = 0x01208000; memset(tx_ring, 0, sizeof(*tx_ring) * NUM_TX_DESC); + + flush_dcache_range((unsigned long)tx_ring, + (unsigned long)tx_ring + + (sizeof(*tx_ring) * NUM_TX_DESC)); } static void read_hw_addr(struct eth_device *dev, bd_t *bis) -- cgit v1.1 From d47cf87db9c89eb0cd00d586111b3b6579b6a5ef Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sat, 23 May 2020 15:02:47 +0200 Subject: net: eepro100: Remove volatile misuse Remove all the remaining use of the 'volatile' keyword, as this is no longer required. All the accesses which might have needed this use of 'volatile' have been repaired properly. Signed-off-by: Marek Vasut --- drivers/net/eepro100.c | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/net/eepro100.c b/drivers/net/eepro100.c index 89bfcfb..f3bcb0d 100644 --- a/drivers/net/eepro100.c +++ b/drivers/net/eepro100.c @@ -103,13 +103,13 @@ /* Receive frame descriptors. */ struct eepro100_rxfd { - volatile u16 status; - volatile u16 control; - volatile u32 link; /* struct eepro100_rxfd * */ - volatile u32 rx_buf_addr; /* void * */ - volatile u32 count; + u16 status; + u16 control; + u32 link; /* struct eepro100_rxfd * */ + u32 rx_buf_addr; /* void * */ + u32 count; - volatile u8 data[PKTSIZE_ALIGN]; + u8 data[PKTSIZE_ALIGN]; }; #define RFD_STATUS_C 0x8000 /* completion of received frame */ @@ -136,17 +136,17 @@ struct eepro100_rxfd { #define RFD_RX_TCO 0x0001 /* TCO indication */ /* Transmit frame descriptors */ -struct eepro100_txfd { /* Transmit frame descriptor set. */ - volatile u16 status; - volatile u16 command; - volatile u32 link; /* void * */ - volatile u32 tx_desc_addr; /* Always points to the tx_buf_addr element. */ - volatile s32 count; - - volatile u32 tx_buf_addr0; /* void *, frame to be transmitted. */ - volatile s32 tx_buf_size0; /* Length of Tx frame. */ - volatile u32 tx_buf_addr1; /* void *, frame to be transmitted. */ - volatile s32 tx_buf_size1; /* Length of Tx frame. */ +struct eepro100_txfd { /* Transmit frame descriptor set. */ + u16 status; + u16 command; + u32 link; /* void * */ + u32 tx_desc_addr; /* Always points to the tx_buf_addr element. */ + s32 count; + + u32 tx_buf_addr0; /* void *, frame to be transmitted. */ + s32 tx_buf_size0; /* Length of Tx frame. */ + u32 tx_buf_addr1; /* void *, frame to be transmitted. */ + s32 tx_buf_size1; /* Length of Tx frame. */ }; #define TXCB_CMD_TRANSMIT 0x0004 /* transmit command */ @@ -160,10 +160,10 @@ struct eepro100_txfd { /* Transmit frame descriptor set. */ #define TXCB_COUNT_EOF 0x8000 /* The Speedo3 Rx and Tx frame/buffer descriptors. */ -struct descriptor { /* A generic descriptor. */ - volatile u16 status; - volatile u16 command; - volatile u32 link; /* struct descriptor * */ +struct descriptor { /* A generic descriptor. */ + u16 status; + u16 command; + u32 link; /* struct descriptor * */ unsigned char params[0]; }; -- cgit v1.1 From 047a800dd6370c5f004b47751f72bb9d4a5d2af5 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sat, 23 May 2020 15:07:30 +0200 Subject: net: eepro100: Reorder functions in the driver Move the functions around in the driver to prepare it for DM conversion. Drop forward declarations which are not necessary anymore. No functional change. Signed-off-by: Marek Vasut --- drivers/net/eepro100.c | 330 ++++++++++++++++++++++++------------------------- 1 file changed, 160 insertions(+), 170 deletions(-) (limited to 'drivers') diff --git a/drivers/net/eepro100.c b/drivers/net/eepro100.c index f3bcb0d..9db9367 100644 --- a/drivers/net/eepro100.c +++ b/drivers/net/eepro100.c @@ -5,13 +5,13 @@ */ #include +#include #include #include +#include #include #include -#include #include -#include #include /* Ethernet chip registers. */ @@ -201,16 +201,6 @@ static const char i82558_config_cmd[] = { 0x31, 0x05, }; -static void init_rx_ring(struct eth_device *dev); -static void purge_tx_ring(struct eth_device *dev); - -static void read_hw_addr(struct eth_device *dev, bd_t *bis); - -static int eepro100_init(struct eth_device *dev, bd_t *bis); -static int eepro100_send(struct eth_device *dev, void *packet, int length); -static int eepro100_recv(struct eth_device *dev); -static void eepro100_halt(struct eth_device *dev); - #if defined(CONFIG_E500) #define bus_to_phys(a) (a) #define phys_to_bus(a) (a) @@ -353,105 +343,50 @@ static int eepro100_miiphy_write(struct mii_dev *bus, int addr, int devad, #endif -/* Wait for the chip get the command. */ -static int wait_for_eepro100(struct eth_device *dev) +static void init_rx_ring(struct eth_device *dev) { int i; - for (i = 0; INW(dev, SCB_CMD) & (CU_CMD_MASK | RU_CMD_MASK); i++) { - if (i >= TOUT_LOOP) - return 0; + for (i = 0; i < NUM_RX_DESC; i++) { + rx_ring[i].status = 0; + rx_ring[i].control = (i == NUM_RX_DESC - 1) ? + cpu_to_le16 (RFD_CONTROL_S) : 0; + rx_ring[i].link = + cpu_to_le32(phys_to_bus((u32)&rx_ring[(i + 1) % + NUM_RX_DESC])); + rx_ring[i].rx_buf_addr = 0xffffffff; + rx_ring[i].count = cpu_to_le32(PKTSIZE_ALIGN << 16); } - return 1; -} + flush_dcache_range((unsigned long)rx_ring, + (unsigned long)rx_ring + + (sizeof(*rx_ring) * NUM_RX_DESC)); -static struct pci_device_id supported[] = { - {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82557}, - {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82559}, - {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82559ER}, - {} -}; + rx_next = 0; +} -int eepro100_initialize(bd_t *bis) +static void purge_tx_ring(struct eth_device *dev) { - pci_dev_t devno; - int card_number = 0; - struct eth_device *dev; - u32 iobase, status; - int idx = 0; - - while (1) { - /* Find PCI device */ - devno = pci_find_devices(supported, idx++); - if (devno < 0) - break; - - pci_read_config_dword(devno, PCI_BASE_ADDRESS_0, &iobase); - iobase &= ~0xf; - - debug("eepro100: Intel i82559 PCI EtherExpressPro @0x%x\n", - iobase); - - pci_write_config_dword(devno, PCI_COMMAND, - PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); - - /* Check if I/O accesses and Bus Mastering are enabled. */ - pci_read_config_dword(devno, PCI_COMMAND, &status); - if (!(status & PCI_COMMAND_MEMORY)) { - printf("Error: Can not enable MEM access.\n"); - continue; - } - - if (!(status & PCI_COMMAND_MASTER)) { - printf("Error: Can not enable Bus Mastering.\n"); - continue; - } - - dev = (struct eth_device *)malloc(sizeof(*dev)); - if (!dev) { - printf("eepro100: Can not allocate memory\n"); - break; - } - memset(dev, 0, sizeof(*dev)); - - sprintf(dev->name, "i82559#%d", card_number); - dev->priv = (void *)devno; /* this have to come before bus_to_phys() */ - dev->iobase = bus_to_phys(iobase); - dev->init = eepro100_init; - dev->halt = eepro100_halt; - dev->send = eepro100_send; - dev->recv = eepro100_recv; - - eth_register(dev); - -#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) - /* register mii command access routines */ - int retval; - struct mii_dev *mdiodev = mdio_alloc(); - - if (!mdiodev) - return -ENOMEM; - strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN); - mdiodev->read = eepro100_miiphy_read; - mdiodev->write = eepro100_miiphy_write; - - retval = mdio_register(mdiodev); - if (retval < 0) - return retval; -#endif - - card_number++; + tx_next = 0; + tx_threshold = 0x01208000; + memset(tx_ring, 0, sizeof(*tx_ring) * NUM_TX_DESC); - /* Set the latency timer for value. */ - pci_write_config_byte(devno, PCI_LATENCY_TIMER, 0x20); + flush_dcache_range((unsigned long)tx_ring, + (unsigned long)tx_ring + + (sizeof(*tx_ring) * NUM_TX_DESC)); +} - udelay(10 * 1000); +/* Wait for the chip get the command. */ +static int wait_for_eepro100(struct eth_device *dev) +{ + int i; - read_hw_addr(dev, bis); + for (i = 0; INW(dev, SCB_CMD) & (CU_CMD_MASK | RU_CMD_MASK); i++) { + if (i >= TOUT_LOOP) + return 0; } - return card_number; + return 1; } static int eepro100_txcmd_send(struct eth_device *dev, @@ -494,6 +429,71 @@ static int eepro100_txcmd_send(struct eth_device *dev, return 0; } +/* SROM Read. */ +static int read_eeprom(struct eth_device *dev, int location, int addr_len) +{ + unsigned short retval = 0; + int read_cmd = location | EE_READ_CMD; + int i; + + OUTW(dev, EE_ENB & ~EE_CS, SCB_EEPROM); + OUTW(dev, EE_ENB, SCB_EEPROM); + + /* Shift the read command bits out. */ + for (i = 12; i >= 0; i--) { + short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0; + + OUTW(dev, EE_ENB | dataval, SCB_EEPROM); + udelay(1); + OUTW(dev, EE_ENB | dataval | EE_SHIFT_CLK, SCB_EEPROM); + udelay(1); + } + OUTW(dev, EE_ENB, SCB_EEPROM); + + for (i = 15; i >= 0; i--) { + OUTW(dev, EE_ENB | EE_SHIFT_CLK, SCB_EEPROM); + udelay(1); + retval = (retval << 1) | + ((INW(dev, SCB_EEPROM) & EE_DATA_READ) ? 1 : 0); + OUTW(dev, EE_ENB, SCB_EEPROM); + udelay(1); + } + + /* Terminate the EEPROM access. */ + OUTW(dev, EE_ENB & ~EE_CS, SCB_EEPROM); + return retval; +} + +static struct pci_device_id supported[] = { + {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82557}, + {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82559}, + {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82559ER}, + {} +}; + +static void read_hw_addr(struct eth_device *dev, bd_t *bis) +{ + u16 sum = 0; + int i, j; + int addr_len = read_eeprom(dev, 0, 6) == 0xffff ? 8 : 6; + + for (j = 0, i = 0; i < 0x40; i++) { + u16 value = read_eeprom(dev, i, addr_len); + + sum += value; + if (i < 3) { + dev->enetaddr[j++] = value; + dev->enetaddr[j++] = value >> 8; + } + } + + if (sum != 0xBABA) { + memset(dev->enetaddr, 0, ETH_ALEN); + debug("%s: Invalid EEPROM checksum %#4.4x, check settings before activating this device!\n", + dev->name, sum); + } +} + static int eepro100_init(struct eth_device *dev, bd_t *bis) { struct eepro100_txfd *ias_cmd, *cfg_cmd; @@ -711,93 +711,83 @@ done: return; } -/* SROM Read. */ -static int read_eeprom(struct eth_device *dev, int location, int addr_len) +int eepro100_initialize(bd_t *bis) { - unsigned short retval = 0; - int read_cmd = location | EE_READ_CMD; - int i; + pci_dev_t devno; + int card_number = 0; + struct eth_device *dev; + u32 iobase, status; + int idx = 0; - OUTW(dev, EE_ENB & ~EE_CS, SCB_EEPROM); - OUTW(dev, EE_ENB, SCB_EEPROM); + while (1) { + /* Find PCI device */ + devno = pci_find_devices(supported, idx++); + if (devno < 0) + break; - /* Shift the read command bits out. */ - for (i = 12; i >= 0; i--) { - short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0; + pci_read_config_dword(devno, PCI_BASE_ADDRESS_0, &iobase); + iobase &= ~0xf; - OUTW(dev, EE_ENB | dataval, SCB_EEPROM); - udelay(1); - OUTW(dev, EE_ENB | dataval | EE_SHIFT_CLK, SCB_EEPROM); - udelay(1); - } - OUTW(dev, EE_ENB, SCB_EEPROM); + debug("eepro100: Intel i82559 PCI EtherExpressPro @0x%x\n", + iobase); - for (i = 15; i >= 0; i--) { - OUTW(dev, EE_ENB | EE_SHIFT_CLK, SCB_EEPROM); - udelay(1); - retval = (retval << 1) | - ((INW(dev, SCB_EEPROM) & EE_DATA_READ) ? 1 : 0); - OUTW(dev, EE_ENB, SCB_EEPROM); - udelay(1); - } + pci_write_config_dword(devno, PCI_COMMAND, + PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); - /* Terminate the EEPROM access. */ - OUTW(dev, EE_ENB & ~EE_CS, SCB_EEPROM); - return retval; -} + /* Check if I/O accesses and Bus Mastering are enabled. */ + pci_read_config_dword(devno, PCI_COMMAND, &status); + if (!(status & PCI_COMMAND_MEMORY)) { + printf("Error: Can not enable MEM access.\n"); + continue; + } -static void init_rx_ring(struct eth_device *dev) -{ - int i; + if (!(status & PCI_COMMAND_MASTER)) { + printf("Error: Can not enable Bus Mastering.\n"); + continue; + } - for (i = 0; i < NUM_RX_DESC; i++) { - rx_ring[i].status = 0; - rx_ring[i].control = (i == NUM_RX_DESC - 1) ? - cpu_to_le16 (RFD_CONTROL_S) : 0; - rx_ring[i].link = - cpu_to_le32(phys_to_bus((u32)&rx_ring[(i + 1) % - NUM_RX_DESC])); - rx_ring[i].rx_buf_addr = 0xffffffff; - rx_ring[i].count = cpu_to_le32(PKTSIZE_ALIGN << 16); - } + dev = (struct eth_device *)malloc(sizeof(*dev)); + if (!dev) { + printf("eepro100: Can not allocate memory\n"); + break; + } + memset(dev, 0, sizeof(*dev)); - flush_dcache_range((unsigned long)rx_ring, - (unsigned long)rx_ring + - (sizeof(*rx_ring) * NUM_RX_DESC)); + sprintf(dev->name, "i82559#%d", card_number); + dev->priv = (void *)devno; /* this have to come before bus_to_phys() */ + dev->iobase = bus_to_phys(iobase); + dev->init = eepro100_init; + dev->halt = eepro100_halt; + dev->send = eepro100_send; + dev->recv = eepro100_recv; - rx_next = 0; -} + eth_register(dev); -static void purge_tx_ring(struct eth_device *dev) -{ - tx_next = 0; - tx_threshold = 0x01208000; - memset(tx_ring, 0, sizeof(*tx_ring) * NUM_TX_DESC); +#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) + /* register mii command access routines */ + int retval; + struct mii_dev *mdiodev = mdio_alloc(); - flush_dcache_range((unsigned long)tx_ring, - (unsigned long)tx_ring + - (sizeof(*tx_ring) * NUM_TX_DESC)); -} + if (!mdiodev) + return -ENOMEM; + strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN); + mdiodev->read = eepro100_miiphy_read; + mdiodev->write = eepro100_miiphy_write; -static void read_hw_addr(struct eth_device *dev, bd_t *bis) -{ - u16 sum = 0; - int i, j; - int addr_len = read_eeprom(dev, 0, 6) == 0xffff ? 8 : 6; + retval = mdio_register(mdiodev); + if (retval < 0) + return retval; +#endif - for (j = 0, i = 0; i < 0x40; i++) { - u16 value = read_eeprom(dev, i, addr_len); + card_number++; - sum += value; - if (i < 3) { - dev->enetaddr[j++] = value; - dev->enetaddr[j++] = value >> 8; - } - } + /* Set the latency timer for value. */ + pci_write_config_byte(devno, PCI_LATENCY_TIMER, 0x20); - if (sum != 0xBABA) { - memset(dev->enetaddr, 0, ETH_ALEN); - debug("%s: Invalid EEPROM checksum %#4.4x, check settings before activating this device!\n", - dev->name, sum); + udelay(10 * 1000); + + read_hw_addr(dev, bis); } + + return card_number; } -- cgit v1.1 From 3a15684dc6ecc9dcc74e3a9357d8e91ebd50aed7 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sat, 23 May 2020 15:11:30 +0200 Subject: net: eepro100: Use PCI_DEVICE() to define PCI device compat list Use this macro to fully fill the PCI device ID table. This is mandatory for the DM PCI support, which checks all the fields. Signed-off-by: Marek Vasut --- drivers/net/eepro100.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/eepro100.c b/drivers/net/eepro100.c index 9db9367..74b09e9 100644 --- a/drivers/net/eepro100.c +++ b/drivers/net/eepro100.c @@ -465,10 +465,10 @@ static int read_eeprom(struct eth_device *dev, int location, int addr_len) } static struct pci_device_id supported[] = { - {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82557}, - {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82559}, - {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82559ER}, - {} + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82557) }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82559) }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82559ER) }, + { } }; static void read_hw_addr(struct eth_device *dev, bd_t *bis) -- cgit v1.1 From 6c7d3f6b3fb5860f55d1c7733d2b5929e0721e99 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sat, 23 May 2020 16:13:30 +0200 Subject: net: eepro100: Switch from malloc()+memset() to calloc() Replace malloc()+memset() combination with calloc(), no functional change. Signed-off-by: Marek Vasut --- drivers/net/eepro100.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/eepro100.c b/drivers/net/eepro100.c index 74b09e9..8fa6657 100644 --- a/drivers/net/eepro100.c +++ b/drivers/net/eepro100.c @@ -746,12 +746,11 @@ int eepro100_initialize(bd_t *bis) continue; } - dev = (struct eth_device *)malloc(sizeof(*dev)); + dev = calloc(1, sizeof(*dev)); if (!dev) { printf("eepro100: Can not allocate memory\n"); break; } - memset(dev, 0, sizeof(*dev)); sprintf(dev->name, "i82559#%d", card_number); dev->priv = (void *)devno; /* this have to come before bus_to_phys() */ -- cgit v1.1 From 66fed7300d250197c24fb54cad7f6cae7df95fe1 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sat, 23 May 2020 16:20:25 +0200 Subject: net: eepro100: Factor out MII registration Pull the MII registration code into a separate function. Moreover, properly free memory in case any of the registration or allocation functions fail, so this fixes an existing memleak. Signed-off-by: Marek Vasut --- drivers/net/eepro100.c | 56 +++++++++++++++++++++++++++++++++++--------------- 1 file changed, 39 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/net/eepro100.c b/drivers/net/eepro100.c index 8fa6657..861d39c 100644 --- a/drivers/net/eepro100.c +++ b/drivers/net/eepro100.c @@ -464,6 +464,36 @@ static int read_eeprom(struct eth_device *dev, int location, int addr_len) return retval; } +#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) +static int eepro100_initialize_mii(struct eth_device *dev) +{ + /* register mii command access routines */ + struct mii_dev *mdiodev; + int ret; + + mdiodev = mdio_alloc(); + if (!mdiodev) + return -ENOMEM; + + strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN); + mdiodev->read = eepro100_miiphy_read; + mdiodev->write = eepro100_miiphy_write; + + ret = mdio_register(mdiodev); + if (ret < 0) { + mdio_free(mdiodev); + return ret; + } + + return 0; +} +#else +static int eepro100_initialize_mii(struct eth_device *dev) +{ + return 0; +} +#endif + static struct pci_device_id supported[] = { { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82557) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82559) }, @@ -713,11 +743,12 @@ done: int eepro100_initialize(bd_t *bis) { - pci_dev_t devno; - int card_number = 0; struct eth_device *dev; + int card_number = 0; u32 iobase, status; + pci_dev_t devno; int idx = 0; + int ret; while (1) { /* Find PCI device */ @@ -762,21 +793,12 @@ int eepro100_initialize(bd_t *bis) eth_register(dev); -#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) - /* register mii command access routines */ - int retval; - struct mii_dev *mdiodev = mdio_alloc(); - - if (!mdiodev) - return -ENOMEM; - strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN); - mdiodev->read = eepro100_miiphy_read; - mdiodev->write = eepro100_miiphy_write; - - retval = mdio_register(mdiodev); - if (retval < 0) - return retval; -#endif + ret = eepro100_initialize_mii(dev); + if (ret) { + eth_unregister(dev); + free(dev); + return ret; + } card_number++; -- cgit v1.1 From a6c06ec8f6598f248ade50d4dd7e5b2f32df2dde Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sat, 23 May 2020 16:23:28 +0200 Subject: net: eepro100: Fix EE_*_CMD macros Those macros depended on specific variable names to be declared at their usage sites, fix this by adding an argument to those macros and also protect the argument with braces. Signed-off-by: Marek Vasut --- drivers/net/eepro100.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/eepro100.c b/drivers/net/eepro100.c index 861d39c..a8d617c 100644 --- a/drivers/net/eepro100.c +++ b/drivers/net/eepro100.c @@ -96,10 +96,10 @@ #define EE_DATA_BITS 16 /* The EEPROM commands include the alway-set leading bit. */ -#define EE_EWENB_CMD (4 << addr_len) -#define EE_WRITE_CMD (5 << addr_len) -#define EE_READ_CMD (6 << addr_len) -#define EE_ERASE_CMD (7 << addr_len) +#define EE_EWENB_CMD(addr_len) (4 << (addr_len)) +#define EE_WRITE_CMD(addr_len) (5 << (addr_len)) +#define EE_READ_CMD(addr_len) (6 << (addr_len)) +#define EE_ERASE_CMD(addr_len) (7 << (addr_len)) /* Receive frame descriptors. */ struct eepro100_rxfd { @@ -433,7 +433,7 @@ static int eepro100_txcmd_send(struct eth_device *dev, static int read_eeprom(struct eth_device *dev, int location, int addr_len) { unsigned short retval = 0; - int read_cmd = location | EE_READ_CMD; + int read_cmd = location | EE_READ_CMD(addr_len); int i; OUTW(dev, EE_ENB & ~EE_CS, SCB_EEPROM); -- cgit v1.1 From acdf5d88827a0420ed0ceee3e45fa08f9d39b483 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sat, 23 May 2020 16:27:37 +0200 Subject: net: eepro100: Drop inline keyword Drop the inline keyword from the static functions, the compiler has a much better overview and can decide how to inline those functions much better. Signed-off-by: Marek Vasut --- drivers/net/eepro100.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/eepro100.c b/drivers/net/eepro100.c index a8d617c..4446251 100644 --- a/drivers/net/eepro100.c +++ b/drivers/net/eepro100.c @@ -209,23 +209,23 @@ static const char i82558_config_cmd[] = { #define phys_to_bus(a) pci_phys_to_mem((pci_dev_t)dev->priv, a) #endif -static inline int INW(struct eth_device *dev, u_long addr) +static int INW(struct eth_device *dev, u_long addr) { return le16_to_cpu(readw(addr + (void *)dev->iobase)); } -static inline void OUTW(struct eth_device *dev, int command, u_long addr) +static void OUTW(struct eth_device *dev, int command, u_long addr) { writew(cpu_to_le16(command), addr + (void *)dev->iobase); } -static inline void OUTL(struct eth_device *dev, int command, u_long addr) +static void OUTL(struct eth_device *dev, int command, u_long addr) { writel(cpu_to_le32(command), addr + (void *)dev->iobase); } #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) -static inline int INL(struct eth_device *dev, u_long addr) +static int INL(struct eth_device *dev, u_long addr) { return le32_to_cpu(readl(addr + (void *)dev->iobase)); } -- cgit v1.1 From fa9e12102dfc6a5f1f10a75fd1804c16a166ded9 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sat, 23 May 2020 16:38:41 +0200 Subject: net: eepro100: Pass PCI BDF into bus_to_phys()/phys_to_bus() This is a trick in preparation for adding DM support. By passing in the PCI BDF into the bus_to_phys()/phys_to_bus() macros and calling that dev, we can substitute dev with udevice when DM support lands and do minor adjustment to the macros to support both DM and non-DM operation. No functional change. Signed-off-by: Marek Vasut --- drivers/net/eepro100.c | 36 ++++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/net/eepro100.c b/drivers/net/eepro100.c index 4446251..532d7aa 100644 --- a/drivers/net/eepro100.c +++ b/drivers/net/eepro100.c @@ -202,11 +202,11 @@ static const char i82558_config_cmd[] = { }; #if defined(CONFIG_E500) -#define bus_to_phys(a) (a) -#define phys_to_bus(a) (a) +#define bus_to_phys(dev, a) (a) +#define phys_to_bus(dev, a) (a) #else -#define bus_to_phys(a) pci_mem_to_phys((pci_dev_t)dev->priv, a) -#define phys_to_bus(a) pci_phys_to_mem((pci_dev_t)dev->priv, a) +#define bus_to_phys(dev, a) pci_mem_to_phys((dev), (a)) +#define phys_to_bus(dev, a) pci_phys_to_mem((dev), (a)) #endif static int INW(struct eth_device *dev, u_long addr) @@ -352,7 +352,8 @@ static void init_rx_ring(struct eth_device *dev) rx_ring[i].control = (i == NUM_RX_DESC - 1) ? cpu_to_le16 (RFD_CONTROL_S) : 0; rx_ring[i].link = - cpu_to_le32(phys_to_bus((u32)&rx_ring[(i + 1) % + cpu_to_le32(phys_to_bus((pci_dev_t)dev->priv, + (u32)&rx_ring[(i + 1) % NUM_RX_DESC])); rx_ring[i].rx_buf_addr = 0xffffffff; rx_ring[i].count = cpu_to_le32(PKTSIZE_ALIGN << 16); @@ -401,7 +402,7 @@ static int eepro100_txcmd_send(struct eth_device *dev, if (!wait_for_eepro100(dev)) return -ETIMEDOUT; - OUTL(dev, phys_to_bus((u32)desc), SCB_POINTER); + OUTL(dev, phys_to_bus((pci_dev_t)dev->priv, (u32)desc), SCB_POINTER); OUTW(dev, SCB_M | CU_START, SCB_CMD); while (true) { @@ -562,7 +563,8 @@ static int eepro100_init(struct eth_device *dev, bd_t *bis) } /* RX ring cache was already flushed in init_rx_ring() */ - OUTL(dev, phys_to_bus((u32)&rx_ring[rx_next]), SCB_POINTER); + OUTL(dev, phys_to_bus((pci_dev_t)dev->priv, (u32)&rx_ring[rx_next]), + SCB_POINTER); OUTW(dev, SCB_M | RUC_START, SCB_CMD); /* Send the Configure frame */ @@ -573,7 +575,8 @@ static int eepro100_init(struct eth_device *dev, bd_t *bis) cfg_cmd->command = cpu_to_le16(CONFIG_SYS_CMD_SUSPEND | CONFIG_SYS_CMD_CONFIGURE); cfg_cmd->status = 0; - cfg_cmd->link = cpu_to_le32(phys_to_bus((u32)&tx_ring[tx_next])); + cfg_cmd->link = cpu_to_le32(phys_to_bus((pci_dev_t)dev->priv, + (u32)&tx_ring[tx_next])); memcpy(((struct descriptor *)cfg_cmd)->params, i82558_config_cmd, sizeof(i82558_config_cmd)); @@ -593,7 +596,8 @@ static int eepro100_init(struct eth_device *dev, bd_t *bis) ias_cmd->command = cpu_to_le16(CONFIG_SYS_CMD_SUSPEND | CONFIG_SYS_CMD_IAS); ias_cmd->status = 0; - ias_cmd->link = cpu_to_le32(phys_to_bus((u32)&tx_ring[tx_next])); + ias_cmd->link = cpu_to_le32(phys_to_bus((pci_dev_t)dev->priv, + (u32)&tx_ring[tx_next])); memcpy(((struct descriptor *)ias_cmd)->params, dev->enetaddr, 6); @@ -629,9 +633,12 @@ static int eepro100_send(struct eth_device *dev, void *packet, int length) TXCB_CMD_S | TXCB_CMD_EL); desc->status = 0; desc->count = cpu_to_le32(tx_threshold); - desc->link = cpu_to_le32(phys_to_bus((u32)&tx_ring[tx_next])); - desc->tx_desc_addr = cpu_to_le32(phys_to_bus((u32)&desc->tx_buf_addr0)); - desc->tx_buf_addr0 = cpu_to_le32(phys_to_bus((u_long)packet)); + desc->link = cpu_to_le32(phys_to_bus((pci_dev_t)dev->priv, + (u32)&tx_ring[tx_next])); + desc->tx_desc_addr = cpu_to_le32(phys_to_bus((pci_dev_t)dev->priv, + (u32)&desc->tx_buf_addr0)); + desc->tx_buf_addr0 = cpu_to_le32(phys_to_bus((pci_dev_t)dev->priv, + (u_long)packet)); desc->tx_buf_size0 = cpu_to_le32(length); ret = eepro100_txcmd_send(dev, &tx_ring[tx_cur]); @@ -706,7 +713,8 @@ static int eepro100_recv(struct eth_device *dev) } /* RX ring cache was already flushed in init_rx_ring() */ - OUTL(dev, phys_to_bus((u32)&rx_ring[rx_next]), SCB_POINTER); + OUTL(dev, phys_to_bus((pci_dev_t)dev->priv, + (u32)&rx_ring[rx_next]), SCB_POINTER); OUTW(dev, SCB_M | RUC_START, SCB_CMD); } @@ -785,7 +793,7 @@ int eepro100_initialize(bd_t *bis) sprintf(dev->name, "i82559#%d", card_number); dev->priv = (void *)devno; /* this have to come before bus_to_phys() */ - dev->iobase = bus_to_phys(iobase); + dev->iobase = bus_to_phys(devno, iobase); dev->init = eepro100_init; dev->halt = eepro100_halt; dev->send = eepro100_send; -- cgit v1.1 From bd159c6185676c87e4a1cdbb33a869d4c1e05f9e Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sat, 23 May 2020 16:49:07 +0200 Subject: net: eepro100: Introduce device private data Signed-off-by: Marek Vasut --- drivers/net/eepro100.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/eepro100.c b/drivers/net/eepro100.c index 532d7aa..2c25307 100644 --- a/drivers/net/eepro100.c +++ b/drivers/net/eepro100.c @@ -201,6 +201,10 @@ static const char i82558_config_cmd[] = { 0x31, 0x05, }; +struct eepro100_priv { + struct eth_device dev; +}; + #if defined(CONFIG_E500) #define bus_to_phys(dev, a) (a) #define phys_to_bus(dev, a) (a) @@ -751,6 +755,7 @@ done: int eepro100_initialize(bd_t *bis) { + struct eepro100_priv *priv; struct eth_device *dev; int card_number = 0; u32 iobase, status; @@ -785,11 +790,12 @@ int eepro100_initialize(bd_t *bis) continue; } - dev = calloc(1, sizeof(*dev)); - if (!dev) { + priv = calloc(1, sizeof(*priv)); + if (!priv) { printf("eepro100: Can not allocate memory\n"); break; } + dev = &priv->dev; sprintf(dev->name, "i82559#%d", card_number); dev->priv = (void *)devno; /* this have to come before bus_to_phys() */ @@ -804,7 +810,7 @@ int eepro100_initialize(bd_t *bis) ret = eepro100_initialize_mii(dev); if (ret) { eth_unregister(dev); - free(dev); + free(priv); return ret; } -- cgit v1.1 From 389da9743c269a0c8536f4700c11c333a0309958 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sat, 23 May 2020 17:10:03 +0200 Subject: net: eepro100: Pass device private data around This patch replaces the various uses of struct eth_device for accessing device private data with struct eepro100_priv, which is compatible both with DM and non-DM operation. Signed-off-by: Marek Vasut --- drivers/net/eepro100.c | 264 ++++++++++++++++++++++++++----------------------- 1 file changed, 140 insertions(+), 124 deletions(-) (limited to 'drivers') diff --git a/drivers/net/eepro100.c b/drivers/net/eepro100.c index 2c25307..1c33ec3 100644 --- a/drivers/net/eepro100.c +++ b/drivers/net/eepro100.c @@ -203,6 +203,10 @@ static const char i82558_config_cmd[] = { struct eepro100_priv { struct eth_device dev; + pci_dev_t devno; + char *name; + void __iomem *iobase; + u8 *enetaddr; }; #if defined(CONFIG_E500) @@ -213,40 +217,40 @@ struct eepro100_priv { #define phys_to_bus(dev, a) pci_phys_to_mem((dev), (a)) #endif -static int INW(struct eth_device *dev, u_long addr) +static int INW(struct eepro100_priv *priv, u_long addr) { - return le16_to_cpu(readw(addr + (void *)dev->iobase)); + return le16_to_cpu(readw(addr + priv->iobase)); } -static void OUTW(struct eth_device *dev, int command, u_long addr) +static void OUTW(struct eepro100_priv *priv, int command, u_long addr) { - writew(cpu_to_le16(command), addr + (void *)dev->iobase); + writew(cpu_to_le16(command), addr + priv->iobase); } -static void OUTL(struct eth_device *dev, int command, u_long addr) +static void OUTL(struct eepro100_priv *priv, int command, u_long addr) { - writel(cpu_to_le32(command), addr + (void *)dev->iobase); + writel(cpu_to_le32(command), addr + priv->iobase); } #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) -static int INL(struct eth_device *dev, u_long addr) +static int INL(struct eepro100_priv *priv, u_long addr) { - return le32_to_cpu(readl(addr + (void *)dev->iobase)); + return le32_to_cpu(readl(addr + priv->iobase)); } -static int get_phyreg(struct eth_device *dev, unsigned char addr, +static int get_phyreg(struct eepro100_priv *priv, unsigned char addr, unsigned char reg, unsigned short *value) { - int cmd; int timeout = 50; + int cmd; /* read requested data */ cmd = (2 << 26) | ((addr & 0x1f) << 21) | ((reg & 0x1f) << 16); - OUTL(dev, cmd, SCB_CTRL_MDI); + OUTL(priv, cmd, SCB_CTRL_MDI); do { udelay(1000); - cmd = INL(dev, SCB_CTRL_MDI); + cmd = INL(priv, SCB_CTRL_MDI); } while (!(cmd & (1 << 28)) && (--timeout)); if (timeout == 0) @@ -257,17 +261,17 @@ static int get_phyreg(struct eth_device *dev, unsigned char addr, return 0; } -static int set_phyreg(struct eth_device *dev, unsigned char addr, +static int set_phyreg(struct eepro100_priv *priv, unsigned char addr, unsigned char reg, unsigned short value) { - int cmd; int timeout = 50; + int cmd; /* write requested data */ cmd = (1 << 26) | ((addr & 0x1f) << 21) | ((reg & 0x1f) << 16); - OUTL(dev, cmd | value, SCB_CTRL_MDI); + OUTL(priv, cmd | value, SCB_CTRL_MDI); - while (!(INL(dev, SCB_CTRL_MDI) & (1 << 28)) && (--timeout)) + while (!(INL(priv, SCB_CTRL_MDI) & (1 << 28)) && (--timeout)) udelay(1000); if (timeout == 0) @@ -280,49 +284,45 @@ static int set_phyreg(struct eth_device *dev, unsigned char addr, * Check if given phyaddr is valid, i.e. there is a PHY connected. * Do this by checking model value field from ID2 register. */ -static struct eth_device *verify_phyaddr(const char *devname, - unsigned char addr) +static int verify_phyaddr(struct eepro100_priv *priv, unsigned char addr) { - struct eth_device *dev; - unsigned short value; - unsigned char model; - - dev = eth_get_dev_by_name(devname); - if (!dev) { - printf("%s: no such device\n", devname); - return NULL; - } + unsigned short value, model; + int ret; /* read id2 register */ - if (get_phyreg(dev, addr, MII_PHYSID2, &value) != 0) { - printf("%s: mii read timeout!\n", devname); - return NULL; + ret = get_phyreg(priv, addr, MII_PHYSID2, &value); + if (ret) { + printf("%s: mii read timeout!\n", priv->name); + return ret; } /* get model */ - model = (unsigned char)((value >> 4) & 0x003f); - - if (model == 0) { - printf("%s: no PHY at address %d\n", devname, addr); - return NULL; + model = (value >> 4) & 0x003f; + if (!model) { + printf("%s: no PHY at address %d\n", priv->name, addr); + return -EINVAL; } - return dev; + return 0; } static int eepro100_miiphy_read(struct mii_dev *bus, int addr, int devad, int reg) { + struct eth_device *dev = eth_get_dev_by_name(bus->name); + struct eepro100_priv *priv = + container_of(dev, struct eepro100_priv, dev); unsigned short value = 0; - struct eth_device *dev; + int ret; - dev = verify_phyaddr(bus->name, addr); - if (!dev) - return -1; + ret = verify_phyaddr(priv, addr); + if (ret) + return ret; - if (get_phyreg(dev, addr, reg, &value) != 0) { + ret = get_phyreg(priv, addr, reg, &value); + if (ret) { printf("%s: mii read timeout!\n", bus->name); - return -1; + return ret; } return value; @@ -331,23 +331,26 @@ static int eepro100_miiphy_read(struct mii_dev *bus, int addr, int devad, static int eepro100_miiphy_write(struct mii_dev *bus, int addr, int devad, int reg, u16 value) { - struct eth_device *dev; + struct eth_device *dev = eth_get_dev_by_name(bus->name); + struct eepro100_priv *priv = + container_of(dev, struct eepro100_priv, dev); + int ret; - dev = verify_phyaddr(bus->name, addr); - if (!dev) - return -1; + ret = verify_phyaddr(priv, addr); + if (ret) + return ret; - if (set_phyreg(dev, addr, reg, value) != 0) { + ret = set_phyreg(priv, addr, reg, value); + if (ret) { printf("%s: mii write timeout!\n", bus->name); - return -1; + return ret; } return 0; } - #endif -static void init_rx_ring(struct eth_device *dev) +static void init_rx_ring(struct eepro100_priv *priv) { int i; @@ -356,7 +359,7 @@ static void init_rx_ring(struct eth_device *dev) rx_ring[i].control = (i == NUM_RX_DESC - 1) ? cpu_to_le16 (RFD_CONTROL_S) : 0; rx_ring[i].link = - cpu_to_le32(phys_to_bus((pci_dev_t)dev->priv, + cpu_to_le32(phys_to_bus(priv->devno, (u32)&rx_ring[(i + 1) % NUM_RX_DESC])); rx_ring[i].rx_buf_addr = 0xffffffff; @@ -370,7 +373,7 @@ static void init_rx_ring(struct eth_device *dev) rx_next = 0; } -static void purge_tx_ring(struct eth_device *dev) +static void purge_tx_ring(struct eepro100_priv *priv) { tx_next = 0; tx_threshold = 0x01208000; @@ -382,11 +385,11 @@ static void purge_tx_ring(struct eth_device *dev) } /* Wait for the chip get the command. */ -static int wait_for_eepro100(struct eth_device *dev) +static int wait_for_eepro100(struct eepro100_priv *priv) { int i; - for (i = 0; INW(dev, SCB_CMD) & (CU_CMD_MASK | RU_CMD_MASK); i++) { + for (i = 0; INW(priv, SCB_CMD) & (CU_CMD_MASK | RU_CMD_MASK); i++) { if (i >= TOUT_LOOP) return 0; } @@ -394,7 +397,7 @@ static int wait_for_eepro100(struct eth_device *dev) return 1; } -static int eepro100_txcmd_send(struct eth_device *dev, +static int eepro100_txcmd_send(struct eepro100_priv *priv, struct eepro100_txfd *desc) { u16 rstat; @@ -403,11 +406,11 @@ static int eepro100_txcmd_send(struct eth_device *dev, flush_dcache_range((unsigned long)desc, (unsigned long)desc + sizeof(*desc)); - if (!wait_for_eepro100(dev)) + if (!wait_for_eepro100(priv)) return -ETIMEDOUT; - OUTL(dev, phys_to_bus((pci_dev_t)dev->priv, (u32)desc), SCB_POINTER); - OUTW(dev, SCB_M | CU_START, SCB_CMD); + OUTL(priv, phys_to_bus(priv->devno, (u32)desc), SCB_POINTER); + OUTW(priv, SCB_M | CU_START, SCB_CMD); while (true) { invalidate_dcache_range((unsigned long)desc, @@ -417,7 +420,7 @@ static int eepro100_txcmd_send(struct eth_device *dev, break; if (i++ >= TOUT_LOOP) { - printf("%s: Tx error buffer not ready\n", dev->name); + printf("%s: Tx error buffer not ready\n", priv->name); return -EINVAL; } } @@ -435,42 +438,42 @@ static int eepro100_txcmd_send(struct eth_device *dev, } /* SROM Read. */ -static int read_eeprom(struct eth_device *dev, int location, int addr_len) +static int read_eeprom(struct eepro100_priv *priv, int location, int addr_len) { unsigned short retval = 0; int read_cmd = location | EE_READ_CMD(addr_len); int i; - OUTW(dev, EE_ENB & ~EE_CS, SCB_EEPROM); - OUTW(dev, EE_ENB, SCB_EEPROM); + OUTW(priv, EE_ENB & ~EE_CS, SCB_EEPROM); + OUTW(priv, EE_ENB, SCB_EEPROM); /* Shift the read command bits out. */ for (i = 12; i >= 0; i--) { short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0; - OUTW(dev, EE_ENB | dataval, SCB_EEPROM); + OUTW(priv, EE_ENB | dataval, SCB_EEPROM); udelay(1); - OUTW(dev, EE_ENB | dataval | EE_SHIFT_CLK, SCB_EEPROM); + OUTW(priv, EE_ENB | dataval | EE_SHIFT_CLK, SCB_EEPROM); udelay(1); } - OUTW(dev, EE_ENB, SCB_EEPROM); + OUTW(priv, EE_ENB, SCB_EEPROM); for (i = 15; i >= 0; i--) { - OUTW(dev, EE_ENB | EE_SHIFT_CLK, SCB_EEPROM); + OUTW(priv, EE_ENB | EE_SHIFT_CLK, SCB_EEPROM); udelay(1); retval = (retval << 1) | - ((INW(dev, SCB_EEPROM) & EE_DATA_READ) ? 1 : 0); - OUTW(dev, EE_ENB, SCB_EEPROM); + !!(INW(priv, SCB_EEPROM) & EE_DATA_READ); + OUTW(priv, EE_ENB, SCB_EEPROM); udelay(1); } /* Terminate the EEPROM access. */ - OUTW(dev, EE_ENB & ~EE_CS, SCB_EEPROM); + OUTW(priv, EE_ENB & ~EE_CS, SCB_EEPROM); return retval; } #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) -static int eepro100_initialize_mii(struct eth_device *dev) +static int eepro100_initialize_mii(struct eepro100_priv *priv) { /* register mii command access routines */ struct mii_dev *mdiodev; @@ -480,7 +483,7 @@ static int eepro100_initialize_mii(struct eth_device *dev) if (!mdiodev) return -ENOMEM; - strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN); + strncpy(mdiodev->name, priv->name, MDIO_NAME_LEN); mdiodev->read = eepro100_miiphy_read; mdiodev->write = eepro100_miiphy_write; @@ -493,7 +496,7 @@ static int eepro100_initialize_mii(struct eth_device *dev) return 0; } #else -static int eepro100_initialize_mii(struct eth_device *dev) +static int eepro100_initialize_mii(struct eepro100_priv *priv) { return 0; } @@ -506,70 +509,72 @@ static struct pci_device_id supported[] = { { } }; -static void read_hw_addr(struct eth_device *dev, bd_t *bis) +static void read_hw_addr(struct eepro100_priv *priv, bd_t *bis) { u16 sum = 0; int i, j; - int addr_len = read_eeprom(dev, 0, 6) == 0xffff ? 8 : 6; + int addr_len = read_eeprom(priv, 0, 6) == 0xffff ? 8 : 6; for (j = 0, i = 0; i < 0x40; i++) { - u16 value = read_eeprom(dev, i, addr_len); + u16 value = read_eeprom(priv, i, addr_len); sum += value; if (i < 3) { - dev->enetaddr[j++] = value; - dev->enetaddr[j++] = value >> 8; + priv->enetaddr[j++] = value; + priv->enetaddr[j++] = value >> 8; } } if (sum != 0xBABA) { - memset(dev->enetaddr, 0, ETH_ALEN); + memset(priv->enetaddr, 0, ETH_ALEN); debug("%s: Invalid EEPROM checksum %#4.4x, check settings before activating this device!\n", - dev->name, sum); + priv->name, sum); } } static int eepro100_init(struct eth_device *dev, bd_t *bis) { + struct eepro100_priv *priv = + container_of(dev, struct eepro100_priv, dev); struct eepro100_txfd *ias_cmd, *cfg_cmd; int ret, status = -1; int tx_cur; /* Reset the ethernet controller */ - OUTL(dev, I82559_SELECTIVE_RESET, SCB_PORT); + OUTL(priv, I82559_SELECTIVE_RESET, SCB_PORT); udelay(20); - OUTL(dev, I82559_RESET, SCB_PORT); + OUTL(priv, I82559_RESET, SCB_PORT); udelay(20); - if (!wait_for_eepro100(dev)) { + if (!wait_for_eepro100(priv)) { printf("Error: Can not reset ethernet controller.\n"); goto done; } - OUTL(dev, 0, SCB_POINTER); - OUTW(dev, SCB_M | RUC_ADDR_LOAD, SCB_CMD); + OUTL(priv, 0, SCB_POINTER); + OUTW(priv, SCB_M | RUC_ADDR_LOAD, SCB_CMD); - if (!wait_for_eepro100(dev)) { + if (!wait_for_eepro100(priv)) { printf("Error: Can not reset ethernet controller.\n"); goto done; } - OUTL(dev, 0, SCB_POINTER); - OUTW(dev, SCB_M | CU_ADDR_LOAD, SCB_CMD); + OUTL(priv, 0, SCB_POINTER); + OUTW(priv, SCB_M | CU_ADDR_LOAD, SCB_CMD); /* Initialize Rx and Tx rings. */ - init_rx_ring(dev); - purge_tx_ring(dev); + init_rx_ring(priv); + purge_tx_ring(priv); /* Tell the adapter where the RX ring is located. */ - if (!wait_for_eepro100(dev)) { + if (!wait_for_eepro100(priv)) { printf("Error: Can not reset ethernet controller.\n"); goto done; } /* RX ring cache was already flushed in init_rx_ring() */ - OUTL(dev, phys_to_bus((pci_dev_t)dev->priv, (u32)&rx_ring[rx_next]), + OUTL(priv, phys_to_bus(priv->devno, (u32)&rx_ring[rx_next]), SCB_POINTER); - OUTW(dev, SCB_M | RUC_START, SCB_CMD); + OUTW(priv, SCB_M | RUC_START, SCB_CMD); /* Send the Configure frame */ tx_cur = tx_next; @@ -579,13 +584,13 @@ static int eepro100_init(struct eth_device *dev, bd_t *bis) cfg_cmd->command = cpu_to_le16(CONFIG_SYS_CMD_SUSPEND | CONFIG_SYS_CMD_CONFIGURE); cfg_cmd->status = 0; - cfg_cmd->link = cpu_to_le32(phys_to_bus((pci_dev_t)dev->priv, + cfg_cmd->link = cpu_to_le32(phys_to_bus(priv->devno, (u32)&tx_ring[tx_next])); memcpy(((struct descriptor *)cfg_cmd)->params, i82558_config_cmd, sizeof(i82558_config_cmd)); - ret = eepro100_txcmd_send(dev, cfg_cmd); + ret = eepro100_txcmd_send(priv, cfg_cmd); if (ret) { if (ret == -ETIMEDOUT) printf("Error---CONFIG_SYS_CMD_CONFIGURE: Can not reset ethernet controller.\n"); @@ -600,12 +605,12 @@ static int eepro100_init(struct eth_device *dev, bd_t *bis) ias_cmd->command = cpu_to_le16(CONFIG_SYS_CMD_SUSPEND | CONFIG_SYS_CMD_IAS); ias_cmd->status = 0; - ias_cmd->link = cpu_to_le32(phys_to_bus((pci_dev_t)dev->priv, + ias_cmd->link = cpu_to_le32(phys_to_bus(priv->devno, (u32)&tx_ring[tx_next])); - memcpy(((struct descriptor *)ias_cmd)->params, dev->enetaddr, 6); + memcpy(((struct descriptor *)ias_cmd)->params, priv->enetaddr, 6); - ret = eepro100_txcmd_send(dev, ias_cmd); + ret = eepro100_txcmd_send(priv, ias_cmd); if (ret) { if (ret == -ETIMEDOUT) printf("Error: Can not reset ethernet controller.\n"); @@ -620,12 +625,14 @@ done: static int eepro100_send(struct eth_device *dev, void *packet, int length) { + struct eepro100_priv *priv = + container_of(dev, struct eepro100_priv, dev); struct eepro100_txfd *desc; int ret, status = -1; int tx_cur; if (length <= 0) { - printf("%s: bad packet size: %d\n", dev->name, length); + printf("%s: bad packet size: %d\n", priv->name, length); goto done; } @@ -637,19 +644,19 @@ static int eepro100_send(struct eth_device *dev, void *packet, int length) TXCB_CMD_S | TXCB_CMD_EL); desc->status = 0; desc->count = cpu_to_le32(tx_threshold); - desc->link = cpu_to_le32(phys_to_bus((pci_dev_t)dev->priv, - (u32)&tx_ring[tx_next])); - desc->tx_desc_addr = cpu_to_le32(phys_to_bus((pci_dev_t)dev->priv, + desc->link = cpu_to_le32(phys_to_bus(priv->devno, + (u32)&tx_ring[tx_next])); + desc->tx_desc_addr = cpu_to_le32(phys_to_bus(priv->devno, (u32)&desc->tx_buf_addr0)); - desc->tx_buf_addr0 = cpu_to_le32(phys_to_bus((pci_dev_t)dev->priv, + desc->tx_buf_addr0 = cpu_to_le32(phys_to_bus(priv->devno, (u_long)packet)); desc->tx_buf_size0 = cpu_to_le32(length); - ret = eepro100_txcmd_send(dev, &tx_ring[tx_cur]); + ret = eepro100_txcmd_send(priv, &tx_ring[tx_cur]); if (ret) { if (ret == -ETIMEDOUT) printf("%s: Tx error ethernet controller not ready.\n", - dev->name); + priv->name); goto done; } @@ -661,12 +668,14 @@ done: static int eepro100_recv(struct eth_device *dev) { + struct eepro100_priv *priv = + container_of(dev, struct eepro100_priv, dev); struct eepro100_rxfd *desc; int rx_prev, length = 0; u16 status, stat; - stat = INW(dev, SCB_STATUS); - OUTW(dev, stat & SCB_STATUS_RNR, SCB_STATUS); + stat = INW(priv, SCB_STATUS); + OUTW(priv, stat & SCB_STATUS_RNR, SCB_STATUS); for (;;) { desc = &rx_ring[rx_next]; @@ -706,20 +715,20 @@ static int eepro100_recv(struct eth_device *dev) } if (stat & SCB_STATUS_RNR) { - printf("%s: Receiver is not ready, restart it !\n", dev->name); + printf("%s: Receiver is not ready, restart it !\n", priv->name); /* Reinitialize Rx ring. */ - init_rx_ring(dev); + init_rx_ring(priv); - if (!wait_for_eepro100(dev)) { + if (!wait_for_eepro100(priv)) { printf("Error: Can not restart ethernet controller.\n"); goto done; } /* RX ring cache was already flushed in init_rx_ring() */ - OUTL(dev, phys_to_bus((pci_dev_t)dev->priv, - (u32)&rx_ring[rx_next]), SCB_POINTER); - OUTW(dev, SCB_M | RUC_START, SCB_CMD); + OUTL(priv, phys_to_bus(priv->devno, + (u32)&rx_ring[rx_next]), SCB_POINTER); + OUTW(priv, SCB_M | RUC_START, SCB_CMD); } done: @@ -728,26 +737,29 @@ done: static void eepro100_halt(struct eth_device *dev) { + struct eepro100_priv *priv = + container_of(dev, struct eepro100_priv, dev); + /* Reset the ethernet controller */ - OUTL(dev, I82559_SELECTIVE_RESET, SCB_PORT); + OUTL(priv, I82559_SELECTIVE_RESET, SCB_PORT); udelay(20); - OUTL(dev, I82559_RESET, SCB_PORT); + OUTL(priv, I82559_RESET, SCB_PORT); udelay(20); - if (!wait_for_eepro100(dev)) { + if (!wait_for_eepro100(priv)) { printf("Error: Can not reset ethernet controller.\n"); goto done; } - OUTL(dev, 0, SCB_POINTER); - OUTW(dev, SCB_M | RUC_ADDR_LOAD, SCB_CMD); + OUTL(priv, 0, SCB_POINTER); + OUTW(priv, SCB_M | RUC_ADDR_LOAD, SCB_CMD); - if (!wait_for_eepro100(dev)) { + if (!wait_for_eepro100(priv)) { printf("Error: Can not reset ethernet controller.\n"); goto done; } - OUTL(dev, 0, SCB_POINTER); - OUTW(dev, SCB_M | CU_ADDR_LOAD, SCB_CMD); + OUTL(priv, 0, SCB_POINTER); + OUTW(priv, SCB_M | CU_ADDR_LOAD, SCB_CMD); done: return; @@ -798,8 +810,12 @@ int eepro100_initialize(bd_t *bis) dev = &priv->dev; sprintf(dev->name, "i82559#%d", card_number); - dev->priv = (void *)devno; /* this have to come before bus_to_phys() */ - dev->iobase = bus_to_phys(devno, iobase); + priv->name = dev->name; + /* this have to come before bus_to_phys() */ + priv->devno = devno; + priv->iobase = (void __iomem *)bus_to_phys(devno, iobase); + priv->enetaddr = dev->enetaddr; + dev->init = eepro100_init; dev->halt = eepro100_halt; dev->send = eepro100_send; @@ -807,7 +823,7 @@ int eepro100_initialize(bd_t *bis) eth_register(dev); - ret = eepro100_initialize_mii(dev); + ret = eepro100_initialize_mii(priv); if (ret) { eth_unregister(dev); free(priv); @@ -821,7 +837,7 @@ int eepro100_initialize(bd_t *bis) udelay(10 * 1000); - read_hw_addr(dev, bis); + read_hw_addr(priv, bis); } return card_number; -- cgit v1.1 From 39daab23768895c32b82e153c21a7955ae7dacb8 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sat, 23 May 2020 17:55:50 +0200 Subject: net: eepro100: Pass device private data into mdiobus Instead of doing ethernet device lookup by name every time there is an MDIO access, pass the driver private data via mdiobus priv to the MDIO bus accessors. Signed-off-by: Marek Vasut --- drivers/net/eepro100.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/eepro100.c b/drivers/net/eepro100.c index 1c33ec3..78dedbd 100644 --- a/drivers/net/eepro100.c +++ b/drivers/net/eepro100.c @@ -309,9 +309,7 @@ static int verify_phyaddr(struct eepro100_priv *priv, unsigned char addr) static int eepro100_miiphy_read(struct mii_dev *bus, int addr, int devad, int reg) { - struct eth_device *dev = eth_get_dev_by_name(bus->name); - struct eepro100_priv *priv = - container_of(dev, struct eepro100_priv, dev); + struct eepro100_priv *priv = bus->priv; unsigned short value = 0; int ret; @@ -331,9 +329,7 @@ static int eepro100_miiphy_read(struct mii_dev *bus, int addr, int devad, static int eepro100_miiphy_write(struct mii_dev *bus, int addr, int devad, int reg, u16 value) { - struct eth_device *dev = eth_get_dev_by_name(bus->name); - struct eepro100_priv *priv = - container_of(dev, struct eepro100_priv, dev); + struct eepro100_priv *priv = bus->priv; int ret; ret = verify_phyaddr(priv, addr); @@ -486,6 +482,7 @@ static int eepro100_initialize_mii(struct eepro100_priv *priv) strncpy(mdiodev->name, priv->name, MDIO_NAME_LEN); mdiodev->read = eepro100_miiphy_read; mdiodev->write = eepro100_miiphy_write; + mdiodev->priv = priv; ret = mdio_register(mdiodev); if (ret < 0) { -- cgit v1.1 From fb8307e52af1e9dd4854c7b3addd27ef04a098d4 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sat, 23 May 2020 17:13:26 +0200 Subject: net: eepro100: Add RX/TX rings into the private data The RX/TX DMA descriptor rings are per-device-instance private data, so move them into the private data. Signed-off-by: Marek Vasut --- drivers/net/eepro100.c | 59 ++++++++++++++++++++++++++++++-------------------- 1 file changed, 35 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/net/eepro100.c b/drivers/net/eepro100.c index 78dedbd..ed6bbd5 100644 --- a/drivers/net/eepro100.c +++ b/drivers/net/eepro100.c @@ -183,12 +183,6 @@ struct descriptor { /* A generic descriptor. */ #define TOUT_LOOP 1000000 -static struct eepro100_rxfd rx_ring[NUM_RX_DESC]; /* RX descriptor ring */ -static struct eepro100_txfd tx_ring[NUM_TX_DESC]; /* TX descriptor ring */ -static int rx_next; /* RX descriptor ring pointer */ -static int tx_next; /* TX descriptor ring pointer */ -static int tx_threshold; - /* * The parameters for a CmdConfigure operation. * There are so many options that it would be difficult to document @@ -202,6 +196,15 @@ static const char i82558_config_cmd[] = { }; struct eepro100_priv { + /* RX descriptor ring */ + struct eepro100_rxfd rx_ring[NUM_RX_DESC]; + /* TX descriptor ring */ + struct eepro100_txfd tx_ring[NUM_TX_DESC]; + /* RX descriptor ring pointer */ + int rx_next; + /* TX descriptor ring pointer */ + int tx_next; + int tx_threshold; struct eth_device dev; pci_dev_t devno; char *name; @@ -348,6 +351,7 @@ static int eepro100_miiphy_write(struct mii_dev *bus, int addr, int devad, static void init_rx_ring(struct eepro100_priv *priv) { + struct eepro100_rxfd *rx_ring = priv->rx_ring; int i; for (i = 0; i < NUM_RX_DESC; i++) { @@ -366,13 +370,15 @@ static void init_rx_ring(struct eepro100_priv *priv) (unsigned long)rx_ring + (sizeof(*rx_ring) * NUM_RX_DESC)); - rx_next = 0; + priv->rx_next = 0; } static void purge_tx_ring(struct eepro100_priv *priv) { - tx_next = 0; - tx_threshold = 0x01208000; + struct eepro100_txfd *tx_ring = priv->tx_ring; + + priv->tx_next = 0; + priv->tx_threshold = 0x01208000; memset(tx_ring, 0, sizeof(*tx_ring) * NUM_TX_DESC); flush_dcache_range((unsigned long)tx_ring, @@ -533,6 +539,8 @@ static int eepro100_init(struct eth_device *dev, bd_t *bis) { struct eepro100_priv *priv = container_of(dev, struct eepro100_priv, dev); + struct eepro100_rxfd *rx_ring = priv->rx_ring; + struct eepro100_txfd *tx_ring = priv->tx_ring; struct eepro100_txfd *ias_cmd, *cfg_cmd; int ret, status = -1; int tx_cur; @@ -569,20 +577,20 @@ static int eepro100_init(struct eth_device *dev, bd_t *bis) } /* RX ring cache was already flushed in init_rx_ring() */ - OUTL(priv, phys_to_bus(priv->devno, (u32)&rx_ring[rx_next]), + OUTL(priv, phys_to_bus(priv->devno, (u32)&rx_ring[priv->rx_next]), SCB_POINTER); OUTW(priv, SCB_M | RUC_START, SCB_CMD); /* Send the Configure frame */ - tx_cur = tx_next; - tx_next = ((tx_next + 1) % NUM_TX_DESC); + tx_cur = priv->tx_next; + priv->tx_next = ((priv->tx_next + 1) % NUM_TX_DESC); cfg_cmd = &tx_ring[tx_cur]; cfg_cmd->command = cpu_to_le16(CONFIG_SYS_CMD_SUSPEND | CONFIG_SYS_CMD_CONFIGURE); cfg_cmd->status = 0; cfg_cmd->link = cpu_to_le32(phys_to_bus(priv->devno, - (u32)&tx_ring[tx_next])); + (u32)&tx_ring[priv->tx_next])); memcpy(((struct descriptor *)cfg_cmd)->params, i82558_config_cmd, sizeof(i82558_config_cmd)); @@ -595,15 +603,15 @@ static int eepro100_init(struct eth_device *dev, bd_t *bis) } /* Send the Individual Address Setup frame */ - tx_cur = tx_next; - tx_next = ((tx_next + 1) % NUM_TX_DESC); + tx_cur = priv->tx_next; + priv->tx_next = ((priv->tx_next + 1) % NUM_TX_DESC); ias_cmd = &tx_ring[tx_cur]; ias_cmd->command = cpu_to_le16(CONFIG_SYS_CMD_SUSPEND | CONFIG_SYS_CMD_IAS); ias_cmd->status = 0; ias_cmd->link = cpu_to_le32(phys_to_bus(priv->devno, - (u32)&tx_ring[tx_next])); + (u32)&tx_ring[priv->tx_next])); memcpy(((struct descriptor *)ias_cmd)->params, priv->enetaddr, 6); @@ -624,6 +632,7 @@ static int eepro100_send(struct eth_device *dev, void *packet, int length) { struct eepro100_priv *priv = container_of(dev, struct eepro100_priv, dev); + struct eepro100_txfd *tx_ring = priv->tx_ring; struct eepro100_txfd *desc; int ret, status = -1; int tx_cur; @@ -633,16 +642,16 @@ static int eepro100_send(struct eth_device *dev, void *packet, int length) goto done; } - tx_cur = tx_next; - tx_next = (tx_next + 1) % NUM_TX_DESC; + tx_cur = priv->tx_next; + priv->tx_next = (priv->tx_next + 1) % NUM_TX_DESC; desc = &tx_ring[tx_cur]; desc->command = cpu_to_le16(TXCB_CMD_TRANSMIT | TXCB_CMD_SF | TXCB_CMD_S | TXCB_CMD_EL); desc->status = 0; - desc->count = cpu_to_le32(tx_threshold); + desc->count = cpu_to_le32(priv->tx_threshold); desc->link = cpu_to_le32(phys_to_bus(priv->devno, - (u32)&tx_ring[tx_next])); + (u32)&tx_ring[priv->tx_next])); desc->tx_desc_addr = cpu_to_le32(phys_to_bus(priv->devno, (u32)&desc->tx_buf_addr0)); desc->tx_buf_addr0 = cpu_to_le32(phys_to_bus(priv->devno, @@ -667,6 +676,7 @@ static int eepro100_recv(struct eth_device *dev) { struct eepro100_priv *priv = container_of(dev, struct eepro100_priv, dev); + struct eepro100_rxfd *rx_ring = priv->rx_ring; struct eepro100_rxfd *desc; int rx_prev, length = 0; u16 status, stat; @@ -675,7 +685,7 @@ static int eepro100_recv(struct eth_device *dev) OUTW(priv, stat & SCB_STATUS_RNR, SCB_STATUS); for (;;) { - desc = &rx_ring[rx_next]; + desc = &rx_ring[priv->rx_next]; invalidate_dcache_range((unsigned long)desc, (unsigned long)desc + sizeof(*desc)); status = le16_to_cpu(desc->status); @@ -701,14 +711,14 @@ static int eepro100_recv(struct eth_device *dev) flush_dcache_range((unsigned long)desc, (unsigned long)desc + sizeof(*desc)); - rx_prev = (rx_next + NUM_RX_DESC - 1) % NUM_RX_DESC; + rx_prev = (priv->rx_next + NUM_RX_DESC - 1) % NUM_RX_DESC; desc = &rx_ring[rx_prev]; desc->control = 0; flush_dcache_range((unsigned long)desc, (unsigned long)desc + sizeof(*desc)); /* Update entry information. */ - rx_next = (rx_next + 1) % NUM_RX_DESC; + priv->rx_next = (priv->rx_next + 1) % NUM_RX_DESC; } if (stat & SCB_STATUS_RNR) { @@ -724,7 +734,8 @@ static int eepro100_recv(struct eth_device *dev) /* RX ring cache was already flushed in init_rx_ring() */ OUTL(priv, phys_to_bus(priv->devno, - (u32)&rx_ring[rx_next]), SCB_POINTER); + (u32)&rx_ring[priv->rx_next]), + SCB_POINTER); OUTW(priv, SCB_M | RUC_START, SCB_CMD); } -- cgit v1.1 From 43b738350ce133bc19c2bd4586ecff486e39e835 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sat, 23 May 2020 17:20:39 +0200 Subject: net: eepro100: Drop bd_t pointer from read_hw_addr() The pointer is unused, so drop it. Rename the function to start with the eepro100_ prefix. Signed-off-by: Marek Vasut --- drivers/net/eepro100.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/eepro100.c b/drivers/net/eepro100.c index ed6bbd5..fb8a68f 100644 --- a/drivers/net/eepro100.c +++ b/drivers/net/eepro100.c @@ -512,7 +512,7 @@ static struct pci_device_id supported[] = { { } }; -static void read_hw_addr(struct eepro100_priv *priv, bd_t *bis) +static void eepro100_get_hwaddr(struct eepro100_priv *priv) { u16 sum = 0; int i, j; @@ -845,7 +845,7 @@ int eepro100_initialize(bd_t *bis) udelay(10 * 1000); - read_hw_addr(priv, bis); + eepro100_get_hwaddr(priv); } return card_number; -- cgit v1.1 From 8835103e24622cefd37a1a8d5011c160da6a34df Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sat, 23 May 2020 17:28:20 +0200 Subject: net: eepro100: Split common parts of non-DM functions out Split the common code from the non-DM code, so it can be reused by the DM code later. As always, the recv() function had to be split into the actual receiving part and free_pkt part to fit with the DM. Signed-off-by: Marek Vasut --- drivers/net/eepro100.c | 162 ++++++++++++++++++++++++++++++------------------- 1 file changed, 100 insertions(+), 62 deletions(-) (limited to 'drivers') diff --git a/drivers/net/eepro100.c b/drivers/net/eepro100.c index fb8a68f..f474832 100644 --- a/drivers/net/eepro100.c +++ b/drivers/net/eepro100.c @@ -202,6 +202,7 @@ struct eepro100_priv { struct eepro100_txfd tx_ring[NUM_TX_DESC]; /* RX descriptor ring pointer */ int rx_next; + u16 rx_stat; /* TX descriptor ring pointer */ int tx_next; int tx_threshold; @@ -535,10 +536,8 @@ static void eepro100_get_hwaddr(struct eepro100_priv *priv) } } -static int eepro100_init(struct eth_device *dev, bd_t *bis) +static int eepro100_init_common(struct eepro100_priv *priv) { - struct eepro100_priv *priv = - container_of(dev, struct eepro100_priv, dev); struct eepro100_rxfd *rx_ring = priv->rx_ring; struct eepro100_txfd *tx_ring = priv->tx_ring; struct eepro100_txfd *ias_cmd, *cfg_cmd; @@ -628,10 +627,9 @@ done: return status; } -static int eepro100_send(struct eth_device *dev, void *packet, int length) +static int eepro100_send_common(struct eepro100_priv *priv, + void *packet, int length) { - struct eepro100_priv *priv = - container_of(dev, struct eepro100_priv, dev); struct eepro100_txfd *tx_ring = priv->tx_ring; struct eepro100_txfd *desc; int ret, status = -1; @@ -672,82 +670,82 @@ done: return status; } -static int eepro100_recv(struct eth_device *dev) +static int eepro100_recv_common(struct eepro100_priv *priv, uchar **packetp) { - struct eepro100_priv *priv = - container_of(dev, struct eepro100_priv, dev); struct eepro100_rxfd *rx_ring = priv->rx_ring; struct eepro100_rxfd *desc; - int rx_prev, length = 0; - u16 status, stat; + int length; + u16 status; - stat = INW(priv, SCB_STATUS); - OUTW(priv, stat & SCB_STATUS_RNR, SCB_STATUS); + priv->rx_stat = INW(priv, SCB_STATUS); + OUTW(priv, priv->rx_stat & SCB_STATUS_RNR, SCB_STATUS); - for (;;) { - desc = &rx_ring[priv->rx_next]; - invalidate_dcache_range((unsigned long)desc, - (unsigned long)desc + sizeof(*desc)); - status = le16_to_cpu(desc->status); + desc = &rx_ring[priv->rx_next]; + invalidate_dcache_range((unsigned long)desc, + (unsigned long)desc + sizeof(*desc)); + status = le16_to_cpu(desc->status); + + if (!(status & RFD_STATUS_C)) + return 0; + + /* Valid frame status. */ + if (status & RFD_STATUS_OK) { + /* A valid frame received. */ + length = le32_to_cpu(desc->count) & 0x3fff; + /* Pass the packet up to the protocol layers. */ + *packetp = desc->data; + return length; + } - if (!(status & RFD_STATUS_C)) - break; + /* There was an error. */ + printf("RX error status = 0x%08X\n", status); + return -EINVAL; +} - /* Valid frame status. */ - if ((status & RFD_STATUS_OK)) { - /* A valid frame received. */ - length = le32_to_cpu(desc->count) & 0x3fff; +static void eepro100_free_pkt_common(struct eepro100_priv *priv) +{ + struct eepro100_rxfd *rx_ring = priv->rx_ring; + struct eepro100_rxfd *desc; + int rx_prev; - /* Pass the packet up to the protocol layers. */ - net_process_received_packet((u8 *)desc->data, length); - } else { - /* There was an error. */ - printf("RX error status = 0x%08X\n", status); - } + desc = &rx_ring[priv->rx_next]; - desc->control = cpu_to_le16(RFD_CONTROL_S); - desc->status = 0; - desc->count = cpu_to_le32(PKTSIZE_ALIGN << 16); - flush_dcache_range((unsigned long)desc, - (unsigned long)desc + sizeof(*desc)); + desc->control = cpu_to_le16(RFD_CONTROL_S); + desc->status = 0; + desc->count = cpu_to_le32(PKTSIZE_ALIGN << 16); + flush_dcache_range((unsigned long)desc, + (unsigned long)desc + sizeof(*desc)); - rx_prev = (priv->rx_next + NUM_RX_DESC - 1) % NUM_RX_DESC; - desc = &rx_ring[rx_prev]; - desc->control = 0; - flush_dcache_range((unsigned long)desc, - (unsigned long)desc + sizeof(*desc)); + rx_prev = (priv->rx_next + NUM_RX_DESC - 1) % NUM_RX_DESC; + desc = &rx_ring[rx_prev]; + desc->control = 0; + flush_dcache_range((unsigned long)desc, + (unsigned long)desc + sizeof(*desc)); - /* Update entry information. */ - priv->rx_next = (priv->rx_next + 1) % NUM_RX_DESC; - } + /* Update entry information. */ + priv->rx_next = (priv->rx_next + 1) % NUM_RX_DESC; - if (stat & SCB_STATUS_RNR) { - printf("%s: Receiver is not ready, restart it !\n", priv->name); + if (!(priv->rx_stat & SCB_STATUS_RNR)) + return; - /* Reinitialize Rx ring. */ - init_rx_ring(priv); + printf("%s: Receiver is not ready, restart it !\n", priv->name); - if (!wait_for_eepro100(priv)) { - printf("Error: Can not restart ethernet controller.\n"); - goto done; - } + /* Reinitialize Rx ring. */ + init_rx_ring(priv); - /* RX ring cache was already flushed in init_rx_ring() */ - OUTL(priv, phys_to_bus(priv->devno, - (u32)&rx_ring[priv->rx_next]), - SCB_POINTER); - OUTW(priv, SCB_M | RUC_START, SCB_CMD); + if (!wait_for_eepro100(priv)) { + printf("Error: Can not restart ethernet controller.\n"); + return; } -done: - return length; + /* RX ring cache was already flushed in init_rx_ring() */ + OUTL(priv, phys_to_bus(priv->devno, (u32)&rx_ring[priv->rx_next]), + SCB_POINTER); + OUTW(priv, SCB_M | RUC_START, SCB_CMD); } -static void eepro100_halt(struct eth_device *dev) +static void eepro100_halt_common(struct eepro100_priv *priv) { - struct eepro100_priv *priv = - container_of(dev, struct eepro100_priv, dev); - /* Reset the ethernet controller */ OUTL(priv, I82559_SELECTIVE_RESET, SCB_PORT); udelay(20); @@ -773,6 +771,46 @@ done: return; } +static int eepro100_init(struct eth_device *dev, bd_t *bis) +{ + struct eepro100_priv *priv = + container_of(dev, struct eepro100_priv, dev); + + return eepro100_init_common(priv); +} + +static void eepro100_halt(struct eth_device *dev) +{ + struct eepro100_priv *priv = + container_of(dev, struct eepro100_priv, dev); + + eepro100_halt_common(priv); +} + +static int eepro100_send(struct eth_device *dev, void *packet, int length) +{ + struct eepro100_priv *priv = + container_of(dev, struct eepro100_priv, dev); + + return eepro100_send_common(priv, packet, length); +} + +static int eepro100_recv(struct eth_device *dev) +{ + struct eepro100_priv *priv = + container_of(dev, struct eepro100_priv, dev); + uchar *packet; + int ret; + + ret = eepro100_recv_common(priv, &packet); + if (ret > 0) + net_process_received_packet(packet, ret); + if (ret) + eepro100_free_pkt_common(priv); + + return ret; +} + int eepro100_initialize(bd_t *bis) { struct eepro100_priv *priv; -- cgit v1.1 From af8ecdf7e5d9ec13581906172a1a9762d9a7a504 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sat, 23 May 2020 16:26:20 +0200 Subject: net: eepro100: Add DM support Add support for driver model to the driver. Signed-off-by: Marek Vasut --- drivers/net/eepro100.c | 129 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 128 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/eepro100.c b/drivers/net/eepro100.c index f474832..45ea3b7 100644 --- a/drivers/net/eepro100.c +++ b/drivers/net/eepro100.c @@ -206,14 +206,21 @@ struct eepro100_priv { /* TX descriptor ring pointer */ int tx_next; int tx_threshold; +#ifdef CONFIG_DM_ETH + struct udevice *devno; +#else struct eth_device dev; pci_dev_t devno; +#endif char *name; void __iomem *iobase; u8 *enetaddr; }; -#if defined(CONFIG_E500) +#if defined(CONFIG_DM_ETH) +#define bus_to_phys(dev, a) dm_pci_mem_to_phys((dev), (a)) +#define phys_to_bus(dev, a) dm_pci_phys_to_mem((dev), (a)) +#elif defined(CONFIG_E500) #define bus_to_phys(dev, a) (a) #define phys_to_bus(dev, a) (a) #else @@ -771,6 +778,7 @@ done: return; } +#ifndef CONFIG_DM_ETH static int eepro100_init(struct eth_device *dev, bd_t *bis) { struct eepro100_priv *priv = @@ -888,3 +896,122 @@ int eepro100_initialize(bd_t *bis) return card_number; } + +#else /* DM_ETH */ +static int eepro100_start(struct udevice *dev) +{ + struct eth_pdata *plat = dev_get_platdata(dev); + struct eepro100_priv *priv = dev_get_priv(dev); + + memcpy(priv->enetaddr, plat->enetaddr, sizeof(plat->enetaddr)); + + return eepro100_init_common(priv); +} + +static void eepro100_stop(struct udevice *dev) +{ + struct eepro100_priv *priv = dev_get_priv(dev); + + eepro100_halt_common(priv); +} + +static int eepro100_send(struct udevice *dev, void *packet, int length) +{ + struct eepro100_priv *priv = dev_get_priv(dev); + int ret; + + ret = eepro100_send_common(priv, packet, length); + + return ret ? 0 : -ETIMEDOUT; +} + +static int eepro100_recv(struct udevice *dev, int flags, uchar **packetp) +{ + struct eepro100_priv *priv = dev_get_priv(dev); + + return eepro100_recv_common(priv, packetp); +} + +static int eepro100_free_pkt(struct udevice *dev, uchar *packet, int length) +{ + struct eepro100_priv *priv = dev_get_priv(dev); + + eepro100_free_pkt_common(priv); + + return 0; +} + +static int eepro100_read_rom_hwaddr(struct udevice *dev) +{ + struct eepro100_priv *priv = dev_get_priv(dev); + + eepro100_get_hwaddr(priv); + + return 0; +} + +static int eepro100_bind(struct udevice *dev) +{ + static int card_number; + char name[16]; + + sprintf(name, "eepro100#%u", card_number++); + + return device_set_name(dev, name); +} + +static int eepro100_probe(struct udevice *dev) +{ + struct eth_pdata *plat = dev_get_platdata(dev); + struct eepro100_priv *priv = dev_get_priv(dev); + u16 command, status; + u32 iobase; + int ret; + + dm_pci_read_config32(dev, PCI_BASE_ADDRESS_0, &iobase); + iobase &= ~0xf; + + debug("eepro100: Intel i82559 PCI EtherExpressPro @0x%x\n", iobase); + + priv->devno = dev; + priv->enetaddr = plat->enetaddr; + priv->iobase = (void __iomem *)bus_to_phys(dev, iobase); + + command = PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; + dm_pci_write_config16(dev, PCI_COMMAND, command); + dm_pci_read_config16(dev, PCI_COMMAND, &status); + if ((status & command) != command) { + printf("eepro100: Couldn't enable IO access or Bus Mastering\n"); + return -EINVAL; + } + + ret = eepro100_initialize_mii(priv); + if (ret) + return ret; + + dm_pci_write_config8(dev, PCI_LATENCY_TIMER, 0x20); + + return 0; +} + +static const struct eth_ops eepro100_ops = { + .start = eepro100_start, + .send = eepro100_send, + .recv = eepro100_recv, + .stop = eepro100_stop, + .free_pkt = eepro100_free_pkt, + .read_rom_hwaddr = eepro100_read_rom_hwaddr, +}; + +U_BOOT_DRIVER(eth_eepro100) = { + .name = "eth_eepro100", + .id = UCLASS_ETH, + .bind = eepro100_bind, + .probe = eepro100_probe, + .ops = &eepro100_ops, + .priv_auto_alloc_size = sizeof(struct eepro100_priv), + .platdata_auto_alloc_size = sizeof(struct eth_pdata), +}; + +U_BOOT_PCI_DEVICE(eth_eepro100, supported); +#endif -- cgit v1.1 From 6463b73e0b25b058404c52b48c991abf4f8a94ce Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sat, 23 May 2020 18:07:53 +0200 Subject: net: eepro100: Add Kconfig entries Add Kconfig entries for the eepro100 driver and convert various boards. Signed-off-by: Marek Vasut --- drivers/net/Kconfig | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index bb23f73..ed07a78 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -193,6 +193,12 @@ config CMD_E1000 used on devices with SPI support you can reprogram the EEPROM from U-Boot. +config EEPRO100 + bool "Intel PRO/100 82557/82559/82559ER Fast Ethernet support" + help + This driver supports Intel(R) PRO/100 82557/82559/82559ER fast + ethernet family of adapters. + config ETH_SANDBOX depends on DM_ETH && SANDBOX default y -- cgit v1.1 From 97d5c145592c1d2aa38a8d074fed9aee059ac119 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 17 May 2020 15:10:41 +0200 Subject: net: pcnet: Drop typedef struct pcnet_priv_t Use struct pcnet_priv all over the place instead. Signed-off-by: Marek Vasut Cc: Daniel Schwierzeck Cc: Joe Hershberger --- drivers/net/pcnet.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/pcnet.c b/drivers/net/pcnet.c index 260a5a3..c6f080d 100644 --- a/drivers/net/pcnet.c +++ b/drivers/net/pcnet.c @@ -76,15 +76,15 @@ struct pcnet_uncached_priv { struct pcnet_init_block init_block; }; -typedef struct pcnet_priv { +struct pcnet_priv { struct pcnet_uncached_priv *uc; /* Receive Buffer space */ unsigned char (*rx_buf)[RX_RING_SIZE][PKT_BUF_SZ + 4]; int cur_rx; int cur_tx; -} pcnet_priv_t; +}; -static pcnet_priv_t *lp; +static struct pcnet_priv *lp; /* Offsets from base I/O address for WIO mode */ #define PCNET_RDP 0x10 @@ -340,9 +340,9 @@ static int pcnet_init(struct eth_device *dev, bd_t *bis) * must be aligned on 16-byte boundaries. */ if (lp == NULL) { - addr = (unsigned long)malloc(sizeof(pcnet_priv_t) + 0x10); + addr = (unsigned long)malloc(sizeof(*lp) + 0x10); addr = (addr + 0xf) & ~0xf; - lp = (pcnet_priv_t *)addr; + lp = (struct pcnet_priv *)addr; addr = (unsigned long)memalign(ARCH_DMA_MINALIGN, sizeof(*lp->uc)); -- cgit v1.1 From 1524e409ef130e20e6554446d08be967422d27f7 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 17 May 2020 18:12:19 +0200 Subject: net: pcnet: Drop PCNET_HAS_PROM All of one PCNET users has this option set, make this default and drop this config option. Signed-off-by: Marek Vasut Cc: Daniel Schwierzeck Cc: Joe Hershberger --- drivers/net/pcnet.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/pcnet.c b/drivers/net/pcnet.c index c6f080d..edc4dba 100644 --- a/drivers/net/pcnet.c +++ b/drivers/net/pcnet.c @@ -241,10 +241,7 @@ static int pcnet_probe(struct eth_device *dev, bd_t *bis, int dev_nr) { int chip_version; char *chipname; - -#ifdef PCNET_HAS_PROM int i; -#endif /* Reset the PCnet controller */ pcnet_reset(dev); @@ -279,7 +276,6 @@ static int pcnet_probe(struct eth_device *dev, bd_t *bis, int dev_nr) PCNET_DEBUG1("AMD %s\n", chipname); -#ifdef PCNET_HAS_PROM /* * In most chips, after a chip reset, the ethernet address is read from * the station address PROM at the base address and programmed into the @@ -293,7 +289,6 @@ static int pcnet_probe(struct eth_device *dev, bd_t *bis, int dev_nr) dev->enetaddr[2 * i] = val & 0x0ff; dev->enetaddr[2 * i + 1] = (val >> 8) & 0x0ff; } -#endif /* PCNET_HAS_PROM */ return 0; } -- cgit v1.1 From e4797c31612d9c31b7b65fce8c3081ae2d150d00 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 17 May 2020 17:33:17 +0200 Subject: net: pcnet: Use PCI_DEVICE() to define PCI device compat list Use this macro to fully fill the PCI device ID table. This is mandatory for the DM PCI support, which checks all the fields. Signed-off-by: Marek Vasut Cc: Daniel Schwierzeck Cc: Joe Hershberger --- drivers/net/pcnet.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/pcnet.c b/drivers/net/pcnet.c index edc4dba..e7ce79e 100644 --- a/drivers/net/pcnet.c +++ b/drivers/net/pcnet.c @@ -155,7 +155,7 @@ static inline pci_addr_t pcnet_virt_to_mem(const struct eth_device *dev, } static struct pci_device_id supported[] = { - {PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE}, + { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE) }, {} }; -- cgit v1.1 From 1c38c36eb99abfd1bc46b90c80f7daa5c65f3527 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 17 May 2020 16:16:45 +0200 Subject: net: pcnet: Simplify private data allocation The current code is horribly complex. Both the RX and TX buffer descriptors are 16 bytes in size, the init block is 32 bytes in size, so simplify the code such that the entire private data of the driver are allocated cache aligned and the RX and TX buffer descriptors are part of the private data. This removes multiple malloc calls and cache flushes. Signed-off-by: Marek Vasut Cc: Daniel Schwierzeck Cc: Joe Hershberger --- drivers/net/pcnet.c | 33 ++++++++++++--------------------- 1 file changed, 12 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/net/pcnet.c b/drivers/net/pcnet.c index e7ce79e..72b9380 100644 --- a/drivers/net/pcnet.c +++ b/drivers/net/pcnet.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -74,12 +75,13 @@ struct pcnet_uncached_priv { struct pcnet_rx_head rx_ring[RX_RING_SIZE]; struct pcnet_tx_head tx_ring[TX_RING_SIZE]; struct pcnet_init_block init_block; -}; +} __aligned(ARCH_DMA_MINALIGN); struct pcnet_priv { - struct pcnet_uncached_priv *uc; + struct pcnet_uncached_priv ucp; /* Receive Buffer space */ - unsigned char (*rx_buf)[RX_RING_SIZE][PKT_BUF_SZ + 4]; + unsigned char rx_buf[RX_RING_SIZE][PKT_BUF_SZ + 4]; + struct pcnet_uncached_priv *uc; int cur_rx; int cur_tx; }; @@ -335,22 +337,11 @@ static int pcnet_init(struct eth_device *dev, bd_t *bis) * must be aligned on 16-byte boundaries. */ if (lp == NULL) { - addr = (unsigned long)malloc(sizeof(*lp) + 0x10); - addr = (addr + 0xf) & ~0xf; - lp = (struct pcnet_priv *)addr; - - addr = (unsigned long)memalign(ARCH_DMA_MINALIGN, - sizeof(*lp->uc)); - flush_dcache_range(addr, addr + sizeof(*lp->uc)); - addr = (unsigned long)map_physmem(addr, - roundup(sizeof(*lp->uc), ARCH_DMA_MINALIGN), - MAP_NOCACHE); - lp->uc = (struct pcnet_uncached_priv *)addr; - - addr = (unsigned long)memalign(ARCH_DMA_MINALIGN, - sizeof(*lp->rx_buf)); - flush_dcache_range(addr, addr + sizeof(*lp->rx_buf)); - lp->rx_buf = (void *)addr; + lp = malloc_cache_aligned(sizeof(*lp)); + lp->uc = map_physmem((phys_addr_t)&lp->ucp, + sizeof(lp->ucp), MAP_NOCACHE); + flush_dcache_range((unsigned long)lp, + (unsigned long)lp + sizeof(*lp)); } uc = lp->uc; @@ -364,7 +355,7 @@ static int pcnet_init(struct eth_device *dev, bd_t *bis) */ lp->cur_rx = 0; for (i = 0; i < RX_RING_SIZE; i++) { - addr = pcnet_virt_to_mem(dev, (*lp->rx_buf)[i]); + addr = pcnet_virt_to_mem(dev, lp->rx_buf[i]); uc->rx_ring[i].base = cpu_to_le32(addr); uc->rx_ring[i].buf_length = cpu_to_le16(-PKT_BUF_SZ); uc->rx_ring[i].status = cpu_to_le16(0x8000); @@ -521,7 +512,7 @@ static int pcnet_recv (struct eth_device *dev) printf("%s: Rx%d: invalid packet length %d\n", dev->name, lp->cur_rx, pkt_len); } else { - buf = (*lp->rx_buf)[lp->cur_rx]; + buf = lp->rx_buf[lp->cur_rx]; invalidate_dcache_range((unsigned long)buf, (unsigned long)buf + pkt_len); net_process_received_packet(buf, pkt_len); -- cgit v1.1 From ae38e96c23f3d08e2ec49206a99271252f5b3dc2 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 17 May 2020 16:26:57 +0200 Subject: net: pcnet: Replace memset+malloc with calloc This combination of functions can be replaced with calloc(), make it so. Signed-off-by: Marek Vasut Cc: Daniel Schwierzeck Cc: Joe Hershberger --- drivers/net/pcnet.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/pcnet.c b/drivers/net/pcnet.c index 72b9380..b670cff 100644 --- a/drivers/net/pcnet.c +++ b/drivers/net/pcnet.c @@ -184,12 +184,11 @@ int pcnet_initialize(bd_t *bis) /* * Allocate and pre-fill the device structure. */ - dev = (struct eth_device *)malloc(sizeof(*dev)); + dev = calloc(1, sizeof(*dev)); if (!dev) { printf("pcnet: Can not allocate memory\n"); break; } - memset(dev, 0, sizeof(*dev)); dev->priv = (void *)(unsigned long)devbusfn; sprintf(dev->name, "pcnet#%d", dev_nr); -- cgit v1.1 From 246d2bfcf244326c43dcfffcecfdf684b8a4513d Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 17 May 2020 16:26:00 +0200 Subject: net: pcnet: Move private data allocation to initialize The private data allocation does not have to be done every time the NIC is initialized at run time, move the allocation to initialize function, which means it will be done only once when the driver starts. Signed-off-by: Marek Vasut Cc: Daniel Schwierzeck Cc: Joe Hershberger --- drivers/net/pcnet.c | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/net/pcnet.c b/drivers/net/pcnet.c index b670cff..073ffca 100644 --- a/drivers/net/pcnet.c +++ b/drivers/net/pcnet.c @@ -189,6 +189,20 @@ int pcnet_initialize(bd_t *bis) printf("pcnet: Can not allocate memory\n"); break; } + + /* + * We only maintain one structure because the drivers will + * never be used concurrently. In 32bit mode the RX and TX + * ring entries must be aligned on 16-byte boundaries. + */ + if (!lp) { + lp = malloc_cache_aligned(sizeof(*lp)); + lp->uc = map_physmem((phys_addr_t)&lp->ucp, + sizeof(lp->ucp), MAP_NOCACHE); + flush_dcache_range((unsigned long)lp, + (unsigned long)lp + sizeof(*lp)); + } + dev->priv = (void *)(unsigned long)devbusfn; sprintf(dev->name, "pcnet#%d", dev_nr); @@ -330,19 +344,6 @@ static int pcnet_init(struct eth_device *dev, bd_t *bis) val |= 0x3 << 10; pcnet_write_csr(dev, 80, val); - /* - * We only maintain one structure because the drivers will never - * be used concurrently. In 32bit mode the RX and TX ring entries - * must be aligned on 16-byte boundaries. - */ - if (lp == NULL) { - lp = malloc_cache_aligned(sizeof(*lp)); - lp->uc = map_physmem((phys_addr_t)&lp->ucp, - sizeof(lp->ucp), MAP_NOCACHE); - flush_dcache_range((unsigned long)lp, - (unsigned long)lp + sizeof(*lp)); - } - uc = lp->uc; uc->init_block.mode = cpu_to_le16(0x0000); -- cgit v1.1 From 69e08bd735c6d90a00959e0062f587f521f5d3df Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 17 May 2020 16:31:41 +0200 Subject: net: pcnet: Move initialize function at the end Move the function at the end of the driver, so we could drop various forward declarations later. No functional change. Signed-off-by: Marek Vasut Cc: Daniel Schwierzeck Cc: Joe Hershberger --- drivers/net/pcnet.c | 180 ++++++++++++++++++++++++++-------------------------- 1 file changed, 89 insertions(+), 91 deletions(-) (limited to 'drivers') diff --git a/drivers/net/pcnet.c b/drivers/net/pcnet.c index 073ffca..6d464cd 100644 --- a/drivers/net/pcnet.c +++ b/drivers/net/pcnet.c @@ -161,97 +161,6 @@ static struct pci_device_id supported[] = { {} }; - -int pcnet_initialize(bd_t *bis) -{ - pci_dev_t devbusfn; - struct eth_device *dev; - u16 command, status; - int dev_nr = 0; - u32 bar; - - PCNET_DEBUG1("\npcnet_initialize...\n"); - - for (dev_nr = 0;; dev_nr++) { - - /* - * Find the PCnet PCI device(s). - */ - devbusfn = pci_find_devices(supported, dev_nr); - if (devbusfn < 0) - break; - - /* - * Allocate and pre-fill the device structure. - */ - dev = calloc(1, sizeof(*dev)); - if (!dev) { - printf("pcnet: Can not allocate memory\n"); - break; - } - - /* - * We only maintain one structure because the drivers will - * never be used concurrently. In 32bit mode the RX and TX - * ring entries must be aligned on 16-byte boundaries. - */ - if (!lp) { - lp = malloc_cache_aligned(sizeof(*lp)); - lp->uc = map_physmem((phys_addr_t)&lp->ucp, - sizeof(lp->ucp), MAP_NOCACHE); - flush_dcache_range((unsigned long)lp, - (unsigned long)lp + sizeof(*lp)); - } - - dev->priv = (void *)(unsigned long)devbusfn; - sprintf(dev->name, "pcnet#%d", dev_nr); - - /* - * Setup the PCI device. - */ - pci_read_config_dword(devbusfn, PCI_BASE_ADDRESS_1, &bar); - dev->iobase = pci_mem_to_phys(devbusfn, bar); - dev->iobase &= ~0xf; - - PCNET_DEBUG1("%s: devbusfn=0x%x iobase=0x%lx: ", - dev->name, devbusfn, (unsigned long)dev->iobase); - - command = PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; - pci_write_config_word(devbusfn, PCI_COMMAND, command); - pci_read_config_word(devbusfn, PCI_COMMAND, &status); - if ((status & command) != command) { - printf("%s: Couldn't enable IO access or Bus Mastering\n", - dev->name); - free(dev); - continue; - } - - pci_write_config_byte(devbusfn, PCI_LATENCY_TIMER, 0x40); - - /* - * Probe the PCnet chip. - */ - if (pcnet_probe(dev, bis, dev_nr) < 0) { - free(dev); - continue; - } - - /* - * Setup device structure and register the driver. - */ - dev->init = pcnet_init; - dev->halt = pcnet_halt; - dev->send = pcnet_send; - dev->recv = pcnet_recv; - - eth_register(dev); - } - - udelay(10 * 1000); - - return dev_nr; -} - static int pcnet_probe(struct eth_device *dev, bd_t *bis, int dev_nr) { int chip_version; @@ -548,3 +457,92 @@ static void pcnet_halt(struct eth_device *dev) if (i <= 0) printf("%s: TIMEOUT: controller reset failed\n", dev->name); } + +int pcnet_initialize(bd_t *bis) +{ + pci_dev_t devbusfn; + struct eth_device *dev; + u16 command, status; + int dev_nr = 0; + u32 bar; + + PCNET_DEBUG1("\npcnet_initialize...\n"); + + for (dev_nr = 0; ; dev_nr++) { + /* + * Find the PCnet PCI device(s). + */ + devbusfn = pci_find_devices(supported, dev_nr); + if (devbusfn < 0) + break; + + /* + * Allocate and pre-fill the device structure. + */ + dev = calloc(1, sizeof(*dev)); + if (!dev) { + printf("pcnet: Can not allocate memory\n"); + break; + } + + /* + * We only maintain one structure because the drivers will + * never be used concurrently. In 32bit mode the RX and TX + * ring entries must be aligned on 16-byte boundaries. + */ + if (!lp) { + lp = malloc_cache_aligned(sizeof(*lp)); + lp->uc = map_physmem((phys_addr_t)&lp->ucp, + sizeof(lp->ucp), MAP_NOCACHE); + flush_dcache_range((unsigned long)lp, + (unsigned long)lp + sizeof(*lp)); + } + + dev->priv = (void *)(unsigned long)devbusfn; + sprintf(dev->name, "pcnet#%d", dev_nr); + + /* + * Setup the PCI device. + */ + pci_read_config_dword(devbusfn, PCI_BASE_ADDRESS_1, &bar); + dev->iobase = pci_mem_to_phys(devbusfn, bar); + dev->iobase &= ~0xf; + + PCNET_DEBUG1("%s: devbusfn=0x%x iobase=0x%lx: ", + dev->name, devbusfn, (unsigned long)dev->iobase); + + command = PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; + pci_write_config_word(devbusfn, PCI_COMMAND, command); + pci_read_config_word(devbusfn, PCI_COMMAND, &status); + if ((status & command) != command) { + printf("%s: Couldn't enable IO access or Bus Mastering\n", + dev->name); + free(dev); + continue; + } + + pci_write_config_byte(devbusfn, PCI_LATENCY_TIMER, 0x40); + + /* + * Probe the PCnet chip. + */ + if (pcnet_probe(dev, bis, dev_nr) < 0) { + free(dev); + continue; + } + + /* + * Setup device structure and register the driver. + */ + dev->init = pcnet_init; + dev->halt = pcnet_halt; + dev->send = pcnet_send; + dev->recv = pcnet_recv; + + eth_register(dev); + } + + udelay(10 * 1000); + + return dev_nr; +} -- cgit v1.1 From d20e857e6b60720ff8ca98f8a4411336303e8d5f Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 17 May 2020 16:28:41 +0200 Subject: net: pcnet: Drop useless forward declarations Remove those as they are not needed anymore. Signed-off-by: Marek Vasut Cc: Daniel Schwierzeck Cc: Joe Hershberger --- drivers/net/pcnet.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/pcnet.c b/drivers/net/pcnet.c index 6d464cd..d8249f0 100644 --- a/drivers/net/pcnet.c +++ b/drivers/net/pcnet.c @@ -141,12 +141,6 @@ static int pcnet_check(struct eth_device *dev) return readw(base + PCNET_RAP) == 88; } -static int pcnet_init (struct eth_device *dev, bd_t * bis); -static int pcnet_send(struct eth_device *dev, void *packet, int length); -static int pcnet_recv (struct eth_device *dev); -static void pcnet_halt (struct eth_device *dev); -static int pcnet_probe (struct eth_device *dev, bd_t * bis, int dev_num); - static inline pci_addr_t pcnet_virt_to_mem(const struct eth_device *dev, void *addr) { -- cgit v1.1 From 60074d9d3ea048ea0ca369687aaaaed65695fc44 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 17 May 2020 16:31:04 +0200 Subject: net: pcnet: Wrap devbusfn into private data Instead of using eth_device priv for this PCI devbusfn, free it so it could be used for driver private data, and wrap devbusfn into those driver private data. Note that using the name dev for the variable is a trick left for later, when DM support is in place, so dm_pci_virt_to_mem() can be used with minimal ifdeffery. Signed-off-by: Marek Vasut Cc: Daniel Schwierzeck Cc: Joe Hershberger --- drivers/net/pcnet.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/net/pcnet.c b/drivers/net/pcnet.c index d8249f0..f7f1b8f 100644 --- a/drivers/net/pcnet.c +++ b/drivers/net/pcnet.c @@ -82,6 +82,7 @@ struct pcnet_priv { /* Receive Buffer space */ unsigned char rx_buf[RX_RING_SIZE][PKT_BUF_SZ + 4]; struct pcnet_uncached_priv *uc; + pci_dev_t dev; int cur_rx; int cur_tx; }; @@ -141,13 +142,11 @@ static int pcnet_check(struct eth_device *dev) return readw(base + PCNET_RAP) == 88; } -static inline pci_addr_t pcnet_virt_to_mem(const struct eth_device *dev, - void *addr) +static inline pci_addr_t pcnet_virt_to_mem(struct pcnet_priv *lp, void *addr) { - pci_dev_t devbusfn = (pci_dev_t)(unsigned long)dev->priv; void *virt_addr = addr; - return pci_virt_to_mem(devbusfn, virt_addr); + return pci_virt_to_mem(lp->dev, virt_addr); } static struct pci_device_id supported[] = { @@ -258,7 +257,7 @@ static int pcnet_init(struct eth_device *dev, bd_t *bis) */ lp->cur_rx = 0; for (i = 0; i < RX_RING_SIZE; i++) { - addr = pcnet_virt_to_mem(dev, lp->rx_buf[i]); + addr = pcnet_virt_to_mem(lp, lp->rx_buf[i]); uc->rx_ring[i].base = cpu_to_le32(addr); uc->rx_ring[i].buf_length = cpu_to_le16(-PKT_BUF_SZ); uc->rx_ring[i].status = cpu_to_le16(0x8000); @@ -290,9 +289,9 @@ static int pcnet_init(struct eth_device *dev, bd_t *bis) uc->init_block.tlen_rlen = cpu_to_le16(TX_RING_LEN_BITS | RX_RING_LEN_BITS); - addr = pcnet_virt_to_mem(dev, uc->rx_ring); + addr = pcnet_virt_to_mem(lp, uc->rx_ring); uc->init_block.rx_ring = cpu_to_le32(addr); - addr = pcnet_virt_to_mem(dev, uc->tx_ring); + addr = pcnet_virt_to_mem(lp, uc->tx_ring); uc->init_block.tx_ring = cpu_to_le32(addr); PCNET_DEBUG1("\ntlen_rlen=0x%x rx_ring=0x%x tx_ring=0x%x\n", @@ -303,7 +302,7 @@ static int pcnet_init(struct eth_device *dev, bd_t *bis) * Tell the controller where the Init Block is located. */ barrier(); - addr = pcnet_virt_to_mem(dev, &lp->uc->init_block); + addr = pcnet_virt_to_mem(lp, &lp->uc->init_block); pcnet_write_csr(dev, 1, addr & 0xffff); pcnet_write_csr(dev, 2, (addr >> 16) & 0xffff); @@ -361,7 +360,7 @@ static int pcnet_send(struct eth_device *dev, void *packet, int pkt_len) * Setup Tx ring. Caution: the write order is important here, * set the status with the "ownership" bits last. */ - addr = pcnet_virt_to_mem(dev, packet); + addr = pcnet_virt_to_mem(lp, packet); writew(-pkt_len, &entry->length); writel(0, &entry->misc); writel(addr, &entry->base); @@ -492,7 +491,7 @@ int pcnet_initialize(bd_t *bis) (unsigned long)lp + sizeof(*lp)); } - dev->priv = (void *)(unsigned long)devbusfn; + lp->dev = devbusfn; sprintf(dev->name, "pcnet#%d", dev_nr); /* -- cgit v1.1 From fdf6cbe54d1bdf217bed9b117ed2a823ae5c8dc2 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 17 May 2020 16:47:07 +0200 Subject: net: pcnet: Pass private data through dev->priv Get rid of the global point to private data, and rather pass it thought dev->priv. Also remove the unnecessary check for lp being non-NULL, since it is always NULL at this point. Signed-off-by: Marek Vasut Cc: Daniel Schwierzeck Cc: Joe Hershberger --- drivers/net/pcnet.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/net/pcnet.c b/drivers/net/pcnet.c index f7f1b8f..dab08c0 100644 --- a/drivers/net/pcnet.c +++ b/drivers/net/pcnet.c @@ -87,8 +87,6 @@ struct pcnet_priv { int cur_tx; }; -static struct pcnet_priv *lp; - /* Offsets from base I/O address for WIO mode */ #define PCNET_RDP 0x10 #define PCNET_RAP 0x12 @@ -212,6 +210,7 @@ static int pcnet_probe(struct eth_device *dev, bd_t *bis, int dev_nr) static int pcnet_init(struct eth_device *dev, bd_t *bis) { + struct pcnet_priv *lp = dev->priv; struct pcnet_uncached_priv *uc; int i, val; unsigned long addr; @@ -331,6 +330,7 @@ static int pcnet_init(struct eth_device *dev, bd_t *bis) static int pcnet_send(struct eth_device *dev, void *packet, int pkt_len) { + struct pcnet_priv *lp = dev->priv; int i, status; u32 addr; struct pcnet_tx_head *entry = &lp->uc->tx_ring[lp->cur_tx]; @@ -379,6 +379,7 @@ static int pcnet_send(struct eth_device *dev, void *packet, int pkt_len) static int pcnet_recv (struct eth_device *dev) { + struct pcnet_priv *lp = dev->priv; struct pcnet_rx_head *entry; unsigned char *buf; int pkt_len = 0; @@ -455,6 +456,7 @@ int pcnet_initialize(bd_t *bis) { pci_dev_t devbusfn; struct eth_device *dev; + struct pcnet_priv *lp; u16 command, status; int dev_nr = 0; u32 bar; @@ -483,15 +485,13 @@ int pcnet_initialize(bd_t *bis) * never be used concurrently. In 32bit mode the RX and TX * ring entries must be aligned on 16-byte boundaries. */ - if (!lp) { - lp = malloc_cache_aligned(sizeof(*lp)); - lp->uc = map_physmem((phys_addr_t)&lp->ucp, - sizeof(lp->ucp), MAP_NOCACHE); - flush_dcache_range((unsigned long)lp, - (unsigned long)lp + sizeof(*lp)); - } - + lp = malloc_cache_aligned(sizeof(*lp)); + lp->uc = map_physmem((phys_addr_t)&lp->ucp, + sizeof(lp->ucp), MAP_NOCACHE); lp->dev = devbusfn; + flush_dcache_range((unsigned long)lp, + (unsigned long)lp + sizeof(*lp)); + dev->priv = lp; sprintf(dev->name, "pcnet#%d", dev_nr); /* -- cgit v1.1 From 3b2d63a739f27d8a139f880cc92e66072e1ef5e4 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 17 May 2020 17:00:42 +0200 Subject: net: pcnet: Wrap iobase into private data Instead of using the non-DM-only iobase in struct eth_device, add one into the private data to make DM and non-DM operation possible. Signed-off-by: Marek Vasut Cc: Daniel Schwierzeck Cc: Joe Hershberger --- drivers/net/pcnet.c | 103 +++++++++++++++++++++++----------------------------- 1 file changed, 46 insertions(+), 57 deletions(-) (limited to 'drivers') diff --git a/drivers/net/pcnet.c b/drivers/net/pcnet.c index dab08c0..b0bd4af 100644 --- a/drivers/net/pcnet.c +++ b/drivers/net/pcnet.c @@ -83,6 +83,7 @@ struct pcnet_priv { unsigned char rx_buf[RX_RING_SIZE][PKT_BUF_SZ + 4]; struct pcnet_uncached_priv *uc; pci_dev_t dev; + void __iomem *iobase; int cur_rx; int cur_tx; }; @@ -93,51 +94,39 @@ struct pcnet_priv { #define PCNET_RESET 0x14 #define PCNET_BDP 0x16 -static u16 pcnet_read_csr(struct eth_device *dev, int index) +static u16 pcnet_read_csr(struct pcnet_priv *lp, int index) { - void __iomem *base = (void __iomem *)dev->iobase; - - writew(index, base + PCNET_RAP); - return readw(base + PCNET_RDP); + writew(index, lp->iobase + PCNET_RAP); + return readw(lp->iobase + PCNET_RDP); } -static void pcnet_write_csr(struct eth_device *dev, int index, u16 val) +static void pcnet_write_csr(struct pcnet_priv *lp, int index, u16 val) { - void __iomem *base = (void __iomem *)dev->iobase; - - writew(index, base + PCNET_RAP); - writew(val, base + PCNET_RDP); + writew(index, lp->iobase + PCNET_RAP); + writew(val, lp->iobase + PCNET_RDP); } -static u16 pcnet_read_bcr(struct eth_device *dev, int index) +static u16 pcnet_read_bcr(struct pcnet_priv *lp, int index) { - void __iomem *base = (void __iomem *)dev->iobase; - - writew(index, base + PCNET_RAP); - return readw(base + PCNET_BDP); + writew(index, lp->iobase + PCNET_RAP); + return readw(lp->iobase + PCNET_BDP); } -static void pcnet_write_bcr(struct eth_device *dev, int index, u16 val) +static void pcnet_write_bcr(struct pcnet_priv *lp, int index, u16 val) { - void __iomem *base = (void __iomem *)dev->iobase; - - writew(index, base + PCNET_RAP); - writew(val, base + PCNET_BDP); + writew(index, lp->iobase + PCNET_RAP); + writew(val, lp->iobase + PCNET_BDP); } -static void pcnet_reset(struct eth_device *dev) +static void pcnet_reset(struct pcnet_priv *lp) { - void __iomem *base = (void __iomem *)dev->iobase; - - readw(base + PCNET_RESET); + readw(lp->iobase + PCNET_RESET); } -static int pcnet_check(struct eth_device *dev) +static int pcnet_check(struct pcnet_priv *lp) { - void __iomem *base = (void __iomem *)dev->iobase; - - writew(88, base + PCNET_RAP); - return readw(base + PCNET_RAP) == 88; + writew(88, lp->iobase + PCNET_RAP); + return readw(lp->iobase + PCNET_RAP) == 88; } static inline pci_addr_t pcnet_virt_to_mem(struct pcnet_priv *lp, void *addr) @@ -154,22 +143,22 @@ static struct pci_device_id supported[] = { static int pcnet_probe(struct eth_device *dev, bd_t *bis, int dev_nr) { + struct pcnet_priv *lp = dev->priv; int chip_version; char *chipname; int i; /* Reset the PCnet controller */ - pcnet_reset(dev); + pcnet_reset(lp); /* Check if register access is working */ - if (pcnet_read_csr(dev, 0) != 4 || !pcnet_check(dev)) { + if (pcnet_read_csr(lp, 0) != 4 || !pcnet_check(lp)) { printf("%s: CSR register access check failed\n", dev->name); return -1; } /* Identify the chip */ - chip_version = - pcnet_read_csr(dev, 88) | (pcnet_read_csr(dev, 89) << 16); + chip_version = pcnet_read_csr(lp, 88) | (pcnet_read_csr(lp, 89) << 16); if ((chip_version & 0xfff) != 0x003) return -1; chip_version = (chip_version >> 12) & 0xffff; @@ -199,7 +188,7 @@ static int pcnet_probe(struct eth_device *dev, bd_t *bis, int dev_nr) for (i = 0; i < 3; i++) { unsigned int val; - val = pcnet_read_csr(dev, i + 12) & 0x0ffff; + val = pcnet_read_csr(lp, i + 12) & 0x0ffff; /* There may be endianness issues here. */ dev->enetaddr[2 * i] = val & 0x0ff; dev->enetaddr[2 * i + 1] = (val >> 8) & 0x0ff; @@ -218,17 +207,17 @@ static int pcnet_init(struct eth_device *dev, bd_t *bis) PCNET_DEBUG1("%s: pcnet_init...\n", dev->name); /* Switch pcnet to 32bit mode */ - pcnet_write_bcr(dev, 20, 2); + pcnet_write_bcr(lp, 20, 2); /* Set/reset autoselect bit */ - val = pcnet_read_bcr(dev, 2) & ~2; + val = pcnet_read_bcr(lp, 2) & ~2; val |= 2; - pcnet_write_bcr(dev, 2, val); + pcnet_write_bcr(lp, 2, val); /* Enable auto negotiate, setup, disable fd */ - val = pcnet_read_bcr(dev, 32) & ~0x98; + val = pcnet_read_bcr(lp, 32) & ~0x98; val |= 0x20; - pcnet_write_bcr(dev, 32, val); + pcnet_write_bcr(lp, 32, val); /* * Enable NOUFLO on supported controllers, with the transmit @@ -238,12 +227,12 @@ static int pcnet_init(struct eth_device *dev, bd_t *bis) * slower devices. Controllers which do not support NOUFLO will * simply be left with a larger transmit FIFO threshold. */ - val = pcnet_read_bcr(dev, 18); + val = pcnet_read_bcr(lp, 18); val |= 1 << 11; - pcnet_write_bcr(dev, 18, val); - val = pcnet_read_csr(dev, 80); + pcnet_write_bcr(lp, 18, val); + val = pcnet_read_csr(lp, 80); val |= 0x3 << 10; - pcnet_write_csr(dev, 80, val); + pcnet_write_csr(lp, 80, val); uc = lp->uc; @@ -302,28 +291,28 @@ static int pcnet_init(struct eth_device *dev, bd_t *bis) */ barrier(); addr = pcnet_virt_to_mem(lp, &lp->uc->init_block); - pcnet_write_csr(dev, 1, addr & 0xffff); - pcnet_write_csr(dev, 2, (addr >> 16) & 0xffff); + pcnet_write_csr(lp, 1, addr & 0xffff); + pcnet_write_csr(lp, 2, (addr >> 16) & 0xffff); - pcnet_write_csr(dev, 4, 0x0915); - pcnet_write_csr(dev, 0, 0x0001); /* start */ + pcnet_write_csr(lp, 4, 0x0915); + pcnet_write_csr(lp, 0, 0x0001); /* start */ /* Wait for Init Done bit */ for (i = 10000; i > 0; i--) { - if (pcnet_read_csr(dev, 0) & 0x0100) + if (pcnet_read_csr(lp, 0) & 0x0100) break; udelay(10); } if (i <= 0) { printf("%s: TIMEOUT: controller init failed\n", dev->name); - pcnet_reset(dev); + pcnet_reset(lp); return -1; } /* * Finally start network controller operation. */ - pcnet_write_csr(dev, 0, 0x0002); + pcnet_write_csr(lp, 0, 0x0002); return 0; } @@ -367,7 +356,7 @@ static int pcnet_send(struct eth_device *dev, void *packet, int pkt_len) writew(0x8300, &entry->status); /* Trigger an immediate send poll. */ - pcnet_write_csr(dev, 0, 0x0008); + pcnet_write_csr(lp, 0, 0x0008); failure: if (++lp->cur_tx >= TX_RING_SIZE) @@ -435,16 +424,17 @@ static int pcnet_recv (struct eth_device *dev) static void pcnet_halt(struct eth_device *dev) { + struct pcnet_priv *lp = dev->priv; int i; PCNET_DEBUG1("%s: pcnet_halt...\n", dev->name); /* Reset the PCnet controller */ - pcnet_reset(dev); + pcnet_reset(lp); /* Wait for Stop bit */ for (i = 1000; i > 0; i--) { - if (pcnet_read_csr(dev, 0) & 0x4) + if (pcnet_read_csr(lp, 0) & 0x4) break; udelay(10); } @@ -498,11 +488,10 @@ int pcnet_initialize(bd_t *bis) * Setup the PCI device. */ pci_read_config_dword(devbusfn, PCI_BASE_ADDRESS_1, &bar); - dev->iobase = pci_mem_to_phys(devbusfn, bar); - dev->iobase &= ~0xf; + lp->iobase = (void *)(pci_mem_to_phys(devbusfn, bar) & ~0xf); - PCNET_DEBUG1("%s: devbusfn=0x%x iobase=0x%lx: ", - dev->name, devbusfn, (unsigned long)dev->iobase); + PCNET_DEBUG1("%s: devbusfn=0x%x iobase=0x%p: ", + dev->name, devbusfn, lp->iobase); command = PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; pci_write_config_word(devbusfn, PCI_COMMAND, command); -- cgit v1.1 From 1023a1e6a9b506c318ee9330d90d3acdf5593f89 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 17 May 2020 17:04:19 +0200 Subject: net: pcnet: Wrap name and enetaddr into private data Instead of using the non-DM-only name and enetaddr in struct eth_device, add pointers into the private data which can either point to that non-DM name or a DM one later on. Signed-off-by: Marek Vasut Cc: Daniel Schwierzeck Cc: Joe Hershberger --- drivers/net/pcnet.c | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/net/pcnet.c b/drivers/net/pcnet.c index b0bd4af..669b256 100644 --- a/drivers/net/pcnet.c +++ b/drivers/net/pcnet.c @@ -84,6 +84,8 @@ struct pcnet_priv { struct pcnet_uncached_priv *uc; pci_dev_t dev; void __iomem *iobase; + char *name; + u8 *enetaddr; int cur_rx; int cur_tx; }; @@ -153,7 +155,7 @@ static int pcnet_probe(struct eth_device *dev, bd_t *bis, int dev_nr) /* Check if register access is working */ if (pcnet_read_csr(lp, 0) != 4 || !pcnet_check(lp)) { - printf("%s: CSR register access check failed\n", dev->name); + printf("%s: CSR register access check failed\n", lp->name); return -1; } @@ -174,7 +176,7 @@ static int pcnet_probe(struct eth_device *dev, bd_t *bis, int dev_nr) break; default: printf("%s: PCnet version %#x not supported\n", - dev->name, chip_version); + lp->name, chip_version); return -1; } @@ -190,8 +192,8 @@ static int pcnet_probe(struct eth_device *dev, bd_t *bis, int dev_nr) val = pcnet_read_csr(lp, i + 12) & 0x0ffff; /* There may be endianness issues here. */ - dev->enetaddr[2 * i] = val & 0x0ff; - dev->enetaddr[2 * i + 1] = (val >> 8) & 0x0ff; + lp->enetaddr[2 * i] = val & 0x0ff; + lp->enetaddr[2 * i + 1] = (val >> 8) & 0x0ff; } return 0; @@ -204,7 +206,7 @@ static int pcnet_init(struct eth_device *dev, bd_t *bis) int i, val; unsigned long addr; - PCNET_DEBUG1("%s: pcnet_init...\n", dev->name); + PCNET_DEBUG1("%s: %s...\n", lp->name, __func__); /* Switch pcnet to 32bit mode */ pcnet_write_bcr(lp, 20, 2); @@ -271,7 +273,7 @@ static int pcnet_init(struct eth_device *dev, bd_t *bis) PCNET_DEBUG1("Init block at 0x%p: MAC", &lp->uc->init_block); for (i = 0; i < 6; i++) { - lp->uc->init_block.phys_addr[i] = dev->enetaddr[i]; + lp->uc->init_block.phys_addr[i] = lp->enetaddr[i]; PCNET_DEBUG1(" %02x", lp->uc->init_block.phys_addr[i]); } @@ -304,7 +306,7 @@ static int pcnet_init(struct eth_device *dev, bd_t *bis) udelay(10); } if (i <= 0) { - printf("%s: TIMEOUT: controller init failed\n", dev->name); + printf("%s: TIMEOUT: controller init failed\n", lp->name); pcnet_reset(lp); return -1; } @@ -340,7 +342,7 @@ static int pcnet_send(struct eth_device *dev, void *packet, int pkt_len) } if (i <= 0) { printf("%s: TIMEOUT: Tx%d failed (status = 0x%x)\n", - dev->name, lp->cur_tx, status); + lp->name, lp->cur_tx, status); pkt_len = 0; goto failure; } @@ -385,7 +387,7 @@ static int pcnet_recv (struct eth_device *dev) err_status = status >> 8; if (err_status != 0x03) { /* There was an error. */ - printf("%s: Rx%d", dev->name, lp->cur_rx); + printf("%s: Rx%d", lp->name, lp->cur_rx); PCNET_DEBUG1(" (status=0x%x)", err_status); if (err_status & 0x20) printf(" Frame"); @@ -402,7 +404,7 @@ static int pcnet_recv (struct eth_device *dev) pkt_len = (readl(&entry->msg_length) & 0xfff) - 4; if (pkt_len < 60) { printf("%s: Rx%d: invalid packet length %d\n", - dev->name, lp->cur_rx, pkt_len); + lp->name, lp->cur_rx, pkt_len); } else { buf = lp->rx_buf[lp->cur_rx]; invalidate_dcache_range((unsigned long)buf, @@ -427,7 +429,7 @@ static void pcnet_halt(struct eth_device *dev) struct pcnet_priv *lp = dev->priv; int i; - PCNET_DEBUG1("%s: pcnet_halt...\n", dev->name); + PCNET_DEBUG1("%s: %s...\n", lp->name, __func__); /* Reset the PCnet controller */ pcnet_reset(lp); @@ -439,7 +441,7 @@ static void pcnet_halt(struct eth_device *dev) udelay(10); } if (i <= 0) - printf("%s: TIMEOUT: controller reset failed\n", dev->name); + printf("%s: TIMEOUT: controller reset failed\n", lp->name); } int pcnet_initialize(bd_t *bis) @@ -451,7 +453,7 @@ int pcnet_initialize(bd_t *bis) int dev_nr = 0; u32 bar; - PCNET_DEBUG1("\npcnet_initialize...\n"); + PCNET_DEBUG1("\n%s...\n", __func__); for (dev_nr = 0; ; dev_nr++) { /* @@ -483,6 +485,8 @@ int pcnet_initialize(bd_t *bis) (unsigned long)lp + sizeof(*lp)); dev->priv = lp; sprintf(dev->name, "pcnet#%d", dev_nr); + lp->name = dev->name; + lp->enetaddr = dev->enetaddr; /* * Setup the PCI device. @@ -491,14 +495,14 @@ int pcnet_initialize(bd_t *bis) lp->iobase = (void *)(pci_mem_to_phys(devbusfn, bar) & ~0xf); PCNET_DEBUG1("%s: devbusfn=0x%x iobase=0x%p: ", - dev->name, devbusfn, lp->iobase); + lp->name, devbusfn, lp->iobase); command = PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; pci_write_config_word(devbusfn, PCI_COMMAND, command); pci_read_config_word(devbusfn, PCI_COMMAND, &status); if ((status & command) != command) { printf("%s: Couldn't enable IO access or Bus Mastering\n", - dev->name); + lp->name); free(dev); continue; } -- cgit v1.1 From dea9b6014b2e8a62b615ebe6f8778e5c624076e4 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 17 May 2020 17:28:31 +0200 Subject: net: pcnet: Split common and non-DM functions Pull the common parts of functions out so they can be reused by both DM and non-DM code paths. The recv() function had to be reworked to fit into this scheme and this means it now only receives one packet at a time instead of spinning in an endless loop. Signed-off-by: Marek Vasut Cc: Daniel Schwierzeck Cc: Joe Hershberger --- drivers/net/pcnet.c | 149 +++++++++++++++++++++++++++++++++------------------- 1 file changed, 94 insertions(+), 55 deletions(-) (limited to 'drivers') diff --git a/drivers/net/pcnet.c b/drivers/net/pcnet.c index 669b256..0a4cab8 100644 --- a/drivers/net/pcnet.c +++ b/drivers/net/pcnet.c @@ -86,6 +86,7 @@ struct pcnet_priv { void __iomem *iobase; char *name; u8 *enetaddr; + u16 status; int cur_rx; int cur_tx; }; @@ -143,9 +144,8 @@ static struct pci_device_id supported[] = { {} }; -static int pcnet_probe(struct eth_device *dev, bd_t *bis, int dev_nr) +static int pcnet_probe_common(struct pcnet_priv *lp) { - struct pcnet_priv *lp = dev->priv; int chip_version; char *chipname; int i; @@ -199,9 +199,8 @@ static int pcnet_probe(struct eth_device *dev, bd_t *bis, int dev_nr) return 0; } -static int pcnet_init(struct eth_device *dev, bd_t *bis) +static int pcnet_init_common(struct pcnet_priv *lp) { - struct pcnet_priv *lp = dev->priv; struct pcnet_uncached_priv *uc; int i, val; unsigned long addr; @@ -319,9 +318,8 @@ static int pcnet_init(struct eth_device *dev, bd_t *bis) return 0; } -static int pcnet_send(struct eth_device *dev, void *packet, int pkt_len) +static int pcnet_send_common(struct pcnet_priv *lp, void *packet, int pkt_len) { - struct pcnet_priv *lp = dev->priv; int i, status; u32 addr; struct pcnet_tx_head *entry = &lp->uc->tx_ring[lp->cur_tx]; @@ -368,65 +366,70 @@ static int pcnet_send(struct eth_device *dev, void *packet, int pkt_len) return pkt_len; } -static int pcnet_recv (struct eth_device *dev) +static int pcnet_recv_common(struct pcnet_priv *lp, unsigned char **bufp) { - struct pcnet_priv *lp = dev->priv; struct pcnet_rx_head *entry; unsigned char *buf; int pkt_len = 0; - u16 status, err_status; + u16 err_status; - while (1) { - entry = &lp->uc->rx_ring[lp->cur_rx]; - /* - * If we own the next entry, it's a new packet. Send it up. - */ - status = readw(&entry->status); - if ((status & 0x8000) != 0) - break; - err_status = status >> 8; - - if (err_status != 0x03) { /* There was an error. */ - printf("%s: Rx%d", lp->name, lp->cur_rx); - PCNET_DEBUG1(" (status=0x%x)", err_status); - if (err_status & 0x20) - printf(" Frame"); - if (err_status & 0x10) - printf(" Overflow"); - if (err_status & 0x08) - printf(" CRC"); - if (err_status & 0x04) - printf(" Fifo"); - printf(" Error\n"); - status &= 0x03ff; - - } else { - pkt_len = (readl(&entry->msg_length) & 0xfff) - 4; - if (pkt_len < 60) { - printf("%s: Rx%d: invalid packet length %d\n", - lp->name, lp->cur_rx, pkt_len); - } else { - buf = lp->rx_buf[lp->cur_rx]; - invalidate_dcache_range((unsigned long)buf, - (unsigned long)buf + pkt_len); - net_process_received_packet(buf, pkt_len); - PCNET_DEBUG2("Rx%d: %d bytes from 0x%p\n", - lp->cur_rx, pkt_len, buf); - } - } - - status |= 0x8000; - writew(status, &entry->status); + entry = &lp->uc->rx_ring[lp->cur_rx]; + /* + * If we own the next entry, it's a new packet. Send it up. + */ + lp->status = readw(&entry->status); + if ((lp->status & 0x8000) != 0) + return 0; + err_status = lp->status >> 8; + + if (err_status != 0x03) { /* There was an error. */ + printf("%s: Rx%d", lp->name, lp->cur_rx); + PCNET_DEBUG1(" (status=0x%x)", err_status); + if (err_status & 0x20) + printf(" Frame"); + if (err_status & 0x10) + printf(" Overflow"); + if (err_status & 0x08) + printf(" CRC"); + if (err_status & 0x04) + printf(" Fifo"); + printf(" Error\n"); + lp->status &= 0x03ff; + return 0; + } - if (++lp->cur_rx >= RX_RING_SIZE) - lp->cur_rx = 0; + pkt_len = (readl(&entry->msg_length) & 0xfff) - 4; + if (pkt_len < 60) { + printf("%s: Rx%d: invalid packet length %d\n", + lp->name, lp->cur_rx, pkt_len); + return 0; } + + *bufp = lp->rx_buf[lp->cur_rx]; + invalidate_dcache_range((unsigned long)*bufp, + (unsigned long)*bufp + pkt_len); + + PCNET_DEBUG2("Rx%d: %d bytes from 0x%p\n", + lp->cur_rx, pkt_len, buf); + return pkt_len; } -static void pcnet_halt(struct eth_device *dev) +static void pcnet_free_pkt_common(struct pcnet_priv *lp, unsigned int len) +{ + struct pcnet_rx_head *entry; + + entry = &lp->uc->rx_ring[lp->cur_rx]; + + lp->status |= 0x8000; + writew(lp->status, &entry->status); + + if (++lp->cur_rx >= RX_RING_SIZE) + lp->cur_rx = 0; +} + +static void pcnet_halt_common(struct pcnet_priv *lp) { - struct pcnet_priv *lp = dev->priv; int i; PCNET_DEBUG1("%s: %s...\n", lp->name, __func__); @@ -444,6 +447,42 @@ static void pcnet_halt(struct eth_device *dev) printf("%s: TIMEOUT: controller reset failed\n", lp->name); } +static int pcnet_init(struct eth_device *dev, bd_t *bis) +{ + struct pcnet_priv *lp = dev->priv; + + return pcnet_init_common(lp); +} + +static int pcnet_send(struct eth_device *dev, void *packet, int pkt_len) +{ + struct pcnet_priv *lp = dev->priv; + + return pcnet_send_common(lp, packet, pkt_len); +} + +static int pcnet_recv(struct eth_device *dev) +{ + struct pcnet_priv *lp = dev->priv; + uchar *packet; + int ret; + + ret = pcnet_recv_common(lp, &packet); + if (ret > 0) + net_process_received_packet(packet, ret); + if (ret) + pcnet_free_pkt_common(lp, ret); + + return ret; +} + +static void pcnet_halt(struct eth_device *dev) +{ + struct pcnet_priv *lp = dev->priv; + + pcnet_halt_common(lp); +} + int pcnet_initialize(bd_t *bis) { pci_dev_t devbusfn; @@ -512,7 +551,7 @@ int pcnet_initialize(bd_t *bis) /* * Probe the PCnet chip. */ - if (pcnet_probe(dev, bis, dev_nr) < 0) { + if (pcnet_probe_common(lp) < 0) { free(dev); continue; } -- cgit v1.1 From 59edb2668eabf51c8587a786af9eca95e3294806 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 17 May 2020 17:43:22 +0200 Subject: net: pcnet: Add DM support With all the changes in place, add support for DM into the pcnet driver. Signed-off-by: Marek Vasut Cc: Daniel Schwierzeck Cc: Joe Hershberger --- drivers/net/pcnet.c | 127 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 126 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/pcnet.c b/drivers/net/pcnet.c index 0a4cab8..d9ab37b 100644 --- a/drivers/net/pcnet.c +++ b/drivers/net/pcnet.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -82,9 +83,14 @@ struct pcnet_priv { /* Receive Buffer space */ unsigned char rx_buf[RX_RING_SIZE][PKT_BUF_SZ + 4]; struct pcnet_uncached_priv *uc; +#ifdef CONFIG_DM_ETH + struct udevice *dev; + const char *name; +#else pci_dev_t dev; - void __iomem *iobase; char *name; +#endif + void __iomem *iobase; u8 *enetaddr; u16 status; int cur_rx; @@ -136,7 +142,11 @@ static inline pci_addr_t pcnet_virt_to_mem(struct pcnet_priv *lp, void *addr) { void *virt_addr = addr; +#ifdef CONFIG_DM_ETH + return dm_pci_virt_to_mem(lp->dev, virt_addr); +#else return pci_virt_to_mem(lp->dev, virt_addr); +#endif } static struct pci_device_id supported[] = { @@ -447,6 +457,7 @@ static void pcnet_halt_common(struct pcnet_priv *lp) printf("%s: TIMEOUT: controller reset failed\n", lp->name); } +#ifndef CONFIG_DM_ETH static int pcnet_init(struct eth_device *dev, bd_t *bis) { struct pcnet_priv *lp = dev->priv; @@ -571,3 +582,117 @@ int pcnet_initialize(bd_t *bis) return dev_nr; } +#else /* DM_ETH */ +static int pcnet_start(struct udevice *dev) +{ + struct eth_pdata *plat = dev_get_platdata(dev); + struct pcnet_priv *priv = dev_get_priv(dev); + + memcpy(priv->enetaddr, plat->enetaddr, sizeof(plat->enetaddr)); + + return pcnet_init_common(priv); +} + +static void pcnet_stop(struct udevice *dev) +{ + struct pcnet_priv *priv = dev_get_priv(dev); + + pcnet_halt_common(priv); +} + +static int pcnet_send(struct udevice *dev, void *packet, int length) +{ + struct pcnet_priv *priv = dev_get_priv(dev); + int ret; + + ret = pcnet_send_common(priv, packet, length); + + return ret ? 0 : -ETIMEDOUT; +} + +static int pcnet_recv(struct udevice *dev, int flags, uchar **packetp) +{ + struct pcnet_priv *priv = dev_get_priv(dev); + + return pcnet_recv_common(priv, packetp); +} + +static int pcnet_free_pkt(struct udevice *dev, uchar *packet, int length) +{ + struct pcnet_priv *priv = dev_get_priv(dev); + + pcnet_free_pkt_common(priv, length); + + return 0; +} + +static int pcnet_bind(struct udevice *dev) +{ + static int card_number; + char name[16]; + + sprintf(name, "pcnet#%u", card_number++); + + return device_set_name(dev, name); +} + +static int pcnet_probe(struct udevice *dev) +{ + struct eth_pdata *plat = dev_get_platdata(dev); + struct pcnet_priv *lp = dev_get_priv(dev); + u16 command, status; + u32 iobase; + int ret; + + dm_pci_read_config32(dev, PCI_BASE_ADDRESS_1, &iobase); + iobase &= ~0xf; + + lp->uc = map_physmem((phys_addr_t)&lp->ucp, + sizeof(lp->ucp), MAP_NOCACHE); + lp->dev = dev; + lp->name = dev->name; + lp->enetaddr = plat->enetaddr; + lp->iobase = (void *)dm_pci_mem_to_phys(dev, iobase); + + flush_dcache_range((unsigned long)lp, + (unsigned long)lp + sizeof(*lp)); + + command = PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; + dm_pci_write_config16(dev, PCI_COMMAND, command); + dm_pci_read_config16(dev, PCI_COMMAND, &status); + if ((status & command) != command) { + printf("%s: Couldn't enable IO access or Bus Mastering\n", + lp->name); + return -EINVAL; + } + + dm_pci_write_config8(dev, PCI_LATENCY_TIMER, 0x20); + + ret = pcnet_probe_common(lp); + if (ret) + return ret; + + return 0; +} + +static const struct eth_ops pcnet_ops = { + .start = pcnet_start, + .send = pcnet_send, + .recv = pcnet_recv, + .stop = pcnet_stop, + .free_pkt = pcnet_free_pkt, +}; + +U_BOOT_DRIVER(eth_pcnet) = { + .name = "eth_pcnet", + .id = UCLASS_ETH, + .bind = pcnet_bind, + .probe = pcnet_probe, + .ops = &pcnet_ops, + .priv_auto_alloc_size = sizeof(struct pcnet_priv), + .platdata_auto_alloc_size = sizeof(struct eth_pdata), + .flags = DM_UC_FLAG_ALLOC_PRIV_DMA, +}; + +U_BOOT_PCI_DEVICE(eth_pcnet, supported); +#endif -- cgit v1.1 From d789a8259e3b3b77e3eb2b090373ab2cbc225629 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 17 May 2020 18:14:17 +0200 Subject: net: pcnet: Add Kconfig entries Add Kconfig entries for the pcnet driver and convert MIPS malta to use those. Signed-off-by: Marek Vasut Cc: Daniel Schwierzeck Cc: Joe Hershberger --- drivers/net/Kconfig | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index ed07a78..1566b3b 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -398,6 +398,12 @@ config MII help Enable support of the Media-Independent Interface (MII) +config PCNET + bool "AMD PCnet series Ethernet controller driver" + help + This driver supports AMD PCnet series fast ethernet family of + PCI chipsets/adapters. + config RTL8139 bool "Realtek 8139 series Ethernet controller driver" help -- cgit v1.1 From fb3dd9c005045c2748e30d555d252c6985b97349 Mon Sep 17 00:00:00 2001 From: Anatolij Gustschin Date: Tue, 26 May 2020 09:38:17 +0200 Subject: video: ipuv3: remove non-DM code All ipuv3 users have been converted, drop obsolete code. Signed-off-by: Anatolij Gustschin --- drivers/video/imx/Kconfig | 2 +- drivers/video/imx/mxc_ipuv3_fb.c | 43 ---------------------------------------- 2 files changed, 1 insertion(+), 44 deletions(-) (limited to 'drivers') diff --git a/drivers/video/imx/Kconfig b/drivers/video/imx/Kconfig index c33620e..78eb0f2 100644 --- a/drivers/video/imx/Kconfig +++ b/drivers/video/imx/Kconfig @@ -1,7 +1,7 @@ config VIDEO_IPUV3 bool "i.MX IPUv3 Core video support" - depends on (VIDEO || DM_VIDEO) && (MX5 || MX6) + depends on DM_VIDEO && (MX5 || MX6) help This enables framebuffer driver for i.MX processors working on the IPUv3(Image Processing Unit) internal graphic processor. diff --git a/drivers/video/imx/mxc_ipuv3_fb.c b/drivers/video/imx/mxc_ipuv3_fb.c index 6787201..587d62f 100644 --- a/drivers/video/imx/mxc_ipuv3_fb.c +++ b/drivers/video/imx/mxc_ipuv3_fb.c @@ -38,10 +38,6 @@ DECLARE_GLOBAL_DATA_PTR; static int mxcfb_map_video_memory(struct fb_info *fbi); static int mxcfb_unmap_video_memory(struct fb_info *fbi); -#if !CONFIG_IS_ENABLED(DM_VIDEO) -/* graphics setup */ -static GraphicDevice panel; -#endif static struct fb_videomode const *gmode; static uint8_t gdisp; static uint32_t gpixfmt; @@ -391,12 +387,7 @@ static int mxcfb_map_video_memory(struct fb_info *fbi) } fbi->fix.smem_len = roundup(fbi->fix.smem_len, ARCH_DMA_MINALIGN); -#if CONFIG_IS_ENABLED(DM_VIDEO) fbi->screen_base = (char *)gd->video_bottom; -#else - fbi->screen_base = (char *)memalign(ARCH_DMA_MINALIGN, - fbi->fix.smem_len); -#endif fbi->fix.smem_start = (unsigned long)fbi->screen_base; if (fbi->screen_base == 0) { @@ -410,10 +401,7 @@ static int mxcfb_map_video_memory(struct fb_info *fbi) (uint32_t) fbi->fix.smem_start, fbi->fix.smem_len); fbi->screen_size = fbi->fix.smem_len; - -#if CONFIG_IS_ENABLED(VIDEO) gd->fb_base = fbi->fix.smem_start; -#endif /* Clear the screen */ memset((char *)fbi->screen_base, 0, fbi->fix.smem_len); @@ -544,18 +532,6 @@ static int mxcfb_probe(u32 interface_pix_fmt, uint8_t disp, mxcfb_set_par(fbi); -#if !CONFIG_IS_ENABLED(DM_VIDEO) - panel.winSizeX = mode->xres; - panel.winSizeY = mode->yres; - panel.plnSizeX = mode->xres; - panel.plnSizeY = mode->yres; - - panel.frameAdrs = (u32)fbi->screen_base; - panel.memSize = fbi->screen_size; - - panel.gdfBytesPP = 2; - panel.gdfIndex = GDF_16BIT_565RGB; -#endif #ifdef DEBUG ipu_dump_registers(); #endif @@ -585,23 +561,6 @@ void ipuv3_fb_shutdown(void) } } -#if !CONFIG_IS_ENABLED(DM_VIDEO) -void *video_hw_init(void) -{ - int ret; - - ret = ipu_probe(); - if (ret) - puts("Error initializing IPU\n"); - - ret = mxcfb_probe(gpixfmt, gdisp, gmode); - debug("Framebuffer at 0x%x\n", (unsigned int)panel.frameAdrs); - gd->fb_base = panel.frameAdrs; - - return (void *)&panel; -} -#endif - int ipuv3_fb_init(struct fb_videomode const *mode, uint8_t disp, uint32_t pixfmt) @@ -613,7 +572,6 @@ int ipuv3_fb_init(struct fb_videomode const *mode, return 0; } -#if CONFIG_IS_ENABLED(DM_VIDEO) enum { /* Maximum display size we support */ LCD_MAX_WIDTH = 1920, @@ -711,4 +669,3 @@ U_BOOT_DRIVER(ipuv3_video) = { .priv_auto_alloc_size = sizeof(struct ipuv3_video_priv), .flags = DM_FLAG_PRE_RELOC, }; -#endif /* CONFIG_DM_VIDEO */ -- cgit v1.1 From aeb3c386c81017657f4faef34d5c203fe32d3aeb Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Thu, 16 Apr 2020 14:48:44 +0200 Subject: mmc: zynq_sdhci: Remove global pointer Driver is not calling gd anywhere that's why there is not need to define it. Signed-off-by: Michal Simek --- drivers/mmc/zynq_sdhci.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/mmc/zynq_sdhci.c b/drivers/mmc/zynq_sdhci.c index de404aa..43b9f21 100644 --- a/drivers/mmc/zynq_sdhci.c +++ b/drivers/mmc/zynq_sdhci.c @@ -19,8 +19,6 @@ #include #include -DECLARE_GLOBAL_DATA_PTR; - struct arasan_sdhci_plat { struct mmc_config cfg; struct mmc mmc; -- cgit v1.1 From 2b2012d1c1d8515417ba139339d0aa9b47789dca Mon Sep 17 00:00:00 2001 From: Rajan Vaja Date: Mon, 4 May 2020 22:53:56 -0700 Subject: clk: versal: Remove alt_ref_clk from clock sources alt_ref_clk is applicable only for PS extended version. For PS base version there is no separate alt_ref_clk. It is tied with ref_clk, so remove it from driver. Signed-off-by: Rajan Vaja Signed-off-by: Michal Simek --- drivers/clk/clk_versal.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/clk_versal.c b/drivers/clk/clk_versal.c index 2fb3171..6f82b60 100644 --- a/drivers/clk/clk_versal.c +++ b/drivers/clk/clk_versal.c @@ -117,7 +117,6 @@ struct versal_clk_priv { struct versal_clock *clk; }; -static ulong alt_ref_clk; static ulong pl_alt_ref_clk; static ulong ref_clk; @@ -548,8 +547,7 @@ int soc_clk_dump(void) printf("\n ****** VERSAL CLOCKS *****\n"); - printf("alt_ref_clk:%ld pl_alt_ref_clk:%ld ref_clk:%ld\n", - alt_ref_clk, pl_alt_ref_clk, ref_clk); + printf("pl_alt_ref_clk:%ld ref_clk:%ld\n", pl_alt_ref_clk, ref_clk); for (i = 0; i < clock_max_idx; i++) { debug("%s\n", clock[i].clk_name); ret = versal_get_clock_type(i, &type); @@ -667,10 +665,6 @@ static int versal_clk_probe(struct udevice *dev) debug("%s\n", __func__); - ret = versal_clock_get_freq_by_name("alt_ref_clk", dev, &alt_ref_clk); - if (ret < 0) - return -EINVAL; - ret = versal_clock_get_freq_by_name("pl_alt_ref_clk", dev, &pl_alt_ref_clk); if (ret < 0) -- cgit v1.1 From 4c86e0834aeb3ae06389534ccbc90b8bcf5d95bf Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Mon, 27 Apr 2020 11:51:40 +0200 Subject: firmware: zynqmp: Change panic logic in zynqmp_pmufw_load_config_object() There is no need to panic all the time when pmufw config object loading failed. The patch improves function logic to report permission deny case and also panic only for SPL case. Signed-off-by: Michal Simek Reviewed-by: Luca Ceresoli --- drivers/firmware/firmware-zynqmp.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/firmware/firmware-zynqmp.c b/drivers/firmware/firmware-zynqmp.c index 2bdf777..66edc16 100644 --- a/drivers/firmware/firmware-zynqmp.c +++ b/drivers/firmware/firmware-zynqmp.c @@ -18,6 +18,8 @@ #define PMUFW_PAYLOAD_ARG_CNT 8 +#define XST_PM_NO_ACCESS 2002L + struct zynqmp_power { struct mbox_chan tx_chan; struct mbox_chan rx_chan; @@ -99,16 +101,25 @@ void zynqmp_pmufw_load_config_object(const void *cfg_obj, size_t size) PM_SET_CONFIGURATION, (u32)((u64)cfg_obj) }; - u32 response; + u32 response = 0; int err; printf("Loading new PMUFW cfg obj (%ld bytes)\n", size); err = send_req(request, ARRAY_SIZE(request), &response, 1); + if (err == XST_PM_NO_ACCESS) { + printf("PMUFW no permission to change config object\n"); + return; + } + if (err) - panic("Cannot load PMUFW configuration object (%d)\n", err); - if (response != 0) - panic("PMUFW returned 0x%08x status!\n", response); + printf("Cannot load PMUFW configuration object (%d)\n", err); + + if (response) + printf("PMUFW returned 0x%08x status!\n", response); + + if ((err || response) && IS_ENABLED(CONFIG_SPL_BUILD)) + panic("PMUFW config object loading failed in EL3\n"); } static int zynqmp_power_probe(struct udevice *dev) -- cgit v1.1 From 3427f4d2045729c8995b19407daf91ea9a50e4f8 Mon Sep 17 00:00:00 2001 From: Siva Durga Prasad Paladugu Date: Wed, 9 Dec 2015 18:46:43 +0530 Subject: fpga: zynqpl: Correct PL bitstream loading sequence for zynqaes Correct the PL bitstream loading sequence for zynqaes command by clearing the loaded PL bitstream before loading the new encrypted bitstream using the zynq aes command. This was done by setting the PROG_B same as in case of fpgaload commands. This patch fixes the issue of loading the encrypted PL bitstream onto the PL in which a bitstream has already been loaded successfully. Signed-off-by: Siva Durga Prasad Paladugu Signed-off-by: Michal Simek --- drivers/fpga/zynqpl.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/fpga/zynqpl.c b/drivers/fpga/zynqpl.c index dcfe513..4ab354b 100644 --- a/drivers/fpga/zynqpl.c +++ b/drivers/fpga/zynqpl.c @@ -204,7 +204,7 @@ static int zynq_dma_xfer_init(bitstream_type bstype) /* Clear loopback bit */ clrbits_le32(&devcfg_base->mctrl, DEVCFG_MCTRL_PCAP_LPBK); - if (bstype != BIT_PARTIAL) { + if (bstype != BIT_PARTIAL && bstype != BIT_NONE) { zynq_slcr_devcfg_disable(); /* Setting PCFG_PROG_B signal to high */ @@ -511,7 +511,8 @@ struct xilinx_fpga_op zynq_op = { * Load the encrypted image from src addr and decrypt the image and * place it back the decrypted image into dstaddr. */ -int zynq_decrypt_load(u32 srcaddr, u32 srclen, u32 dstaddr, u32 dstlen) +int zynq_decrypt_load(u32 srcaddr, u32 srclen, u32 dstaddr, u32 dstlen, + u8 bstype) { if (srcaddr < SZ_1M || dstaddr < SZ_1M) { printf("%s: src and dst addr should be > 1M\n", @@ -519,7 +520,7 @@ int zynq_decrypt_load(u32 srcaddr, u32 srclen, u32 dstaddr, u32 dstlen) return FPGA_FAIL; } - if (zynq_dma_xfer_init(BIT_NONE)) { + if (zynq_dma_xfer_init(bstype)) { printf("%s: zynq_dma_xfer_init FAIL\n", __func__); return FPGA_FAIL; } -- cgit v1.1 From 1d9632a3ccca00638ace1ff6bbce7eba1e15aac7 Mon Sep 17 00:00:00 2001 From: T Karthik Reddy Date: Tue, 12 Mar 2019 20:20:20 +0530 Subject: fpga: zynqpl: Check fpga config completion This patch checks fpga config completion when a bitstream is loaded into PL. Signed-off-by: T Karthik Reddy Signed-off-by: Siva Durga Prasad Paladugu Signed-off-by: Michal Simek --- drivers/fpga/zynqpl.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/fpga/zynqpl.c b/drivers/fpga/zynqpl.c index 4ab354b..de71969 100644 --- a/drivers/fpga/zynqpl.c +++ b/drivers/fpga/zynqpl.c @@ -514,6 +514,8 @@ struct xilinx_fpga_op zynq_op = { int zynq_decrypt_load(u32 srcaddr, u32 srclen, u32 dstaddr, u32 dstlen, u8 bstype) { + u32 isr_status, ts; + if (srcaddr < SZ_1M || dstaddr < SZ_1M) { printf("%s: src and dst addr should be > 1M\n", __func__); @@ -544,8 +546,21 @@ int zynq_decrypt_load(u32 srcaddr, u32 srclen, u32 dstaddr, u32 dstlen, if (zynq_dma_transfer(srcaddr | 1, srclen, dstaddr | 1, dstlen)) return FPGA_FAIL; - writel((readl(&devcfg_base->ctrl) & ~DEVCFG_CTRL_PCAP_RATE_EN_MASK), - &devcfg_base->ctrl); + if (bstype == BIT_FULL) { + isr_status = readl(&devcfg_base->int_sts); + /* Check FPGA configuration completion */ + ts = get_timer(0); + while (!(isr_status & DEVCFG_ISR_PCFG_DONE)) { + if (get_timer(ts) > CONFIG_SYS_FPGA_WAIT) { + printf("%s: Timeout wait for FPGA to config\n", + __func__); + return FPGA_FAIL; + } + isr_status = readl(&devcfg_base->int_sts); + } + printf("%s: FPGA config done\n", __func__); + zynq_slcr_devcfg_enable(); + } return FPGA_SUCCESS; } -- cgit v1.1 From c64afba2fb483d416ad5da9dfe3f1f156ccf2366 Mon Sep 17 00:00:00 2001 From: Ibai Erkiaga Date: Thu, 5 Apr 2018 05:19:27 -0700 Subject: fpga: zynqpl: Check if aes engine is enabled AES engine cannot be used if has not been enabled at boot time with an encrypted boot image. Signed-off-by: Ibai Erkiaga Acked-by: Siva Durga Prasad Paladugu Signed-off-by: Michal Simek --- drivers/fpga/zynqpl.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/fpga/zynqpl.c b/drivers/fpga/zynqpl.c index de71969..90bb850 100644 --- a/drivers/fpga/zynqpl.c +++ b/drivers/fpga/zynqpl.c @@ -22,6 +22,7 @@ #define DEVCFG_CTRL_PCFG_PROG_B 0x40000000 #define DEVCFG_CTRL_PCFG_AES_EFUSE_MASK 0x00001000 #define DEVCFG_CTRL_PCAP_RATE_EN_MASK 0x02000000 +#define DEVCFG_CTRL_PCFG_AES_EN_MASK 0x00000E00 #define DEVCFG_ISR_FATAL_ERROR_MASK 0x00740040 #define DEVCFG_ISR_ERROR_FLAGS_MASK 0x00340840 #define DEVCFG_ISR_RX_FIFO_OV 0x00040000 @@ -522,6 +523,13 @@ int zynq_decrypt_load(u32 srcaddr, u32 srclen, u32 dstaddr, u32 dstlen, return FPGA_FAIL; } + /* Check AES engine is enabled */ + if (!(readl(&devcfg_base->ctrl) & + DEVCFG_CTRL_PCFG_AES_EN_MASK)) { + printf("%s: AES engine is not enabled\n", __func__); + return FPGA_FAIL; + } + if (zynq_dma_xfer_init(bstype)) { printf("%s: zynq_dma_xfer_init FAIL\n", __func__); return FPGA_FAIL; -- cgit v1.1 From ca0c0e07adf3c3baf3851fc17490a0160398c834 Mon Sep 17 00:00:00 2001 From: T Karthik Reddy Date: Tue, 12 Mar 2019 20:20:23 +0530 Subject: fpga: zynqpl: Flush dcache only for non-bitstream data In case of aes decryption destination address range must be flushed before transferring decrypted data to destination. Signed-off-by: T Karthik Reddy Signed-off-by: Siva Durga Prasad Paladugu Signed-off-by: Michal Simek --- drivers/fpga/zynqpl.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/fpga/zynqpl.c b/drivers/fpga/zynqpl.c index 90bb850..a11e485 100644 --- a/drivers/fpga/zynqpl.c +++ b/drivers/fpga/zynqpl.c @@ -548,8 +548,9 @@ int zynq_decrypt_load(u32 srcaddr, u32 srclen, u32 dstaddr, u32 dstlen, * Flush destination address range only if image is not * bitstream. */ - flush_dcache_range((u32)dstaddr, (u32)dstaddr + - roundup(dstlen << 2, ARCH_DMA_MINALIGN)); + if (bstype == BIT_NONE && dstaddr != 0xFFFFFFFF) + flush_dcache_range((u32)dstaddr, (u32)dstaddr + + roundup(dstlen << 2, ARCH_DMA_MINALIGN)); if (zynq_dma_transfer(srcaddr | 1, srclen, dstaddr | 1, dstlen)) return FPGA_FAIL; -- cgit v1.1 From 26e62cc9713ebe728d01826e8c22c3c56f8e3bf4 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Wed, 13 May 2020 08:05:01 -0600 Subject: net: gem: Disable PCS autonegotiation in case of fixed-link Disable PCS autonegotiation if fixed-link node is present in device tree. This way systems with multiple GEM instances with a combination of SGMII-fixed and SGMII-PHY will work. Reported-by: Goran Marinkovic Signed-off-by: Michal Simek Signed-off-by: Ashok Reddy Soma Signed-off-by: Michal Simek --- drivers/net/zynq_gem.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/net/zynq_gem.c b/drivers/net/zynq_gem.c index 412daf7..da4b6fb 100644 --- a/drivers/net/zynq_gem.c +++ b/drivers/net/zynq_gem.c @@ -451,8 +451,12 @@ static int zynq_gem_init(struct udevice *dev) nwconfig |= ZYNQ_GEM_NWCFG_SGMII_ENBL | ZYNQ_GEM_NWCFG_PCS_SEL; #ifdef CONFIG_ARM64 + if (priv->phydev->phy_id != PHY_FIXED_ID) writel(readl(®s->pcscntrl) | ZYNQ_GEM_PCS_CTL_ANEG_ENBL, ®s->pcscntrl); + else + writel(readl(®s->pcscntrl) & ~ZYNQ_GEM_PCS_CTL_ANEG_ENBL, + ®s->pcscntrl); #endif } -- cgit v1.1 From f44bd3bcfd91cd7b1be709c9cfb0824e6a71b9b0 Mon Sep 17 00:00:00 2001 From: Ashok Reddy Soma Date: Mon, 18 May 2020 01:11:00 -0600 Subject: spi: zynq_[q]spi: Convert config's to macro's Remove below config options and convert them to macros. They have never been configured to different values than default one. And also it makes sense to reduce the config_whitelist. CONFIG_SYS_ZYNQ_SPI_WAIT CONFIG_SYS_ZYNQ_QSPI_WAIT CONFIG_XILINX_SPI_IDLE_VAL Signed-off-by: Ashok Reddy Soma Signed-off-by: Michal Simek --- drivers/spi/xilinx_spi.c | 6 ++---- drivers/spi/zynq_qspi.c | 6 ++---- drivers/spi/zynq_spi.c | 6 ++---- 3 files changed, 6 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/xilinx_spi.c b/drivers/spi/xilinx_spi.c index 05768ee..348630f 100644 --- a/drivers/spi/xilinx_spi.c +++ b/drivers/spi/xilinx_spi.c @@ -76,9 +76,7 @@ SPICR_SPE) #define XILSPI_SPICR_DFLT_OFF (SPICR_MASTER_INHIBIT | SPICR_MANUAL_SS) -#ifndef CONFIG_XILINX_SPI_IDLE_VAL -#define CONFIG_XILINX_SPI_IDLE_VAL GENMASK(7, 0) -#endif +#define XILINX_SPI_IDLE_VAL GENMASK(7, 0) #define XILINX_SPISR_TIMEOUT 10000 /* in milliseconds */ @@ -176,7 +174,7 @@ static u32 xilinx_spi_fill_txfifo(struct udevice *bus, const u8 *txp, while (txbytes && !(readl(®s->spisr) & SPISR_TX_FULL) && i < priv->fifo_depth) { - d = txp ? *txp++ : CONFIG_XILINX_SPI_IDLE_VAL; + d = txp ? *txp++ : XILINX_SPI_IDLE_VAL; debug("spi_xfer: tx:%x ", d); /* write out and wait for processing (receive data) */ writel(d & SPIDTR_8BIT_MASK, ®s->spidtr); diff --git a/drivers/spi/zynq_qspi.c b/drivers/spi/zynq_qspi.c index db473da..3f39ef0 100644 --- a/drivers/spi/zynq_qspi.c +++ b/drivers/spi/zynq_qspi.c @@ -47,9 +47,7 @@ DECLARE_GLOBAL_DATA_PTR; #define ZYNQ_QSPI_CR_SS_SHIFT 10 /* Slave select shift */ #define ZYNQ_QSPI_FIFO_DEPTH 63 -#ifndef CONFIG_SYS_ZYNQ_QSPI_WAIT -#define CONFIG_SYS_ZYNQ_QSPI_WAIT CONFIG_SYS_HZ/100 /* 10 ms */ -#endif +#define ZYNQ_QSPI_WAIT (CONFIG_SYS_HZ / 100) /* 10 ms */ /* zynq qspi register set */ struct zynq_qspi_regs { @@ -350,7 +348,7 @@ static int zynq_qspi_irq_poll(struct zynq_qspi_priv *priv) do { status = readl(®s->isr); } while ((status == 0) && - (get_timer(timeout) < CONFIG_SYS_ZYNQ_QSPI_WAIT)); + (get_timer(timeout) < ZYNQ_QSPI_WAIT)); if (status == 0) { printf("zynq_qspi_irq_poll: Timeout!\n"); diff --git a/drivers/spi/zynq_spi.c b/drivers/spi/zynq_spi.c index 3e66b34..78ffd3e 100644 --- a/drivers/spi/zynq_spi.c +++ b/drivers/spi/zynq_spi.c @@ -36,9 +36,7 @@ DECLARE_GLOBAL_DATA_PTR; #define ZYNQ_SPI_CR_SS_SHIFT 10 /* Slave select shift */ #define ZYNQ_SPI_FIFO_DEPTH 128 -#ifndef CONFIG_SYS_ZYNQ_SPI_WAIT -#define CONFIG_SYS_ZYNQ_SPI_WAIT (CONFIG_SYS_HZ/100) /* 10 ms */ -#endif +#define ZYNQ_SPI_WAIT (CONFIG_SYS_HZ / 100) /* 10 ms */ /* zynq spi register set */ struct zynq_spi_regs { @@ -251,7 +249,7 @@ static int zynq_spi_xfer(struct udevice *dev, unsigned int bitlen, ts = get_timer(0); status = readl(®s->isr); while (!(status & ZYNQ_SPI_IXR_TXOW_MASK)) { - if (get_timer(ts) > CONFIG_SYS_ZYNQ_SPI_WAIT) { + if (get_timer(ts) > ZYNQ_SPI_WAIT) { printf("spi_xfer: Timeout! TX FIFO not full\n"); return -1; } -- cgit v1.1 From 33d3f8e57754f9b498fa7c14408f2bc20be43900 Mon Sep 17 00:00:00 2001 From: T Karthik Reddy Date: Thu, 14 May 2020 07:49:36 -0600 Subject: arm64: xilinx: Print fpga error value in hex Fpga returns error value when fails, error status should be printed in hex format. Signed-off-by: T Karthik Reddy Signed-off-by: Michal Simek --- drivers/fpga/versalpl.c | 2 +- drivers/fpga/zynqmppl.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/fpga/versalpl.c b/drivers/fpga/versalpl.c index b96519e..8e2ef4f 100644 --- a/drivers/fpga/versalpl.c +++ b/drivers/fpga/versalpl.c @@ -45,7 +45,7 @@ static int versal_load(xilinx_desc *desc, const void *buf, size_t bsize, ret = xilinx_pm_request(VERSAL_PM_LOAD_PDI, VERSAL_PM_PDI_TYPE, buf_lo, buf_hi, 0, ret_payload); if (ret) - puts("PL FPGA LOAD fail\n"); + printf("PL FPGA LOAD failed with err: 0x%08x\n", ret); return ret; } diff --git a/drivers/fpga/zynqmppl.c b/drivers/fpga/zynqmppl.c index 2ac4e38..5b103cf 100644 --- a/drivers/fpga/zynqmppl.c +++ b/drivers/fpga/zynqmppl.c @@ -239,7 +239,7 @@ static int zynqmp_load(xilinx_desc *desc, const void *buf, size_t bsize, buf_hi, (u32)bsize, 0, ret_payload); if (ret) - puts("PL FPGA LOAD fail\n"); + printf("PL FPGA LOAD failed with err: 0x%08x\n", ret); return ret; } -- cgit v1.1 From 945a55050dbd2e916724c2db0ac7eb6c3e29518e Mon Sep 17 00:00:00 2001 From: Patrick van Gelder Date: Wed, 3 Jun 2020 14:18:04 +0200 Subject: net: xilinx: axi_emac: Fix endless loop when no PHYs are connected The index used to iterate over the possible PHYs in axiemac_phy_init was an unsigned int and decremented. Therefor it was always >= 0 and never exited the loop. Signed-off-by: Patrick van Gelder Signed-off-by: Michal Simek --- drivers/net/xilinx_axi_emac.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/xilinx_axi_emac.c b/drivers/net/xilinx_axi_emac.c index d0683db..2cd5596 100644 --- a/drivers/net/xilinx_axi_emac.c +++ b/drivers/net/xilinx_axi_emac.c @@ -244,7 +244,8 @@ static u32 phywrite(struct axidma_priv *priv, u32 phyaddress, u32 registernum, static int axiemac_phy_init(struct udevice *dev) { u16 phyreg; - u32 i, ret; + int i; + u32 ret; struct axidma_priv *priv = dev_get_priv(dev); struct axi_regs *regs = priv->iobase; struct phy_device *phydev; -- cgit v1.1 From aef43ea0606deefc97ed085b16618f18a911cdb5 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 10 May 2020 14:17:01 -0600 Subject: bdinfo: dm: Update fb_base when using driver model Update this value with the address of a video device so that it shows with the 'bd' command. It would be better to obtain the address from the uclass by looking in struct video_uc_platdata for each device. We can move over to that once DM_VIDEO migration is complete. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- drivers/video/video-uclass.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/video/video-uclass.c b/drivers/video/video-uclass.c index bf396d1..1f28745 100644 --- a/drivers/video/video-uclass.c +++ b/drivers/video/video-uclass.c @@ -84,6 +84,7 @@ int video_reserve(ulong *addrp) __func__, size, *addrp, dev->name); } gd->video_bottom = *addrp; + gd->fb_base = *addrp; debug("Video frame buffers from %lx to %lx\n", gd->video_bottom, gd->video_top); -- cgit v1.1 From 0735ac85224a8b518eec6792bac116781dc67aac Mon Sep 17 00:00:00 2001 From: Tom Rini Date: Tue, 16 Jun 2020 19:06:01 -0400 Subject: Convert CONFIG_AM335X_LCD to Kconfig This converts the following to Kconfig: CONFIG_AM335X_LCD Signed-off-by: Tom Rini --- drivers/video/Kconfig | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 01e8dbf..f5f3f28 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -508,7 +508,6 @@ config ATMEL_HLCD config AM335X_LCD bool "Enable AM335x video support" - depends on DM_VIDEO help Supports video output to an attached LCD panel. -- cgit v1.1 From b40fa972863701dc554e2a4825c048bfc5a8d709 Mon Sep 17 00:00:00 2001 From: Tom Rini Date: Tue, 16 Jun 2020 19:06:03 -0400 Subject: Convert CONFIG_ARM_PL180_MMCI to Kconfig This converts the following to Kconfig: CONFIG_ARM_PL180_MMCI Signed-off-by: Tom Rini --- drivers/mmc/Kconfig | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig index 8f56572..33b128d 100644 --- a/drivers/mmc/Kconfig +++ b/drivers/mmc/Kconfig @@ -66,7 +66,6 @@ config MMC_SPI_CRC_ON config ARM_PL180_MMCI bool "ARM AMBA Multimedia Card Interface and compatible support" - depends on DM_MMC && OF_CONTROL help This selects the ARM(R) AMBA(R) PrimeCell Multimedia Card Interface (PL180, PL181 and compatible) support. -- cgit v1.1 From 348d183e546bf28f78fe0ca03b36d8f76526c10c Mon Sep 17 00:00:00 2001 From: Tom Rini Date: Tue, 16 Jun 2020 19:06:05 -0400 Subject: Convert CONFIG_AT91_GPIO to Kconfig This converts the following to Kconfig: CONFIG_AT91_GPIO Signed-off-by: Tom Rini --- drivers/gpio/Kconfig | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index d87f6cc..af608b7 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -77,7 +77,6 @@ config DWAPB_GPIO config AT91_GPIO bool "AT91 PIO GPIO driver" - depends on DM_GPIO default n help Say yes here to select AT91 PIO GPIO driver. AT91 PIO -- cgit v1.1 From a60becc8c7ec06db2c0b8bec3c6ea25850911749 Mon Sep 17 00:00:00 2001 From: Tom Rini Date: Tue, 16 Jun 2020 19:06:06 -0400 Subject: Convert CONFIG_ATMEL_HLCD to Kconfig This converts the following to Kconfig: CONFIG_ATMEL_HLCD Signed-off-by: Tom Rini --- drivers/video/Kconfig | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index f5f3f28..52f5bc6 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -502,7 +502,6 @@ config NXP_TDA19988 config ATMEL_HLCD bool "Enable ATMEL video support using HLCDC" - depends on DM_VIDEO help HLCDC supports video output to an attached LCD panel. -- cgit v1.1 From 56c404603825a4e3229dcf0d3d88318b20493fa6 Mon Sep 17 00:00:00 2001 From: Lukasz Majewski Date: Thu, 4 Jun 2020 23:11:53 +0800 Subject: spi: Convert CONFIG_DM_SPI* to CONFIG_$(SPL_TPL_)DM_SPI* This change allows more fine tuning of driver model based SPI support in SPL and TPL. It is now possible to explicitly enable/disable the DM_SPI support in SPL and TPL via Kconfig option. Before this change it was necessary to use: /* SPI Flash Configs */ #if defined(CONFIG_SPL_BUILD) #undef CONFIG_DM_SPI #undef CONFIG_DM_SPI_FLASH #undef CONFIG_SPI_FLASH_MTD #endif in the ./include/configs/.h, which is error prone and shall be avoided when we strive to switch to Kconfig. The goal of this patch: Provide distinction for DM_SPI support in both U-Boot proper and SPL (TPL). Valid use case is when U-Boot proper wants to use DM_SPI, but SPL must still support non DM driver. Another use case is the conversion of non DM/DTS SPI driver to support DM/DTS. When such driver needs to work in both SPL and U-Boot proper, the distinction is needed in Kconfig (also if SPL version of the driver supports OF_PLATDATA). In the end of the day one would have to support following use cases (in single driver file - e.g. mxs_spi.c): - U-Boot proper driver supporting DT/DTS - U-Boot proper driver without DT/DTS support (deprecated) - SPL driver without DT/DTS support - SPL (and TPL) driver with DT/DTS (when the SoC has enough resources to run full blown DT/DTS) - SPL driver with DT/DTS and SPL_OF_PLATDATA (when one have constrained environment with no fitImage and OF_LIBFDT support). Some boards do require SPI support (with DM) in SPL (TPL) and some only have DM_SPI{_FLASH} defined to allow compiling SPL. This patch converts #ifdef CONFIG_DM_SPI* to #if CONFIG_IS_ENABLED(DM_SPI) and provides corresponding defines in Kconfig. Signed-off-by: Lukasz Majewski Tested-by: Adam Ford #da850-evm Signed-off-by: Hou Zhiqiang [trini: Fixup a few platforms] Signed-off-by: Tom Rini --- drivers/mtd/spi/Makefile | 4 ++-- drivers/mtd/spi/sf_probe.c | 2 +- drivers/net/fm/fm.c | 4 ++-- drivers/spi/Makefile | 2 +- drivers/spi/kirkwood_spi.c | 2 +- drivers/spi/mxc_spi.c | 6 +++--- drivers/spi/omap3_spi.c | 4 ++-- drivers/spi/sh_qspi.c | 4 ++-- 8 files changed, 14 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/mtd/spi/Makefile b/drivers/mtd/spi/Makefile index b5dfa30..952fd1e 100644 --- a/drivers/mtd/spi/Makefile +++ b/drivers/mtd/spi/Makefile @@ -3,7 +3,7 @@ # (C) Copyright 2006 # Wolfgang Denk, DENX Software Engineering, wd@denx.de. -obj-$(CONFIG_DM_SPI_FLASH) += sf-uclass.o +obj-$(CONFIG_$(SPL_TPL_)DM_SPI_FLASH) += sf-uclass.o spi-nor-y := sf_probe.o spi-nor-ids.o ifdef CONFIG_SPL_BUILD @@ -19,5 +19,5 @@ endif obj-$(CONFIG_SPI_FLASH) += spi-nor.o obj-$(CONFIG_SPI_FLASH_DATAFLASH) += sf_dataflash.o -obj-$(CONFIG_$(SPL_)SPI_FLASH_MTD) += sf_mtd.o +obj-$(CONFIG_$(SPL_TPL_)SPI_FLASH_MTD) += sf_mtd.o obj-$(CONFIG_SPI_FLASH_SANDBOX) += sandbox.o diff --git a/drivers/mtd/spi/sf_probe.c b/drivers/mtd/spi/sf_probe.c index 3548d63..afda241 100644 --- a/drivers/mtd/spi/sf_probe.c +++ b/drivers/mtd/spi/sf_probe.c @@ -53,7 +53,7 @@ err_read_id: return ret; } -#ifndef CONFIG_DM_SPI_FLASH +#if !CONFIG_IS_ENABLED(DM_SPI_FLASH) struct spi_flash *spi_flash_probe(unsigned int busnum, unsigned int cs, unsigned int max_hz, unsigned int spi_mode) { diff --git a/drivers/net/fm/fm.c b/drivers/net/fm/fm.c index 8ab1816..bbb1738 100644 --- a/drivers/net/fm/fm.c +++ b/drivers/net/fm/fm.c @@ -383,7 +383,7 @@ int fm_init_common(int index, struct ccsr_fman *reg) addr = malloc(CONFIG_SYS_QE_FMAN_FW_LENGTH); int ret = 0; -#ifdef CONFIG_DM_SPI_FLASH +#if CONFIG_IS_ENABLED(DM_SPI_FLASH) struct udevice *new; /* speed and mode will be read from DT */ @@ -470,7 +470,7 @@ int fm_init_common(int index, struct ccsr_fman *reg) void *addr = malloc(CONFIG_SYS_QE_FMAN_FW_LENGTH); int ret = 0; -#ifdef CONFIG_DM_SPI_FLASH +#if CONFIG_IS_ENABLED(DM_SPI_FLASH) struct udevice *new; /* speed and mode will be read from DT */ diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index 54881a7..9559e93 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -4,7 +4,7 @@ # Wolfgang Denk, DENX Software Engineering, wd@denx.de. # There are many options which enable SPI, so make this library available -ifdef CONFIG_DM_SPI +ifdef CONFIG_$(SPL_TPL_)DM_SPI obj-y += spi-uclass.o obj-$(CONFIG_SANDBOX) += spi-emul-uclass.o obj-$(CONFIG_SOFT_SPI) += soft_spi.o diff --git a/drivers/spi/kirkwood_spi.c b/drivers/spi/kirkwood_spi.c index 3986b06..c03923f 100644 --- a/drivers/spi/kirkwood_spi.c +++ b/drivers/spi/kirkwood_spi.c @@ -94,7 +94,7 @@ static int _spi_xfer(struct kwspi_registers *reg, unsigned int bitlen, return 0; } -#ifndef CONFIG_DM_SPI +#if !CONFIG_IS_ENABLED(DM_SPI) static struct kwspi_registers *spireg = (struct kwspi_registers *)MVEBU_SPI_BASE; diff --git a/drivers/spi/mxc_spi.c b/drivers/spi/mxc_spi.c index f52ebf4..aad3780 100644 --- a/drivers/spi/mxc_spi.c +++ b/drivers/spi/mxc_spi.c @@ -67,7 +67,7 @@ static inline struct mxc_spi_slave *to_mxc_spi_slave(struct spi_slave *slave) static void mxc_spi_cs_activate(struct mxc_spi_slave *mxcs) { -#if defined(CONFIG_DM_SPI) +#if CONFIG_IS_ENABLED(DM_SPI) struct udevice *dev = mxcs->dev; struct dm_spi_slave_platdata *slave_plat = dev_get_parent_platdata(dev); @@ -85,7 +85,7 @@ static void mxc_spi_cs_activate(struct mxc_spi_slave *mxcs) static void mxc_spi_cs_deactivate(struct mxc_spi_slave *mxcs) { -#if defined(CONFIG_DM_SPI) +#if CONFIG_IS_ENABLED(DM_SPI) struct udevice *dev = mxcs->dev; struct dm_spi_slave_platdata *slave_plat = dev_get_parent_platdata(dev); @@ -415,7 +415,7 @@ static int mxc_spi_claim_bus_internal(struct mxc_spi_slave *mxcs, int cs) return 0; } -#ifndef CONFIG_DM_SPI +#if !CONFIG_IS_ENABLED(DM_SPI) int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout, void *din, unsigned long flags) { diff --git a/drivers/spi/omap3_spi.c b/drivers/spi/omap3_spi.c index 6a615d1..ae08531 100644 --- a/drivers/spi/omap3_spi.c +++ b/drivers/spi/omap3_spi.c @@ -109,7 +109,7 @@ struct mcspi { }; struct omap3_spi_priv { -#ifndef CONFIG_DM_SPI +#if !CONFIG_IS_ENABLED(DM_SPI) struct spi_slave slave; #endif struct mcspi *regs; @@ -455,7 +455,7 @@ static void _omap3_spi_claim_bus(struct omap3_spi_priv *priv) writel(conf, &priv->regs->modulctrl); } -#ifndef CONFIG_DM_SPI +#if !CONFIG_IS_ENABLED(DM_SPI) static inline struct omap3_spi_priv *to_omap3_spi(struct spi_slave *slave) { diff --git a/drivers/spi/sh_qspi.c b/drivers/spi/sh_qspi.c index 2839dd1..aa1c030 100644 --- a/drivers/spi/sh_qspi.c +++ b/drivers/spi/sh_qspi.c @@ -68,7 +68,7 @@ struct sh_qspi_regs { }; struct sh_qspi_slave { -#ifndef CONFIG_DM_SPI +#if !CONFIG_IS_ENABLED(DM_SPI) struct spi_slave slave; #endif struct sh_qspi_regs *regs; @@ -223,7 +223,7 @@ static int sh_qspi_xfer_common(struct sh_qspi_slave *ss, unsigned int bitlen, return ret; } -#ifndef CONFIG_DM_SPI +#if !CONFIG_IS_ENABLED(DM_SPI) static inline struct sh_qspi_slave *to_sh_qspi(struct spi_slave *slave) { return container_of(slave, struct sh_qspi_slave, slave); -- cgit v1.1 From 582b4f7f394da21fcb96a56e29dd68115a746b44 Mon Sep 17 00:00:00 2001 From: Tom Rini Date: Tue, 16 Jun 2020 19:06:31 -0400 Subject: Convert CONFIG_CADENCE_QSPI to Kconfig This converts the following to Kconfig: CONFIG_CADENCE_QSPI Signed-off-by: Tom Rini --- drivers/spi/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index 9559e93..4e74617 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -6,6 +6,7 @@ # There are many options which enable SPI, so make this library available ifdef CONFIG_$(SPL_TPL_)DM_SPI obj-y += spi-uclass.o +obj-$(CONFIG_CADENCE_QSPI) += cadence_qspi.o cadence_qspi_apb.o obj-$(CONFIG_SANDBOX) += spi-emul-uclass.o obj-$(CONFIG_SOFT_SPI) += soft_spi.o obj-$(CONFIG_SPI_MEM) += spi-mem.o @@ -22,7 +23,6 @@ obj-$(CONFIG_ATMEL_SPI) += atmel_spi.o obj-$(CONFIG_BCM63XX_HSSPI) += bcm63xx_hsspi.o obj-$(CONFIG_BCM63XX_SPI) += bcm63xx_spi.o obj-$(CONFIG_BCMSTB_SPI) += bcmstb_spi.o -obj-$(CONFIG_CADENCE_QSPI) += cadence_qspi.o cadence_qspi_apb.o obj-$(CONFIG_CF_SPI) += cf_spi.o obj-$(CONFIG_DAVINCI_SPI) += davinci_spi.o obj-$(CONFIG_DESIGNWARE_SPI) += designware_spi.o -- cgit v1.1 From b9c52c50905cfd5973418e925e72c3bbefc7eb34 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 17 May 2020 18:24:11 +0200 Subject: net: pcnet: Drop typedef struct pcnet_priv_t Use struct pcnet_priv all over the place instead. Signed-off-by: Marek Vasut Cc: Daniel Schwierzeck Cc: Joe Hershberger --- drivers/net/pcnet.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/pcnet.c b/drivers/net/pcnet.c index 260a5a3..c6f080d 100644 --- a/drivers/net/pcnet.c +++ b/drivers/net/pcnet.c @@ -76,15 +76,15 @@ struct pcnet_uncached_priv { struct pcnet_init_block init_block; }; -typedef struct pcnet_priv { +struct pcnet_priv { struct pcnet_uncached_priv *uc; /* Receive Buffer space */ unsigned char (*rx_buf)[RX_RING_SIZE][PKT_BUF_SZ + 4]; int cur_rx; int cur_tx; -} pcnet_priv_t; +}; -static pcnet_priv_t *lp; +static struct pcnet_priv *lp; /* Offsets from base I/O address for WIO mode */ #define PCNET_RDP 0x10 @@ -340,9 +340,9 @@ static int pcnet_init(struct eth_device *dev, bd_t *bis) * must be aligned on 16-byte boundaries. */ if (lp == NULL) { - addr = (unsigned long)malloc(sizeof(pcnet_priv_t) + 0x10); + addr = (unsigned long)malloc(sizeof(*lp) + 0x10); addr = (addr + 0xf) & ~0xf; - lp = (pcnet_priv_t *)addr; + lp = (struct pcnet_priv *)addr; addr = (unsigned long)memalign(ARCH_DMA_MINALIGN, sizeof(*lp->uc)); -- cgit v1.1 From b92b8f48fb47c48b3f9df91ea1009b5789d55e19 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 17 May 2020 18:24:12 +0200 Subject: net: pcnet: Drop PCNET_HAS_PROM All of one PCNET users has this option set, make this default and drop this config option. Signed-off-by: Marek Vasut Cc: Daniel Schwierzeck Cc: Joe Hershberger --- drivers/net/pcnet.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/pcnet.c b/drivers/net/pcnet.c index c6f080d..edc4dba 100644 --- a/drivers/net/pcnet.c +++ b/drivers/net/pcnet.c @@ -241,10 +241,7 @@ static int pcnet_probe(struct eth_device *dev, bd_t *bis, int dev_nr) { int chip_version; char *chipname; - -#ifdef PCNET_HAS_PROM int i; -#endif /* Reset the PCnet controller */ pcnet_reset(dev); @@ -279,7 +276,6 @@ static int pcnet_probe(struct eth_device *dev, bd_t *bis, int dev_nr) PCNET_DEBUG1("AMD %s\n", chipname); -#ifdef PCNET_HAS_PROM /* * In most chips, after a chip reset, the ethernet address is read from * the station address PROM at the base address and programmed into the @@ -293,7 +289,6 @@ static int pcnet_probe(struct eth_device *dev, bd_t *bis, int dev_nr) dev->enetaddr[2 * i] = val & 0x0ff; dev->enetaddr[2 * i + 1] = (val >> 8) & 0x0ff; } -#endif /* PCNET_HAS_PROM */ return 0; } -- cgit v1.1 From d3b1df0f396adb2b5c25ff655c3dae8624c41e50 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 17 May 2020 18:24:13 +0200 Subject: net: pcnet: Use PCI_DEVICE() to define PCI device compat list Use this macro to fully fill the PCI device ID table. This is mandatory for the DM PCI support, which checks all the fields. Signed-off-by: Marek Vasut Cc: Daniel Schwierzeck Cc: Joe Hershberger --- drivers/net/pcnet.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/pcnet.c b/drivers/net/pcnet.c index edc4dba..e7ce79e 100644 --- a/drivers/net/pcnet.c +++ b/drivers/net/pcnet.c @@ -155,7 +155,7 @@ static inline pci_addr_t pcnet_virt_to_mem(const struct eth_device *dev, } static struct pci_device_id supported[] = { - {PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE}, + { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE) }, {} }; -- cgit v1.1 From 89369b0ac2ca0621bfc30baed739bb9d9e7fdcad Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 17 May 2020 18:24:14 +0200 Subject: net: pcnet: Simplify private data allocation The current code is horribly complex. Both the RX and TX buffer descriptors are 16 bytes in size, the init block is 32 bytes in size, so simplify the code such that the entire private data of the driver are allocated cache aligned and the RX and TX buffer descriptors are part of the private data. This removes multiple malloc calls and cache flushes. Signed-off-by: Marek Vasut Cc: Daniel Schwierzeck Cc: Joe Hershberger --- drivers/net/pcnet.c | 33 ++++++++++++--------------------- 1 file changed, 12 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/net/pcnet.c b/drivers/net/pcnet.c index e7ce79e..72b9380 100644 --- a/drivers/net/pcnet.c +++ b/drivers/net/pcnet.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -74,12 +75,13 @@ struct pcnet_uncached_priv { struct pcnet_rx_head rx_ring[RX_RING_SIZE]; struct pcnet_tx_head tx_ring[TX_RING_SIZE]; struct pcnet_init_block init_block; -}; +} __aligned(ARCH_DMA_MINALIGN); struct pcnet_priv { - struct pcnet_uncached_priv *uc; + struct pcnet_uncached_priv ucp; /* Receive Buffer space */ - unsigned char (*rx_buf)[RX_RING_SIZE][PKT_BUF_SZ + 4]; + unsigned char rx_buf[RX_RING_SIZE][PKT_BUF_SZ + 4]; + struct pcnet_uncached_priv *uc; int cur_rx; int cur_tx; }; @@ -335,22 +337,11 @@ static int pcnet_init(struct eth_device *dev, bd_t *bis) * must be aligned on 16-byte boundaries. */ if (lp == NULL) { - addr = (unsigned long)malloc(sizeof(*lp) + 0x10); - addr = (addr + 0xf) & ~0xf; - lp = (struct pcnet_priv *)addr; - - addr = (unsigned long)memalign(ARCH_DMA_MINALIGN, - sizeof(*lp->uc)); - flush_dcache_range(addr, addr + sizeof(*lp->uc)); - addr = (unsigned long)map_physmem(addr, - roundup(sizeof(*lp->uc), ARCH_DMA_MINALIGN), - MAP_NOCACHE); - lp->uc = (struct pcnet_uncached_priv *)addr; - - addr = (unsigned long)memalign(ARCH_DMA_MINALIGN, - sizeof(*lp->rx_buf)); - flush_dcache_range(addr, addr + sizeof(*lp->rx_buf)); - lp->rx_buf = (void *)addr; + lp = malloc_cache_aligned(sizeof(*lp)); + lp->uc = map_physmem((phys_addr_t)&lp->ucp, + sizeof(lp->ucp), MAP_NOCACHE); + flush_dcache_range((unsigned long)lp, + (unsigned long)lp + sizeof(*lp)); } uc = lp->uc; @@ -364,7 +355,7 @@ static int pcnet_init(struct eth_device *dev, bd_t *bis) */ lp->cur_rx = 0; for (i = 0; i < RX_RING_SIZE; i++) { - addr = pcnet_virt_to_mem(dev, (*lp->rx_buf)[i]); + addr = pcnet_virt_to_mem(dev, lp->rx_buf[i]); uc->rx_ring[i].base = cpu_to_le32(addr); uc->rx_ring[i].buf_length = cpu_to_le16(-PKT_BUF_SZ); uc->rx_ring[i].status = cpu_to_le16(0x8000); @@ -521,7 +512,7 @@ static int pcnet_recv (struct eth_device *dev) printf("%s: Rx%d: invalid packet length %d\n", dev->name, lp->cur_rx, pkt_len); } else { - buf = (*lp->rx_buf)[lp->cur_rx]; + buf = lp->rx_buf[lp->cur_rx]; invalidate_dcache_range((unsigned long)buf, (unsigned long)buf + pkt_len); net_process_received_packet(buf, pkt_len); -- cgit v1.1 From 0e11d79a533e3c874be1c5975abbc52aaba94d93 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 17 May 2020 18:24:15 +0200 Subject: net: pcnet: Replace memset+malloc with calloc This combination of functions can be replaced with calloc(), make it so. Signed-off-by: Marek Vasut Cc: Daniel Schwierzeck Cc: Joe Hershberger --- drivers/net/pcnet.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/pcnet.c b/drivers/net/pcnet.c index 72b9380..b670cff 100644 --- a/drivers/net/pcnet.c +++ b/drivers/net/pcnet.c @@ -184,12 +184,11 @@ int pcnet_initialize(bd_t *bis) /* * Allocate and pre-fill the device structure. */ - dev = (struct eth_device *)malloc(sizeof(*dev)); + dev = calloc(1, sizeof(*dev)); if (!dev) { printf("pcnet: Can not allocate memory\n"); break; } - memset(dev, 0, sizeof(*dev)); dev->priv = (void *)(unsigned long)devbusfn; sprintf(dev->name, "pcnet#%d", dev_nr); -- cgit v1.1 From ada6a2cea5a0d44c3bd64713babd9d73eaf64863 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 17 May 2020 18:24:16 +0200 Subject: net: pcnet: Move private data allocation to initialize The private data allocation does not have to be done every time the NIC is initialized at run time, move the allocation to initialize function, which means it will be done only once when the driver starts. Signed-off-by: Marek Vasut Cc: Daniel Schwierzeck Cc: Joe Hershberger --- drivers/net/pcnet.c | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/net/pcnet.c b/drivers/net/pcnet.c index b670cff..073ffca 100644 --- a/drivers/net/pcnet.c +++ b/drivers/net/pcnet.c @@ -189,6 +189,20 @@ int pcnet_initialize(bd_t *bis) printf("pcnet: Can not allocate memory\n"); break; } + + /* + * We only maintain one structure because the drivers will + * never be used concurrently. In 32bit mode the RX and TX + * ring entries must be aligned on 16-byte boundaries. + */ + if (!lp) { + lp = malloc_cache_aligned(sizeof(*lp)); + lp->uc = map_physmem((phys_addr_t)&lp->ucp, + sizeof(lp->ucp), MAP_NOCACHE); + flush_dcache_range((unsigned long)lp, + (unsigned long)lp + sizeof(*lp)); + } + dev->priv = (void *)(unsigned long)devbusfn; sprintf(dev->name, "pcnet#%d", dev_nr); @@ -330,19 +344,6 @@ static int pcnet_init(struct eth_device *dev, bd_t *bis) val |= 0x3 << 10; pcnet_write_csr(dev, 80, val); - /* - * We only maintain one structure because the drivers will never - * be used concurrently. In 32bit mode the RX and TX ring entries - * must be aligned on 16-byte boundaries. - */ - if (lp == NULL) { - lp = malloc_cache_aligned(sizeof(*lp)); - lp->uc = map_physmem((phys_addr_t)&lp->ucp, - sizeof(lp->ucp), MAP_NOCACHE); - flush_dcache_range((unsigned long)lp, - (unsigned long)lp + sizeof(*lp)); - } - uc = lp->uc; uc->init_block.mode = cpu_to_le16(0x0000); -- cgit v1.1 From 54c6067486e576eea70020d743a0a19d5ad1e603 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 17 May 2020 18:24:17 +0200 Subject: net: pcnet: Move initialize function at the end Move the function at the end of the driver, so we could drop various forward declarations later. No functional change. Signed-off-by: Marek Vasut Cc: Daniel Schwierzeck Cc: Joe Hershberger --- drivers/net/pcnet.c | 180 ++++++++++++++++++++++++++-------------------------- 1 file changed, 89 insertions(+), 91 deletions(-) (limited to 'drivers') diff --git a/drivers/net/pcnet.c b/drivers/net/pcnet.c index 073ffca..6d464cd 100644 --- a/drivers/net/pcnet.c +++ b/drivers/net/pcnet.c @@ -161,97 +161,6 @@ static struct pci_device_id supported[] = { {} }; - -int pcnet_initialize(bd_t *bis) -{ - pci_dev_t devbusfn; - struct eth_device *dev; - u16 command, status; - int dev_nr = 0; - u32 bar; - - PCNET_DEBUG1("\npcnet_initialize...\n"); - - for (dev_nr = 0;; dev_nr++) { - - /* - * Find the PCnet PCI device(s). - */ - devbusfn = pci_find_devices(supported, dev_nr); - if (devbusfn < 0) - break; - - /* - * Allocate and pre-fill the device structure. - */ - dev = calloc(1, sizeof(*dev)); - if (!dev) { - printf("pcnet: Can not allocate memory\n"); - break; - } - - /* - * We only maintain one structure because the drivers will - * never be used concurrently. In 32bit mode the RX and TX - * ring entries must be aligned on 16-byte boundaries. - */ - if (!lp) { - lp = malloc_cache_aligned(sizeof(*lp)); - lp->uc = map_physmem((phys_addr_t)&lp->ucp, - sizeof(lp->ucp), MAP_NOCACHE); - flush_dcache_range((unsigned long)lp, - (unsigned long)lp + sizeof(*lp)); - } - - dev->priv = (void *)(unsigned long)devbusfn; - sprintf(dev->name, "pcnet#%d", dev_nr); - - /* - * Setup the PCI device. - */ - pci_read_config_dword(devbusfn, PCI_BASE_ADDRESS_1, &bar); - dev->iobase = pci_mem_to_phys(devbusfn, bar); - dev->iobase &= ~0xf; - - PCNET_DEBUG1("%s: devbusfn=0x%x iobase=0x%lx: ", - dev->name, devbusfn, (unsigned long)dev->iobase); - - command = PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; - pci_write_config_word(devbusfn, PCI_COMMAND, command); - pci_read_config_word(devbusfn, PCI_COMMAND, &status); - if ((status & command) != command) { - printf("%s: Couldn't enable IO access or Bus Mastering\n", - dev->name); - free(dev); - continue; - } - - pci_write_config_byte(devbusfn, PCI_LATENCY_TIMER, 0x40); - - /* - * Probe the PCnet chip. - */ - if (pcnet_probe(dev, bis, dev_nr) < 0) { - free(dev); - continue; - } - - /* - * Setup device structure and register the driver. - */ - dev->init = pcnet_init; - dev->halt = pcnet_halt; - dev->send = pcnet_send; - dev->recv = pcnet_recv; - - eth_register(dev); - } - - udelay(10 * 1000); - - return dev_nr; -} - static int pcnet_probe(struct eth_device *dev, bd_t *bis, int dev_nr) { int chip_version; @@ -548,3 +457,92 @@ static void pcnet_halt(struct eth_device *dev) if (i <= 0) printf("%s: TIMEOUT: controller reset failed\n", dev->name); } + +int pcnet_initialize(bd_t *bis) +{ + pci_dev_t devbusfn; + struct eth_device *dev; + u16 command, status; + int dev_nr = 0; + u32 bar; + + PCNET_DEBUG1("\npcnet_initialize...\n"); + + for (dev_nr = 0; ; dev_nr++) { + /* + * Find the PCnet PCI device(s). + */ + devbusfn = pci_find_devices(supported, dev_nr); + if (devbusfn < 0) + break; + + /* + * Allocate and pre-fill the device structure. + */ + dev = calloc(1, sizeof(*dev)); + if (!dev) { + printf("pcnet: Can not allocate memory\n"); + break; + } + + /* + * We only maintain one structure because the drivers will + * never be used concurrently. In 32bit mode the RX and TX + * ring entries must be aligned on 16-byte boundaries. + */ + if (!lp) { + lp = malloc_cache_aligned(sizeof(*lp)); + lp->uc = map_physmem((phys_addr_t)&lp->ucp, + sizeof(lp->ucp), MAP_NOCACHE); + flush_dcache_range((unsigned long)lp, + (unsigned long)lp + sizeof(*lp)); + } + + dev->priv = (void *)(unsigned long)devbusfn; + sprintf(dev->name, "pcnet#%d", dev_nr); + + /* + * Setup the PCI device. + */ + pci_read_config_dword(devbusfn, PCI_BASE_ADDRESS_1, &bar); + dev->iobase = pci_mem_to_phys(devbusfn, bar); + dev->iobase &= ~0xf; + + PCNET_DEBUG1("%s: devbusfn=0x%x iobase=0x%lx: ", + dev->name, devbusfn, (unsigned long)dev->iobase); + + command = PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; + pci_write_config_word(devbusfn, PCI_COMMAND, command); + pci_read_config_word(devbusfn, PCI_COMMAND, &status); + if ((status & command) != command) { + printf("%s: Couldn't enable IO access or Bus Mastering\n", + dev->name); + free(dev); + continue; + } + + pci_write_config_byte(devbusfn, PCI_LATENCY_TIMER, 0x40); + + /* + * Probe the PCnet chip. + */ + if (pcnet_probe(dev, bis, dev_nr) < 0) { + free(dev); + continue; + } + + /* + * Setup device structure and register the driver. + */ + dev->init = pcnet_init; + dev->halt = pcnet_halt; + dev->send = pcnet_send; + dev->recv = pcnet_recv; + + eth_register(dev); + } + + udelay(10 * 1000); + + return dev_nr; +} -- cgit v1.1 From 553286a63ca5e60beb4cf5af68795c7d78a19ceb Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 17 May 2020 18:24:18 +0200 Subject: net: pcnet: Drop useless forward declarations Remove those as they are not needed anymore. Signed-off-by: Marek Vasut Cc: Daniel Schwierzeck Cc: Joe Hershberger --- drivers/net/pcnet.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/pcnet.c b/drivers/net/pcnet.c index 6d464cd..d8249f0 100644 --- a/drivers/net/pcnet.c +++ b/drivers/net/pcnet.c @@ -141,12 +141,6 @@ static int pcnet_check(struct eth_device *dev) return readw(base + PCNET_RAP) == 88; } -static int pcnet_init (struct eth_device *dev, bd_t * bis); -static int pcnet_send(struct eth_device *dev, void *packet, int length); -static int pcnet_recv (struct eth_device *dev); -static void pcnet_halt (struct eth_device *dev); -static int pcnet_probe (struct eth_device *dev, bd_t * bis, int dev_num); - static inline pci_addr_t pcnet_virt_to_mem(const struct eth_device *dev, void *addr) { -- cgit v1.1 From ab6ecbdc3c25761756538129c26d1396dd5b02a9 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 17 May 2020 18:24:19 +0200 Subject: net: pcnet: Wrap devbusfn into private data Instead of using eth_device priv for this PCI devbusfn, free it so it could be used for driver private data, and wrap devbusfn into those driver private data. Note that using the name dev for the variable is a trick left for later, when DM support is in place, so dm_pci_virt_to_mem() can be used with minimal ifdeffery. Signed-off-by: Marek Vasut Cc: Daniel Schwierzeck Cc: Joe Hershberger --- drivers/net/pcnet.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/net/pcnet.c b/drivers/net/pcnet.c index d8249f0..f7f1b8f 100644 --- a/drivers/net/pcnet.c +++ b/drivers/net/pcnet.c @@ -82,6 +82,7 @@ struct pcnet_priv { /* Receive Buffer space */ unsigned char rx_buf[RX_RING_SIZE][PKT_BUF_SZ + 4]; struct pcnet_uncached_priv *uc; + pci_dev_t dev; int cur_rx; int cur_tx; }; @@ -141,13 +142,11 @@ static int pcnet_check(struct eth_device *dev) return readw(base + PCNET_RAP) == 88; } -static inline pci_addr_t pcnet_virt_to_mem(const struct eth_device *dev, - void *addr) +static inline pci_addr_t pcnet_virt_to_mem(struct pcnet_priv *lp, void *addr) { - pci_dev_t devbusfn = (pci_dev_t)(unsigned long)dev->priv; void *virt_addr = addr; - return pci_virt_to_mem(devbusfn, virt_addr); + return pci_virt_to_mem(lp->dev, virt_addr); } static struct pci_device_id supported[] = { @@ -258,7 +257,7 @@ static int pcnet_init(struct eth_device *dev, bd_t *bis) */ lp->cur_rx = 0; for (i = 0; i < RX_RING_SIZE; i++) { - addr = pcnet_virt_to_mem(dev, lp->rx_buf[i]); + addr = pcnet_virt_to_mem(lp, lp->rx_buf[i]); uc->rx_ring[i].base = cpu_to_le32(addr); uc->rx_ring[i].buf_length = cpu_to_le16(-PKT_BUF_SZ); uc->rx_ring[i].status = cpu_to_le16(0x8000); @@ -290,9 +289,9 @@ static int pcnet_init(struct eth_device *dev, bd_t *bis) uc->init_block.tlen_rlen = cpu_to_le16(TX_RING_LEN_BITS | RX_RING_LEN_BITS); - addr = pcnet_virt_to_mem(dev, uc->rx_ring); + addr = pcnet_virt_to_mem(lp, uc->rx_ring); uc->init_block.rx_ring = cpu_to_le32(addr); - addr = pcnet_virt_to_mem(dev, uc->tx_ring); + addr = pcnet_virt_to_mem(lp, uc->tx_ring); uc->init_block.tx_ring = cpu_to_le32(addr); PCNET_DEBUG1("\ntlen_rlen=0x%x rx_ring=0x%x tx_ring=0x%x\n", @@ -303,7 +302,7 @@ static int pcnet_init(struct eth_device *dev, bd_t *bis) * Tell the controller where the Init Block is located. */ barrier(); - addr = pcnet_virt_to_mem(dev, &lp->uc->init_block); + addr = pcnet_virt_to_mem(lp, &lp->uc->init_block); pcnet_write_csr(dev, 1, addr & 0xffff); pcnet_write_csr(dev, 2, (addr >> 16) & 0xffff); @@ -361,7 +360,7 @@ static int pcnet_send(struct eth_device *dev, void *packet, int pkt_len) * Setup Tx ring. Caution: the write order is important here, * set the status with the "ownership" bits last. */ - addr = pcnet_virt_to_mem(dev, packet); + addr = pcnet_virt_to_mem(lp, packet); writew(-pkt_len, &entry->length); writel(0, &entry->misc); writel(addr, &entry->base); @@ -492,7 +491,7 @@ int pcnet_initialize(bd_t *bis) (unsigned long)lp + sizeof(*lp)); } - dev->priv = (void *)(unsigned long)devbusfn; + lp->dev = devbusfn; sprintf(dev->name, "pcnet#%d", dev_nr); /* -- cgit v1.1 From 834d5cebe582eb71a2c76fc5c9078a3a85b1cafe Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 17 May 2020 18:24:20 +0200 Subject: net: pcnet: Pass private data through dev->priv Get rid of the global point to private data, and rather pass it thought dev->priv. Also remove the unnecessary check for lp being non-NULL, since it is always NULL at this point. Signed-off-by: Marek Vasut Cc: Daniel Schwierzeck Cc: Joe Hershberger --- drivers/net/pcnet.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/net/pcnet.c b/drivers/net/pcnet.c index f7f1b8f..dab08c0 100644 --- a/drivers/net/pcnet.c +++ b/drivers/net/pcnet.c @@ -87,8 +87,6 @@ struct pcnet_priv { int cur_tx; }; -static struct pcnet_priv *lp; - /* Offsets from base I/O address for WIO mode */ #define PCNET_RDP 0x10 #define PCNET_RAP 0x12 @@ -212,6 +210,7 @@ static int pcnet_probe(struct eth_device *dev, bd_t *bis, int dev_nr) static int pcnet_init(struct eth_device *dev, bd_t *bis) { + struct pcnet_priv *lp = dev->priv; struct pcnet_uncached_priv *uc; int i, val; unsigned long addr; @@ -331,6 +330,7 @@ static int pcnet_init(struct eth_device *dev, bd_t *bis) static int pcnet_send(struct eth_device *dev, void *packet, int pkt_len) { + struct pcnet_priv *lp = dev->priv; int i, status; u32 addr; struct pcnet_tx_head *entry = &lp->uc->tx_ring[lp->cur_tx]; @@ -379,6 +379,7 @@ static int pcnet_send(struct eth_device *dev, void *packet, int pkt_len) static int pcnet_recv (struct eth_device *dev) { + struct pcnet_priv *lp = dev->priv; struct pcnet_rx_head *entry; unsigned char *buf; int pkt_len = 0; @@ -455,6 +456,7 @@ int pcnet_initialize(bd_t *bis) { pci_dev_t devbusfn; struct eth_device *dev; + struct pcnet_priv *lp; u16 command, status; int dev_nr = 0; u32 bar; @@ -483,15 +485,13 @@ int pcnet_initialize(bd_t *bis) * never be used concurrently. In 32bit mode the RX and TX * ring entries must be aligned on 16-byte boundaries. */ - if (!lp) { - lp = malloc_cache_aligned(sizeof(*lp)); - lp->uc = map_physmem((phys_addr_t)&lp->ucp, - sizeof(lp->ucp), MAP_NOCACHE); - flush_dcache_range((unsigned long)lp, - (unsigned long)lp + sizeof(*lp)); - } - + lp = malloc_cache_aligned(sizeof(*lp)); + lp->uc = map_physmem((phys_addr_t)&lp->ucp, + sizeof(lp->ucp), MAP_NOCACHE); lp->dev = devbusfn; + flush_dcache_range((unsigned long)lp, + (unsigned long)lp + sizeof(*lp)); + dev->priv = lp; sprintf(dev->name, "pcnet#%d", dev_nr); /* -- cgit v1.1 From deca77382114364ca476482ad3e8bd431578fea8 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 17 May 2020 18:24:21 +0200 Subject: net: pcnet: Wrap iobase into private data Instead of using the non-DM-only iobase in struct eth_device, add one into the private data to make DM and non-DM operation possible. Signed-off-by: Marek Vasut Cc: Daniel Schwierzeck Cc: Joe Hershberger --- drivers/net/pcnet.c | 103 +++++++++++++++++++++++----------------------------- 1 file changed, 46 insertions(+), 57 deletions(-) (limited to 'drivers') diff --git a/drivers/net/pcnet.c b/drivers/net/pcnet.c index dab08c0..b0bd4af 100644 --- a/drivers/net/pcnet.c +++ b/drivers/net/pcnet.c @@ -83,6 +83,7 @@ struct pcnet_priv { unsigned char rx_buf[RX_RING_SIZE][PKT_BUF_SZ + 4]; struct pcnet_uncached_priv *uc; pci_dev_t dev; + void __iomem *iobase; int cur_rx; int cur_tx; }; @@ -93,51 +94,39 @@ struct pcnet_priv { #define PCNET_RESET 0x14 #define PCNET_BDP 0x16 -static u16 pcnet_read_csr(struct eth_device *dev, int index) +static u16 pcnet_read_csr(struct pcnet_priv *lp, int index) { - void __iomem *base = (void __iomem *)dev->iobase; - - writew(index, base + PCNET_RAP); - return readw(base + PCNET_RDP); + writew(index, lp->iobase + PCNET_RAP); + return readw(lp->iobase + PCNET_RDP); } -static void pcnet_write_csr(struct eth_device *dev, int index, u16 val) +static void pcnet_write_csr(struct pcnet_priv *lp, int index, u16 val) { - void __iomem *base = (void __iomem *)dev->iobase; - - writew(index, base + PCNET_RAP); - writew(val, base + PCNET_RDP); + writew(index, lp->iobase + PCNET_RAP); + writew(val, lp->iobase + PCNET_RDP); } -static u16 pcnet_read_bcr(struct eth_device *dev, int index) +static u16 pcnet_read_bcr(struct pcnet_priv *lp, int index) { - void __iomem *base = (void __iomem *)dev->iobase; - - writew(index, base + PCNET_RAP); - return readw(base + PCNET_BDP); + writew(index, lp->iobase + PCNET_RAP); + return readw(lp->iobase + PCNET_BDP); } -static void pcnet_write_bcr(struct eth_device *dev, int index, u16 val) +static void pcnet_write_bcr(struct pcnet_priv *lp, int index, u16 val) { - void __iomem *base = (void __iomem *)dev->iobase; - - writew(index, base + PCNET_RAP); - writew(val, base + PCNET_BDP); + writew(index, lp->iobase + PCNET_RAP); + writew(val, lp->iobase + PCNET_BDP); } -static void pcnet_reset(struct eth_device *dev) +static void pcnet_reset(struct pcnet_priv *lp) { - void __iomem *base = (void __iomem *)dev->iobase; - - readw(base + PCNET_RESET); + readw(lp->iobase + PCNET_RESET); } -static int pcnet_check(struct eth_device *dev) +static int pcnet_check(struct pcnet_priv *lp) { - void __iomem *base = (void __iomem *)dev->iobase; - - writew(88, base + PCNET_RAP); - return readw(base + PCNET_RAP) == 88; + writew(88, lp->iobase + PCNET_RAP); + return readw(lp->iobase + PCNET_RAP) == 88; } static inline pci_addr_t pcnet_virt_to_mem(struct pcnet_priv *lp, void *addr) @@ -154,22 +143,22 @@ static struct pci_device_id supported[] = { static int pcnet_probe(struct eth_device *dev, bd_t *bis, int dev_nr) { + struct pcnet_priv *lp = dev->priv; int chip_version; char *chipname; int i; /* Reset the PCnet controller */ - pcnet_reset(dev); + pcnet_reset(lp); /* Check if register access is working */ - if (pcnet_read_csr(dev, 0) != 4 || !pcnet_check(dev)) { + if (pcnet_read_csr(lp, 0) != 4 || !pcnet_check(lp)) { printf("%s: CSR register access check failed\n", dev->name); return -1; } /* Identify the chip */ - chip_version = - pcnet_read_csr(dev, 88) | (pcnet_read_csr(dev, 89) << 16); + chip_version = pcnet_read_csr(lp, 88) | (pcnet_read_csr(lp, 89) << 16); if ((chip_version & 0xfff) != 0x003) return -1; chip_version = (chip_version >> 12) & 0xffff; @@ -199,7 +188,7 @@ static int pcnet_probe(struct eth_device *dev, bd_t *bis, int dev_nr) for (i = 0; i < 3; i++) { unsigned int val; - val = pcnet_read_csr(dev, i + 12) & 0x0ffff; + val = pcnet_read_csr(lp, i + 12) & 0x0ffff; /* There may be endianness issues here. */ dev->enetaddr[2 * i] = val & 0x0ff; dev->enetaddr[2 * i + 1] = (val >> 8) & 0x0ff; @@ -218,17 +207,17 @@ static int pcnet_init(struct eth_device *dev, bd_t *bis) PCNET_DEBUG1("%s: pcnet_init...\n", dev->name); /* Switch pcnet to 32bit mode */ - pcnet_write_bcr(dev, 20, 2); + pcnet_write_bcr(lp, 20, 2); /* Set/reset autoselect bit */ - val = pcnet_read_bcr(dev, 2) & ~2; + val = pcnet_read_bcr(lp, 2) & ~2; val |= 2; - pcnet_write_bcr(dev, 2, val); + pcnet_write_bcr(lp, 2, val); /* Enable auto negotiate, setup, disable fd */ - val = pcnet_read_bcr(dev, 32) & ~0x98; + val = pcnet_read_bcr(lp, 32) & ~0x98; val |= 0x20; - pcnet_write_bcr(dev, 32, val); + pcnet_write_bcr(lp, 32, val); /* * Enable NOUFLO on supported controllers, with the transmit @@ -238,12 +227,12 @@ static int pcnet_init(struct eth_device *dev, bd_t *bis) * slower devices. Controllers which do not support NOUFLO will * simply be left with a larger transmit FIFO threshold. */ - val = pcnet_read_bcr(dev, 18); + val = pcnet_read_bcr(lp, 18); val |= 1 << 11; - pcnet_write_bcr(dev, 18, val); - val = pcnet_read_csr(dev, 80); + pcnet_write_bcr(lp, 18, val); + val = pcnet_read_csr(lp, 80); val |= 0x3 << 10; - pcnet_write_csr(dev, 80, val); + pcnet_write_csr(lp, 80, val); uc = lp->uc; @@ -302,28 +291,28 @@ static int pcnet_init(struct eth_device *dev, bd_t *bis) */ barrier(); addr = pcnet_virt_to_mem(lp, &lp->uc->init_block); - pcnet_write_csr(dev, 1, addr & 0xffff); - pcnet_write_csr(dev, 2, (addr >> 16) & 0xffff); + pcnet_write_csr(lp, 1, addr & 0xffff); + pcnet_write_csr(lp, 2, (addr >> 16) & 0xffff); - pcnet_write_csr(dev, 4, 0x0915); - pcnet_write_csr(dev, 0, 0x0001); /* start */ + pcnet_write_csr(lp, 4, 0x0915); + pcnet_write_csr(lp, 0, 0x0001); /* start */ /* Wait for Init Done bit */ for (i = 10000; i > 0; i--) { - if (pcnet_read_csr(dev, 0) & 0x0100) + if (pcnet_read_csr(lp, 0) & 0x0100) break; udelay(10); } if (i <= 0) { printf("%s: TIMEOUT: controller init failed\n", dev->name); - pcnet_reset(dev); + pcnet_reset(lp); return -1; } /* * Finally start network controller operation. */ - pcnet_write_csr(dev, 0, 0x0002); + pcnet_write_csr(lp, 0, 0x0002); return 0; } @@ -367,7 +356,7 @@ static int pcnet_send(struct eth_device *dev, void *packet, int pkt_len) writew(0x8300, &entry->status); /* Trigger an immediate send poll. */ - pcnet_write_csr(dev, 0, 0x0008); + pcnet_write_csr(lp, 0, 0x0008); failure: if (++lp->cur_tx >= TX_RING_SIZE) @@ -435,16 +424,17 @@ static int pcnet_recv (struct eth_device *dev) static void pcnet_halt(struct eth_device *dev) { + struct pcnet_priv *lp = dev->priv; int i; PCNET_DEBUG1("%s: pcnet_halt...\n", dev->name); /* Reset the PCnet controller */ - pcnet_reset(dev); + pcnet_reset(lp); /* Wait for Stop bit */ for (i = 1000; i > 0; i--) { - if (pcnet_read_csr(dev, 0) & 0x4) + if (pcnet_read_csr(lp, 0) & 0x4) break; udelay(10); } @@ -498,11 +488,10 @@ int pcnet_initialize(bd_t *bis) * Setup the PCI device. */ pci_read_config_dword(devbusfn, PCI_BASE_ADDRESS_1, &bar); - dev->iobase = pci_mem_to_phys(devbusfn, bar); - dev->iobase &= ~0xf; + lp->iobase = (void *)(pci_mem_to_phys(devbusfn, bar) & ~0xf); - PCNET_DEBUG1("%s: devbusfn=0x%x iobase=0x%lx: ", - dev->name, devbusfn, (unsigned long)dev->iobase); + PCNET_DEBUG1("%s: devbusfn=0x%x iobase=0x%p: ", + dev->name, devbusfn, lp->iobase); command = PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; pci_write_config_word(devbusfn, PCI_COMMAND, command); -- cgit v1.1 From 6d76c9f1e6df5338aeaa8699e16ea3bb755f858d Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 17 May 2020 18:24:22 +0200 Subject: net: pcnet: Wrap name and enetaddr into private data Instead of using the non-DM-only name and enetaddr in struct eth_device, add pointers into the private data which can either point to that non-DM name or a DM one later on. Signed-off-by: Marek Vasut Cc: Daniel Schwierzeck Cc: Joe Hershberger --- drivers/net/pcnet.c | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/net/pcnet.c b/drivers/net/pcnet.c index b0bd4af..669b256 100644 --- a/drivers/net/pcnet.c +++ b/drivers/net/pcnet.c @@ -84,6 +84,8 @@ struct pcnet_priv { struct pcnet_uncached_priv *uc; pci_dev_t dev; void __iomem *iobase; + char *name; + u8 *enetaddr; int cur_rx; int cur_tx; }; @@ -153,7 +155,7 @@ static int pcnet_probe(struct eth_device *dev, bd_t *bis, int dev_nr) /* Check if register access is working */ if (pcnet_read_csr(lp, 0) != 4 || !pcnet_check(lp)) { - printf("%s: CSR register access check failed\n", dev->name); + printf("%s: CSR register access check failed\n", lp->name); return -1; } @@ -174,7 +176,7 @@ static int pcnet_probe(struct eth_device *dev, bd_t *bis, int dev_nr) break; default: printf("%s: PCnet version %#x not supported\n", - dev->name, chip_version); + lp->name, chip_version); return -1; } @@ -190,8 +192,8 @@ static int pcnet_probe(struct eth_device *dev, bd_t *bis, int dev_nr) val = pcnet_read_csr(lp, i + 12) & 0x0ffff; /* There may be endianness issues here. */ - dev->enetaddr[2 * i] = val & 0x0ff; - dev->enetaddr[2 * i + 1] = (val >> 8) & 0x0ff; + lp->enetaddr[2 * i] = val & 0x0ff; + lp->enetaddr[2 * i + 1] = (val >> 8) & 0x0ff; } return 0; @@ -204,7 +206,7 @@ static int pcnet_init(struct eth_device *dev, bd_t *bis) int i, val; unsigned long addr; - PCNET_DEBUG1("%s: pcnet_init...\n", dev->name); + PCNET_DEBUG1("%s: %s...\n", lp->name, __func__); /* Switch pcnet to 32bit mode */ pcnet_write_bcr(lp, 20, 2); @@ -271,7 +273,7 @@ static int pcnet_init(struct eth_device *dev, bd_t *bis) PCNET_DEBUG1("Init block at 0x%p: MAC", &lp->uc->init_block); for (i = 0; i < 6; i++) { - lp->uc->init_block.phys_addr[i] = dev->enetaddr[i]; + lp->uc->init_block.phys_addr[i] = lp->enetaddr[i]; PCNET_DEBUG1(" %02x", lp->uc->init_block.phys_addr[i]); } @@ -304,7 +306,7 @@ static int pcnet_init(struct eth_device *dev, bd_t *bis) udelay(10); } if (i <= 0) { - printf("%s: TIMEOUT: controller init failed\n", dev->name); + printf("%s: TIMEOUT: controller init failed\n", lp->name); pcnet_reset(lp); return -1; } @@ -340,7 +342,7 @@ static int pcnet_send(struct eth_device *dev, void *packet, int pkt_len) } if (i <= 0) { printf("%s: TIMEOUT: Tx%d failed (status = 0x%x)\n", - dev->name, lp->cur_tx, status); + lp->name, lp->cur_tx, status); pkt_len = 0; goto failure; } @@ -385,7 +387,7 @@ static int pcnet_recv (struct eth_device *dev) err_status = status >> 8; if (err_status != 0x03) { /* There was an error. */ - printf("%s: Rx%d", dev->name, lp->cur_rx); + printf("%s: Rx%d", lp->name, lp->cur_rx); PCNET_DEBUG1(" (status=0x%x)", err_status); if (err_status & 0x20) printf(" Frame"); @@ -402,7 +404,7 @@ static int pcnet_recv (struct eth_device *dev) pkt_len = (readl(&entry->msg_length) & 0xfff) - 4; if (pkt_len < 60) { printf("%s: Rx%d: invalid packet length %d\n", - dev->name, lp->cur_rx, pkt_len); + lp->name, lp->cur_rx, pkt_len); } else { buf = lp->rx_buf[lp->cur_rx]; invalidate_dcache_range((unsigned long)buf, @@ -427,7 +429,7 @@ static void pcnet_halt(struct eth_device *dev) struct pcnet_priv *lp = dev->priv; int i; - PCNET_DEBUG1("%s: pcnet_halt...\n", dev->name); + PCNET_DEBUG1("%s: %s...\n", lp->name, __func__); /* Reset the PCnet controller */ pcnet_reset(lp); @@ -439,7 +441,7 @@ static void pcnet_halt(struct eth_device *dev) udelay(10); } if (i <= 0) - printf("%s: TIMEOUT: controller reset failed\n", dev->name); + printf("%s: TIMEOUT: controller reset failed\n", lp->name); } int pcnet_initialize(bd_t *bis) @@ -451,7 +453,7 @@ int pcnet_initialize(bd_t *bis) int dev_nr = 0; u32 bar; - PCNET_DEBUG1("\npcnet_initialize...\n"); + PCNET_DEBUG1("\n%s...\n", __func__); for (dev_nr = 0; ; dev_nr++) { /* @@ -483,6 +485,8 @@ int pcnet_initialize(bd_t *bis) (unsigned long)lp + sizeof(*lp)); dev->priv = lp; sprintf(dev->name, "pcnet#%d", dev_nr); + lp->name = dev->name; + lp->enetaddr = dev->enetaddr; /* * Setup the PCI device. @@ -491,14 +495,14 @@ int pcnet_initialize(bd_t *bis) lp->iobase = (void *)(pci_mem_to_phys(devbusfn, bar) & ~0xf); PCNET_DEBUG1("%s: devbusfn=0x%x iobase=0x%p: ", - dev->name, devbusfn, lp->iobase); + lp->name, devbusfn, lp->iobase); command = PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; pci_write_config_word(devbusfn, PCI_COMMAND, command); pci_read_config_word(devbusfn, PCI_COMMAND, &status); if ((status & command) != command) { printf("%s: Couldn't enable IO access or Bus Mastering\n", - dev->name); + lp->name); free(dev); continue; } -- cgit v1.1 From f5e7df58e0b96f97e1d8ef49415401a51e9f18b8 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 17 May 2020 18:24:23 +0200 Subject: net: pcnet: Split common and non-DM functions Pull the common parts of functions out so they can be reused by both DM and non-DM code paths. The recv() function had to be reworked to fit into this scheme and this means it now only receives one packet at a time instead of spinning in an endless loop. Signed-off-by: Marek Vasut Cc: Daniel Schwierzeck Cc: Joe Hershberger --- drivers/net/pcnet.c | 149 +++++++++++++++++++++++++++++++++------------------- 1 file changed, 94 insertions(+), 55 deletions(-) (limited to 'drivers') diff --git a/drivers/net/pcnet.c b/drivers/net/pcnet.c index 669b256..0a4cab8 100644 --- a/drivers/net/pcnet.c +++ b/drivers/net/pcnet.c @@ -86,6 +86,7 @@ struct pcnet_priv { void __iomem *iobase; char *name; u8 *enetaddr; + u16 status; int cur_rx; int cur_tx; }; @@ -143,9 +144,8 @@ static struct pci_device_id supported[] = { {} }; -static int pcnet_probe(struct eth_device *dev, bd_t *bis, int dev_nr) +static int pcnet_probe_common(struct pcnet_priv *lp) { - struct pcnet_priv *lp = dev->priv; int chip_version; char *chipname; int i; @@ -199,9 +199,8 @@ static int pcnet_probe(struct eth_device *dev, bd_t *bis, int dev_nr) return 0; } -static int pcnet_init(struct eth_device *dev, bd_t *bis) +static int pcnet_init_common(struct pcnet_priv *lp) { - struct pcnet_priv *lp = dev->priv; struct pcnet_uncached_priv *uc; int i, val; unsigned long addr; @@ -319,9 +318,8 @@ static int pcnet_init(struct eth_device *dev, bd_t *bis) return 0; } -static int pcnet_send(struct eth_device *dev, void *packet, int pkt_len) +static int pcnet_send_common(struct pcnet_priv *lp, void *packet, int pkt_len) { - struct pcnet_priv *lp = dev->priv; int i, status; u32 addr; struct pcnet_tx_head *entry = &lp->uc->tx_ring[lp->cur_tx]; @@ -368,65 +366,70 @@ static int pcnet_send(struct eth_device *dev, void *packet, int pkt_len) return pkt_len; } -static int pcnet_recv (struct eth_device *dev) +static int pcnet_recv_common(struct pcnet_priv *lp, unsigned char **bufp) { - struct pcnet_priv *lp = dev->priv; struct pcnet_rx_head *entry; unsigned char *buf; int pkt_len = 0; - u16 status, err_status; + u16 err_status; - while (1) { - entry = &lp->uc->rx_ring[lp->cur_rx]; - /* - * If we own the next entry, it's a new packet. Send it up. - */ - status = readw(&entry->status); - if ((status & 0x8000) != 0) - break; - err_status = status >> 8; - - if (err_status != 0x03) { /* There was an error. */ - printf("%s: Rx%d", lp->name, lp->cur_rx); - PCNET_DEBUG1(" (status=0x%x)", err_status); - if (err_status & 0x20) - printf(" Frame"); - if (err_status & 0x10) - printf(" Overflow"); - if (err_status & 0x08) - printf(" CRC"); - if (err_status & 0x04) - printf(" Fifo"); - printf(" Error\n"); - status &= 0x03ff; - - } else { - pkt_len = (readl(&entry->msg_length) & 0xfff) - 4; - if (pkt_len < 60) { - printf("%s: Rx%d: invalid packet length %d\n", - lp->name, lp->cur_rx, pkt_len); - } else { - buf = lp->rx_buf[lp->cur_rx]; - invalidate_dcache_range((unsigned long)buf, - (unsigned long)buf + pkt_len); - net_process_received_packet(buf, pkt_len); - PCNET_DEBUG2("Rx%d: %d bytes from 0x%p\n", - lp->cur_rx, pkt_len, buf); - } - } - - status |= 0x8000; - writew(status, &entry->status); + entry = &lp->uc->rx_ring[lp->cur_rx]; + /* + * If we own the next entry, it's a new packet. Send it up. + */ + lp->status = readw(&entry->status); + if ((lp->status & 0x8000) != 0) + return 0; + err_status = lp->status >> 8; + + if (err_status != 0x03) { /* There was an error. */ + printf("%s: Rx%d", lp->name, lp->cur_rx); + PCNET_DEBUG1(" (status=0x%x)", err_status); + if (err_status & 0x20) + printf(" Frame"); + if (err_status & 0x10) + printf(" Overflow"); + if (err_status & 0x08) + printf(" CRC"); + if (err_status & 0x04) + printf(" Fifo"); + printf(" Error\n"); + lp->status &= 0x03ff; + return 0; + } - if (++lp->cur_rx >= RX_RING_SIZE) - lp->cur_rx = 0; + pkt_len = (readl(&entry->msg_length) & 0xfff) - 4; + if (pkt_len < 60) { + printf("%s: Rx%d: invalid packet length %d\n", + lp->name, lp->cur_rx, pkt_len); + return 0; } + + *bufp = lp->rx_buf[lp->cur_rx]; + invalidate_dcache_range((unsigned long)*bufp, + (unsigned long)*bufp + pkt_len); + + PCNET_DEBUG2("Rx%d: %d bytes from 0x%p\n", + lp->cur_rx, pkt_len, buf); + return pkt_len; } -static void pcnet_halt(struct eth_device *dev) +static void pcnet_free_pkt_common(struct pcnet_priv *lp, unsigned int len) +{ + struct pcnet_rx_head *entry; + + entry = &lp->uc->rx_ring[lp->cur_rx]; + + lp->status |= 0x8000; + writew(lp->status, &entry->status); + + if (++lp->cur_rx >= RX_RING_SIZE) + lp->cur_rx = 0; +} + +static void pcnet_halt_common(struct pcnet_priv *lp) { - struct pcnet_priv *lp = dev->priv; int i; PCNET_DEBUG1("%s: %s...\n", lp->name, __func__); @@ -444,6 +447,42 @@ static void pcnet_halt(struct eth_device *dev) printf("%s: TIMEOUT: controller reset failed\n", lp->name); } +static int pcnet_init(struct eth_device *dev, bd_t *bis) +{ + struct pcnet_priv *lp = dev->priv; + + return pcnet_init_common(lp); +} + +static int pcnet_send(struct eth_device *dev, void *packet, int pkt_len) +{ + struct pcnet_priv *lp = dev->priv; + + return pcnet_send_common(lp, packet, pkt_len); +} + +static int pcnet_recv(struct eth_device *dev) +{ + struct pcnet_priv *lp = dev->priv; + uchar *packet; + int ret; + + ret = pcnet_recv_common(lp, &packet); + if (ret > 0) + net_process_received_packet(packet, ret); + if (ret) + pcnet_free_pkt_common(lp, ret); + + return ret; +} + +static void pcnet_halt(struct eth_device *dev) +{ + struct pcnet_priv *lp = dev->priv; + + pcnet_halt_common(lp); +} + int pcnet_initialize(bd_t *bis) { pci_dev_t devbusfn; @@ -512,7 +551,7 @@ int pcnet_initialize(bd_t *bis) /* * Probe the PCnet chip. */ - if (pcnet_probe(dev, bis, dev_nr) < 0) { + if (pcnet_probe_common(lp) < 0) { free(dev); continue; } -- cgit v1.1 From 53019cf35b5ccf9cb5ad8269acab494b99a3dc0c Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 17 May 2020 18:24:24 +0200 Subject: net: pcnet: Add DM support With all the changes in place, add support for DM into the pcnet driver. Signed-off-by: Marek Vasut Cc: Daniel Schwierzeck Cc: Joe Hershberger --- drivers/net/pcnet.c | 127 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 126 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/pcnet.c b/drivers/net/pcnet.c index 0a4cab8..8e3e3db 100644 --- a/drivers/net/pcnet.c +++ b/drivers/net/pcnet.c @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -82,9 +83,14 @@ struct pcnet_priv { /* Receive Buffer space */ unsigned char rx_buf[RX_RING_SIZE][PKT_BUF_SZ + 4]; struct pcnet_uncached_priv *uc; +#ifdef CONFIG_DM_ETH + struct udevice *dev; + const char *name; +#else pci_dev_t dev; - void __iomem *iobase; char *name; +#endif + void __iomem *iobase; u8 *enetaddr; u16 status; int cur_rx; @@ -136,7 +142,11 @@ static inline pci_addr_t pcnet_virt_to_mem(struct pcnet_priv *lp, void *addr) { void *virt_addr = addr; +#ifdef CONFIG_DM_ETH + return dm_pci_virt_to_mem(lp->dev, virt_addr); +#else return pci_virt_to_mem(lp->dev, virt_addr); +#endif } static struct pci_device_id supported[] = { @@ -447,6 +457,7 @@ static void pcnet_halt_common(struct pcnet_priv *lp) printf("%s: TIMEOUT: controller reset failed\n", lp->name); } +#ifndef CONFIG_DM_ETH static int pcnet_init(struct eth_device *dev, bd_t *bis) { struct pcnet_priv *lp = dev->priv; @@ -571,3 +582,117 @@ int pcnet_initialize(bd_t *bis) return dev_nr; } +#else /* DM_ETH */ +static int pcnet_start(struct udevice *dev) +{ + struct eth_pdata *plat = dev_get_platdata(dev); + struct pcnet_priv *priv = dev_get_priv(dev); + + memcpy(priv->enetaddr, plat->enetaddr, sizeof(plat->enetaddr)); + + return pcnet_init_common(priv); +} + +static void pcnet_stop(struct udevice *dev) +{ + struct pcnet_priv *priv = dev_get_priv(dev); + + pcnet_halt_common(priv); +} + +static int pcnet_send(struct udevice *dev, void *packet, int length) +{ + struct pcnet_priv *priv = dev_get_priv(dev); + int ret; + + ret = pcnet_send_common(priv, packet, length); + + return ret ? 0 : -ETIMEDOUT; +} + +static int pcnet_recv(struct udevice *dev, int flags, uchar **packetp) +{ + struct pcnet_priv *priv = dev_get_priv(dev); + + return pcnet_recv_common(priv, packetp); +} + +static int pcnet_free_pkt(struct udevice *dev, uchar *packet, int length) +{ + struct pcnet_priv *priv = dev_get_priv(dev); + + pcnet_free_pkt_common(priv, length); + + return 0; +} + +static int pcnet_bind(struct udevice *dev) +{ + static int card_number; + char name[16]; + + sprintf(name, "pcnet#%u", card_number++); + + return device_set_name(dev, name); +} + +static int pcnet_probe(struct udevice *dev) +{ + struct eth_pdata *plat = dev_get_platdata(dev); + struct pcnet_priv *lp = dev_get_priv(dev); + u16 command, status; + u32 iobase; + int ret; + + dm_pci_read_config32(dev, PCI_BASE_ADDRESS_1, &iobase); + iobase &= ~0xf; + + lp->uc = map_physmem((phys_addr_t)&lp->ucp, + sizeof(lp->ucp), MAP_NOCACHE); + lp->dev = dev; + lp->name = dev->name; + lp->enetaddr = plat->enetaddr; + lp->iobase = (void *)dm_pci_mem_to_phys(dev, iobase); + + flush_dcache_range((unsigned long)lp, + (unsigned long)lp + sizeof(*lp)); + + command = PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; + dm_pci_write_config16(dev, PCI_COMMAND, command); + dm_pci_read_config16(dev, PCI_COMMAND, &status); + if ((status & command) != command) { + printf("%s: Couldn't enable IO access or Bus Mastering\n", + lp->name); + return -EINVAL; + } + + dm_pci_write_config8(dev, PCI_LATENCY_TIMER, 0x20); + + ret = pcnet_probe_common(lp); + if (ret) + return ret; + + return 0; +} + +static const struct eth_ops pcnet_ops = { + .start = pcnet_start, + .send = pcnet_send, + .recv = pcnet_recv, + .stop = pcnet_stop, + .free_pkt = pcnet_free_pkt, +}; + +U_BOOT_DRIVER(eth_pcnet) = { + .name = "eth_pcnet", + .id = UCLASS_ETH, + .bind = pcnet_bind, + .probe = pcnet_probe, + .ops = &pcnet_ops, + .priv_auto_alloc_size = sizeof(struct pcnet_priv), + .platdata_auto_alloc_size = sizeof(struct eth_pdata), + .flags = DM_UC_FLAG_ALLOC_PRIV_DMA, +}; + +U_BOOT_PCI_DEVICE(eth_pcnet, supported); +#endif -- cgit v1.1 From d8553d6ee3146bc06b8f86787138293d3f6453c3 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 17 May 2020 18:24:25 +0200 Subject: net: pcnet: Add Kconfig entries Add Kconfig entries for the pcnet driver and convert MIPS malta to use those. Signed-off-by: Marek Vasut Cc: Daniel Schwierzeck Cc: Joe Hershberger --- drivers/net/Kconfig | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index bb23f73..19703d4 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -392,6 +392,12 @@ config MII help Enable support of the Media-Independent Interface (MII) +config PCNET + bool "AMD PCnet series Ethernet controller driver" + help + This driver supports AMD PCnet series fast ethernet family of + PCI chipsets/adapters. + config RTL8139 bool "Realtek 8139 series Ethernet controller driver" help -- cgit v1.1 From f5624b104541a6c198b78958581f7e871ef2bb77 Mon Sep 17 00:00:00 2001 From: Marcel Ziswiler Date: Mon, 20 May 2019 02:44:53 +0200 Subject: mmc: add missing space before comment delimiter Add missing space before a comment delimiter. Signed-off-by: Marcel Ziswiler Reviewed-by: Peng Fan Reviewed-by: Igor Opaniuk --- drivers/mmc/mmc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index 620bb93..b61ce8d 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -2824,7 +2824,7 @@ retry: if (err) return err; - /* The internal partition reset to user partition(0) at every CMD0*/ + /* The internal partition reset to user partition(0) at every CMD0 */ mmc_get_blk_desc(mmc)->hwpart = 0; /* Test for SD version 2 */ -- cgit v1.1 From 45224e8f26913bbd70960f316401134f3c366d78 Mon Sep 17 00:00:00 2001 From: Marcel Ziswiler Date: Mon, 20 May 2019 02:44:57 +0200 Subject: dm: core: gracefully handle alias seq without of Gracefully handle alias seq in the platform data rather than OF case. Signed-off-by: Marcel Ziswiler --- drivers/core/read.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/core/read.c b/drivers/core/read.c index 047089c..85b3b7a 100644 --- a/drivers/core/read.c +++ b/drivers/core/read.c @@ -275,15 +275,17 @@ int dev_read_alias_seq(const struct udevice *dev, int *devnump) { ofnode node = dev_ofnode(dev); const char *uc_name = dev->uclass->uc_drv->name; - int ret; + int ret = -ENOTSUPP; if (ofnode_is_np(node)) { ret = of_alias_get_id(ofnode_to_np(node), uc_name); if (ret >= 0) *devnump = ret; } else { +#if CONFIG_IS_ENABLED(OF_CONTROL) ret = fdtdec_get_alias_seq(gd->fdt_blob, uc_name, ofnode_to_offset(node), devnump); +#endif } return ret; -- cgit v1.1 From 9b515a81be7a09307f1af5be40f6bdf8bc4283fd Mon Sep 17 00:00:00 2001 From: Marcel Ziswiler Date: Mon, 20 May 2019 02:44:58 +0200 Subject: kconfig: mmc: move pxa_mmc_generic to kconfig Move CONFIG_PXA_MMC_GENERIC to Kconfig. Signed-off-by: Marcel Ziswiler Reviewed-by: Simon Glass --- drivers/mmc/Kconfig | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig index 33b128d..ad86c23 100644 --- a/drivers/mmc/Kconfig +++ b/drivers/mmc/Kconfig @@ -299,6 +299,14 @@ config MMC_PCI If unsure, say N. +config PXA_MMC_GENERIC + bool "Support for MMC controllers on PXA" + help + This selects MMC controllers on PXA. + If you are on a PXA architecture, say Y here. + + If unsure, say N. + config MMC_OMAP_HS bool "TI OMAP High Speed Multimedia Card Interface support" select DM_REGULATOR_PBIAS if DM_MMC && DM_REGULATOR -- cgit v1.1 From 290e6bb9585e4bf8c7a20c54ffd707f26ee76329 Mon Sep 17 00:00:00 2001 From: Marcel Ziswiler Date: Mon, 20 May 2019 02:44:59 +0200 Subject: arm: pxa: mmc: add driver model support Add driver model (DM) support. Signed-off-by: Marcel Ziswiler --- drivers/mmc/pxa_mmc_gen.c | 160 ++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 132 insertions(+), 28 deletions(-) (limited to 'drivers') diff --git a/drivers/mmc/pxa_mmc_gen.c b/drivers/mmc/pxa_mmc_gen.c index cc60147..2c081fd 100644 --- a/drivers/mmc/pxa_mmc_gen.c +++ b/drivers/mmc/pxa_mmc_gen.c @@ -2,6 +2,9 @@ /* * Copyright (C) 2010 Marek Vasut * + * Modified to add driver model (DM) support + * Copyright (C) 2019 Marcel Ziswiler + * * Loosely based on the old code and Linux's PXA MMC driver */ @@ -11,6 +14,8 @@ #include #include #include +#include +#include #include #include @@ -96,7 +101,7 @@ static int pxa_mmc_stop_clock(struct mmc *mmc) } static int pxa_mmc_start_cmd(struct mmc *mmc, struct mmc_cmd *cmd, - uint32_t cmdat) + uint32_t cmdat) { struct pxa_mmc_priv *priv = mmc->priv; struct pxa_mmc_regs *regs = priv->regs; @@ -143,7 +148,7 @@ static int pxa_mmc_cmd_done(struct mmc *mmc, struct mmc_cmd *cmd) { struct pxa_mmc_priv *priv = mmc->priv; struct pxa_mmc_regs *regs = priv->regs; - uint32_t a, b, c; + u32 a, b, c; int i; int stat; @@ -152,7 +157,7 @@ static int pxa_mmc_cmd_done(struct mmc *mmc, struct mmc_cmd *cmd) /* * Linux says: - * Did I mention this is Sick. We always need to + * Did I mention this is Sick. We always need to * discard the upper 8 bits of the first 16-bit word. */ a = readl(®s->res) & 0xffff; @@ -164,13 +169,13 @@ static int pxa_mmc_cmd_done(struct mmc *mmc, struct mmc_cmd *cmd) } /* The command response didn't arrive */ - if (stat & MMC_STAT_TIME_OUT_RESPONSE) + if (stat & MMC_STAT_TIME_OUT_RESPONSE) { return -ETIMEDOUT; - else if (stat & MMC_STAT_RES_CRC_ERROR - && cmd->resp_type & MMC_RSP_CRC) { -#ifdef PXAMMC_CRC_SKIP - if (cmd->resp_type & MMC_RSP_136 - && cmd->response[0] & (1 << 31)) + } else if (stat & MMC_STAT_RES_CRC_ERROR && + cmd->resp_type & MMC_RSP_CRC) { +#ifdef PXAMMC_CRC_SKIP + if (cmd->resp_type & MMC_RSP_136 && + cmd->response[0] & (1 << 31)) printf("Ignoring CRC, this may be dangerous!\n"); else #endif @@ -185,8 +190,8 @@ static int pxa_mmc_do_read_xfer(struct mmc *mmc, struct mmc_data *data) { struct pxa_mmc_priv *priv = mmc->priv; struct pxa_mmc_regs *regs = priv->regs; - uint32_t len; - uint32_t *buf = (uint32_t *)data->dest; + u32 len; + u32 *buf = (uint32_t *)data->dest; int size; int ret; @@ -202,7 +207,6 @@ static int pxa_mmc_do_read_xfer(struct mmc *mmc, struct mmc_data *data) /* Read data into the buffer */ while (size--) *buf++ = readl(®s->rxfifo); - } if (readl(®s->stat) & MMC_STAT_ERRORS) @@ -221,8 +225,8 @@ static int pxa_mmc_do_write_xfer(struct mmc *mmc, struct mmc_data *data) { struct pxa_mmc_priv *priv = mmc->priv; struct pxa_mmc_regs *regs = priv->regs; - uint32_t len; - uint32_t *buf = (uint32_t *)data->src; + u32 len; + u32 *buf = (uint32_t *)data->src; int size; int ret; @@ -259,12 +263,11 @@ static int pxa_mmc_do_write_xfer(struct mmc *mmc, struct mmc_data *data) return 0; } -static int pxa_mmc_request(struct mmc *mmc, struct mmc_cmd *cmd, - struct mmc_data *data) +static int pxa_mmc_send_cmd_common(struct pxa_mmc_priv *priv, struct mmc *mmc, + struct mmc_cmd *cmd, struct mmc_data *data) { - struct pxa_mmc_priv *priv = mmc->priv; struct pxa_mmc_regs *regs = priv->regs; - uint32_t cmdat = 0; + u32 cmdat = 0; int ret; /* Stop the controller */ @@ -313,12 +316,11 @@ static int pxa_mmc_request(struct mmc *mmc, struct mmc_cmd *cmd, return 0; } -static int pxa_mmc_set_ios(struct mmc *mmc) +static int pxa_mmc_set_ios_common(struct pxa_mmc_priv *priv, struct mmc *mmc) { - struct pxa_mmc_priv *priv = mmc->priv; struct pxa_mmc_regs *regs = priv->regs; - uint32_t tmp; - uint32_t pxa_mmc_clock; + u32 tmp; + u32 pxa_mmc_clock; if (!mmc->clock) { pxa_mmc_stop_clock(mmc); @@ -346,9 +348,8 @@ static int pxa_mmc_set_ios(struct mmc *mmc) return 0; } -static int pxa_mmc_init(struct mmc *mmc) +static int pxa_mmc_init_common(struct pxa_mmc_priv *priv, struct mmc *mmc) { - struct pxa_mmc_priv *priv = mmc->priv; struct pxa_mmc_regs *regs = priv->regs; /* Make sure the clock are stopped */ @@ -362,10 +363,34 @@ static int pxa_mmc_init(struct mmc *mmc) /* Mask all interrupts */ writel(~(MMC_I_MASK_TXFIFO_WR_REQ | MMC_I_MASK_RXFIFO_RD_REQ), - ®s->i_mask); + ®s->i_mask); + return 0; } +#if !CONFIG_IS_ENABLED(DM_MMC) +static int pxa_mmc_init(struct mmc *mmc) +{ + struct pxa_mmc_priv *priv = mmc->priv; + + return pxa_mmc_init_common(priv, mmc); +} + +static int pxa_mmc_request(struct mmc *mmc, struct mmc_cmd *cmd, + struct mmc_data *data) +{ + struct pxa_mmc_priv *priv = mmc->priv; + + return pxa_mmc_send_cmd_common(priv, mmc, cmd, data); +} + +static int pxa_mmc_set_ios(struct mmc *mmc) +{ + struct pxa_mmc_priv *priv = mmc->priv; + + return pxa_mmc_set_ios_common(priv, mmc); +} + static const struct mmc_ops pxa_mmc_ops = { .send_cmd = pxa_mmc_request, .set_ios = pxa_mmc_set_ios, @@ -386,7 +411,7 @@ int pxa_mmc_register(int card_index) { struct mmc *mmc; struct pxa_mmc_priv *priv; - uint32_t reg; + u32 reg; int ret = -ENOMEM; priv = malloc(sizeof(struct pxa_mmc_priv)); @@ -405,7 +430,7 @@ int pxa_mmc_register(int card_index) default: ret = -EINVAL; printf("PXA MMC: Invalid MMC controller ID (card_index = %d)\n", - card_index); + card_index); goto err1; } @@ -420,7 +445,7 @@ int pxa_mmc_register(int card_index) #endif mmc = mmc_create(&pxa_mmc_cfg, priv); - if (mmc == NULL) + if (!mmc) goto err1; return 0; @@ -430,3 +455,82 @@ err1: err0: return ret; } +#else /* !CONFIG_IS_ENABLED(DM_MMC) */ +static int pxa_mmc_probe(struct udevice *dev) +{ + struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); + struct pxa_mmc_plat *plat = dev_get_platdata(dev); + struct mmc_config *cfg = &plat->cfg; + struct mmc *mmc = &plat->mmc; + struct pxa_mmc_priv *priv = dev_get_priv(dev); + u32 reg; + + upriv->mmc = mmc; + + cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT; + cfg->f_max = PXAMMC_MAX_SPEED; + cfg->f_min = PXAMMC_MIN_SPEED; + cfg->host_caps = PXAMMC_HOST_CAPS; + cfg->name = dev->name; + cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34; + + mmc->priv = priv; + + priv->regs = plat->base; + +#ifndef CONFIG_CPU_MONAHANS /* PXA2xx */ + reg = readl(CKEN); + reg |= CKEN12_MMC; + writel(reg, CKEN); +#else /* PXA3xx */ + reg = readl(CKENA); + reg |= CKENA_12_MMC0 | CKENA_13_MMC1; + writel(reg, CKENA); +#endif + + return pxa_mmc_init_common(priv, mmc); +} + +static int pxa_mmc_send_cmd(struct udevice *dev, struct mmc_cmd *cmd, + struct mmc_data *data) +{ + struct pxa_mmc_plat *plat = dev_get_platdata(dev); + struct pxa_mmc_priv *priv = dev_get_priv(dev); + + return pxa_mmc_send_cmd_common(priv, &plat->mmc, cmd, data); +} + +static int pxa_mmc_set_ios(struct udevice *dev) +{ + struct pxa_mmc_plat *plat = dev_get_platdata(dev); + struct pxa_mmc_priv *priv = dev_get_priv(dev); + + return pxa_mmc_set_ios_common(priv, &plat->mmc); +} + +static const struct dm_mmc_ops pxa_mmc_ops = { + .get_cd = NULL, + .send_cmd = pxa_mmc_send_cmd, + .set_ios = pxa_mmc_set_ios, +}; + +#if CONFIG_IS_ENABLED(BLK) +static int pxa_mmc_bind(struct udevice *dev) +{ + struct pxa_mmc_plat *plat = dev_get_platdata(dev); + + return mmc_bind(dev, &plat->mmc, &plat->cfg); +} +#endif + +U_BOOT_DRIVER(pxa_mmc) = { +#if CONFIG_IS_ENABLED(BLK) + .bind = pxa_mmc_bind, +#endif + .id = UCLASS_MMC, + .name = "pxa_mmc", + .ops = &pxa_mmc_ops, + .priv_auto_alloc_size = sizeof(struct pxa_mmc_priv), + .probe = pxa_mmc_probe, +}; +#endif /* !CONFIG_IS_ENABLED(DM_MMC) */ -- cgit v1.1 From 78ce0bd3acafc51e94157ff99aec3ed82e685ef5 Mon Sep 17 00:00:00 2001 From: Sean Anderson Date: Wed, 24 Jun 2020 06:41:06 -0400 Subject: clk: Always use the supplied struct clk CCF clocks should always use the struct clock passed to their methods for extracting the driver-specific clock information struct. Previously, many functions would use the clk->dev->priv if the device was bound. This could cause problems with composite clocks. The individual clocks in a composite clock did not have the ->dev field filled in. This was fine, because the device-specific clock information would be used. However, since there was no ->dev, there was no way to get the parent clock. This caused the recalc_rate method of the CCF divider clock to fail. One option would be to use the clk->priv field to get the composite clock and from there get the appropriate parent device. However, this would tie the implementation to the composite clock. In general, different devices should not rely on the contents of ->priv from another device. The simple solution to this problem is to just always use the supplied struct clock. The composite clock now fills in the ->dev pointer of its child clocks. This allows child clocks to make calls like clk_get_parent() without issue. imx avoided the above problem by using a custom get_rate function with composite clocks. Signed-off-by: Sean Anderson Acked-by: Lukasz Majewski --- drivers/clk/clk-composite.c | 7 +++++++ drivers/clk/clk-divider.c | 6 ++---- drivers/clk/clk-fixed-factor.c | 3 +-- drivers/clk/clk-gate.c | 6 ++---- drivers/clk/clk-mux.c | 12 ++++-------- drivers/clk/imx/clk-gate2.c | 4 ++-- 6 files changed, 18 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/clk-composite.c b/drivers/clk/clk-composite.c index 4141850..2ff1d6b 100644 --- a/drivers/clk/clk-composite.c +++ b/drivers/clk/clk-composite.c @@ -147,6 +147,13 @@ struct clk *clk_register_composite(struct device *dev, const char *name, goto err; } + if (composite->mux) + composite->mux->dev = clk->dev; + if (composite->rate) + composite->rate->dev = clk->dev; + if (composite->gate) + composite->gate->dev = clk->dev; + return clk; err: diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c index 2a68719..3465853 100644 --- a/drivers/clk/clk-divider.c +++ b/drivers/clk/clk-divider.c @@ -73,8 +73,7 @@ unsigned long divider_recalc_rate(struct clk *hw, unsigned long parent_rate, static ulong clk_divider_recalc_rate(struct clk *clk) { - struct clk_divider *divider = to_clk_divider(clk_dev_binded(clk) ? - dev_get_clk_ptr(clk->dev) : clk); + struct clk_divider *divider = to_clk_divider(clk); unsigned long parent_rate = clk_get_parent_rate(clk); unsigned int val; @@ -153,8 +152,7 @@ int divider_get_val(unsigned long rate, unsigned long parent_rate, static ulong clk_divider_set_rate(struct clk *clk, unsigned long rate) { - struct clk_divider *divider = to_clk_divider(clk_dev_binded(clk) ? - dev_get_clk_ptr(clk->dev) : clk); + struct clk_divider *divider = to_clk_divider(clk); unsigned long parent_rate = clk_get_parent_rate(clk); int value; u32 val; diff --git a/drivers/clk/clk-fixed-factor.c b/drivers/clk/clk-fixed-factor.c index 2ceb6bb..0eb24b8 100644 --- a/drivers/clk/clk-fixed-factor.c +++ b/drivers/clk/clk-fixed-factor.c @@ -20,8 +20,7 @@ static ulong clk_factor_recalc_rate(struct clk *clk) { - struct clk_fixed_factor *fix = - to_clk_fixed_factor(dev_get_clk_ptr(clk->dev)); + struct clk_fixed_factor *fix = to_clk_fixed_factor(clk); unsigned long parent_rate = clk_get_parent_rate(clk); unsigned long long int rate; diff --git a/drivers/clk/clk-gate.c b/drivers/clk/clk-gate.c index 23c1f2c..98e4b80 100644 --- a/drivers/clk/clk-gate.c +++ b/drivers/clk/clk-gate.c @@ -46,8 +46,7 @@ */ static void clk_gate_endisable(struct clk *clk, int enable) { - struct clk_gate *gate = to_clk_gate(clk_dev_binded(clk) ? - dev_get_clk_ptr(clk->dev) : clk); + struct clk_gate *gate = to_clk_gate(clk); int set = gate->flags & CLK_GATE_SET_TO_DISABLE ? 1 : 0; u32 reg; @@ -89,8 +88,7 @@ static int clk_gate_disable(struct clk *clk) int clk_gate_is_enabled(struct clk *clk) { - struct clk_gate *gate = to_clk_gate(clk_dev_binded(clk) ? - dev_get_clk_ptr(clk->dev) : clk); + struct clk_gate *gate = to_clk_gate(clk); u32 reg; #if CONFIG_IS_ENABLED(SANDBOX_CLK_CCF) diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c index c69cce0..26991a5 100644 --- a/drivers/clk/clk-mux.c +++ b/drivers/clk/clk-mux.c @@ -38,8 +38,7 @@ int clk_mux_val_to_index(struct clk *clk, u32 *table, unsigned int flags, unsigned int val) { - struct clk_mux *mux = to_clk_mux(clk_dev_binded(clk) ? - dev_get_clk_ptr(clk->dev) : clk); + struct clk_mux *mux = to_clk_mux(clk); int num_parents = mux->num_parents; if (table) { @@ -82,8 +81,7 @@ unsigned int clk_mux_index_to_val(u32 *table, unsigned int flags, u8 index) u8 clk_mux_get_parent(struct clk *clk) { - struct clk_mux *mux = to_clk_mux(clk_dev_binded(clk) ? - dev_get_clk_ptr(clk->dev) : clk); + struct clk_mux *mux = to_clk_mux(clk); u32 val; #if CONFIG_IS_ENABLED(SANDBOX_CLK_CCF) @@ -100,8 +98,7 @@ u8 clk_mux_get_parent(struct clk *clk) static int clk_fetch_parent_index(struct clk *clk, struct clk *parent) { - struct clk_mux *mux = to_clk_mux(clk_dev_binded(clk) ? - dev_get_clk_ptr(clk->dev) : clk); + struct clk_mux *mux = to_clk_mux(clk); int i; @@ -118,8 +115,7 @@ static int clk_fetch_parent_index(struct clk *clk, static int clk_mux_set_parent(struct clk *clk, struct clk *parent) { - struct clk_mux *mux = to_clk_mux(clk_dev_binded(clk) ? - dev_get_clk_ptr(clk->dev) : clk); + struct clk_mux *mux = to_clk_mux(clk); int index; u32 val; u32 reg; diff --git a/drivers/clk/imx/clk-gate2.c b/drivers/clk/imx/clk-gate2.c index b38890d..40b2d4c 100644 --- a/drivers/clk/imx/clk-gate2.c +++ b/drivers/clk/imx/clk-gate2.c @@ -39,7 +39,7 @@ struct clk_gate2 { static int clk_gate2_enable(struct clk *clk) { - struct clk_gate2 *gate = to_clk_gate2(dev_get_clk_ptr(clk->dev)); + struct clk_gate2 *gate = to_clk_gate2(clk); u32 reg; reg = readl(gate->reg); @@ -52,7 +52,7 @@ static int clk_gate2_enable(struct clk *clk) static int clk_gate2_disable(struct clk *clk) { - struct clk_gate2 *gate = to_clk_gate2(dev_get_clk_ptr(clk->dev)); + struct clk_gate2 *gate = to_clk_gate2(clk); u32 reg; reg = readl(gate->reg); -- cgit v1.1 From 5e8317a9faff472e8b83f5760535e9bf40571a8a Mon Sep 17 00:00:00 2001 From: Sean Anderson Date: Wed, 24 Jun 2020 06:41:07 -0400 Subject: clk: Check that ops of composite clock components exist before calling clk_composite_ops was shared between all devices in the composite clock driver. If one clock had a feature (such as supporting set_parent) which another clock did not, it could call a null pointer dereference. This patch does three things 1. It adds null-pointer checks to all composite clock functions. 2. It makes clk_composite_ops const and sets its functions at compile-time. 3. It adds some basic sanity checks to num_parents. The combined effect of these changes is that any of mux, rate, or gate can be NULL, and composite clocks will still function normally. Previously, at least mux had to exist, since clk_composite_get_parent was used to determine the parent for clk_register. Signed-off-by: Sean Anderson Acked-by: Lukasz Majewski --- drivers/clk/clk-composite.c | 57 ++++++++++++++++++++++++++++----------------- 1 file changed, 35 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/clk-composite.c b/drivers/clk/clk-composite.c index 2ff1d6b..819bfca 100644 --- a/drivers/clk/clk-composite.c +++ b/drivers/clk/clk-composite.c @@ -24,7 +24,10 @@ static u8 clk_composite_get_parent(struct clk *clk) (struct clk *)dev_get_clk_ptr(clk->dev) : clk); struct clk *mux = composite->mux; - return clk_mux_get_parent(mux); + if (mux) + return clk_mux_get_parent(mux); + else + return 0; } static int clk_composite_set_parent(struct clk *clk, struct clk *parent) @@ -34,7 +37,10 @@ static int clk_composite_set_parent(struct clk *clk, struct clk *parent) const struct clk_ops *mux_ops = composite->mux_ops; struct clk *mux = composite->mux; - return mux_ops->set_parent(mux, parent); + if (mux && mux_ops) + return mux_ops->set_parent(mux, parent); + else + return -ENOTSUPP; } static unsigned long clk_composite_recalc_rate(struct clk *clk) @@ -44,7 +50,10 @@ static unsigned long clk_composite_recalc_rate(struct clk *clk) const struct clk_ops *rate_ops = composite->rate_ops; struct clk *rate = composite->rate; - return rate_ops->get_rate(rate); + if (rate && rate_ops) + return rate_ops->get_rate(rate); + else + return clk_get_parent_rate(clk); } static ulong clk_composite_set_rate(struct clk *clk, unsigned long rate) @@ -54,7 +63,10 @@ static ulong clk_composite_set_rate(struct clk *clk, unsigned long rate) const struct clk_ops *rate_ops = composite->rate_ops; struct clk *clk_rate = composite->rate; - return rate_ops->set_rate(clk_rate, rate); + if (rate && rate_ops) + return rate_ops->set_rate(clk_rate, rate); + else + return clk_get_rate(clk); } static int clk_composite_enable(struct clk *clk) @@ -64,7 +76,10 @@ static int clk_composite_enable(struct clk *clk) const struct clk_ops *gate_ops = composite->gate_ops; struct clk *gate = composite->gate; - return gate_ops->enable(gate); + if (gate && gate_ops) + return gate_ops->enable(gate); + else + return 0; } static int clk_composite_disable(struct clk *clk) @@ -74,15 +89,12 @@ static int clk_composite_disable(struct clk *clk) const struct clk_ops *gate_ops = composite->gate_ops; struct clk *gate = composite->gate; - gate_ops->disable(gate); - - return 0; + if (gate && gate_ops) + return gate_ops->disable(gate); + else + return 0; } -struct clk_ops clk_composite_ops = { - /* This will be set according to clk_register_composite */ -}; - struct clk *clk_register_composite(struct device *dev, const char *name, const char * const *parent_names, int num_parents, struct clk *mux, @@ -96,7 +108,9 @@ struct clk *clk_register_composite(struct device *dev, const char *name, struct clk *clk; struct clk_composite *composite; int ret; - struct clk_ops *composite_ops = &clk_composite_ops; + + if (!num_parents || (num_parents != 1 && !mux)) + return ERR_PTR(-EINVAL); composite = kzalloc(sizeof(*composite), GFP_KERNEL); if (!composite) @@ -105,8 +119,6 @@ struct clk *clk_register_composite(struct device *dev, const char *name, if (mux && mux_ops) { composite->mux = mux; composite->mux_ops = mux_ops; - if (mux_ops->set_parent) - composite_ops->set_parent = clk_composite_set_parent; mux->data = (ulong)composite; } @@ -115,11 +127,6 @@ struct clk *clk_register_composite(struct device *dev, const char *name, clk = ERR_PTR(-EINVAL); goto err; } - composite_ops->get_rate = clk_composite_recalc_rate; - - /* .set_rate requires either .round_rate or .determine_rate */ - if (rate_ops->set_rate) - composite_ops->set_rate = clk_composite_set_rate; composite->rate = rate; composite->rate_ops = rate_ops; @@ -134,8 +141,6 @@ struct clk *clk_register_composite(struct device *dev, const char *name, composite->gate = gate; composite->gate_ops = gate_ops; - composite_ops->enable = clk_composite_enable; - composite_ops->disable = clk_composite_disable; gate->data = (ulong)composite; } @@ -161,6 +166,14 @@ err: return clk; } +static const struct clk_ops clk_composite_ops = { + .set_parent = clk_composite_set_parent, + .get_rate = clk_composite_recalc_rate, + .set_rate = clk_composite_set_rate, + .enable = clk_composite_enable, + .disable = clk_composite_disable, +}; + U_BOOT_DRIVER(clk_composite) = { .name = UBOOT_DM_CLK_COMPOSITE, .id = UCLASS_CLK, -- cgit v1.1 From 675d79073cc347ba72567668da69aebd1d1915fa Mon Sep 17 00:00:00 2001 From: Sean Anderson Date: Wed, 24 Jun 2020 06:41:08 -0400 Subject: clk: Fix clk_get_by_* handling of index clk_get_by_index_nodev only ever fetched clock 1, due to passing a boolean predicate instead of the index. Other clk_get_by_* functions got the clock correctly, but passed a predicate instead of the index to clk_get_by_tail. This could lead to confusing error messages. Signed-off-by: Sean Anderson CC: Lukasz Majewski --- drivers/clk/clk-uclass.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c index 9ffc224..70df9d4 100644 --- a/drivers/clk/clk-uclass.c +++ b/drivers/clk/clk-uclass.c @@ -123,7 +123,7 @@ static int clk_get_by_indexed_prop(struct udevice *dev, const char *prop_name, return clk_get_by_index_tail(ret, dev_ofnode(dev), &args, "clocks", - index > 0, clk); + index, clk); } int clk_get_by_index(struct udevice *dev, int index, struct clk *clk) @@ -135,7 +135,7 @@ int clk_get_by_index(struct udevice *dev, int index, struct clk *clk) index, &args); return clk_get_by_index_tail(ret, dev_ofnode(dev), &args, "clocks", - index > 0, clk); + index, clk); } int clk_get_by_index_nodev(ofnode node, int index, struct clk *clk) @@ -144,10 +144,10 @@ int clk_get_by_index_nodev(ofnode node, int index, struct clk *clk) int ret; ret = ofnode_parse_phandle_with_args(node, "clocks", "#clock-cells", 0, - index > 0, &args); + index, &args); return clk_get_by_index_tail(ret, node, &args, "clocks", - index > 0, clk); + index, clk); } int clk_get_bulk(struct udevice *dev, struct clk_bulk *bulk) -- cgit v1.1 From 019ef9a3f32642abbf924931ecc9487300e74530 Mon Sep 17 00:00:00 2001 From: Sean Anderson Date: Wed, 24 Jun 2020 06:41:09 -0400 Subject: clk: Add K210 pll support This pll code is primarily based on the code from the kendryte standalone sdk in lib/drivers/sysctl.c. k210_pll_calc_config is roughly analogous to the algorithm used to set the pll frequency, but it has been completely rewritten to be fixed-point based. Signed-off-by: Sean Anderson CC: Lukasz Majewski --- drivers/clk/Kconfig | 1 + drivers/clk/Makefile | 1 + drivers/clk/kendryte/Kconfig | 12 + drivers/clk/kendryte/Makefile | 1 + drivers/clk/kendryte/pll.c | 601 ++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 616 insertions(+) create mode 100644 drivers/clk/kendryte/Kconfig create mode 100644 drivers/clk/kendryte/Makefile create mode 100644 drivers/clk/kendryte/pll.c (limited to 'drivers') diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index 8b8b719..82cb187 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -156,6 +156,7 @@ source "drivers/clk/analogbits/Kconfig" source "drivers/clk/at91/Kconfig" source "drivers/clk/exynos/Kconfig" source "drivers/clk/imx/Kconfig" +source "drivers/clk/kendryte/Kconfig" source "drivers/clk/meson/Kconfig" source "drivers/clk/mvebu/Kconfig" source "drivers/clk/owl/Kconfig" diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index e017833..d911954 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -27,6 +27,7 @@ obj-$(CONFIG_CLK_BOSTON) += clk_boston.o obj-$(CONFIG_CLK_EXYNOS) += exynos/ obj-$(CONFIG_$(SPL_TPL_)CLK_INTEL) += intel/ obj-$(CONFIG_CLK_HSDK) += clk-hsdk-cgu.o +obj-$(CONFIG_CLK_K210) += kendryte/ obj-$(CONFIG_CLK_MPC83XX) += mpc83xx_clk.o obj-$(CONFIG_CLK_OWL) += owl/ obj-$(CONFIG_CLK_RENESAS) += renesas/ diff --git a/drivers/clk/kendryte/Kconfig b/drivers/clk/kendryte/Kconfig new file mode 100644 index 0000000..7b69c8a --- /dev/null +++ b/drivers/clk/kendryte/Kconfig @@ -0,0 +1,12 @@ +config CLK_K210 + bool "Clock support for Kendryte K210" + depends on CLK && CLK_CCF + help + This enables support clock driver for Kendryte K210 platforms. + +config CLK_K210_SET_RATE + bool "Enable setting the Kendryte K210 PLL rate" + depends on CLK_K210 + help + Add functionality to calculate new rates for K210 PLLs. Enabling this + feature adds around 1K to U-Boot's final size. diff --git a/drivers/clk/kendryte/Makefile b/drivers/clk/kendryte/Makefile new file mode 100644 index 0000000..c56d93e --- /dev/null +++ b/drivers/clk/kendryte/Makefile @@ -0,0 +1 @@ +obj-y += pll.o diff --git a/drivers/clk/kendryte/pll.c b/drivers/clk/kendryte/pll.c new file mode 100644 index 0000000..19e3588 --- /dev/null +++ b/drivers/clk/kendryte/pll.c @@ -0,0 +1,601 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2019-20 Sean Anderson + */ +#define LOG_CATEGORY UCLASS_CLK +#include + +#include +/* For DIV_ROUND_DOWN_ULL, defined in linux/kernel.h */ +#include +#include +#include +#include +#include +#include +#include +#include + +#define CLK_K210_PLL "k210_clk_pll" + +#ifdef CONFIG_CLK_K210_SET_RATE +static int k210_pll_enable(struct clk *clk); +static int k210_pll_disable(struct clk *clk); + +/* + * The PLL included with the Kendryte K210 appears to be a True Circuits, Inc. + * General-Purpose PLL. The logical layout of the PLL with internal feedback is + * approximately the following: + * + * +---------------+ + * |reference clock| + * +---------------+ + * | + * v + * +--+ + * |/r| + * +--+ + * | + * v + * +-------------+ + * |divided clock| + * +-------------+ + * | + * v + * +--------------+ + * |phase detector|<---+ + * +--------------+ | + * | | + * v +--------------+ + * +---+ |feedback clock| + * |VCO| +--------------+ + * +---+ ^ + * | +--+ | + * +--->|/f|---+ + * | +--+ + * v + * +---+ + * |/od| + * +---+ + * | + * v + * +------+ + * |output| + * +------+ + * + * The k210 PLLs have three factors: r, f, and od. Because of the feedback mode, + * the effect of the division by f is to multiply the input frequency. The + * equation for the output rate is + * rate = (rate_in * f) / (r * od). + * Moving knowns to one side of the equation, we get + * rate / rate_in = f / (r * od) + * Rearranging slightly, + * abs_error = abs((rate / rate_in) - (f / (r * od))). + * To get relative, error, we divide by the expected ratio + * error = abs((rate / rate_in) - (f / (r * od))) / (rate / rate_in). + * Simplifying, + * error = abs(1 - f / (r * od)) / (rate / rate_in) + * error = abs(1 - (f * rate_in) / (r * od * rate)) + * Using the constants ratio = rate / rate_in and inv_ratio = rate_in / rate, + * error = abs((f * inv_ratio) / (r * od) - 1) + * This is the error used in evaluating parameters. + * + * r and od are four bits each, while f is six bits. Because r and od are + * multiplied together, instead of the full 256 values possible if both bits + * were used fully, there are only 97 distinct products. Combined with f, there + * are 6208 theoretical settings for the PLL. However, most of these settings + * can be ruled out immediately because they do not have the correct ratio. + * + * In addition to the constraint of approximating the desired ratio, parameters + * must also keep internal pll frequencies within acceptable ranges. The divided + * clock's minimum and maximum frequencies have a ratio of around 128. This + * leaves fairly substantial room to work with, especially since the only + * affected parameter is r. The VCO's minimum and maximum frequency have a ratio + * of 5, which is considerably more restrictive. + * + * The r and od factors are stored in a table. This is to make it easy to find + * the next-largest product. Some products have multiple factorizations, but + * only when one factor has at least a 2.5x ratio to the factors of the other + * factorization. This is because any smaller ratio would not make a difference + * when ensuring the VCO's frequency is within spec. + * + * Throughout the calculation function, fixed point arithmetic is used. Because + * the range of rate and rate_in may be up to 1.75 GHz, or around 2^30, 64-bit + * 32.32 fixed-point numbers are used to represent ratios. In general, to + * implement division, the numerator is first multiplied by 2^32. This gives a + * result where the whole number part is in the upper 32 bits, and the fraction + * is in the lower 32 bits. + * + * In general, rounding is done to the closest integer. This helps find the best + * approximation for the ratio. Rounding in one direction (e.g down) could cause + * the function to miss a better ratio with one of the parameters increased by + * one. + */ + +/* + * The factors table was generated with the following python code: + * + * def p(x, y): + * return (1.0*x/y > 2.5) or (1.0*y/x > 2.5) + * + * factors = {} + * for i in range(1, 17): + * for j in range(1, 17): + * fs = factors.get(i*j) or [] + * if fs == [] or all([ + * (p(i, x) and p(i, y)) or (p(j, x) and p(j, y)) + * for (x, y) in fs]): + * fs.append((i, j)) + * factors[i*j] = fs + * + * for k, l in sorted(factors.items()): + * for v in l: + * print("PACK(%s, %s)," % v) + */ +#define PACK(r, od) (((((r) - 1) & 0xF) << 4) | (((od) - 1) & 0xF)) +#define UNPACK_R(val) ((((val) >> 4) & 0xF) + 1) +#define UNPACK_OD(val) (((val) & 0xF) + 1) +static const u8 factors[] = { + PACK(1, 1), + PACK(1, 2), + PACK(1, 3), + PACK(1, 4), + PACK(1, 5), + PACK(1, 6), + PACK(1, 7), + PACK(1, 8), + PACK(1, 9), + PACK(3, 3), + PACK(1, 10), + PACK(1, 11), + PACK(1, 12), + PACK(3, 4), + PACK(1, 13), + PACK(1, 14), + PACK(1, 15), + PACK(3, 5), + PACK(1, 16), + PACK(4, 4), + PACK(2, 9), + PACK(2, 10), + PACK(3, 7), + PACK(2, 11), + PACK(2, 12), + PACK(5, 5), + PACK(2, 13), + PACK(3, 9), + PACK(2, 14), + PACK(2, 15), + PACK(2, 16), + PACK(3, 11), + PACK(5, 7), + PACK(3, 12), + PACK(3, 13), + PACK(4, 10), + PACK(3, 14), + PACK(4, 11), + PACK(3, 15), + PACK(3, 16), + PACK(7, 7), + PACK(5, 10), + PACK(4, 13), + PACK(6, 9), + PACK(5, 11), + PACK(4, 14), + PACK(4, 15), + PACK(7, 9), + PACK(4, 16), + PACK(5, 13), + PACK(6, 11), + PACK(5, 14), + PACK(6, 12), + PACK(5, 15), + PACK(7, 11), + PACK(6, 13), + PACK(5, 16), + PACK(9, 9), + PACK(6, 14), + PACK(8, 11), + PACK(6, 15), + PACK(7, 13), + PACK(6, 16), + PACK(7, 14), + PACK(9, 11), + PACK(10, 10), + PACK(8, 13), + PACK(7, 15), + PACK(9, 12), + PACK(10, 11), + PACK(7, 16), + PACK(9, 13), + PACK(8, 15), + PACK(11, 11), + PACK(9, 14), + PACK(8, 16), + PACK(10, 13), + PACK(11, 12), + PACK(9, 15), + PACK(10, 14), + PACK(11, 13), + PACK(9, 16), + PACK(10, 15), + PACK(11, 14), + PACK(12, 13), + PACK(10, 16), + PACK(11, 15), + PACK(12, 14), + PACK(13, 13), + PACK(11, 16), + PACK(12, 15), + PACK(13, 14), + PACK(12, 16), + PACK(13, 15), + PACK(14, 14), + PACK(13, 16), + PACK(14, 15), + PACK(14, 16), + PACK(15, 15), + PACK(15, 16), + PACK(16, 16), +}; + +TEST_STATIC int k210_pll_calc_config(u32 rate, u32 rate_in, + struct k210_pll_config *best) +{ + int i; + s64 error, best_error; + u64 ratio, inv_ratio; /* fixed point 32.32 ratio of the rates */ + u64 max_r; + u64 r, f, od; + + /* + * Can't go over 1.75 GHz or under 21.25 MHz due to limitations on the + * VCO frequency. These are not the same limits as below because od can + * reduce the output frequency by 16. + */ + if (rate > 1750000000 || rate < 21250000) + return -EINVAL; + + /* Similar restrictions on the input rate */ + if (rate_in > 1750000000 || rate_in < 13300000) + return -EINVAL; + + ratio = DIV_ROUND_CLOSEST_ULL((u64)rate << 32, rate_in); + inv_ratio = DIV_ROUND_CLOSEST_ULL((u64)rate_in << 32, rate); + /* Can't increase by more than 64 or reduce by more than 256 */ + if (rate > rate_in && ratio > (64ULL << 32)) + return -EINVAL; + else if (rate <= rate_in && inv_ratio > (256ULL << 32)) + return -EINVAL; + + /* + * The divided clock (rate_in / r) must stay between 1.75 GHz and 13.3 + * MHz. There is no minimum, since the only way to get a higher input + * clock than 26 MHz is to use a clock generated by a PLL. Because PLLs + * cannot output frequencies greater than 1.75 GHz, the minimum would + * never be greater than one. + */ + max_r = DIV_ROUND_DOWN_ULL(rate_in, 13300000); + + /* Variables get immediately incremented, so start at -1th iteration */ + i = -1; + f = 0; + r = 0; + od = 0; + best_error = S64_MAX; + error = best_error; + /* do-while here so we always try at least one ratio */ + do { + /* + * Whether we swapped r and od while enforcing frequency limits + */ + bool swapped = false; + u64 last_od = od; + u64 last_r = r; + + /* + * Try the next largest value for f (or r and od) and + * recalculate the other parameters based on that + */ + if (rate > rate_in) { + /* + * Skip factors of the same product if we already tried + * out that product + */ + do { + i++; + r = UNPACK_R(factors[i]); + od = UNPACK_OD(factors[i]); + } while (i + 1 < ARRAY_SIZE(factors) && + r * od == last_r * last_od); + + /* Round close */ + f = (r * od * ratio + BIT(31)) >> 32; + if (f > 64) + f = 64; + } else { + u64 tmp = ++f * inv_ratio; + bool round_up = !!(tmp & BIT(31)); + u32 goal = (tmp >> 32) + round_up; + u32 err, last_err; + + /* Get the next r/od pair in factors */ + while (r * od < goal && i + 1 < ARRAY_SIZE(factors)) { + i++; + r = UNPACK_R(factors[i]); + od = UNPACK_OD(factors[i]); + } + + /* + * This is a case of double rounding. If we rounded up + * above, we need to round down (in cases of ties) here. + * This prevents off-by-one errors resulting from + * choosing X+2 over X when X.Y rounds up to X+1 and + * there is no r * od = X+1. For the converse, when X.Y + * is rounded down to X, we should choose X+1 over X-1. + */ + err = abs(r * od - goal); + last_err = abs(last_r * last_od - goal); + if (last_err < err || (round_up && last_err == err)) { + i--; + r = last_r; + od = last_od; + } + } + + /* + * Enforce limits on internal clock frequencies. If we + * aren't in spec, try swapping r and od. If everything is + * in-spec, calculate the relative error. + */ + while (true) { + /* + * Whether the intermediate frequencies are out-of-spec + */ + bool out_of_spec = false; + + if (r > max_r) { + out_of_spec = true; + } else { + /* + * There is no way to only divide once; we need + * to examine the frequency with and without the + * effect of od. + */ + u64 vco = DIV_ROUND_CLOSEST_ULL(rate_in * f, r); + + if (vco > 1750000000 || vco < 340000000) + out_of_spec = true; + } + + if (out_of_spec) { + if (!swapped) { + u64 tmp = r; + + r = od; + od = tmp; + swapped = true; + continue; + } else { + /* + * Try looking ahead to see if there are + * additional factors for the same + * product. + */ + if (i + 1 < ARRAY_SIZE(factors)) { + u64 new_r, new_od; + + i++; + new_r = UNPACK_R(factors[i]); + new_od = UNPACK_OD(factors[i]); + if (r * od == new_r * new_od) { + r = new_r; + od = new_od; + swapped = false; + continue; + } + i--; + } + break; + } + } + + error = DIV_ROUND_CLOSEST_ULL(f * inv_ratio, r * od); + /* The lower 16 bits are spurious */ + error = abs((error - BIT(32))) >> 16; + + if (error < best_error) { + best->r = r; + best->f = f; + best->od = od; + best_error = error; + } + break; + } + } while (f < 64 && i + 1 < ARRAY_SIZE(factors) && error != 0); + + if (best_error == S64_MAX) + return -EINVAL; + + log_debug("best error %lld\n", best_error); + return 0; +} + +static ulong k210_pll_set_rate(struct clk *clk, ulong rate) +{ + int err; + long long rate_in = clk_get_parent_rate(clk); + struct k210_pll_config config = {}; + struct k210_pll *pll = to_k210_pll(clk); + u32 reg; + + if (rate_in < 0) + return rate_in; + + log_debug("Calculating parameters with rate=%lu and rate_in=%lld\n", + rate, rate_in); + err = k210_pll_calc_config(rate, rate_in, &config); + if (err) + return err; + log_debug("Got r=%u f=%u od=%u\n", config.r, config.f, config.od); + + /* + * Don't use clk_disable as it might not actually disable the pll due to + * refcounting + */ + k210_pll_disable(clk); + + reg = readl(pll->reg); + reg &= ~K210_PLL_CLKR + & ~K210_PLL_CLKF + & ~K210_PLL_CLKOD + & ~K210_PLL_BWADJ; + reg |= FIELD_PREP(K210_PLL_CLKR, config.r - 1) + | FIELD_PREP(K210_PLL_CLKF, config.f - 1) + | FIELD_PREP(K210_PLL_CLKOD, config.od - 1) + | FIELD_PREP(K210_PLL_BWADJ, config.f - 1); + writel(reg, pll->reg); + + err = k210_pll_enable(clk); + if (err) + return err; + + serial_setbrg(); + return clk_get_rate(clk); +} +#endif /* CONFIG_CLK_K210_SET_RATE */ + +static ulong k210_pll_get_rate(struct clk *clk) +{ + long long rate_in = clk_get_parent_rate(clk); + struct k210_pll *pll = to_k210_pll(clk); + u64 r, f, od; + u32 reg = readl(pll->reg); + + if (rate_in < 0 || (reg & K210_PLL_BYPASS)) + return rate_in; + + if (!(reg & K210_PLL_PWRD)) + return 0; + + r = FIELD_GET(K210_PLL_CLKR, reg) + 1; + f = FIELD_GET(K210_PLL_CLKF, reg) + 1; + od = FIELD_GET(K210_PLL_CLKOD, reg) + 1; + + return DIV_ROUND_DOWN_ULL(((u64)rate_in) * f, r * od); +} + +/* + * Wait for the PLL to be locked. If the PLL is not locked, try clearing the + * slip before retrying + */ +static void k210_pll_waitfor_lock(struct k210_pll *pll) +{ + u32 mask = GENMASK(pll->width - 1, 0) << pll->shift; + + while (true) { + u32 reg = readl(pll->lock); + + if ((reg & mask) == mask) + break; + + reg |= BIT(pll->shift + K210_PLL_CLEAR_SLIP); + writel(reg, pll->lock); + } +} + +/* Adapted from sysctl_pll_enable */ +static int k210_pll_enable(struct clk *clk) +{ + struct k210_pll *pll = to_k210_pll(clk); + u32 reg = readl(pll->reg); + + if ((reg | K210_PLL_PWRD) && !(reg | K210_PLL_RESET)) + return 0; + + reg |= K210_PLL_PWRD; + writel(reg, pll->reg); + + /* Ensure reset is low before asserting it */ + reg &= ~K210_PLL_RESET; + writel(reg, pll->reg); + reg |= K210_PLL_RESET; + writel(reg, pll->reg); + nop(); + nop(); + reg &= ~K210_PLL_RESET; + writel(reg, pll->reg); + + k210_pll_waitfor_lock(pll); + + reg &= ~K210_PLL_BYPASS; + writel(reg, pll->reg); + + return 0; +} + +static int k210_pll_disable(struct clk *clk) +{ + struct k210_pll *pll = to_k210_pll(clk); + u32 reg = readl(pll->reg); + + /* + * Bypassing before powering off is important so child clocks don't stop + * working. This is especially important for pll0, the indirect parent + * of the cpu clock. + */ + reg |= K210_PLL_BYPASS; + writel(reg, pll->reg); + + reg &= ~K210_PLL_PWRD; + writel(reg, pll->reg); + return 0; +} + +const struct clk_ops k210_pll_ops = { + .get_rate = k210_pll_get_rate, +#ifdef CONFIG_CLK_K210_SET_RATE + .set_rate = k210_pll_set_rate, +#endif + .enable = k210_pll_enable, + .disable = k210_pll_disable, +}; + +struct clk *k210_register_pll_struct(const char *name, const char *parent_name, + struct k210_pll *pll) +{ + int ret; + struct clk *clk = &pll->clk; + + ret = clk_register(clk, CLK_K210_PLL, name, parent_name); + if (ret) + return ERR_PTR(ret); + return clk; +} + +struct clk *k210_register_pll(const char *name, const char *parent_name, + void __iomem *reg, void __iomem *lock, u8 shift, + u8 width) +{ + struct clk *clk; + struct k210_pll *pll; + + pll = kzalloc(sizeof(*pll), GFP_KERNEL); + if (!pll) + return ERR_PTR(-ENOMEM); + pll->reg = reg; + pll->lock = lock; + pll->shift = shift; + pll->width = width; + + clk = k210_register_pll_struct(name, parent_name, pll); + if (IS_ERR(clk)) + kfree(pll); + return clk; +} + +U_BOOT_DRIVER(k210_pll) = { + .name = CLK_K210_PLL, + .id = UCLASS_CLK, + .ops = &k210_pll_ops, +}; -- cgit v1.1 From 1a198cf8862b0540894ba6569c55244b1bd3e824 Mon Sep 17 00:00:00 2001 From: Sean Anderson Date: Wed, 24 Jun 2020 06:41:10 -0400 Subject: clk: Add a bypass clock for K210 This is a small driver to do a software bypass of a clock if hardware bypass is not working. I have tried to write this in a generic fashion, so that it could be potentially broken out of the kendryte code at some future date. For the K210, it is used to have aclk bypass pll0 and use in0 instead so that the CPU keeps on working. Signed-off-by: Sean Anderson CC: Lukasz Majewski --- drivers/clk/kendryte/Makefile | 2 +- drivers/clk/kendryte/bypass.c | 270 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 271 insertions(+), 1 deletion(-) create mode 100644 drivers/clk/kendryte/bypass.c (limited to 'drivers') diff --git a/drivers/clk/kendryte/Makefile b/drivers/clk/kendryte/Makefile index c56d93e..47f682f 100644 --- a/drivers/clk/kendryte/Makefile +++ b/drivers/clk/kendryte/Makefile @@ -1 +1 @@ -obj-y += pll.o +obj-y += bypass.o pll.o diff --git a/drivers/clk/kendryte/bypass.c b/drivers/clk/kendryte/bypass.c new file mode 100644 index 0000000..d1fd281 --- /dev/null +++ b/drivers/clk/kendryte/bypass.c @@ -0,0 +1,270 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2020 Sean Anderson + */ + +#define LOG_CATEGORY UCLASS_CLK +#include + +#include +#include +#include +#include + +#define CLK_K210_BYPASS "k210_clk_bypass" + +/* + * This is a small driver to do a software bypass of a clock if hardware bypass + * is not working. I have tried to write this in a generic fashion, so that it + * could be potentially broken out of the kendryte code at some future date. + * + * Say you have the following clock configuration + * + * +---+ +---+ + * |osc| |pll| + * +---+ +---+ + * ^ + * /| + * / | + * / | + * / | + * / | + * +---+ +---+ + * |clk| |clk| + * +---+ +---+ + * + * But the pll does not have a bypass, so when you configure the pll, the + * configuration needs to change to look like + * + * +---+ +---+ + * |osc| |pll| + * +---+ +---+ + * ^ + * |\ + * | \ + * | \ + * | \ + * | \ + * +---+ +---+ + * |clk| |clk| + * +---+ +---+ + * + * To set this up, create a bypass clock with bypassee=pll and alt=osc. When + * creating the child clocks, set their parent to the bypass clock. After + * creating all the children, call k210_bypass_setchildren(). + */ + +static int k210_bypass_dobypass(struct k210_bypass *bypass) +{ + int ret, i; + + /* + * If we already have saved parents, then the children are already + * bypassed + */ + if (bypass->child_count && bypass->saved_parents[0]) + return 0; + + for (i = 0; i < bypass->child_count; i++) { + struct clk *child = bypass->children[i]; + struct clk *parent = clk_get_parent(child); + + if (IS_ERR(parent)) { + for (; i; i--) + bypass->saved_parents[i] = NULL; + return PTR_ERR(parent); + } + bypass->saved_parents[i] = parent; + } + + for (i = 0; i < bypass->child_count; i++) { + struct clk *child = bypass->children[i]; + + ret = clk_set_parent(child, bypass->alt); + if (ret) { + for (; i; i--) + clk_set_parent(bypass->children[i], + bypass->saved_parents[i]); + for (i = 0; i < bypass->child_count; i++) + bypass->saved_parents[i] = NULL; + return ret; + } + } + + return 0; +} + +static int k210_bypass_unbypass(struct k210_bypass *bypass) +{ + int err, ret, i; + + if (!bypass->child_count && !bypass->saved_parents[0]) { + log_warning("Cannot unbypass children; dobypass not called first\n"); + return 0; + } + + ret = 0; + for (i = 0; i < bypass->child_count; i++) { + err = clk_set_parent(bypass->children[i], + bypass->saved_parents[i]); + if (err) + ret = err; + bypass->saved_parents[i] = NULL; + } + return ret; +} + +static ulong k210_bypass_get_rate(struct clk *clk) +{ + struct k210_bypass *bypass = to_k210_bypass(clk); + const struct clk_ops *ops = bypass->bypassee_ops; + + if (ops->get_rate) + return ops->get_rate(bypass->bypassee); + else + return clk_get_parent_rate(bypass->bypassee); +} + +static ulong k210_bypass_set_rate(struct clk *clk, unsigned long rate) +{ + int ret; + struct k210_bypass *bypass = to_k210_bypass(clk); + const struct clk_ops *ops = bypass->bypassee_ops; + + /* Don't bother bypassing if we aren't going to set the rate */ + if (!ops->set_rate) + return k210_bypass_get_rate(clk); + + ret = k210_bypass_dobypass(bypass); + if (ret) + return ret; + + ret = ops->set_rate(bypass->bypassee, rate); + if (ret < 0) + return ret; + + return k210_bypass_unbypass(bypass); +} + +static int k210_bypass_set_parent(struct clk *clk, struct clk *parent) +{ + struct k210_bypass *bypass = to_k210_bypass(clk); + const struct clk_ops *ops = bypass->bypassee_ops; + + if (ops->set_parent) + return ops->set_parent(bypass->bypassee, parent); + else + return -ENOTSUPP; +} + +/* + * For these next two functions, do the bypassing even if there is no + * en-/-disable function, since the bypassing itself can be observed in between + * calls. + */ +static int k210_bypass_enable(struct clk *clk) +{ + int ret; + struct k210_bypass *bypass = to_k210_bypass(clk); + const struct clk_ops *ops = bypass->bypassee_ops; + + ret = k210_bypass_dobypass(bypass); + if (ret) + return ret; + + if (ops->enable) + ret = ops->enable(bypass->bypassee); + else + ret = 0; + if (ret) + return ret; + + return k210_bypass_unbypass(bypass); +} + +static int k210_bypass_disable(struct clk *clk) +{ + int ret; + struct k210_bypass *bypass = to_k210_bypass(clk); + const struct clk_ops *ops = bypass->bypassee_ops; + + ret = k210_bypass_dobypass(bypass); + if (ret) + return ret; + + if (ops->disable) + return ops->disable(bypass->bypassee); + else + return 0; +} + +static const struct clk_ops k210_bypass_ops = { + .get_rate = k210_bypass_get_rate, + .set_rate = k210_bypass_set_rate, + .set_parent = k210_bypass_set_parent, + .enable = k210_bypass_enable, + .disable = k210_bypass_disable, +}; + +int k210_bypass_set_children(struct clk *clk, struct clk **children, + size_t child_count) +{ + struct k210_bypass *bypass = to_k210_bypass(clk); + + kfree(bypass->saved_parents); + if (child_count) { + bypass->saved_parents = + kcalloc(child_count, sizeof(struct clk *), GFP_KERNEL); + if (!bypass->saved_parents) + return -ENOMEM; + } + bypass->child_count = child_count; + bypass->children = children; + + return 0; +} + +struct clk *k210_register_bypass_struct(const char *name, + const char *parent_name, + struct k210_bypass *bypass) +{ + int ret; + struct clk *clk; + + clk = &bypass->clk; + + ret = clk_register(clk, CLK_K210_BYPASS, name, parent_name); + if (ret) + return ERR_PTR(ret); + + bypass->bypassee->dev = clk->dev; + return clk; +} + +struct clk *k210_register_bypass(const char *name, const char *parent_name, + struct clk *bypassee, + const struct clk_ops *bypassee_ops, + struct clk *alt) +{ + struct clk *clk; + struct k210_bypass *bypass; + + bypass = kzalloc(sizeof(*bypass), GFP_KERNEL); + if (!bypass) + return ERR_PTR(-ENOMEM); + + bypass->bypassee = bypassee; + bypass->bypassee_ops = bypassee_ops; + bypass->alt = alt; + + clk = k210_register_bypass_struct(name, parent_name, bypass); + if (IS_ERR(clk)) + kfree(bypass); + return clk; +} + +U_BOOT_DRIVER(k210_bypass) = { + .name = CLK_K210_BYPASS, + .id = UCLASS_CLK, + .ops = &k210_bypass_ops, +}; -- cgit v1.1 From f9c7d4f99f51ac9c1cf513111c21395f93d2dd53 Mon Sep 17 00:00:00 2001 From: Sean Anderson Date: Wed, 24 Jun 2020 06:41:11 -0400 Subject: clk: Add K210 clock support Due to the large number of clocks, I decided to use the CCF. The overall structure is modeled after the imx code. Clocks parameters are stored in several arrays, and are then instantiated at run-time. There are some translation macros (FOOIFY()) which allow for more dense packing. Signed-off-by: Sean Anderson CC: Lukasz Majewski --- drivers/clk/kendryte/Kconfig | 2 +- drivers/clk/kendryte/Makefile | 2 +- drivers/clk/kendryte/clk.c | 663 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 665 insertions(+), 2 deletions(-) create mode 100644 drivers/clk/kendryte/clk.c (limited to 'drivers') diff --git a/drivers/clk/kendryte/Kconfig b/drivers/clk/kendryte/Kconfig index 7b69c8a..073fca0 100644 --- a/drivers/clk/kendryte/Kconfig +++ b/drivers/clk/kendryte/Kconfig @@ -1,6 +1,6 @@ config CLK_K210 bool "Clock support for Kendryte K210" - depends on CLK && CLK_CCF + depends on CLK && CLK_CCF && CLK_COMPOSITE_CCF help This enables support clock driver for Kendryte K210 platforms. diff --git a/drivers/clk/kendryte/Makefile b/drivers/clk/kendryte/Makefile index 47f682f..6fb6825 100644 --- a/drivers/clk/kendryte/Makefile +++ b/drivers/clk/kendryte/Makefile @@ -1 +1 @@ -obj-y += bypass.o pll.o +obj-y += bypass.o clk.o pll.o diff --git a/drivers/clk/kendryte/clk.c b/drivers/clk/kendryte/clk.c new file mode 100644 index 0000000..981b3b7 --- /dev/null +++ b/drivers/clk/kendryte/clk.c @@ -0,0 +1,663 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2019-20 Sean Anderson + */ +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +/* All methods are delegated to CCF clocks */ + +static ulong k210_clk_get_rate(struct clk *clk) +{ + struct clk *c; + int err = clk_get_by_id(clk->id, &c); + + if (err) + return err; + return clk_get_rate(c); +} + +static ulong k210_clk_set_rate(struct clk *clk, unsigned long rate) +{ + struct clk *c; + int err = clk_get_by_id(clk->id, &c); + + if (err) + return err; + return clk_set_rate(c, rate); +} + +static int k210_clk_set_parent(struct clk *clk, struct clk *parent) +{ + struct clk *c, *p; + int err = clk_get_by_id(clk->id, &c); + + if (err) + return err; + + err = clk_get_by_id(parent->id, &p); + if (err) + return err; + + return clk_set_parent(c, p); +} + +static int k210_clk_endisable(struct clk *clk, bool enable) +{ + struct clk *c; + int err = clk_get_by_id(clk->id, &c); + + if (err) + return err; + return enable ? clk_enable(c) : clk_disable(c); +} + +static int k210_clk_enable(struct clk *clk) +{ + return k210_clk_endisable(clk, true); +} + +static int k210_clk_disable(struct clk *clk) +{ + return k210_clk_endisable(clk, false); +} + +static const struct clk_ops k210_clk_ops = { + .set_rate = k210_clk_set_rate, + .get_rate = k210_clk_get_rate, + .set_parent = k210_clk_set_parent, + .enable = k210_clk_enable, + .disable = k210_clk_disable, +}; + +/* Parents for muxed clocks */ +static const char * const generic_sels[] = { "in0_half", "pll0_half" }; +/* The first clock is in0, which is filled in by k210_clk_probe */ +static const char *aclk_sels[] = { NULL, "pll0_half" }; +static const char *pll2_sels[] = { NULL, "pll0", "pll1" }; + +/* + * All parameters for different sub-clocks are collected into parameter arrays. + * These parameters are then initialized by the clock which uses them during + * probe. To save space, ids are automatically generated for each sub-clock by + * using an enum. Instead of storing a parameter struct for each clock, even for + * those clocks which don't use a particular type of sub-clock, we can just + * store the parameters for the clocks which need them. + * + * So why do it like this? Arranging all the sub-clocks together makes it very + * easy to find bugs in the code. + */ + +#define DIV(id, off, shift, width) DIV_FLAGS(id, off, shift, width, 0) +#define DIV_LIST \ + DIV_FLAGS(K210_CLK_ACLK, K210_SYSCTL_SEL0, 1, 2, \ + CLK_DIVIDER_POWER_OF_TWO) \ + DIV(K210_CLK_APB0, K210_SYSCTL_SEL0, 3, 3) \ + DIV(K210_CLK_APB1, K210_SYSCTL_SEL0, 6, 3) \ + DIV(K210_CLK_APB2, K210_SYSCTL_SEL0, 9, 3) \ + DIV(K210_CLK_SRAM0, K210_SYSCTL_THR0, 0, 4) \ + DIV(K210_CLK_SRAM1, K210_SYSCTL_THR0, 4, 4) \ + DIV(K210_CLK_AI, K210_SYSCTL_THR0, 8, 4) \ + DIV(K210_CLK_DVP, K210_SYSCTL_THR0, 12, 4) \ + DIV(K210_CLK_ROM, K210_SYSCTL_THR0, 16, 4) \ + DIV(K210_CLK_SPI0, K210_SYSCTL_THR1, 0, 8) \ + DIV(K210_CLK_SPI1, K210_SYSCTL_THR1, 8, 8) \ + DIV(K210_CLK_SPI2, K210_SYSCTL_THR1, 16, 8) \ + DIV(K210_CLK_SPI3, K210_SYSCTL_THR1, 24, 8) \ + DIV(K210_CLK_TIMER0, K210_SYSCTL_THR2, 0, 8) \ + DIV(K210_CLK_TIMER1, K210_SYSCTL_THR2, 8, 8) \ + DIV(K210_CLK_TIMER2, K210_SYSCTL_THR2, 16, 8) \ + DIV(K210_CLK_I2S0, K210_SYSCTL_THR3, 0, 16) \ + DIV(K210_CLK_I2S1, K210_SYSCTL_THR3, 16, 16) \ + DIV(K210_CLK_I2S2, K210_SYSCTL_THR4, 0, 16) \ + DIV(K210_CLK_I2S0_M, K210_SYSCTL_THR4, 16, 8) \ + DIV(K210_CLK_I2S1_M, K210_SYSCTL_THR4, 24, 8) \ + DIV(K210_CLK_I2S2_M, K210_SYSCTL_THR4, 0, 8) \ + DIV(K210_CLK_I2C0, K210_SYSCTL_THR5, 8, 8) \ + DIV(K210_CLK_I2C1, K210_SYSCTL_THR5, 16, 8) \ + DIV(K210_CLK_I2C2, K210_SYSCTL_THR5, 24, 8) \ + DIV(K210_CLK_WDT0, K210_SYSCTL_THR6, 0, 8) \ + DIV(K210_CLK_WDT1, K210_SYSCTL_THR6, 8, 8) + +#define _DIVIFY(id) K210_CLK_DIV_##id +#define DIVIFY(id) _DIVIFY(id) + +enum k210_div_ids { +#define DIV_FLAGS(id, ...) DIVIFY(id), + DIV_LIST +#undef DIV_FLAGS +}; + +struct k210_div_params { + u8 off; + u8 shift; + u8 width; + u8 flags; +}; + +static const struct k210_div_params k210_divs[] = { +#define DIV_FLAGS(id, _off, _shift, _width, _flags) \ + [DIVIFY(id)] = { \ + .off = (_off), \ + .shift = (_shift), \ + .width = (_width), \ + .flags = (_flags), \ + }, + DIV_LIST +#undef DIV_FLAGS +}; + +#undef DIV +#undef DIV_LIST + +#define GATE_LIST \ + GATE(K210_CLK_CPU, K210_SYSCTL_EN_CENT, 0) \ + GATE(K210_CLK_SRAM0, K210_SYSCTL_EN_CENT, 1) \ + GATE(K210_CLK_SRAM1, K210_SYSCTL_EN_CENT, 2) \ + GATE(K210_CLK_APB0, K210_SYSCTL_EN_CENT, 3) \ + GATE(K210_CLK_APB1, K210_SYSCTL_EN_CENT, 4) \ + GATE(K210_CLK_APB2, K210_SYSCTL_EN_CENT, 5) \ + GATE(K210_CLK_ROM, K210_SYSCTL_EN_PERI, 0) \ + GATE(K210_CLK_DMA, K210_SYSCTL_EN_PERI, 1) \ + GATE(K210_CLK_AI, K210_SYSCTL_EN_PERI, 2) \ + GATE(K210_CLK_DVP, K210_SYSCTL_EN_PERI, 3) \ + GATE(K210_CLK_FFT, K210_SYSCTL_EN_PERI, 4) \ + GATE(K210_CLK_GPIO, K210_SYSCTL_EN_PERI, 5) \ + GATE(K210_CLK_SPI0, K210_SYSCTL_EN_PERI, 6) \ + GATE(K210_CLK_SPI1, K210_SYSCTL_EN_PERI, 7) \ + GATE(K210_CLK_SPI2, K210_SYSCTL_EN_PERI, 8) \ + GATE(K210_CLK_SPI3, K210_SYSCTL_EN_PERI, 9) \ + GATE(K210_CLK_I2S0, K210_SYSCTL_EN_PERI, 10) \ + GATE(K210_CLK_I2S1, K210_SYSCTL_EN_PERI, 11) \ + GATE(K210_CLK_I2S2, K210_SYSCTL_EN_PERI, 12) \ + GATE(K210_CLK_I2C0, K210_SYSCTL_EN_PERI, 13) \ + GATE(K210_CLK_I2C1, K210_SYSCTL_EN_PERI, 14) \ + GATE(K210_CLK_I2C2, K210_SYSCTL_EN_PERI, 15) \ + GATE(K210_CLK_UART1, K210_SYSCTL_EN_PERI, 16) \ + GATE(K210_CLK_UART2, K210_SYSCTL_EN_PERI, 17) \ + GATE(K210_CLK_UART3, K210_SYSCTL_EN_PERI, 18) \ + GATE(K210_CLK_AES, K210_SYSCTL_EN_PERI, 19) \ + GATE(K210_CLK_FPIOA, K210_SYSCTL_EN_PERI, 20) \ + GATE(K210_CLK_TIMER0, K210_SYSCTL_EN_PERI, 21) \ + GATE(K210_CLK_TIMER1, K210_SYSCTL_EN_PERI, 22) \ + GATE(K210_CLK_TIMER2, K210_SYSCTL_EN_PERI, 23) \ + GATE(K210_CLK_WDT0, K210_SYSCTL_EN_PERI, 24) \ + GATE(K210_CLK_WDT1, K210_SYSCTL_EN_PERI, 25) \ + GATE(K210_CLK_SHA, K210_SYSCTL_EN_PERI, 26) \ + GATE(K210_CLK_OTP, K210_SYSCTL_EN_PERI, 27) \ + GATE(K210_CLK_RTC, K210_SYSCTL_EN_PERI, 29) + +#define _GATEIFY(id) K210_CLK_GATE_##id +#define GATEIFY(id) _GATEIFY(id) + +enum k210_gate_ids { +#define GATE(id, ...) GATEIFY(id), + GATE_LIST +#undef GATE +}; + +struct k210_gate_params { + u8 off; + u8 bit_idx; +}; + +static const struct k210_gate_params k210_gates[] = { +#define GATE(id, _off, _idx) \ + [GATEIFY(id)] = { \ + .off = (_off), \ + .bit_idx = (_idx), \ + }, + GATE_LIST +#undef GATE +}; + +#undef GATE_LIST + +#define MUX(id, reg, shift, width) \ + MUX_PARENTS(id, generic_sels, reg, shift, width) +#define MUX_LIST \ + MUX_PARENTS(K210_CLK_PLL2, pll2_sels, K210_SYSCTL_PLL2, 26, 2) \ + MUX_PARENTS(K210_CLK_ACLK, aclk_sels, K210_SYSCTL_SEL0, 0, 1) \ + MUX(K210_CLK_SPI3, K210_SYSCTL_SEL0, 12, 1) \ + MUX(K210_CLK_TIMER0, K210_SYSCTL_SEL0, 13, 1) \ + MUX(K210_CLK_TIMER1, K210_SYSCTL_SEL0, 14, 1) \ + MUX(K210_CLK_TIMER2, K210_SYSCTL_SEL0, 15, 1) + +#define _MUXIFY(id) K210_CLK_MUX_##id +#define MUXIFY(id) _MUXIFY(id) + +enum k210_mux_ids { +#define MUX_PARENTS(id, ...) MUXIFY(id), + MUX_LIST +#undef MUX_PARENTS + K210_CLK_MUX_NONE, +}; + +struct k210_mux_params { + const char *const *parent_names; + u8 num_parents; + u8 off; + u8 shift; + u8 width; +}; + +static const struct k210_mux_params k210_muxes[] = { +#define MUX_PARENTS(id, parents, _off, _shift, _width) \ + [MUXIFY(id)] = { \ + .parent_names = (const char * const *)(parents), \ + .num_parents = ARRAY_SIZE(parents), \ + .off = (_off), \ + .shift = (_shift), \ + .width = (_width), \ + }, + MUX_LIST +#undef MUX_PARENTS +}; + +#undef MUX +#undef MUX_LIST + +struct k210_pll_params { + u8 off; + u8 lock_off; + u8 shift; + u8 width; +}; + +static const struct k210_pll_params k210_plls[] = { +#define PLL(_off, _shift, _width) { \ + .off = (_off), \ + .lock_off = K210_SYSCTL_PLL_LOCK, \ + .shift = (_shift), \ + .width = (_width), \ +} + [0] = PLL(K210_SYSCTL_PLL0, 0, 2), + [1] = PLL(K210_SYSCTL_PLL1, 8, 1), + [2] = PLL(K210_SYSCTL_PLL2, 16, 1), +#undef PLL +}; + +#define COMP(id) \ + COMP_FULL(id, MUXIFY(id), DIVIFY(id), GATEIFY(id)) +#define COMP_NOMUX(id) \ + COMP_FULL(id, K210_CLK_MUX_NONE, DIVIFY(id), GATEIFY(id)) +#define COMP_LIST \ + COMP(K210_CLK_SPI3) \ + COMP(K210_CLK_TIMER0) \ + COMP(K210_CLK_TIMER1) \ + COMP(K210_CLK_TIMER2) \ + COMP_NOMUX(K210_CLK_SRAM0) \ + COMP_NOMUX(K210_CLK_SRAM1) \ + COMP_NOMUX(K210_CLK_ROM) \ + COMP_NOMUX(K210_CLK_DVP) \ + COMP_NOMUX(K210_CLK_APB0) \ + COMP_NOMUX(K210_CLK_APB1) \ + COMP_NOMUX(K210_CLK_APB2) \ + COMP_NOMUX(K210_CLK_AI) \ + COMP_NOMUX(K210_CLK_I2S0) \ + COMP_NOMUX(K210_CLK_I2S1) \ + COMP_NOMUX(K210_CLK_I2S2) \ + COMP_NOMUX(K210_CLK_WDT0) \ + COMP_NOMUX(K210_CLK_WDT1) \ + COMP_NOMUX(K210_CLK_SPI0) \ + COMP_NOMUX(K210_CLK_SPI1) \ + COMP_NOMUX(K210_CLK_SPI2) \ + COMP_NOMUX(K210_CLK_I2C0) \ + COMP_NOMUX(K210_CLK_I2C1) \ + COMP_NOMUX(K210_CLK_I2C2) + +#define _COMPIFY(id) K210_CLK_COMP_##id +#define COMPIFY(id) _COMPIFY(id) + +enum k210_comp_ids { +#define COMP_FULL(id, ...) COMPIFY(id), + COMP_LIST +#undef COMP_FULL +}; + +struct k210_comp_params { + u8 mux; + u8 div; + u8 gate; +}; + +static const struct k210_comp_params k210_comps[] = { +#define COMP_FULL(id, _mux, _div, _gate) \ + [COMPIFY(id)] = { \ + .mux = (_mux), \ + .div = (_div), \ + .gate = (_gate), \ + }, + COMP_LIST +#undef COMP_FULL +}; + +#undef COMP +#undef COMP_ID +#undef COMP_NOMUX +#undef COMP_NOMUX_ID +#undef COMP_LIST + +static struct clk *k210_bypass_children = { + NULL, +}; + +/* Helper functions to create sub-clocks */ +static struct clk_mux *k210_create_mux(const struct k210_mux_params *params, + void *base) +{ + struct clk_mux *mux = kzalloc(sizeof(*mux), GFP_KERNEL); + + if (!mux) + return mux; + + mux->reg = base + params->off; + mux->mask = BIT(params->width) - 1; + mux->shift = params->shift; + mux->parent_names = params->parent_names; + mux->num_parents = params->num_parents; + + return mux; +} + +static struct clk_divider *k210_create_div(const struct k210_div_params *params, + void *base) +{ + struct clk_divider *div = kzalloc(sizeof(*div), GFP_KERNEL); + + if (!div) + return div; + + div->reg = base + params->off; + div->shift = params->shift; + div->width = params->width; + div->flags = params->flags; + + return div; +} + +static struct clk_gate *k210_create_gate(const struct k210_gate_params *params, + void *base) +{ + struct clk_gate *gate = kzalloc(sizeof(*gate), GFP_KERNEL); + + if (!gate) + return gate; + + gate->reg = base + params->off; + gate->bit_idx = params->bit_idx; + + return gate; +} + +static struct k210_pll *k210_create_pll(const struct k210_pll_params *params, + void *base) +{ + struct k210_pll *pll = kzalloc(sizeof(*pll), GFP_KERNEL); + + if (!pll) + return pll; + + pll->reg = base + params->off; + pll->lock = base + params->lock_off; + pll->shift = params->shift; + pll->width = params->width; + + return pll; +} + +/* Create all sub-clocks, and then register the composite clock */ +static struct clk *k210_register_comp(const struct k210_comp_params *params, + void *base, const char *name, + const char *parent) +{ + const char *const *parent_names; + int num_parents; + struct clk *comp; + const struct clk_ops *mux_ops; + struct clk_mux *mux; + struct clk_divider *div; + struct clk_gate *gate; + + if (params->mux == K210_CLK_MUX_NONE) { + if (!parent) + return ERR_PTR(-EINVAL); + + mux_ops = NULL; + mux = NULL; + parent_names = &parent; + num_parents = 1; + } else { + mux_ops = &clk_mux_ops; + mux = k210_create_mux(&k210_muxes[params->mux], base); + if (!mux) + return ERR_PTR(-ENOMEM); + + parent_names = mux->parent_names; + num_parents = mux->num_parents; + } + + div = k210_create_div(&k210_divs[params->div], base); + if (!div) { + comp = ERR_PTR(-ENOMEM); + goto cleanup_mux; + } + + gate = k210_create_gate(&k210_gates[params->gate], base); + if (!gate) { + comp = ERR_PTR(-ENOMEM); + goto cleanup_div; + } + + comp = clk_register_composite(NULL, name, parent_names, num_parents, + &mux->clk, mux_ops, + &div->clk, &clk_divider_ops, + &gate->clk, &clk_gate_ops, 0); + if (IS_ERR(comp)) + goto cleanup_gate; + return comp; + +cleanup_gate: + free(gate); +cleanup_div: + free(div); +cleanup_mux: + if (mux) + free(mux); + return comp; +} + +static bool probed; + +static int k210_clk_probe(struct udevice *dev) +{ + int ret; + const char *in0; + struct clk *in0_clk, *bypass; + struct clk_mux *mux; + struct clk_divider *div; + struct k210_pll *pll; + void *base; + + /* + * Only one instance of this driver allowed. This prevents weird bugs + * when the driver fails part-way through probing. Some clocks will + * already have been registered, and re-probing will register them + * again, creating a bunch of duplicates. Better error-handling/cleanup + * could fix this, but it's Probably Not Worth It (TM). + */ + if (probed) + return -ENOTSUPP; + + base = dev_read_addr_ptr(dev_get_parent(dev)); + if (!base) + return -EINVAL; + + in0_clk = kzalloc(sizeof(*in0_clk), GFP_KERNEL); + if (!in0_clk) + return -ENOMEM; + + ret = clk_get_by_index(dev, 0, in0_clk); + if (ret) + return ret; + in0 = in0_clk->dev->name; + + probed = true; + + aclk_sels[0] = in0; + pll2_sels[0] = in0; + + /* + * All PLLs have a broken bypass, but pll0 has the CPU downstream, so we + * need to manually reparent it whenever we configure pll0 + */ + pll = k210_create_pll(&k210_plls[0], base); + if (pll) { + bypass = k210_register_bypass("pll0", in0, &pll->clk, + &k210_pll_ops, in0_clk); + clk_dm(K210_CLK_PLL0, bypass); + } else { + return -ENOMEM; + } + + { + const struct k210_pll_params *params = &k210_plls[1]; + + clk_dm(K210_CLK_PLL1, + k210_register_pll("pll1", in0, base + params->off, + base + params->lock_off, params->shift, + params->width)); + } + + /* PLL2 is muxed, so set up a composite clock */ + mux = k210_create_mux(&k210_muxes[MUXIFY(K210_CLK_PLL2)], base); + pll = k210_create_pll(&k210_plls[2], base); + if (!mux || !pll) { + free(mux); + free(pll); + } else { + clk_dm(K210_CLK_PLL2, + clk_register_composite(NULL, "pll2", pll2_sels, + ARRAY_SIZE(pll2_sels), + &mux->clk, &clk_mux_ops, + &pll->clk, &k210_pll_ops, + &pll->clk, &k210_pll_ops, 0)); + } + + /* Half-frequency clocks for "even" dividers */ + clk_dm(K210_CLK_IN0_H, k210_clk_half("in0_half", in0)); + clk_dm(K210_CLK_PLL0_H, k210_clk_half("pll0_half", "pll0")); + clk_dm(K210_CLK_PLL2_H, k210_clk_half("pll2_half", "pll2")); + + /* ACLK has no gate */ + mux = k210_create_mux(&k210_muxes[MUXIFY(K210_CLK_ACLK)], base); + div = k210_create_div(&k210_divs[DIVIFY(K210_CLK_ACLK)], base); + if (!mux || !div) { + free(mux); + free(div); + } else { + struct clk *aclk = + clk_register_composite(NULL, "aclk", aclk_sels, + ARRAY_SIZE(aclk_sels), + &mux->clk, &clk_mux_ops, + &div->clk, &clk_divider_ops, + NULL, NULL, 0); + clk_dm(K210_CLK_ACLK, aclk); + if (!IS_ERR(aclk)) { + k210_bypass_children = aclk; + k210_bypass_set_children(bypass, + &k210_bypass_children, 1); + } + } + +#define REGISTER_COMP(id, name) \ + clk_dm(id, \ + k210_register_comp(&k210_comps[COMPIFY(id)], base, name, NULL)) + REGISTER_COMP(K210_CLK_SPI3, "spi3"); + REGISTER_COMP(K210_CLK_TIMER0, "timer0"); + REGISTER_COMP(K210_CLK_TIMER1, "timer1"); + REGISTER_COMP(K210_CLK_TIMER2, "timer2"); +#undef REGISTER_COMP + + /* Dividing clocks, no mux */ +#define REGISTER_COMP_NOMUX(id, name, parent) \ + clk_dm(id, \ + k210_register_comp(&k210_comps[COMPIFY(id)], base, name, parent)) + REGISTER_COMP_NOMUX(K210_CLK_SRAM0, "sram0", "aclk"); + REGISTER_COMP_NOMUX(K210_CLK_SRAM1, "sram1", "aclk"); + REGISTER_COMP_NOMUX(K210_CLK_ROM, "rom", "aclk"); + REGISTER_COMP_NOMUX(K210_CLK_DVP, "dvp", "aclk"); + REGISTER_COMP_NOMUX(K210_CLK_APB0, "apb0", "aclk"); + REGISTER_COMP_NOMUX(K210_CLK_APB1, "apb1", "aclk"); + REGISTER_COMP_NOMUX(K210_CLK_APB2, "apb2", "aclk"); + REGISTER_COMP_NOMUX(K210_CLK_AI, "ai", "pll1"); + REGISTER_COMP_NOMUX(K210_CLK_I2S0, "i2s0", "pll2_half"); + REGISTER_COMP_NOMUX(K210_CLK_I2S1, "i2s1", "pll2_half"); + REGISTER_COMP_NOMUX(K210_CLK_I2S2, "i2s2", "pll2_half"); + REGISTER_COMP_NOMUX(K210_CLK_WDT0, "wdt0", "in0_half"); + REGISTER_COMP_NOMUX(K210_CLK_WDT1, "wdt1", "in0_half"); + REGISTER_COMP_NOMUX(K210_CLK_SPI0, "spi0", "pll0_half"); + REGISTER_COMP_NOMUX(K210_CLK_SPI1, "spi1", "pll0_half"); + REGISTER_COMP_NOMUX(K210_CLK_SPI2, "spi2", "pll0_half"); + REGISTER_COMP_NOMUX(K210_CLK_I2C0, "i2c0", "pll0_half"); + REGISTER_COMP_NOMUX(K210_CLK_I2C1, "i2c1", "pll0_half"); + REGISTER_COMP_NOMUX(K210_CLK_I2C2, "i2c2", "pll0_half"); +#undef REGISTER_COMP_NOMUX + + /* Dividing clocks */ +#define REGISTER_DIV(id, name, parent) do {\ + const struct k210_div_params *params = &k210_divs[DIVIFY(id)]; \ + clk_dm(id, \ + clk_register_divider(NULL, name, parent, 0, base + params->off, \ + params->shift, params->width, 0)); \ +} while (false) + REGISTER_DIV(K210_CLK_I2S0_M, "i2s0_m", "pll2_half"); + REGISTER_DIV(K210_CLK_I2S1_M, "i2s1_m", "pll2_half"); + REGISTER_DIV(K210_CLK_I2S2_M, "i2s2_m", "pll2_half"); +#undef REGISTER_DIV + + /* Gated clocks */ +#define REGISTER_GATE(id, name, parent) do { \ + const struct k210_gate_params *params = &k210_gates[GATEIFY(id)]; \ + clk_dm(id, \ + clk_register_gate(NULL, name, parent, 0, base + params->off, \ + params->bit_idx, 0, NULL)); \ +} while (false) + REGISTER_GATE(K210_CLK_CPU, "cpu", "aclk"); + REGISTER_GATE(K210_CLK_DMA, "dma", "aclk"); + REGISTER_GATE(K210_CLK_FFT, "fft", "aclk"); + REGISTER_GATE(K210_CLK_GPIO, "gpio", "apb0"); + REGISTER_GATE(K210_CLK_UART1, "uart1", "apb0"); + REGISTER_GATE(K210_CLK_UART2, "uart2", "apb0"); + REGISTER_GATE(K210_CLK_UART3, "uart3", "apb0"); + REGISTER_GATE(K210_CLK_FPIOA, "fpioa", "apb0"); + REGISTER_GATE(K210_CLK_SHA, "sha", "apb0"); + REGISTER_GATE(K210_CLK_AES, "aes", "apb1"); + REGISTER_GATE(K210_CLK_OTP, "otp", "apb1"); + REGISTER_GATE(K210_CLK_RTC, "rtc", in0); +#undef REGISTER_GATE + + return 0; +} + +static const struct udevice_id k210_clk_ids[] = { + { .compatible = "kendryte,k210-clk" }, + { }, +}; + +U_BOOT_DRIVER(k210_clk) = { + .name = "k210_clk", + .id = UCLASS_CLK, + .of_match = k210_clk_ids, + .ops = &k210_clk_ops, + .probe = k210_clk_probe, +}; -- cgit v1.1 From 4a3390f1d3b71f0645eb281176f00cd0d5ac2dcb Mon Sep 17 00:00:00 2001 From: Sean Anderson Date: Wed, 24 Jun 2020 06:41:12 -0400 Subject: dm: Add support for simple-pm-bus This type of bus is used in Linux to designate buses which have power domains and/or clocks which need to be enabled before their child devices can be used. Because power domains are automatically enabled before probing in U-Boot, we just need to enable any clocks present. Signed-off-by: Sean Anderson Reviewed-by: Simon Glass --- drivers/core/Kconfig | 7 ++++++ drivers/core/Makefile | 1 + drivers/core/simple-pm-bus.c | 56 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 64 insertions(+) create mode 100644 drivers/core/simple-pm-bus.c (limited to 'drivers') diff --git a/drivers/core/Kconfig b/drivers/core/Kconfig index a3b0399..a594899 100644 --- a/drivers/core/Kconfig +++ b/drivers/core/Kconfig @@ -195,6 +195,13 @@ config SPL_SIMPLE_BUS Supports the 'simple-bus' driver, which is used on some systems in SPL. +config SIMPLE_PM_BUS + bool "Support simple-pm-bus driver" + depends on DM && OF_CONTROL && CLK && POWER_DOMAIN + help + Supports the 'simple-pm-bus' driver, which is used for busses that + have power domains and/or clocks which need to be enabled before use. + config OF_TRANSLATE bool "Translate addresses using fdt_translate_address" depends on DM && OF_CONTROL diff --git a/drivers/core/Makefile b/drivers/core/Makefile index c707026..10f4bec 100644 --- a/drivers/core/Makefile +++ b/drivers/core/Makefile @@ -7,6 +7,7 @@ obj-$(CONFIG_$(SPL_TPL_)ACPIGEN) += acpi.o obj-$(CONFIG_DEVRES) += devres.o obj-$(CONFIG_$(SPL_)DM_DEVICE_REMOVE) += device-remove.o obj-$(CONFIG_$(SPL_)SIMPLE_BUS) += simple-bus.o +obj-$(CONFIG_SIMPLE_PM_BUS) += simple-pm-bus.o obj-$(CONFIG_DM) += dump.o obj-$(CONFIG_$(SPL_TPL_)REGMAP) += regmap.o obj-$(CONFIG_$(SPL_TPL_)SYSCON) += syscon-uclass.o diff --git a/drivers/core/simple-pm-bus.c b/drivers/core/simple-pm-bus.c new file mode 100644 index 0000000..51dc9b2 --- /dev/null +++ b/drivers/core/simple-pm-bus.c @@ -0,0 +1,56 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2020 Sean Anderson + */ + +#include +#include +#include + +/* + * Power domains are taken care of by driver_probe, so we just have to enable + * clocks + */ +static int simple_pm_bus_probe(struct udevice *dev) +{ + int ret; + struct clk_bulk *bulk = dev_get_priv(dev); + + ret = clk_get_bulk(dev, bulk); + if (ret) + return ret; + + ret = clk_enable_bulk(bulk); + if (ret && ret != -ENOSYS && ret != -ENOTSUPP) { + clk_release_bulk(bulk); + return ret; + } + return 0; +} + +static int simple_pm_bus_remove(struct udevice *dev) +{ + int ret; + struct clk_bulk *bulk = dev_get_priv(dev); + + ret = clk_release_bulk(bulk); + if (ret && ret != -ENOSYS && ret != -ENOTSUPP) + return ret; + else + return 0; +} + +static const struct udevice_id simple_pm_bus_ids[] = { + { .compatible = "simple-pm-bus" }, + { } +}; + +U_BOOT_DRIVER(simple_pm_bus_drv) = { + .name = "simple_pm_bus", + .id = UCLASS_SIMPLE_BUS, + .of_match = simple_pm_bus_ids, + .probe = simple_pm_bus_probe, + .remove = simple_pm_bus_remove, + .priv_auto_alloc_size = sizeof(struct clk_bulk), + .flags = DM_FLAG_PRE_RELOC, +}; -- cgit v1.1 From 082faeb86526b41bb9c5ca8373168e12f2de3a10 Mon Sep 17 00:00:00 2001 From: Sean Anderson Date: Wed, 24 Jun 2020 06:41:13 -0400 Subject: dm: Fix error handling for dev_read_addr_ptr dev_read_addr_ptr had different semantics depending on whether OF_LIVE was enabled. This patch converts both implementations to return NULL on error, and converts all call sites which check for FDT_ADDR_T_NONE to check for NULL instead. This patch also removes the call to map_physmem, since we have dev_remap_addr* for those semantics. Signed-off-by: Sean Anderson Reviewed-by: Bin Meng Reviewed-by: Simon Glass --- drivers/clk/imx/clk-imx8mp.c | 2 +- drivers/core/read.c | 2 +- drivers/pinctrl/broadcom/pinctrl-bcm283x.c | 2 +- drivers/pinctrl/mediatek/pinctrl-mtk-common.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/imx/clk-imx8mp.c b/drivers/clk/imx/clk-imx8mp.c index 3d7aebb..124138c 100644 --- a/drivers/clk/imx/clk-imx8mp.c +++ b/drivers/clk/imx/clk-imx8mp.c @@ -282,7 +282,7 @@ static int imx8mp_clk_probe(struct udevice *dev) clk_dm(IMX8MP_SYS_PLL2_1000M, imx_clk_fixed_factor("sys_pll2_1000m", "sys_pll2_out", 1, 1)); base = dev_read_addr_ptr(dev); - if (base == (void *)FDT_ADDR_T_NONE) + if (!base) return -EINVAL; clk_dm(IMX8MP_CLK_A53_SRC, imx_clk_mux2("arm_a53_src", base + 0x8000, 24, 3, imx8mp_a53_sels, ARRAY_SIZE(imx8mp_a53_sels))); diff --git a/drivers/core/read.c b/drivers/core/read.c index 85b3b7a..8bb456b 100644 --- a/drivers/core/read.c +++ b/drivers/core/read.c @@ -167,7 +167,7 @@ void *dev_read_addr_ptr(const struct udevice *dev) { fdt_addr_t addr = dev_read_addr(dev); - return (addr == FDT_ADDR_T_NONE) ? NULL : map_sysmem(addr, 0); + return (addr == FDT_ADDR_T_NONE) ? NULL : (void *)(uintptr_t)addr; } void *dev_remap_addr(const struct udevice *dev) diff --git a/drivers/pinctrl/broadcom/pinctrl-bcm283x.c b/drivers/pinctrl/broadcom/pinctrl-bcm283x.c index f44af6c..c22d534 100644 --- a/drivers/pinctrl/broadcom/pinctrl-bcm283x.c +++ b/drivers/pinctrl/broadcom/pinctrl-bcm283x.c @@ -117,7 +117,7 @@ int bcm283x_pinctl_probe(struct udevice *dev) } priv->base_reg = dev_read_addr_ptr(dev); - if (priv->base_reg == (void *)FDT_ADDR_T_NONE) { + if (!priv->base_reg) { debug("%s: Failed to get base address\n", __func__); return -EINVAL; } diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c index 5fdc150..e8187a3 100644 --- a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c +++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c @@ -631,7 +631,7 @@ int mtk_pinctrl_common_probe(struct udevice *dev, int ret; priv->base = dev_read_addr_ptr(dev); - if (priv->base == (void *)FDT_ADDR_T_NONE) + if (!priv->base) return -EINVAL; priv->soc = soc; -- cgit v1.1 From 038b13ee8134ba755a323732f3b2b838b9dc17a4 Mon Sep 17 00:00:00 2001 From: Sean Anderson Date: Wed, 24 Jun 2020 06:41:14 -0400 Subject: reset: Add generic reset driver This patch adds a generic reset driver. It is designed to be useful when one has a register in a regmap which contains bits that reset other devices. I thought this seemed like a very generic use, so here is a generic driver. The overall structure has been modeled on the syscon-reboot driver. Signed-off-by: Sean Anderson Reviewed-by: Simon Glass --- drivers/reset/Kconfig | 5 +++ drivers/reset/Makefile | 1 + drivers/reset/reset-syscon.c | 81 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 87 insertions(+) create mode 100644 drivers/reset/reset-syscon.c (limited to 'drivers') diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig index 88d3be1..58ba0c6 100644 --- a/drivers/reset/Kconfig +++ b/drivers/reset/Kconfig @@ -148,4 +148,9 @@ config RESET_IMX7 help Support for reset controller on i.MX7/8 SoCs. +config RESET_SYSCON + bool "Enable generic syscon reset driver support" + depends on DM_RESET + help + Support generic syscon mapped register reset devices. endmenu diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile index 0a044d5..433f1ec 100644 --- a/drivers/reset/Makefile +++ b/drivers/reset/Makefile @@ -23,3 +23,4 @@ obj-$(CONFIG_RESET_MTMIPS) += reset-mtmips.o obj-$(CONFIG_RESET_SUNXI) += reset-sunxi.o obj-$(CONFIG_RESET_HISILICON) += reset-hisilicon.o obj-$(CONFIG_RESET_IMX7) += reset-imx7.o +obj-$(CONFIG_RESET_SYSCON) += reset-syscon.o diff --git a/drivers/reset/reset-syscon.c b/drivers/reset/reset-syscon.c new file mode 100644 index 0000000..8520227 --- /dev/null +++ b/drivers/reset/reset-syscon.c @@ -0,0 +1,81 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2020 Sean Anderson + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +struct syscon_reset_priv { + struct regmap *regmap; + uint offset; + uint mask; + bool assert_high; +}; + +static int syscon_reset_request(struct reset_ctl *rst) +{ + struct syscon_reset_priv *priv = dev_get_priv(rst->dev); + + if (BIT(rst->id) & priv->mask) + return 0; + else + return -EINVAL; +} + +static int syscon_reset_assert(struct reset_ctl *rst) +{ + struct syscon_reset_priv *priv = dev_get_priv(rst->dev); + + return regmap_update_bits(priv->regmap, priv->offset, BIT(rst->id), + priv->assert_high ? BIT(rst->id) : 0); +} + +static int syscon_reset_deassert(struct reset_ctl *rst) +{ + struct syscon_reset_priv *priv = dev_get_priv(rst->dev); + + return regmap_update_bits(priv->regmap, priv->offset, BIT(rst->id), + priv->assert_high ? 0 : BIT(rst->id)); +} + +static const struct reset_ops syscon_reset_ops = { + .request = syscon_reset_request, + .rst_assert = syscon_reset_assert, + .rst_deassert = syscon_reset_deassert, +}; + +int syscon_reset_probe(struct udevice *dev) +{ + struct syscon_reset_priv *priv = dev_get_priv(dev); + + priv->regmap = syscon_regmap_lookup_by_phandle(dev, "regmap"); + if (IS_ERR(priv->regmap)) + return -ENODEV; + + priv->offset = dev_read_u32_default(dev, "offset", 0); + priv->mask = dev_read_u32_default(dev, "mask", 0); + priv->assert_high = dev_read_u32_default(dev, "assert-high", true); + + return 0; +} + +static const struct udevice_id syscon_reset_ids[] = { + { .compatible = "syscon-reset" }, + { }, +}; + +U_BOOT_DRIVER(syscon_reset) = { + .name = "syscon_reset", + .id = UCLASS_RESET, + .of_match = syscon_reset_ids, + .probe = syscon_reset_probe, + .priv_auto_alloc_size = sizeof(struct syscon_reset_priv), + .ops = &syscon_reset_ops, +}; -- cgit v1.1 From ab24017a19b482d9026d21a2ec03416c5c4a388d Mon Sep 17 00:00:00 2001 From: Sean Anderson Date: Wed, 24 Jun 2020 06:41:21 -0400 Subject: riscv: Try to get cpu frequency from a "clocks" node if it exists Instead of always using the "clock-frequency" property to determine cpu frequency, try using a clock in "clocks" if it exists. This patch also fixes a bug where there could be spurious higher frequencies if sizeof(u32) != sizeof(ulong). Signed-off-by: Sean Anderson Reviewed-by: Bin Meng --- drivers/cpu/riscv_cpu.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/cpu/riscv_cpu.c b/drivers/cpu/riscv_cpu.c index cb04f56..2d44d1c 100644 --- a/drivers/cpu/riscv_cpu.c +++ b/drivers/cpu/riscv_cpu.c @@ -3,6 +3,7 @@ * Copyright (C) 2018, Bin Meng */ +#include #include #include #include @@ -11,6 +12,7 @@ #include #include #include +#include DECLARE_GLOBAL_DATA_PTR; @@ -29,9 +31,24 @@ static int riscv_cpu_get_desc(struct udevice *dev, char *buf, int size) static int riscv_cpu_get_info(struct udevice *dev, struct cpu_info *info) { + int ret; + struct clk clk; const char *mmu; - dev_read_u32(dev, "clock-frequency", (u32 *)&info->cpu_freq); + /* Zero out the frequency, in case sizeof(ulong) != sizeof(u32) */ + info->cpu_freq = 0; + + /* First try getting the frequency from the assigned clock */ + ret = clk_get_by_index(dev, 0, &clk); + if (!ret) { + ret = clk_get_rate(&clk); + if (!IS_ERR_VALUE(ret)) + info->cpu_freq = ret; + clk_free(&clk); + } + + if (!info->cpu_freq) + dev_read_u32(dev, "clock-frequency", (u32 *)&info->cpu_freq); mmu = dev_read_string(dev, "mmu-type"); if (!mmu) -- cgit v1.1 From 627718626b05f715da555cc005426ab10f44bb98 Mon Sep 17 00:00:00 2001 From: Sean Anderson Date: Wed, 24 Jun 2020 06:41:22 -0400 Subject: riscv: Enable cpu clock if it is present The cpu clock is probably already enabled if we are executing code (though we could be executing from a different core). This patch prevents the cpu clock or its parents from being disabled. Signed-off-by: Sean Anderson Reviewed-by: Bin Meng --- drivers/cpu/riscv_cpu.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'drivers') diff --git a/drivers/cpu/riscv_cpu.c b/drivers/cpu/riscv_cpu.c index 2d44d1c..76b0489 100644 --- a/drivers/cpu/riscv_cpu.c +++ b/drivers/cpu/riscv_cpu.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0+ /* * Copyright (C) 2018, Bin Meng + * Copyright (C) 2020, Sean Anderson */ #include @@ -119,6 +120,24 @@ static int riscv_cpu_bind(struct udevice *dev) return 0; } +static int riscv_cpu_probe(struct udevice *dev) +{ + int ret = 0; + struct clk clk; + + /* Get a clock if it exists */ + ret = clk_get_by_index(dev, 0, &clk); + if (ret) + return 0; + + ret = clk_enable(&clk); + clk_free(&clk); + if (ret == -ENOSYS || ret == -ENOTSUPP) + return 0; + else + return ret; +} + static const struct cpu_ops riscv_cpu_ops = { .get_desc = riscv_cpu_get_desc, .get_info = riscv_cpu_get_info, @@ -135,6 +154,7 @@ U_BOOT_DRIVER(riscv_cpu) = { .id = UCLASS_CPU, .of_match = riscv_cpu_ids, .bind = riscv_cpu_bind, + .probe = riscv_cpu_probe, .ops = &riscv_cpu_ops, .flags = DM_FLAG_PRE_RELOC, }; -- cgit v1.1 From 969251a5a4d3515abc233621bc8ca6f1c93d6dd4 Mon Sep 17 00:00:00 2001 From: Sagar Shrikant Kadam Date: Sun, 28 Jun 2020 07:45:01 -0700 Subject: uclass: cpu: fix to display proper CPU features The cmd "cpu detail" fetches uninitialized cpu feature information and thus displays wrong / inconsitent details as below. For eg: FU540-C000 doesn't have any microcode, yet the cmd display's it. => cpu detail 1: cpu@1 rv64imafdc ID = 1, freq = 999.100 MHz: L1 cache, MMU, Microcode, Device ID Microcode version 0x0 Device ID 0x0 2: cpu@2 rv64imafdc ID = 2, freq = 999.100 MHz: L1 cache, MMU, Microcode, Device ID Microcode version 0x0 Device ID 0x0 3: cpu@3 rv64imafdc ID = 3, freq = 999.100 MHz: L1 cache, MMU, Microcode, Device ID Microcode version 0x0 Device ID 0x0 4: cpu@4 rv64imafdc ID = 4, freq = 999.100 MHz: L1 cache, MMU, Microcode, Device ID Microcode version 0x0 Device ID 0x0 The L1 cache or MMU entry seen above is also displayed inconsistently. So initialize cpu information to zero into cpu-uclass itself so that similar issues can be avoided for other CPU drivers. We now see correct features as: => cpu detail 1: cpu@1 rv64imafdc ID = 1, freq = 999.100 MHz 2: cpu@2 rv64imafdc ID = 2, freq = 999.100 MHz 3: cpu@3 rv64imafdc ID = 3, freq = 999.100 MHz 4: cpu@4 rv64imafdc ID = 4, freq = 999.100 MHz Signed-off-by: Sagar Shrikant Kadam Reviewed-by: Pragnesh Patel Reviewed-by: Bin Meng --- drivers/cpu/cpu-uclass.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/cpu/cpu-uclass.c b/drivers/cpu/cpu-uclass.c index 7418c26..cbb4419 100644 --- a/drivers/cpu/cpu-uclass.c +++ b/drivers/cpu/cpu-uclass.c @@ -86,6 +86,9 @@ int cpu_get_info(struct udevice *dev, struct cpu_info *info) if (!ops->get_info) return -ENOSYS; + /* Init cpu_info to 0 */ + memset(info, 0, sizeof(struct cpu_info)); + return ops->get_info(dev, info); } -- cgit v1.1 From b6b233ddb78205abc76dde60179bd129368dc3e8 Mon Sep 17 00:00:00 2001 From: Sagar Shrikant Kadam Date: Sun, 28 Jun 2020 07:45:02 -0700 Subject: riscv: cpu: correctly handle the setting of CPU_FEAT_MMU bit The conditional check to read "mmu-type" from the device tree is not rightly handled due to which the cpu feature doesn't include CPU_FEAT_MMU even if it's corresponding entry is present in the device tree. The initialization of cpu features is now taken care in cpu-uclass driver, so no need to zero out cpu_freq in riscv_cpu driver and can be removed. Signed-off-by: Sagar Shrikant Kadam Reviewed-by: Pragnesh Patel Reviewed-by: Bin Meng --- drivers/cpu/riscv_cpu.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/cpu/riscv_cpu.c b/drivers/cpu/riscv_cpu.c index 76b0489..112690f 100644 --- a/drivers/cpu/riscv_cpu.c +++ b/drivers/cpu/riscv_cpu.c @@ -36,9 +36,6 @@ static int riscv_cpu_get_info(struct udevice *dev, struct cpu_info *info) struct clk clk; const char *mmu; - /* Zero out the frequency, in case sizeof(ulong) != sizeof(u32) */ - info->cpu_freq = 0; - /* First try getting the frequency from the assigned clock */ ret = clk_get_by_index(dev, 0, &clk); if (!ret) { @@ -52,7 +49,7 @@ static int riscv_cpu_get_info(struct udevice *dev, struct cpu_info *info) dev_read_u32(dev, "clock-frequency", (u32 *)&info->cpu_freq); mmu = dev_read_string(dev, "mmu-type"); - if (!mmu) + if (mmu) info->features |= BIT(CPU_FEAT_MMU); return 0; -- cgit v1.1 From add0dc1f7de91112d9e738f9482b09b75fa86acb Mon Sep 17 00:00:00 2001 From: Sagar Shrikant Kadam Date: Sun, 28 Jun 2020 07:45:03 -0700 Subject: riscv: cpu: check and append L1 cache to cpu features All cpu cores within FU540-C000 having split I/D caches. Set the L1 cache feature bit using the i-cache-size or d-cache-size as one of the property from device tree indicating that L1 cache is present on the cpu core. => cpu detail 1: cpu@1 rv64imafdc ID = 1, freq = 999.100 MHz: L1 cache, MMU 2: cpu@2 rv64imafdc ID = 2, freq = 999.100 MHz: L1 cache, MMU 3: cpu@3 rv64imafdc ID = 3, freq = 999.100 MHz: L1 cache, MMU 4: cpu@4 rv64imafdc ID = 4, freq = 999.100 MHz: L1 cache, MMU Signed-off-by: Sagar Shrikant Kadam Reviewed-by: Pragnesh Patel Reviewed-by: Bin Meng --- drivers/cpu/riscv_cpu.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'drivers') diff --git a/drivers/cpu/riscv_cpu.c b/drivers/cpu/riscv_cpu.c index 112690f..100fe55 100644 --- a/drivers/cpu/riscv_cpu.c +++ b/drivers/cpu/riscv_cpu.c @@ -35,6 +35,8 @@ static int riscv_cpu_get_info(struct udevice *dev, struct cpu_info *info) int ret; struct clk clk; const char *mmu; + u32 i_cache_size; + u32 d_cache_size; /* First try getting the frequency from the assigned clock */ ret = clk_get_by_index(dev, 0, &clk); @@ -52,6 +54,16 @@ static int riscv_cpu_get_info(struct udevice *dev, struct cpu_info *info) if (mmu) info->features |= BIT(CPU_FEAT_MMU); + /* check if I cache is present */ + ret = dev_read_u32(dev, "i-cache-size", &i_cache_size); + if (ret) + /* if not found check if d-cache is present */ + ret = dev_read_u32(dev, "d-cache-size", &d_cache_size); + + /* if either I or D cache is present set L1 cache feature */ + if (!ret) + info->features |= BIT(CPU_FEAT_L1_CACHE); + return 0; } -- cgit v1.1 From 8214791daa290119243134fcfbebe631fd0ed249 Mon Sep 17 00:00:00 2001 From: Tom Rini Date: Wed, 1 Jul 2020 11:46:45 -0400 Subject: pci: rockchip: Mark inline functions as static inline Unless we mark the function as 'static inline' it may end up being non-inlined by the compiled and result in duplicate functions. Cc: Jagan Teki Cc: Kever Yang Signed-off-by: Tom Rini --- drivers/pci/pcie_rockchip.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/pcie_rockchip.h b/drivers/pci/pcie_rockchip.h index c3a0a28..845d505 100644 --- a/drivers/pci/pcie_rockchip.h +++ b/drivers/pci/pcie_rockchip.h @@ -130,13 +130,12 @@ struct rockchip_pcie { int rockchip_pcie_phy_get(struct udevice *dev); -inline struct rockchip_pcie_phy *pcie_get_phy(struct rockchip_pcie *pcie) +static inline struct rockchip_pcie_phy *pcie_get_phy(struct rockchip_pcie *pcie) { return pcie->phy; } -inline -struct rockchip_pcie_phy_ops *phy_get_ops(struct rockchip_pcie_phy *phy) +static inline struct rockchip_pcie_phy_ops *phy_get_ops(struct rockchip_pcie_phy *phy) { return (struct rockchip_pcie_phy_ops *)phy->ops; } -- cgit v1.1