2019-10-09 10:18:54

by Thomas Bogendoerfer

[permalink] [raw]
Subject: [PATCH v7 0/5] Use MFD framework for SGI IOC3 drivers

SGI IOC3 ASIC includes support for ethernet, PS2 keyboard/mouse,
NIC (number in a can), GPIO and a byte bus. By attaching a
SuperIO chip to it, it also supports serial lines and a parallel
port. The chip is used on a variety of SGI systems with different
configurations. This patchset moves code out of the network driver,
which doesn't belong there, into its new place a MFD driver and
specific platform drivers for the different subfunctions.

Changes in v8:
- Re-worked comments in drivers/mfd/ioc3.c
- Added select CRC16 to ioc3-eth.c
- Patches 1 and 2 are already taken to mips-next, but
for completeness of the series they are still included.
What's missing to get the remaining 3 patches via the MIPS
tree is an ack from a network maintainer

Changes in v7:
- added patch to enable ethernet phy for Origin 200 systems
- depend on 64bit for ioc3 mfd driver

Changes in v6:
- dropped patches accepted for v5.4-rc1
- moved serio patch to ip30 patch series
- adapted nvmem patch

Changes in v5:
- requested by Jakub I've splited ioc3 ethernet driver changes into
more steps to make the transition more visible; on the way there
I've "checkpatched" the driver and reduced code reorderings
- dropped all uint16_t and uint32_t
- added nvmem API extension to the documenation file
- changed to use request_irq/free_irq in serio driver
- removed wrong kfree() in serio error path

Changes in v4:
- added w1 drivers to the series after merge in 5.3 failed because
of no response from maintainer and other parts of this series
won't work without that drivers
- moved ip30 systemboard support to the ip30 series, which will
deal with rtc oddity Lee found
- converted to use devm_platform_ioremap_resource
- use PLATFORM_DEVID_AUTO for serial, ethernet and serio in mfd driver
- fixed reverse christmas order in ioc3-eth.c
- formating issue found by Lee
- re-worked irq request/free in serio driver to avoid crashes during
probe/remove

Changes in v3:
- use 1-wire subsystem for handling proms
- pci-xtalk driver uses prom information to create PCI subsystem
ids for use in MFD driver
- changed MFD driver to only use static declared mfd_cells
- added IP30 system board setup to MFD driver
- mac address is now read from ioc3-eth driver with nvmem framework

Changes in v2:
- fixed issue in ioc3kbd.c reported by Dmitry Torokhov
- merged IP27 RTC removal and 8250 serial driver addition into
main MFD patch to keep patches bisectable

Thomas Bogendoerfer (5):
nvmem: core: add nvmem_device_find
MIPS: PCI: use information from 1-wire PROM for IOC3 detection
mfd: ioc3: Add driver for SGI IOC3 chip
MIPS: SGI-IP27: fix readb/writeb addressing
MIPS: SGI-IP27: Enable ethernet phy on second Origin 200 module

Documentation/driver-api/nvmem.rst | 2 +
arch/mips/include/asm/mach-ip27/mangle-port.h | 4 +-
arch/mips/include/asm/pci/bridge.h | 1 +
arch/mips/include/asm/sn/ioc3.h | 47 +-
arch/mips/pci/pci-ip27.c | 22 +
arch/mips/pci/pci-xtalk-bridge.c | 135 +++++-
arch/mips/sgi-ip27/ip27-timer.c | 20 -
arch/mips/sgi-ip27/ip27-xtalk.c | 38 +-
drivers/mfd/Kconfig | 13 +
drivers/mfd/Makefile | 1 +
drivers/mfd/ioc3.c | 588 ++++++++++++++++++++++++++
drivers/net/ethernet/sgi/Kconfig | 5 +-
drivers/net/ethernet/sgi/ioc3-eth.c | 561 +++++-------------------
drivers/nvmem/core.c | 61 ++-
drivers/rtc/rtc-m48t35.c | 11 +
drivers/tty/serial/8250/8250_ioc3.c | 98 +++++
drivers/tty/serial/8250/Kconfig | 11 +
drivers/tty/serial/8250/Makefile | 1 +
include/linux/nvmem-consumer.h | 9 +
19 files changed, 1080 insertions(+), 548 deletions(-)
create mode 100644 drivers/mfd/ioc3.c
create mode 100644 drivers/tty/serial/8250/8250_ioc3.c

--
2.16.4


2019-10-09 10:18:58

