All of lore.kernel.org
 help / color / mirror / Atom feed
From: Yoshinori Sato <ysato@users.sourceforge.jp>
To: linux-sh@vger.kernel.org
Cc: "Yoshinori Sato" <ysato@users.sourceforge.jp>,
	"Lorenzo Pieralisi" <lpieralisi@kernel.org>,
	"Krzysztof Wilczyński" <kw@linux.com>,
	"Rob Herring" <robh@kernel.org>,
	"Bjorn Helgaas" <bhelgaas@google.com>,
	"Geert Uytterhoeven" <geert+renesas@glider.be>,
	"Magnus Damm" <magnus.damm@gmail.com>
Subject: [PATCH v4 12/37] pci: pci-sh7751: Add SH7751 PCI driver
Date: Tue, 14 Nov 2023 17:00:03 +0900	[thread overview]
Message-ID: <90c0f0810c778e4f515bb9d8582b501d77e2bf1a.1699856600.git.ysato@users.sourceforge.jp> (raw)
In-Reply-To: <cover.1699856600.git.ysato@users.sourceforge.jp>

Renesas SH7751 CPU Internal PCI Controller driver.

Signed-off-by: Yoshinori Sato <ysato@users.sourceforge.jp>
---
 drivers/pci/controller/Kconfig      |   9 +
 drivers/pci/controller/Makefile     |   1 +
 drivers/pci/controller/pci-sh7751.c | 293 ++++++++++++++++++++++++++++
 3 files changed, 303 insertions(+)
 create mode 100644 drivers/pci/controller/pci-sh7751.c

diff --git a/drivers/pci/controller/Kconfig b/drivers/pci/controller/Kconfig
index e534c02ee34f..a2fd917a2e03 100644
--- a/drivers/pci/controller/Kconfig
+++ b/drivers/pci/controller/Kconfig
@@ -353,6 +353,15 @@ config PCIE_XILINX_CPM
 	  Say 'Y' here if you want kernel support for the
 	  Xilinx Versal CPM host bridge.
 
+config PCI_SH7751
+	bool "Renesas SH7751 PCI controller"
+	depends on OF
+	depends on CPU_SUBTYPE_SH7751 || CPU_SUBTYPE_SH7751R || COMPILE_TEST
+	select PCI_HOST_COMMON
+	help
+	  Say 'Y' here if you want kernel to support the Renesas SH7751 PCI
+	  Host Bridge driver.
+
 source "drivers/pci/controller/cadence/Kconfig"
 source "drivers/pci/controller/dwc/Kconfig"
 source "drivers/pci/controller/mobiveil/Kconfig"
diff --git a/drivers/pci/controller/Makefile b/drivers/pci/controller/Makefile
index f2b19e6174af..aa97e5d74e58 100644
--- a/drivers/pci/controller/Makefile
+++ b/drivers/pci/controller/Makefile
@@ -40,6 +40,7 @@ obj-$(CONFIG_PCI_LOONGSON) += pci-loongson.o
 obj-$(CONFIG_PCIE_HISI_ERR) += pcie-hisi-error.o
 obj-$(CONFIG_PCIE_APPLE) += pcie-apple.o
 obj-$(CONFIG_PCIE_MT7621) += pcie-mt7621.o
+obj-$(CONFIG_PCI_SH7751) += pci-sh7751.o
 
 # pcie-hisi.o quirks are needed even without CONFIG_PCIE_DW
 obj-y				+= dwc/