by Thomas Bogendoerfer

[permalink] [raw]
Subject: [PATCH v8 1/5] nvmem: core: add nvmem_device_find

nvmem_device_find provides a way to search for nvmem devices with
the help of a match function simlair to bus_find_device.

Reviewed-by: Srinivas Kandagatla <[email protected]>
Acked-by: Srinivas Kandagatla <[email protected]>
Signed-off-by: Thomas Bogendoerfer <[email protected]>
---
Documentation/driver-api/nvmem.rst | 2 ++
drivers/nvmem/core.c | 61 +++++++++++++++++---------------------
include/linux/nvmem-consumer.h | 9 ++++++
3 files changed, 38 insertions(+), 34 deletions(-)

diff --git a/Documentation/driver-api/nvmem.rst b/Documentation/driver-api/nvmem.rst
index d9d958d5c824..287e86819640 100644
--- a/Documentation/driver-api/nvmem.rst
+++ b/Documentation/driver-api/nvmem.rst
@@ -129,6 +129,8 @@ To facilitate such consumers NVMEM framework provides below apis::
struct nvmem_device *nvmem_device_get(struct device *dev, const char *name);
struct nvmem_device *devm_nvmem_device_get(struct device *dev,
const char *name);
+ struct nvmem_device *nvmem_device_find(void *data,
+ int (*match)(struct device *dev, const void *data));
void nvmem_device_put(struct nvmem_device *nvmem);
int nvmem_device_read(struct nvmem_device *nvmem, unsigned int offset,
size_t bytes, void *buf);
diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
index 057d1ff87d5d..9f1ee9c766ec 100644
--- a/drivers/nvmem/core.c
+++ b/drivers/nvmem/core.c
@@ -76,33 +76,6 @@ static struct bus_type nvmem_bus_type = {
.name = "nvmem",
};

-static struct nvmem_device *of_nvmem_find(struct device_node *nvmem_np)
-{
- struct device *d;
-
- if (!nvmem_np)
- return NULL;
-
- d = bus_find_device_by_of_node(&nvmem_bus_type, nvmem_np);
-
- if (!d)
- return NULL;
-
- return to_nvmem_device(d);
-}
-
-static struct nvmem_device *nvmem_find(const char *name)
-{
- struct device *d;
-
- d = bus_find_device_by_name(&nvmem_bus_type, NULL, name);
-
- if (!d)
- return NULL;
-
- return to_nvmem_device(d);
-}
-
static void nvmem_cell_drop(struct nvmem_cell *cell)
{
blocking_notifier_call_chain(&nvmem_notifier, NVMEM_CELL_REMOVE, cell);
@@ -532,13 +505,16 @@ int devm_nvmem_unregister(struct device *dev, struct nvmem_device *nvmem)
}
EXPORT_SYMBOL(devm_nvmem_unregister);

-static struct nvmem_device *__nvmem_device_get(struct device_node *np,
- const char *nvmem_name)
+static struct nvmem_device *__nvmem_device_get(void *data,
+ int (*match)(struct device *dev, const void *data))
{
struct nvmem_device *nvmem = NULL;
+ struct device *dev;

mutex_lock(&nvmem_mutex);
- nvmem = np ? of_nvmem_find(np) : nvmem_find(nvmem_name);
+ dev = bus_find_device(&nvmem_bus_type, NULL, data, match);
+ if (dev)
+ nvmem = to_nvmem_device(dev);
mutex_unlock(&nvmem_mutex);
if (!nvmem)
return ERR_PTR(-EPROBE_DEFER);
@@ -587,7 +563,7 @@ struct nvmem_device *of_nvmem_device_get(struct device_node *np, const char *id)
if (!nvmem_np)
return ERR_PTR(-ENOENT);

- return __nvmem_device_get(nvmem_np, NULL);
+ return __nvmem_device_get(nvmem_np, device_match_of_node);
}
EXPORT_SYMBOL_GPL(of_nvmem_device_get);
#endif
@@ -613,10 +589,26 @@ struct nvmem_device *nvmem_device_get(struct device *dev, const char *dev_name)

}

- return __nvmem_device_get(NULL, dev_name);
+ return __nvmem_device_get((void *)dev_name, device_match_name);
}
EXPORT_SYMBOL_GPL(nvmem_device_get);

+/**
+ * nvmem_device_find() - Find nvmem device with matching function
+ *
+ * @data: Data to pass to match function
+ * @match: Callback function to check device
+ *
+ * Return: ERR_PTR() on error or a valid pointer to a struct nvmem_device
+ * on success.
+ */
+struct nvmem_device *nvmem_device_find(void *data,
+ int (*match)(struct device *dev, const void *data))
+{
+ return __nvmem_device_get(data, match);
+}
+EXPORT_SYMBOL_GPL(nvmem_device_find);
+
static int devm_nvmem_device_match(struct device *dev, void *res, void *data)
{
struct nvmem_device **nvmem = res;
@@ -710,7 +702,8 @@ nvmem_cell_get_from_lookup(struct device *dev, const char *con_id)
if ((strcmp(lookup->dev_id, dev_id) == 0) &&
(strcmp(lookup->con_id, con_id) == 0)) {
/* This is the right entry. */
- nvmem = __nvmem_device_get(NULL, lookup->nvmem_name);
+ nvmem = __nvmem_device_get((void *)lookup->nvmem_name,
+ device_match_name);
if (IS_ERR(nvmem)) {
/* Provider may not be registered yet. */
cell = ERR_CAST(nvmem);
@@ -780,7 +773,7 @@ struct nvmem_cell *of_nvmem_cell_get(struct device_node *np, const char *id)
if (!nvmem_np)
return ERR_PTR(-EINVAL);

- nvmem = __nvmem_device_get(nvmem_np, NULL);
+ nvmem = __nvmem_device_get(nvmem_np, device_match_of_node);
of_node_put(nvmem_np);
if (IS_ERR(nvmem))
return ERR_CAST(nvmem);
diff --git a/include/linux/nvmem-consumer.h b/include/linux/nvmem-consumer.h
index 8f8be5b00060..02dc4aa992b2 100644
--- a/include/linux/nvmem-consumer.h
+++ b/include/linux/nvmem-consumer.h
@@ -89,6 +89,9 @@ void nvmem_del_cell_lookups(struct nvmem_cell_lookup *entries,
int nvmem_register_notifier(struct notifier_block *nb);
int nvmem_unregister_notifier(struct notifier_block *nb);

+struct nvmem_device *nvmem_device_find(void *data,
+ int (*match)(struct device *dev, const void *data));
+
#else

static inline struct nvmem_cell *nvmem_cell_get(struct device *dev,
@@ -204,6 +207,12 @@ static inline int nvmem_unregister_notifier(struct notifier_block *nb)
return -EOPNOTSUPP;
}

+static inline struct nvmem_device *nvmem_device_find(void *data,
+ int (*match)(struct device *dev, const void *data))
+{
+ return NULL;
+}
+
#endif /* CONFIG_NVMEM */

#if IS_ENABLED(CONFIG_NVMEM) && IS_ENABLED(CONFIG_OF)
--
2.16.4

2019-10-09 10:20:08

by Thomas Bogendoerfer

[permalink] [raw]
Subject: [PATCH v8 2/5] MIPS: PCI: use information from 1-wire PROM for IOC3 detection

IOC3 chips in SGI system are conntected to a bridge ASIC, which has
a 1-wire prom attached with part number information. This changeset
uses this information to create PCI subsystem information, which
the MFD driver uses for further platform device setup.

Signed-off-by: Thomas Bogendoerfer <[email protected]>
---
arch/mips/include/asm/pci/bridge.h | 1 +
arch/mips/include/asm/sn/ioc3.h | 9 +++
arch/mips/pci/pci-xtalk-bridge.c | 135 ++++++++++++++++++++++++++++++++++++-
arch/mips/sgi-ip27/ip27-xtalk.c | 38 +++++++++--
4 files changed, 175 insertions(+), 8 deletions(-)

diff --git a/arch/mips/include/asm/pci/bridge.h b/arch/mips/include/asm/pci/bridge.h
index a92cd30b48c9..3bc630ff9ad4 100644
--- a/arch/mips/include/asm/pci/bridge.h
+++ b/arch/mips/include/asm/pci/bridge.h
@@ -807,6 +807,7 @@ struct bridge_controller {
unsigned long intr_addr;
struct irq_domain *domain;
unsigned int pci_int[8];
+ u32 ioc3_sid[8];
nasid_t nasid;
};

diff --git a/arch/mips/include/asm/sn/ioc3.h b/arch/mips/include/asm/sn/ioc3.h
index a947eed48fee..78ef760ddde4 100644
--- a/arch/mips/include/asm/sn/ioc3.h
+++ b/arch/mips/include/asm/sn/ioc3.h
@@ -590,4 +590,13 @@ struct ioc3_etxd {

#define MIDR_DATA_MASK 0x0000ffff

+/* subsystem IDs supplied by card detection in pci-xtalk-bridge */
+#define IOC3_SUBSYS_IP27_BASEIO6G 0xc300
+#define IOC3_SUBSYS_IP27_MIO 0xc301
+#define IOC3_SUBSYS_IP27_BASEIO 0xc302
+#define IOC3_SUBSYS_IP29_SYSBOARD 0xc303
+#define IOC3_SUBSYS_IP30_SYSBOARD 0xc304
+#define IOC3_SUBSYS_MENET 0xc305
+#define IOC3_SUBSYS_MENET4 0xc306
+
#endif /* MIPS_SN_IOC3_H */
diff --git a/arch/mips/pci/pci-xtalk-bridge.c b/arch/mips/pci/pci-xtalk-bridge.c
index 7b4d40354ee7..dcf6117a17c3 100644
--- a/arch/mips/pci/pci-xtalk-bridge.c
+++ b/arch/mips/pci/pci-xtalk-bridge.c
@@ -11,16 +11,22 @@
#include <linux/dma-direct.h>
#include <linux/platform_device.h>
#include <linux/platform_data/xtalk-bridge.h>
+#include <linux/nvmem-consumer.h>
+#include <linux/crc16.h>

#include <asm/pci/bridge.h>
#include <asm/paccess.h>
#include <asm/sn/irq_alloc.h>
+#include <asm/sn/ioc3.h>
+
+#define CRC16_INIT 0
+#define CRC16_VALID 0xb001

/*
* Most of the IOC3 PCI config register aren't present
* we emulate what is needed for a normal PCI enumeration
*/
-static int ioc3_cfg_rd(void *addr, int where, int size, u32 *value)
+static int ioc3_cfg_rd(void *addr, int where, int size, u32 *value, u32 sid)
{
u32 cf, shift, mask;

@@ -30,6 +36,9 @@ static int ioc3_cfg_rd(void *addr, int where, int size, u32 *value)
if (get_dbe(cf, (u32 *)addr))
return PCIBIOS_DEVICE_NOT_FOUND;
break;
+ case 0x2c:
+ cf = sid;
+ break;
case 0x3c:
/* emulate sane interrupt pin value */
cf = 0x00000100;
@@ -111,7 +120,8 @@ static int pci_conf0_read_config(struct pci_bus *bus, unsigned int devfn,
*/
if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16))) {
addr = &bridge->b_type0_cfg_dev[slot].f[fn].l[where >> 2];
- return ioc3_cfg_rd(addr, where, size, value);
+ return ioc3_cfg_rd(addr, where, size, value,
+ bc->ioc3_sid[slot]);
}

addr = &bridge->b_type0_cfg_dev[slot].f[fn].c[where ^ (4 - size)];
@@ -149,7 +159,8 @@ static int pci_conf1_read_config(struct pci_bus *bus, unsigned int devfn,
*/
if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16))) {
addr = &bridge->b_type1_cfg.c[(fn << 8) | (where & ~3)];
- return ioc3_cfg_rd(addr, where, size, value);
+ return ioc3_cfg_rd(addr, where, size, value,
+ bc->ioc3_sid[slot]);
}

addr = &bridge->b_type1_cfg.c[(fn << 8) | (where ^ (4 - size))];
@@ -426,6 +437,117 @@ static int bridge_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
return irq;
}

+#define IOC3_SID(sid) (PCI_VENDOR_ID_SGI << 16 | (sid))
+
+static void bridge_setup_ip27_baseio6g(struct bridge_controller *bc)
+{
+ bc->ioc3_sid[2] = IOC3_SID(IOC3_SUBSYS_IP27_BASEIO6G);
+ bc->ioc3_sid[6] = IOC3_SID(IOC3_SUBSYS_IP27_MIO);
+}
+
+static void bridge_setup_ip27_baseio(struct bridge_controller *bc)
+{
+ bc->ioc3_sid[2] = IOC3_SID(IOC3_SUBSYS_IP27_BASEIO);
+}
+
+static void bridge_setup_ip29_baseio(struct bridge_controller *bc)
+{
+ bc->ioc3_sid[2] = IOC3_SID(IOC3_SUBSYS_IP29_SYSBOARD);
+}
+
+static void bridge_setup_ip30_sysboard(struct bridge_controller *bc)
+{
+ bc->ioc3_sid[2] = IOC3_SID(IOC3_SUBSYS_IP30_SYSBOARD);
+}
+
+static void bridge_setup_menet(struct bridge_controller *bc)
+{
+ bc->ioc3_sid[0] = IOC3_SID(IOC3_SUBSYS_MENET);
+ bc->ioc3_sid[1] = IOC3_SID(IOC3_SUBSYS_MENET);
+ bc->ioc3_sid[2] = IOC3_SID(IOC3_SUBSYS_MENET);
+ bc->ioc3_sid[3] = IOC3_SID(IOC3_SUBSYS_MENET4);
+}
+
+#define BRIDGE_BOARD_SETUP(_partno, _setup) \
+ { .match = _partno, .setup = _setup }
+
+static const struct {
+ char *match;
+ void (*setup)(struct bridge_controller *bc);
+} bridge_ioc3_devid[] = {
+ BRIDGE_BOARD_SETUP("030-0734-", bridge_setup_ip27_baseio6g),
+ BRIDGE_BOARD_SETUP("030-0880-", bridge_setup_ip27_baseio6g),
+ BRIDGE_BOARD_SETUP("030-1023-", bridge_setup_ip27_baseio),
+ BRIDGE_BOARD_SETUP("030-1124-", bridge_setup_ip27_baseio),
+ BRIDGE_BOARD_SETUP("030-1025-", bridge_setup_ip29_baseio),
+ BRIDGE_BOARD_SETUP("030-1244-", bridge_setup_ip29_baseio),
+ BRIDGE_BOARD_SETUP("030-1389-", bridge_setup_ip29_baseio),
+ BRIDGE_BOARD_SETUP("030-0887-", bridge_setup_ip30_sysboard),
+ BRIDGE_BOARD_SETUP("030-1467-", bridge_setup_ip30_sysboard),
+ BRIDGE_BOARD_SETUP("030-0873-", bridge_setup_menet),
+};
+
+static void bridge_setup_board(struct bridge_controller *bc, char *partnum)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(bridge_ioc3_devid); i++)
+ if (!strncmp(partnum, bridge_ioc3_devid[i].match,
+ strlen(bridge_ioc3_devid[i].match))) {
+ bridge_ioc3_devid[i].setup(bc);
+ }
+}
+
+static int bridge_nvmem_match(struct device *dev, const void *data)
+{
+ const char *name = dev_name(dev);
+ const char *prefix = data;
+
+ if (strlen(name) < strlen(prefix))
+ return 0;
+
+ return memcmp(prefix, dev_name(dev), strlen(prefix)) == 0;
+}
+
+static int bridge_get_partnum(u64 baddr, char *partnum)
+{
+ struct nvmem_device *nvmem;
+ char prefix[24];
+ u8 prom[64];
+ int i, j;
+ int ret;
+
+ snprintf(prefix, sizeof(prefix), "bridge-%012llx-0b-", baddr);
+
+ nvmem = nvmem_device_find(prefix, bridge_nvmem_match);
+ if (IS_ERR(nvmem))
+ return PTR_ERR(nvmem);
+
+ ret = nvmem_device_read(nvmem, 0, 64, prom);
+ nvmem_device_put(nvmem);
+
+ if (ret != 64)
+ return ret;
+
+ if (crc16(CRC16_INIT, prom, 32) != CRC16_VALID ||
+ crc16(CRC16_INIT, prom + 32, 32) != CRC16_VALID)
+ return -EINVAL;
+
+ /* Assemble part number */
+ j = 0;
+ for (i = 0; i < 19; i++)
+ if (prom[i + 11] != ' ')
+ partnum[j++] = prom[i + 11];
+
+ for (i = 0; i < 6; i++)
+ if (prom[i + 32] != ' ')
+ partnum[j++] = prom[i + 32];
+
+ partnum[j] = 0;
+
+ return 0;
+}
+
static int bridge_probe(struct platform_device *pdev)
{
struct xtalk_bridge_platform_data *bd = dev_get_platdata(&pdev->dev);
@@ -434,9 +556,14 @@ static int bridge_probe(struct platform_device *pdev)
struct pci_host_bridge *host;
struct irq_domain *domain, *parent;
struct fwnode_handle *fn;
+ char partnum[26];
int slot;
int err;

+ /* get part number from one wire prom */
+ if (bridge_get_partnum(virt_to_phys((void *)bd->bridge_addr), partnum))
+ return -EPROBE_DEFER; /* not available yet */
+
parent = irq_get_default_host();
if (!parent)
return -ENODEV;
@@ -517,6 +644,8 @@ static int bridge_probe(struct platform_device *pdev)
}
bridge_read(bc, b_wid_tflush); /* wait until Bridge PIO complete */