diff --git a/drivers/pci/controller/pci-sh7751.c b/drivers/pci/controller/pci-sh7751.c
new file mode 100644
index 000000000000..36b4f5e9c4a9
--- /dev/null
+++ b/drivers/pci/controller/pci-sh7751.c
@@ -0,0 +1,293 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * SH7751 PCI driver
+ * Copyright (C) 2023 Yoshinori Sato
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of_pci.h>
+#include <linux/of_platform.h>
+#include <linux/pci-ecam.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <asm/pci.h>
+#include <asm/addrspace.h>
+#include <asm/pci-sh4.h>
+
+#define pcic_writel(val, base, reg) __raw_writel(val, base + (reg))
+#define pcic_readl(base, reg) __raw_readl(base + (reg))
+
+/* BSC registers offset */
+#define BSC_BCR1	0x00000000
+#define BSC_BCR2	0x00000004
+#define BSC_WCR1	0x00000008
+#define BSC_WCR2	0x0000000c
+#define BSC_WCR3	0x00000010
+#define BSC_MCR		0x00000014
+
+/*
+ * PCIC fixups
+ */
+
+static inline void pci_fixup_write_regs(struct device_node *np,
+					const char *prop,
+					void __iomem *pcic, int reg,
+					int nr_regs)
+{
+	int i;
+	u32 val;
+
+	for (i = 0; i < nr_regs; i++) {
+		if (of_property_read_u32_index(np, prop, i, &val))
+			pcic_writel(val, pcic, reg + i * 4);
+	}
+}
+
+#define SH7751_NUM_CONFIG 18
+static void pcic_fixups(struct device_node *np,
+		       void __iomem *pcic, void __iomem *bsc)
+{
+	unsigned long bcr1, mcr;
+	u32 val;
+	int i, r;
+	u32 pci_config[SH7751_NUM_CONFIG * 2];
+
+	const struct {
+		const char *name;
+		int reg;
+		int nr;
+	} reg_prop[] = {
+		/*
+		 *  The bus timing uses the bootloader settings,
+		 *  so do not change them here.
+		 */
+		{ "renesas,intm",  SH4_PCIINTM,  1, },
+		{ "renesas,aintm", SH4_PCIAINTM, 1, },
+		{ "renesas,lsr",   SH4_PCILSR0,  2, },
+		{ "renesas,lar",   SH4_PCILAR0,  2, },
+		{ "renesas,dmabt", SH4_PCIDMABT, 1, },
+		{ "renesas,pintm", SH4_PCIPINTM, 1, },
+	};
+
+	if (of_property_read_u32(np, "sh7751-pci,bcr1", &val)) {
+		bcr1 = ioread32(bsc + BSC_BCR1);
+		bcr1 |= val;
+		pcic_writel(bcr1, pcic, SH4_PCIBCR1);
+	}
+	if (of_property_read_u32(np, "renesas,clkr", &val)) {
+		val = (0xa5 << 24) | (val & 0xffffff);
+		pcic_writel(val, pcic, SH4_PCICLKR);
+	}
+	for (i = 0; i < ARRAY_SIZE(reg_prop); i++)
+		pci_fixup_write_regs(np, reg_prop[i].name, pcic,
+				     reg_prop[i].reg, reg_prop[i].nr);
+
+	memset(pci_config, 0, sizeof(pci_config));
+	if (of_property_read_u32_array(np, "renesas,config",
+				       pci_config, SH7751_NUM_CONFIG) == 0) {
+		for (i = 0; i < SH7751_NUM_CONFIG; i++) {
+			r = pci_config[i * 2];
+			/* CONFIG0 is read-only, so make it a sentinel. */
+			if (r == 0)
+				break;
+			pcic_writel(pci_config[i * 2 + 1], pcic,
+				    SH7751_PCICONF0 + r * 4);
+		}
+	}
+
+	if (of_property_read_u32(np, "sh7751-pci,mcrmask", &val)) {
+		mcr = ioread32(bsc + BSC_MCR);
+		mcr &= ~val;
+		pcic_writel(mcr, pcic, SH4_PCIMCR);
+	}
+}
+
+/*
+ * Direct access to PCI hardware...
+ */
+#define CONFIG_CMD(bus, devfn, where) \
+	(0x80000000 | (bus->number << 16) | (devfn << 8) | (where & ~3))
+
+/*
+ * We need to avoid collisions with `mirrored' VGA ports
+ * and other strange ISA hardware, so we always want the
+ * addresses to be allocated in the 0x000-0x0ff region
+ * modulo 0x400.
+ */
+#define IO_REGION_BASE 0x1000
+resource_size_t pcibios_align_resource(void *data, const struct resource *res,
+				resource_size_t size, resource_size_t align)
+{
+	resource_size_t start = res->start;
+
+	if (res->flags & IORESOURCE_IO) {
+		if (start < PCIBIOS_MIN_IO + IO_REGION_BASE)
+			start = PCIBIOS_MIN_IO + IO_REGION_BASE;
+
+		/*
+		 * Put everything into 0x00-0xff region modulo 0x400.
+		 */
+		if (start & 0x300)
+			start = (start + 0x3ff) & ~0x3ff;
+	}
+
+	return start;
+}
+
+static int area_sdram_check(struct device *dev, void __iomem *pcic,
+			    void __iomem *bsc, unsigned int area)
+{
+	unsigned long word;
+
+	word = __raw_readl(bsc + BSC_BCR1);
+	/* check BCR for SDRAM in area */
+	if (((word >> area) & 1) == 0) {
+		dev_info(dev, "PCI: Area %d is not configured for SDRAM. BCR1=0x%lx\n",
+		       area, word);
+		return 0;
+	}
+	pcic_writel(word, pcic, SH4_PCIBCR1);
+
+	word = __raw_readw(bsc + BSC_BCR2);
+	/* check BCR2 for 32bit SDRAM interface*/
+	if (((word >> (area << 1)) & 0x3) != 0x3) {
+		dev_info(dev, "PCI: Area %d is not 32 bit SDRAM. BCR2=0x%lx\n",
+			area, word);
+		return 0;
+	}
+	pcic_writel(word, pcic, SH4_PCIBCR2);
+
+	return 1;
+}
+
+static void set_pci_window(void __iomem *pcic, int no, struct resource *res)
+{
+	u32 word;
+
+	word = res->end - res->start - 1;
+	pcic_writel(word, pcic, SH4_PCILSR0 + no * 4);
+	word = P2SEGADDR(res->start);
+	pcic_writel(word, pcic, SH4_PCILAR0 + no * 4);
+	pcic_writel(word, pcic, SH7751_PCICONF5 + no * 4);
+}
+
+static int sh7751_pci_probe(struct platform_device *pdev)
+{
+	struct resource *res, *w0res;
+	u32 id;
+	u32 reg, word;
+	void __iomem *pcic;
+	void __iomem *bsc;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	pcic = (void __iomem *)res->start;
+	if (IS_ERR(pcic))
+		return PTR_ERR(pcic);
+
+	w0res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	if (IS_ERR(w0res))
+		return PTR_ERR(w0res);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
+	bsc = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(bsc))
+		return PTR_ERR(bsc);
+
+	/* check for SH7751/SH7751R hardware */
+	id = pcic_readl(pcic, SH7751_PCICONF0);
+	if (id != ((SH7751_DEVICE_ID << 16) | SH7751_VENDOR_ID) &&
+	    id != ((SH7751R_DEVICE_ID << 16) | SH7751_VENDOR_ID)) {
+		dev_warn(&pdev->dev, "PCI: This is not an SH7751(R)\n");
+		return -ENODEV;
+	}
+	dev_info(&pdev->dev, "PCI core found at %pR\n", pcic);
+
+	/* Set the BCR's to enable PCI access */
+	reg = __raw_readl(bsc);
+	reg |= 0x80000;
+	__raw_writel(reg, bsc);
+
+	/* Turn the clocks back on (not done in reset)*/
+	pcic_writel(0, pcic, SH4_PCICLKR);
+	/* Clear Powerdown IRQ's (not done in reset) */
+	word = SH4_PCIPINT_D3 | SH4_PCIPINT_D0;
+	pcic_writel(word, pcic, SH4_PCIPINT);
+
+	/* set the command/status bits to:
+	 * Wait Cycle Control + Parity Enable + Bus Master +
+	 * Mem space enable
+	 */
+	word = SH7751_PCICONF1_WCC | SH7751_PCICONF1_PER |
+	       SH7751_PCICONF1_BUM | SH7751_PCICONF1_MES;
+	pcic_writel(word, pcic, SH7751_PCICONF1);
+
+	/* define this host as the host bridge */
+	word = PCI_BASE_CLASS_BRIDGE << 24;
+	pcic_writel(word, pcic, SH7751_PCICONF2);
+
+	/* Set IO and Mem windows to local address
+	 * Make PCI and local address the same for easy 1 to 1 mapping
+	 */
+	set_pci_window(pcic, 0, w0res);	/* memory */
+
+	/* check BCR for SDRAM in specified area */
+	area_sdram_check(&pdev->dev, pcic, bsc, (w0res->start >> 27) & 0x07);
+
+	/* configure the wait control registers */
+	word = __raw_readl(bsc + BSC_WCR1);
+	pcic_writel(word, pcic, SH4_PCIWCR1);
+	word = __raw_readl(bsc + BSC_WCR2);
+	pcic_writel(word, pcic, SH4_PCIWCR2);
+	word = __raw_readl(bsc + BSC_WCR3);
+	pcic_writel(word, pcic, SH4_PCIWCR3);
+	word = __raw_readl(bsc + BSC_MCR);
+	pcic_writel(word, pcic, SH4_PCIMCR);
+
+	/* Override register setting */
+	pcic_fixups(pdev->dev.of_node, pcic, bsc);
+
+	/* SH7751 init done, set central function init complete */
+	/* use round robin mode to stop a device starving/overrunning */
+	word = SH4_PCICR_PREFIX | SH4_PCICR_CFIN | SH4_PCICR_ARBM;
+	pcic_writel(word, pcic, SH4_PCICR);
+
+	return pci_host_common_probe(pdev);
+}
+
+static void __iomem *sh4_pci_map_bus(struct pci_bus *bus,
+				     unsigned int devfn, int where)
+{
+	struct pci_config_window *cfg = bus->sysdata;
+	void __iomem *pcic = (void __iomem *)cfg->res.start;
+
+	pcic_writel(CONFIG_CMD(bus, devfn, where), pcic, SH4_PCIPAR);
+	return pcic + SH4_PCIPDR;
+}
+
+static const struct pci_ecam_ops pci_sh7751_bus_ops = {
+	.pci_ops	= {
+		.map_bus = sh4_pci_map_bus,
+		.read    = pci_generic_config_read32,
+		.write   = pci_generic_config_write32,
+	}
+};
+
+static const struct of_device_id sh7751_pci_of_match[] = {
+	{ .compatible = "renesas,sh7751-pci",
+	  .data = &pci_sh7751_bus_ops },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, sh7751_pci_of_match);
+
+static struct platform_driver sh7751_pci_driver = {
+	.driver = {
+		.name = "sh7751-pci",
+		.of_match_table = sh7751_pci_of_match,
+	},
+	.probe = sh7751_pci_probe,
+};
+module_platform_driver(sh7751_pci_driver);
+
+MODULE_DESCRIPTION("SH7751 PCI driver");
-- 
2.39.2


  parent reply	other threads:[~2023-11-14  8:00 UTC|newest]