+ bridge_setup_board(bc, partnum);
+
host->dev.parent = dev;
host->sysdata = bc;
host->busnr = 0;
diff --git a/arch/mips/sgi-ip27/ip27-xtalk.c b/arch/mips/sgi-ip27/ip27-xtalk.c
index 4a1f0b0c29e2..9b7524362a11 100644
--- a/arch/mips/sgi-ip27/ip27-xtalk.c
+++ b/arch/mips/sgi-ip27/ip27-xtalk.c
@@ -10,6 +10,7 @@
#include <linux/kernel.h>
#include <linux/smp.h>
#include <linux/platform_device.h>
+#include <linux/platform_data/sgi-w1.h>
#include <linux/platform_data/xtalk-bridge.h>
#include <asm/sn/addrs.h>
#include <asm/sn/types.h>
@@ -26,9 +27,35 @@
static void bridge_platform_create(nasid_t nasid, int widget, int masterwid)
{
struct xtalk_bridge_platform_data *bd;
+ struct sgi_w1_platform_data *wd;
struct platform_device *pdev;
+ struct resource w1_res;
unsigned long offset;

+ offset = NODE_OFFSET(nasid);
+
+ wd = kzalloc(sizeof(*wd), GFP_KERNEL);
+ if (!wd)
+ goto no_mem;
+
+ snprintf(wd->dev_id, sizeof(wd->dev_id), "bridge-%012lx",
+ offset + (widget << SWIN_SIZE_BITS));
+
+ memset(&w1_res, 0, sizeof(w1_res));
+ w1_res.start = offset + (widget << SWIN_SIZE_BITS) +
+ offsetof(struct bridge_regs, b_nic);
+ w1_res.end = w1_res.start + 3;
+ w1_res.flags = IORESOURCE_MEM;
+
+ pdev = platform_device_alloc("sgi_w1", PLATFORM_DEVID_AUTO);
+ if (!pdev) {
+ kfree(wd);
+ goto no_mem;
+ }
+ platform_device_add_resources(pdev, &w1_res, 1);
+ platform_device_add_data(pdev, wd, sizeof(*wd));
+ platform_device_add(pdev);
+
bd = kzalloc(sizeof(*bd), GFP_KERNEL);
if (!bd)
goto no_mem;
@@ -38,7 +65,6 @@ static void bridge_platform_create(nasid_t nasid, int widget, int masterwid)
goto no_mem;
}

- offset = NODE_OFFSET(nasid);

bd->bridge_addr = RAW_NODE_SWIN_BASE(nasid, widget);
bd->intr_addr = BIT_ULL(47) + 0x01800000 + PI_INT_PEND_MOD;
@@ -46,14 +72,14 @@ static void bridge_platform_create(nasid_t nasid, int widget, int masterwid)
bd->masterwid = masterwid;

bd->mem.name = "Bridge PCI MEM";
- bd->mem.start = offset + (widget << SWIN_SIZE_BITS);
- bd->mem.end = bd->mem.start + SWIN_SIZE - 1;
+ bd->mem.start = offset + (widget << SWIN_SIZE_BITS) + BRIDGE_DEVIO0;
+ bd->mem.end = offset + (widget << SWIN_SIZE_BITS) + SWIN_SIZE - 1;
bd->mem.flags = IORESOURCE_MEM;
bd->mem_offset = offset;

bd->io.name = "Bridge PCI IO";
- bd->io.start = offset + (widget << SWIN_SIZE_BITS);
- bd->io.end = bd->io.start + SWIN_SIZE - 1;
+ bd->io.start = offset + (widget << SWIN_SIZE_BITS) + BRIDGE_DEVIO0;
+ bd->io.end = offset + (widget << SWIN_SIZE_BITS) + SWIN_SIZE - 1;
bd->io.flags = IORESOURCE_IO;
bd->io_offset = offset;