Thread overview: 55+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-11-14  7:59 [PATCH v4 00/37] Device Tree support for SH7751 based board Yoshinori Sato
2023-11-14  7:59 ` [PATCH v4 01/37] sh: passing FDT address to kernel startup Yoshinori Sato
2023-11-14  8:44   ` Sergei Shtylyov
2023-11-14  7:59 ` [PATCH v4 02/37] sh: Kconfig unified OF supported targets Yoshinori Sato
2023-11-14 12:46   ` Arnd Bergmann
2023-11-14  7:59 ` [PATCH v4 03/37] sh: Enable OF support for build and configuration Yoshinori Sato
2023-11-14  7:59 ` [PATCH v4 04/37] dt-bindings: interrupt-controller: Add header for Renesas SH3/4 INTC Yoshinori Sato
2023-11-14 21:25   ` Krzysztof Kozlowski
2023-11-14  7:59 ` [PATCH v4 05/37] sh: GENERIC_IRQ_CHIP support for CONFIG_OF=y Yoshinori Sato
2023-11-14  7:59 ` [PATCH v4 06/37] sh: kernel/setup Update DT support Yoshinori Sato
2023-11-14  7:59 ` [PATCH v4 07/37] sh: Fix COMMON_CLK support in CONFIG_OF=y Yoshinori Sato
2023-11-14  7:59 ` [PATCH v4 08/37] clocksource: sh_tmu: CLOCKSOURCE support Yoshinori Sato
2023-11-14  8:00 ` [PATCH v4 09/37] dt-bindings: timer: renesas,tmu: add renesas,tmu-sh7750 Yoshinori Sato
2023-11-14 21:26   ` Krzysztof Kozlowski
2023-11-15  8:17     ` Geert Uytterhoeven
2023-11-15 21:05       ` Krzysztof Kozlowski
2023-11-14  8:00 ` [PATCH v4 10/37] sh: Common PCI framework support Yoshinori Sato
2023-11-14 13:03   ` Arnd Bergmann
2023-11-14  8:00 ` [PATCH v4 11/37] sh: Add old PCI drivers compatible stub Yoshinori Sato
2023-11-14  8:00 ` Yoshinori Sato [this message]
2023-11-20 18:16   ` [PATCH v4 12/37] pci: pci-sh7751: Add SH7751 PCI driver Bjorn Helgaas
2023-11-14  8:00 ` [PATCH v4 13/37] dt-bindings: pci: pci-sh7751: Add SH7751 PCI Yoshinori Sato
2023-11-14 21:27   ` Krzysztof Kozlowski
2023-11-14  8:00 ` [PATCH v4 14/37] dt-bindings: clock: sh7750-cpg: Add renesas,sh7750-cpg header Yoshinori Sato
2023-11-14 21:29   ` Krzysztof Kozlowski
2023-11-14  8:00 ` [PATCH v4 15/37] clk: Compatible with narrow registers Yoshinori Sato
2023-11-14  8:00 ` [PATCH v4 16/37] clk: renesas: Add SH7750/7751 CPG Driver Yoshinori Sato
2023-11-14  8:00 ` [PATCH v4 17/37] irqchip: Add SH7751 INTC driver Yoshinori Sato
2023-11-14  8:00 ` [PATCH v4 18/37] dt-bindings: interrupt-controller: renesas,sh7751-intc: Add json-schema Yoshinori Sato
2023-11-14  8:00 ` [PATCH v4 19/37] irqchip: SH7751 IRL external encoder with enable gate Yoshinori Sato
2023-11-14  8:00 ` [PATCH v4 20/37] dt-bindings: interrupt-controller: renesas,sh7751-irl-ext: Add json-schema Yoshinori Sato
2023-11-14  8:00 ` [PATCH v4 21/37] serial: sh-sci: fix SH4 OF support Yoshinori Sato
2023-11-14  8:00 ` [PATCH v4 22/37] dt-bindings: serial: renesas,scif: Add scif-sh7751 Yoshinori Sato
2023-11-14  8:00 ` [PATCH v4 23/37] dt-bindings: display: smi,sm501: SMI SM501 binding json-schema Yoshinori Sato
2023-11-14  8:00 ` [PATCH v4 24/37] mfd: sm501: Convert platform_data to OF property Yoshinori Sato
2023-11-23 13:59   ` Lee Jones
2023-11-14  8:00 ` [PATCH v4 25/37] dt-binding: sh: cpus: Add SH CPUs json-schema Yoshinori Sato
2023-11-14  8:00 ` [PATCH v4 26/37] dt-bindings: vendor-prefix: Add new vendor iodata and smi Yoshinori Sato
2023-11-14 16:35   ` Geert Uytterhoeven
2023-11-14  8:00 ` [PATCH v4 27/37] dt-bindings: ata: ata-generic: Add new targets Yoshinori Sato
2023-11-14 18:19   ` Rob Herring
2023-11-14  8:00 ` [PATCH v4 28/37] dt-bindings: soc: renesas: sh: Add SH7751 based target Yoshinori Sato
2023-11-14  8:00 ` [PATCH v4 29/37] sh: SH7751R SoC Internal peripheral definition dtsi Yoshinori Sato
2023-11-14  8:00 ` [PATCH v4 30/37] sh: add RTS7751R2D Plus DTS Yoshinori Sato
2023-11-14  8:00 ` [PATCH v4 31/37] sh: Add IO DATA LANDISK dts Yoshinori Sato
2023-11-14  8:00 ` [PATCH v4 32/37] sh: Add IO DATA USL-5P dts Yoshinori Sato
2023-11-14  9:02   ` Sergei Shtylyov
2023-11-14  9:04     ` Sergei Shtylyov
2023-11-14  8:00 ` [PATCH v4 33/37] sh: j2_mimas_v2.dts update Yoshinori Sato
2023-11-14  8:00 ` [PATCH v4 34/37] sh: Add dtbs target support Yoshinori Sato
2023-11-14  8:00 ` [PATCH v4 35/37] sh: RTS7751R2D Plus OF defconfig Yoshinori Sato
2023-11-14  8:00 ` [PATCH v4 36/37] sh: LANDISK " Yoshinori Sato
2023-11-14  8:00 ` [PATCH v4 37/37] sh: j2_defconfig: update Yoshinori Sato
2023-11-14  8:58 ` [PATCH v4 00/37] Device Tree support for SH7751 based board John Paul Adrian Glaubitz
2023-11-14 18:39   ` John Paul Adrian Glaubitz

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=90c0f0810c778e4f515bb9d8582b501d77e2bf1a.1699856600.git.ysato@users.sourceforge.jp \
    --to=ysato@users.sourceforge.jp \
    --cc=bhelgaas@google.com \
    --cc=geert+renesas@glider.be \
    --cc=kw@linux.com \
    --cc=linux-sh@vger.kernel.org \
    --cc=lpieralisi@kernel.org \
    --cc=magnus.damm@gmail.com \
    --cc=robh@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.