@@ -81,6 +107,8 @@ static int probe_one_port(nasid_t nasid, int widget, int masterwid)
bridge_platform_create(nasid, widget, masterwid);
break;
default:
+ pr_info("xtalk:n%d/%d unknown widget (0x%x)\n",
+ nasid, widget, partnum);
break;
}

--
2.16.4

2019-10-09 12:28:09

by Philippe Mathieu-Daudé

[permalink] [raw]
Subject: Re: [PATCH v8 2/5] MIPS: PCI: use information from 1-wire PROM for IOC3 detection

On 10/9/19 12:17 PM, Thomas Bogendoerfer wrote:
> IOC3 chips in SGI system are conntected to a bridge ASIC, which has

Typo: "connected".

> a 1-wire prom attached with part number information. This changeset
> uses this information to create PCI subsystem information, which
> the MFD driver uses for further platform device setup.
>
> Signed-off-by: Thomas Bogendoerfer <[email protected]>
> ---
> arch/mips/include/asm/pci/bridge.h | 1 +
> arch/mips/include/asm/sn/ioc3.h | 9 +++
> arch/mips/pci/pci-xtalk-bridge.c | 135 ++++++++++++++++++++++++++++++++++++-
> arch/mips/sgi-ip27/ip27-xtalk.c | 38 +++++++++--
> 4 files changed, 175 insertions(+), 8 deletions(-)

2019-10-09 12:34:47

by Philippe Mathieu-Daudé

[permalink] [raw]
Subject: Re: [PATCH v8 1/5] nvmem: core: add nvmem_device_find

On 10/9/19 12:17 PM, Thomas Bogendoerfer wrote:
> nvmem_device_find provides a way to search for nvmem devices with
> the help of a match function simlair to bus_find_device.
>
> Reviewed-by: Srinivas Kandagatla <[email protected]>
> Acked-by: Srinivas Kandagatla <[email protected]>
> Signed-off-by: Thomas Bogendoerfer <[email protected]>
> ---
> Documentation/driver-api/nvmem.rst | 2 ++
> drivers/nvmem/core.c | 61 +++++++++++++++++---------------------
> include/linux/nvmem-consumer.h | 9 ++++++
> 3 files changed, 38 insertions(+), 34 deletions(-)
>
> diff --git a/Documentation/driver-api/nvmem.rst b/Documentation/driver-api/nvmem.rst
> index d9d958d5c824..287e86819640 100644
> --- a/Documentation/driver-api/nvmem.rst
> +++ b/Documentation/driver-api/nvmem.rst
> @@ -129,6 +129,8 @@ To facilitate such consumers NVMEM framework provides below apis::
> struct nvmem_device *nvmem_device_get(struct device *dev, const char *name);
> struct nvmem_device *devm_nvmem_device_get(struct device *dev,
> const char *name);
> + struct nvmem_device *nvmem_device_find(void *data,
> + int (*match)(struct device *dev, const void *data));
> void nvmem_device_put(struct nvmem_device *nvmem);
> int nvmem_device_read(struct nvmem_device *nvmem, unsigned int offset,
> size_t bytes, void *buf);
> diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
> index 057d1ff87d5d..9f1ee9c766ec 100644
> --- a/drivers/nvmem/core.c
> +++ b/drivers/nvmem/core.c
> @@ -76,33 +76,6 @@ static struct bus_type nvmem_bus_type = {
> .name = "nvmem",
> };
>
> -static struct nvmem_device *of_nvmem_find(struct device_node *nvmem_np)
> -{
> - struct device *d;
> -
> - if (!nvmem_np)
> - return NULL;
> -
> - d = bus_find_device_by_of_node(&nvmem_bus_type, nvmem_np);
> -
> - if (!d)
> - return NULL;
> -
> - return to_nvmem_device(d);
> -}
> -
> -static struct nvmem_device *nvmem_find(const char *name)
> -{
> - struct device *d;
> -
> - d = bus_find_device_by_name(&nvmem_bus_type, NULL, name);
> -
> - if (!d)
> - return NULL;
> -
> - return to_nvmem_device(d);
> -}
> -
> static void nvmem_cell_drop(struct nvmem_cell *cell)
> {
> blocking_notifier_call_chain(&nvmem_notifier, NVMEM_CELL_REMOVE, cell);
> @@ -532,13 +505,16 @@ int devm_nvmem_unregister(struct device *dev, struct nvmem_device *nvmem)
> }
> EXPORT_SYMBOL(devm_nvmem_unregister);
>
> -static struct nvmem_device *__nvmem_device_get(struct device_node *np,
> - const char *nvmem_name)
> +static struct nvmem_device *__nvmem_device_get(void *data,
> + int (*match)(struct device *dev, const void *data))
> {
> struct nvmem_device *nvmem = NULL;
> + struct device *dev;
>
> mutex_lock(&nvmem_mutex);
> - nvmem = np ? of_nvmem_find(np) : nvmem_find(nvmem_name);
> + dev = bus_find_device(&nvmem_bus_type, NULL, data, match);
> + if (dev)
> + nvmem = to_nvmem_device(dev);
> mutex_unlock(&nvmem_mutex);
> if (!nvmem)
> return ERR_PTR(-EPROBE_DEFER);
> @@ -587,7 +563,7 @@ struct nvmem_device *of_nvmem_device_get(struct device_node *np, const char *id)
> if (!nvmem_np)
> return ERR_PTR(-ENOENT);
>
> - return __nvmem_device_get(nvmem_np, NULL);
> + return __nvmem_device_get(nvmem_np, device_match_of_node);
> }
> EXPORT_SYMBOL_GPL(of_nvmem_device_get);
> #endif
> @@ -613,10 +589,26 @@ struct nvmem_device *nvmem_device_get(struct device *dev, const char *dev_name)
>
> }
>
> - return __nvmem_device_get(NULL, dev_name);
> + return __nvmem_device_get((void *)dev_name, device_match_name);
> }
> EXPORT_SYMBOL_GPL(nvmem_device_get);
>
> +/**
> + * nvmem_device_find() - Find nvmem device with matching function
> + *
> + * @data: Data to pass to match function
> + * @match: Callback function to check device
> + *
> + * Return: ERR_PTR() on error or a valid pointer to a struct nvmem_device
> + * on success.
> + */
> +struct nvmem_device *nvmem_device_find(void *data,
> + int (*match)(struct device *dev, const void *data))
> +{
> + return __nvmem_device_get(data, match);
> +}
> +EXPORT_SYMBOL_GPL(nvmem_device_find);
> +
> static int devm_nvmem_device_match(struct device *dev, void *res, void *data)
> {
> struct nvmem_device **nvmem = res;
> @@ -710,7 +702,8 @@ nvmem_cell_get_from_lookup(struct device *dev, const char *con_id)
> if ((strcmp(lookup->dev_id, dev_id) == 0) &&
> (strcmp(lookup->con_id, con_id) == 0)) {
> /* This is the right entry. */
> - nvmem = __nvmem_device_get(NULL, lookup->nvmem_name);
> + nvmem = __nvmem_device_get((void *)lookup->nvmem_name,
> + device_match_name);
> if (IS_ERR(nvmem)) {
> /* Provider may not be registered yet. */
> cell = ERR_CAST(nvmem);
> @@ -780,7 +773,7 @@ struct nvmem_cell *of_nvmem_cell_get(struct device_node *np, const char *id)
> if (!nvmem_np)
> return ERR_PTR(-EINVAL);
>
> - nvmem = __nvmem_device_get(nvmem_np, NULL);
> + nvmem = __nvmem_device_get(nvmem_np, device_match_of_node);
> of_node_put(nvmem_np);
> if (IS_ERR(nvmem))
> return ERR_CAST(nvmem);
> diff --git a/include/linux/nvmem-consumer.h b/include/linux/nvmem-consumer.h
> index 8f8be5b00060..02dc4aa992b2 100644
> --- a/include/linux/nvmem-consumer.h
> +++ b/include/linux/nvmem-consumer.h
> @@ -89,6 +89,9 @@ void nvmem_del_cell_lookups(struct nvmem_cell_lookup *entries,
> int nvmem_register_notifier(struct notifier_block *nb);
> int nvmem_unregister_notifier(struct notifier_block *nb);
>
> +struct nvmem_device *nvmem_device_find(void *data,
> + int (*match)(struct device *dev, const void *data));
> +
> #else
>
> static inline struct nvmem_cell *nvmem_cell_get(struct device *dev,
> @@ -204,6 +207,12 @@ static inline int nvmem_unregister_notifier(struct notifier_block *nb)
> return -EOPNOTSUPP;
> }
>
> +static inline struct nvmem_device *nvmem_device_find(void *data,
> + int (*match)(struct device *dev, const void *data))
> +{
> + return NULL;
> +}
> +
> #endif /* CONFIG_NVMEM */
>
> #if IS_ENABLED(CONFIG_NVMEM) && IS_ENABLED(CONFIG_OF)
>

Reviewed-by: Philippe Mathieu-Daudé <[email protected]>