From patchwork Thu Apr 4 04:59:35 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yoshinori Sato X-Patchwork-Id: 13616960 Received: from sakura.ysato.name (ik1-413-38519.vs.sakura.ne.jp [153.127.30.23]) by smtp.subspace.kernel.org (Postfix) with ESMTP id B0E423E476 for ; Thu, 4 Apr 2024 05:00:53 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=153.127.30.23 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712206855; cv=none; b=TAT3FCLISkeSuV5l+XizOBXV18WjRDMlmwX2SViKK+C8A1mhlQOzCvvyd3aWyXuzh60K5KEcqb0J+bTvdwINNbx5pYCzJUAR+lGYWRj+xJ5kjc7kBoVWJW+SBjjR09q/HYTeI/yh2T3N7oCMB5ZdbmdWoMl9noljUx72wgmqX3w= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712206855; c=relaxed/simple; bh=Zl34havtMWRq2iGwzVo/GzpE+MdC5jA9xgxGJw9XNA0=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=fOCcBFdJkSFZtp88gybzrGzRVGEdBDAWHpm9m436MdCCFXheTWJFZvUPXvHlOFPNpCBWXOjcOCQTocxrBtgfzk2408lqNGPMBewRrjZG88XY6VJ1lRCM0XmnyJqMY9BJKg6dnK5b9wF1AwLXzmuaWKRd1gyR7EjK+g/npXVr/QY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=users.sourceforge.jp; spf=fail smtp.mailfrom=users.sourceforge.jp; arc=none smtp.client-ip=153.127.30.23 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=users.sourceforge.jp Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=users.sourceforge.jp Received: from SIOS1075.ysato.name (al128006.dynamic.ppp.asahi-net.or.jp [111.234.128.6]) by sakura.ysato.name (Postfix) with ESMTPSA id C07BD1C03BE; Thu, 4 Apr 2024 14:00:52 +0900 (JST) From: Yoshinori Sato To: linux-sh@vger.kernel.org Cc: Yoshinori Sato Subject: [DO NOT MERGE v7 09/36] sh: Common PCI Framework driver support. Date: Thu, 4 Apr 2024 13:59:35 +0900 Message-Id: X-Mailer: git-send-email 2.39.2 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-sh@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Add New OF based PCI Host driver. This driver conflicts some point in legacy PCI driver. To resolve the conflict, I made some changes to the legacy driver. Signed-off-by: Yoshinori Sato --- arch/sh/include/asm/io.h | 6 ++++++ arch/sh/include/asm/pci.h | 4 ++++ arch/sh/kernel/iomap.c | 18 ++++++++++++++++++ 3 files changed, 28 insertions(+) diff --git a/arch/sh/include/asm/io.h b/arch/sh/include/asm/io.h index 5c544cf5201b..29b5f996cde3 100644 --- a/arch/sh/include/asm/io.h +++ b/arch/sh/include/asm/io.h @@ -20,6 +20,7 @@ #include #include #include +#include #define __IO_PREFIX generic #include @@ -310,4 +311,9 @@ unsigned long long poke_real_address_q(unsigned long long addr, int valid_phys_addr_range(phys_addr_t addr, size_t size); int valid_mmap_phys_addr_range(unsigned long pfn, size_t size); +#if defined(CONFIG_PCI) && !defined(CONFIG_GENERIC_IOMAP) +#define pci_remap_iospace pci_remap_iospace +int pci_remap_iospace(const struct resource *res, phys_addr_t phys_addr); +#endif + #endif /* __ASM_SH_IO_H */ diff --git a/arch/sh/include/asm/pci.h b/arch/sh/include/asm/pci.h index 54c30126ea17..92b3bd604319 100644 --- a/arch/sh/include/asm/pci.h +++ b/arch/sh/include/asm/pci.h @@ -2,6 +2,7 @@ #ifndef __ASM_SH_PCI_H #define __ASM_SH_PCI_H +#ifndef CONFIG_SH_DEVICE_TREE /* Can be used to override the logic in pci_scan_bus for skipping already-configured bus numbers - to be used for buggy BIOSes or architectures with incomplete PCI setup by the loader */ @@ -88,4 +89,7 @@ static inline int pci_proc_domain(struct pci_bus *bus) return hose->need_domain_info; } +#else /* CONFIG_SH_DEVICE_TREE */ +#include +#endif #endif /* __ASM_SH_PCI_H */ diff --git a/arch/sh/kernel/iomap.c b/arch/sh/kernel/iomap.c index 0a0dff4e66de..d1b8e496ca23 100644 --- a/arch/sh/kernel/iomap.c +++ b/arch/sh/kernel/iomap.c @@ -160,3 +160,21 @@ void iowrite32_rep(void __iomem *addr, const void *src, unsigned long count) mmio_outsl(addr, src, count); } EXPORT_SYMBOL(iowrite32_rep); + +#if defined(pci_remap_iospace) +int pci_remap_iospace(const struct resource *res, phys_addr_t phys_addr) +{ + unsigned long vaddr = res->start; + + if (!(res->flags & IORESOURCE_IO)) + return -EINVAL; + + if (res->end > IO_SPACE_LIMIT) + return -EINVAL; + + __set_io_port_base(phys_addr); + return vmap_page_range(vaddr, vaddr + resource_size(res), phys_addr, + pgprot_device(PAGE_KERNEL)); +} +EXPORT_SYMBOL(pci_remap_iospace); +#endif From patchwork Thu Apr 4 04:59:36 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yoshinori Sato X-Patchwork-Id: 13616961 Received: from sakura.ysato.name (ik1-413-38519.vs.sakura.ne.jp [153.127.30.23]) by smtp.subspace.kernel.org (Postfix) with ESMTP id EB80C51034 for ; Thu, 4 Apr 2024 05:00:53 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=153.127.30.23 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712206856; cv=none; b=u9aYjx1huXkgMIoGV4/Uf0Nsi15FL/sVxLCx1W7Or+xNeWuMPEPLJaaZ+afdc4Y+aH98Hh7PiOe/y+aIpgp+8gymohneovonBMsBPyOLJOdVY6c9atuqdtIS3An+MYVtt2vUzq0cZIS1MEgbuHq0AYuleyM5Zzf5pRzwEDuq9ew= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712206856; c=relaxed/simple; bh=C+jQmWPBYq6FMYzgGImgQJNnONf9kmk2gh8nByNKbYc=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=J1MhlD5MzDbwZyNEF7okmGOxzK8c4xNms2FOWpSXWUg0xTiWdZuQPzLvgQrO3DFkTDTA/YrBDVvuBZeEifIylq/HS622EFnzIK12Hpz/pLpP2oEXWeRp13Zxg1bP2Fpb3F6E7V1HDUkE5NLeXupvjErXn+ojpmgA9b6sAnKdmrA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=users.sourceforge.jp; spf=fail smtp.mailfrom=users.sourceforge.jp; arc=none smtp.client-ip=153.127.30.23 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=users.sourceforge.jp Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=users.sourceforge.jp Received: from SIOS1075.ysato.name (al128006.dynamic.ppp.asahi-net.or.jp [111.234.128.6]) by sakura.ysato.name (Postfix) with ESMTPSA id E67171C08D7; Thu, 4 Apr 2024 14:00:52 +0900 (JST) From: Yoshinori Sato To: linux-sh@vger.kernel.org Cc: Yoshinori Sato Subject: [DO NOT MERGE v7 10/36] pci: pci-sh7751: Add SH7751 PCI driver Date: Thu, 4 Apr 2024 13:59:36 +0900 Message-Id: X-Mailer: git-send-email 2.39.2 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-sh@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Renesas SH7751 CPU Internal PCI Controller driver. Signed-off-by: Yoshinori Sato --- drivers/pci/controller/Kconfig | 9 + drivers/pci/controller/Makefile | 1 + drivers/pci/controller/pci-sh7751.c | 342 ++++++++++++++++++++++++++++ 3 files changed, 352 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..a5340689f737 --- /dev/null +++ b/drivers/pci/controller/pci-sh7751.c @@ -0,0 +1,342 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * SH7751 PCI driver + * Copyright (C) 2023 Yoshinori Sato + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* PCICR and PCICLKCR write enable magic key */ +#define PCIC_WE_KEY (0xa5 << 24) + +/* PCIC registers */ +/* 0x0000 - 0x00ff mapped to PCI device configuration space */ +#define PCIC_PCICR 0x100 /* PCI Control Register */ +#define PCIC_PCICR_TRSB BIT(9) /* Target Read Single */ +#define PCIC_PCICR_BSWP BIT(8) /* Target Byte Swap */ +#define PCIC_PCICR_PLUP BIT(7) /* Enable PCI Pullup */ +#define PCIC_PCICR_ARBM BIT(6) /* PCI Arbitration Mode */ +#define PCIC_PCICR_MD10 BIT(5) /* MD10 status */ +#define PCIC_PCICR_MD9 BIT(4) /* MD9 status */ +#define PCIC_PCICR_SERR BIT(3) /* SERR output assert */ +#define PCIC_PCICR_INTA BIT(2) /* INTA output assert */ +#define PCIC_PCICR_PRST BIT(1) /* PCI Reset Assert */ +#define PCIC_PCICR_CFIN BIT(0) /* Central Fun. Init Done */ + +#define PCIC_PCILSR0 0x104 /* PCI Local Space Register0 */ +#define PCIC_PCILSR1 0x108 /* PCI Local Space Register1 */ +#define PCIC_PCILAR0 0x10c /* PCI Local Addr Register1 */ +#define PCIC_PCILAR1 0x110 /* PCI Local Addr Register1 */ +#define PCIC_PCIINT 0x114 /* PCI Interrupt Register */ +#define PCIC_PCIINTM 0x118 /* PCI Interrupt Mask */ +#define PCIC_PCIALR 0x11c /* Error Address Register */ +#define PCIC_PCICLR 0x120 /* Error Command/Data */ +#define PCIC_PCIAINT 0x130 /* Arbiter Interrupt Register */ +#define PCIC_PCIAINTM 0x134 /* Arbiter Int. Mask Register */ +#define PCIC_PCIBMLR 0x138 /* Error Bus Master Register */ +#define PCIC_PCIDMABT 0x140 /* DMA Transfer Arb. Register */ +#define PCIC_PCIPAR 0x1c0 /* PIO Address Register */ +#define PCIC_PCIMBR 0x1c4 /* Memory Base Address */ +#define PCIC_PCIIOBR 0x1c8 /* I/O Base Address Register */ + +#define PCIC_PCIPINT 0x1cc /* Power Mgmnt Int. Register */ +#define PCIC_PCIPINT_D3 BIT(1) /* D3 Pwr Mgmt. Interrupt */ +#define PCIC_PCIPINT_D0 BIT(0) /* D0 Pwr Mgmt. Interrupt */ + +#define PCIC_PCIPINTM 0x1d0 /* Power Mgmnt Mask Register */ +#define PCIC_PCICLKR 0x1d4 /* Clock Ctrl. Register */ +#define PCIC_PCIBCR1 0x1e0 /* Memory BCR1 Register */ +#define PCIC_PCIBCR2 0x1e4 /* Memory BCR2 Register */ +#define PCIC_PCIWCR1 0x1e8 /* Wait Control 1 Register */ +#define PCIC_PCIWCR2 0x1ec /* Wait Control 2 Register */ +#define PCIC_PCIWCR3 0x1f0 /* Wait Control 3 Register */ +#define PCIC_PCIMCR 0x1f4 /* Memory Control Register */ +#define PCIC_PCIBCR3 0x1f8 /* Memory BCR3 Register */ +#define PCIC_PCIPDR 0x220 /* Port IO Data Register */ + +/* PCI IDs */ +/* Hitachi is the company that led to Renesas. */ +/* The SH7751 was designed by Hitachi, so it has a Hitachi ID. */ +#define PCI_VENDOR_ID_HITACHI 0x1054 +#define PCI_DEVICE_ID_SH7751 0x3505 +#define PCI_DEVICE_ID_SH7751R 0x350e + +/* BSC registers */ +/* Copy BSC setting to PCI BSC */ +#define BSC_BCR1 0x0000 +#define BSC_BCR1_SLAVE BIT(30) +#define BSC_BCR1_BRQEN BIT(19) +#define BSC_BCR2 0x0004 +#define BSC_BCR3 0x0050 +#define BSC_WCR1 0x0008 +#define BSC_WCR2 0x000c +#define BSC_WCR3 0x0010 +#define BSC_MCR 0x0014 +#define BSC_MCR_MRSET BIT(30) +#define BSC_MCR_RFSH BIT(2) + +/* PCIC access wrapper */ +#define pcic_writel(val, base, reg) writel(val, base + (reg)) +#define pcic_readl(base, reg) readl(base + (reg)) + +/* + * 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 setup_pci_bsc(struct device *dev, void __iomem *pcic, + void __iomem *bsc, unsigned int area, bool bcr3) +{ + u32 word; + + word = __raw_readl(bsc + BSC_BCR1); + /* check BCR for SDRAM in area */ + if (((word >> area) & 1) == 0) { + dev_err(dev, "Area %u is not configured for SDRAM. BCR1=0x%x\n", + area, word); + return -EINVAL; + } + word |= BSC_BCR1_SLAVE; /* PCIC BSC is slave only */ + pcic_writel(word, pcic, PCIC_PCIBCR1); + + word = __raw_readw(bsc + BSC_BCR2); + /* check BCR2 for 32bit SDRAM interface*/ + if (((word >> (area << 1)) & 0x3) != 0x3) { + dev_err(dev, "Area %u is not 32 bit SDRAM. BCR2=0x%x\n", + area, word); + return -EINVAL; + } + pcic_writel(word, pcic, PCIC_PCIBCR2); + + if (bcr3) { + /* BCR3 have only SH7751R */ + word = __raw_readw(bsc + BSC_BCR3); + pcic_writel(word, pcic, PCIC_PCIBCR3); + } + + /* configure the wait control registers */ + word = __raw_readl(bsc + BSC_WCR1); + pcic_writel(word, pcic, PCIC_PCIWCR1); + word = __raw_readl(bsc + BSC_WCR2); + pcic_writel(word, pcic, PCIC_PCIWCR2); + word = __raw_readl(bsc + BSC_WCR3); + pcic_writel(word, pcic, PCIC_PCIWCR3); + word = __raw_readl(bsc + BSC_MCR); + /* Clear MRSET and RFSH bit */ + word &= ~(BSC_MCR_MRSET | BSC_MCR_RFSH); + pcic_writel(word, pcic, PCIC_PCIMCR); + + return 0; +} + +#define NUM_AREA 7 +static int set_pci_ranges(struct device *dev, + void __iomem *pcic, void __iomem *bsc, bool bcr3) +{ + struct resource_entry *dma, *tmp; + struct pci_host_bridge *bridge; + u32 bsc_done[NUM_AREA]; + unsigned int la; + + bridge = dev_get_drvdata(dev); + pcic_writel(0, pcic, PCIC_PCILAR0); + pcic_writel(0, pcic, PCIC_PCILAR1); + la = 0; + memset(&bsc_done, 0, sizeof(bsc_done)); + resource_list_for_each_entry_safe(dma, tmp, &bridge->dma_ranges) { + struct resource *res = dma->res; + unsigned int area; + u32 word; + + switch (resource_type(res)) { + case IORESOURCE_IO: + /* BAR0 is I/O space */ + word = res->start | 1; + pcic_writel(word, pcic, PCI_BASE_ADDRESS_0); + word = pcic_readl(pcic, PCI_COMMAND); + word |= PCI_COMMAND_IO; + pcic_writel(word, pcic, PCI_COMMAND); + break; + case IORESOURCE_MEM: + if (la > 4) { + dev_err(dev, "Invalid range definition.\n"); + return -EINVAL; + } + area = (res->start >> 26) & 0x07; + word = res->end - res->start; + if (area >= NUM_AREA) { + /* Area 7 is reserved. */ + dev_info(dev, "Invalid local address 0x%08x. Ignore it.\n", + res->start); + break; + } + pcic_writel(res->start, pcic, PCI_BASE_ADDRESS_1 + la); + /* if dummy entry, skip BSC setup */ + if (word < 4) + break; + /* BAR1 is local area 0, BAR2 is local area 1 */ + pcic_writel(word, pcic, PCIC_PCILSR0 + la); + word = P2SEGADDR(res->start); + pcic_writel(word, pcic, PCIC_PCILAR0 + la); + la += 4; + if (!bsc_done[area]) { + /* check BCR for SDRAM in specified area. And setup PCI BSC. */ + if (setup_pci_bsc(dev, pcic, bsc, area, bcr3)) + return -EINVAL; + bsc_done[area] = 1; + } + break; + } + } + return 0; +} + +static int sh7751_pci_probe(struct platform_device *pdev) +{ + struct resource *res, *bscres; + void __iomem *pcic; + void __iomem *bsc; + u16 vid, did; + u32 word; + int ret; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (IS_ERR(res)) + return PTR_ERR(res); + pcic = ioremap(res->start, res->end - res->start + 1); + + bscres = platform_get_resource(pdev, IORESOURCE_MEM, 1); + bsc = devm_ioremap_resource(&pdev->dev, bscres); + if (IS_ERR(bsc)) + return PTR_ERR(bsc); + + /* check for SH7751/SH7751R hardware */ + word = pcic_readl(pcic, PCI_VENDOR_ID); + vid = word & 0xffff; + did = word >> 16; + if ((vid != PCI_VENDOR_ID_HITACHI) || + ((did != PCI_DEVICE_ID_SH7751) && + (did != PCI_DEVICE_ID_SH7751R))) { + dev_err(&pdev->dev, "This is not an SH7751(R)\n"); + return -ENODEV; + } + dev_info(&pdev->dev, "PCI core found at %pR\n", res); + + /* Set the BCR's to enable PCI access */ + word = __raw_readl(bsc + BSC_BCR1); + word |= BSC_BCR1_BRQEN; + __raw_writel(word, bsc + BSC_BCR1); + + /* Turn the clocks back on (not done in reset)*/ + pcic_writel(PCIC_WE_KEY | 0, pcic, PCIC_PCICLKR); + /* Clear Powerdown IRQ's (not done in reset) */ + word = PCIC_PCIPINT_D3 | PCIC_PCIPINT_D0; + pcic_writel(word, pcic, PCIC_PCIPINT); + + /* set the command/status */ + word = PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | + PCI_COMMAND_PARITY | PCI_COMMAND_WAIT; + pcic_writel(word, pcic, PCI_COMMAND); + + /* define this host as the host bridge */ + word = PCI_BASE_CLASS_BRIDGE << 24; + pcic_writel(word, pcic, PCI_CLASS_REVISION); + + ret = pci_host_common_probe(pdev); + if (ret) { + dev_err(&pdev->dev, "Initialize failed (%d)\n", ret); + return ret; + } + + /* Set IO and Mem windows to local address */ + if (set_pci_ranges(&pdev->dev, pcic, bsc, + did == PCI_DEVICE_ID_SH7751R)) + return -EINVAL; + pcic_writel(0, pcic, PCIC_PCIIOBR); + + if (of_property_read_bool(pdev->dev.of_node, "renesas,bus-arbit-round-robin")) + word |= BIT(0); + else + word = 0; + pcic_writel(word, pcic, PCIC_PCIDMABT); + + /* SH7751 init done, set central function init complete */ + /* use round robin mode to stop a device starving/overrunning */ + word = PCIC_PCICR_CFIN | PCIC_PCICR_ARBM; + pcic_writel(PCIC_WE_KEY | word, pcic, PCIC_PCICR); + + return 0; +} + +/* + * Direct access to PCI hardware... + */ +#define CONFIG_CMD(bus, devfn, where) \ + (0x80000000 | (bus->number << 16) | (devfn << 8) | (where & ~3)) + +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, PCIC_PCIPAR); + return pcic + PCIC_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"); From patchwork Thu Apr 4 04:59:38 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yoshinori Sato X-Patchwork-Id: 13616963 Received: from sakura.ysato.name (ik1-413-38519.vs.sakura.ne.jp [153.127.30.23]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 3C53854911 for ; Thu, 4 Apr 2024 05:00:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=153.127.30.23 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712206857; cv=none; b=NKQoFTT1BS4kYWgKM4PSXBpIZOoMBIwtv7aOOKVxsk6CIjCcpqubfX4coeF9p1GfPNGYlWCbNXIy+2aatlfPp8NesFxCU/RP9X4KbJpPxxSovpYdx7ZY+q+u5PIfdyOH4JoHmIQ9oQgcaf7L/p5A/21Bwx3whi0ZZ5xd8QeQiK0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712206857; c=relaxed/simple; bh=s7z/DJLA2hvdIV/rv9zwgO39neOGHSX5TSCrrrQvjFc=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=X47kEV0mycV9eAn/ynR1hmrJT3M/dMVFoPOPpAALXDYk2J4asPykpqsYKaIzfFH6kHANDajQVrt2EPeCNpsz1PBgsfi8H/gtqB+sBNVlMcMYFDH1v9mDcPArrLPafa0032GeWmwF/C+btqeAN4V3NcW93eI46xPTUoYlLxUQ/UE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=users.sourceforge.jp; spf=fail smtp.mailfrom=users.sourceforge.jp; arc=none smtp.client-ip=153.127.30.23 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=users.sourceforge.jp Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=users.sourceforge.jp Received: from SIOS1075.ysato.name (al128006.dynamic.ppp.asahi-net.or.jp [111.234.128.6]) by sakura.ysato.name (Postfix) with ESMTPSA id 250741C03E3; Thu, 4 Apr 2024 14:00:55 +0900 (JST) From: Yoshinori Sato To: linux-sh@vger.kernel.org Cc: Yoshinori Sato Subject: [DO NOT MERGE v7 11/36] dt-bindings: pci: pci-sh7751: Add SH7751 PCI Date: Thu, 4 Apr 2024 13:59:38 +0900 Message-Id: <4d3b2398e724dfa0682eb6108dfca2ae6593b3ee.1712041249.git.ysato@users.sourceforge.jp> X-Mailer: git-send-email 2.39.2 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-sh@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Renesas SH7751 PCI Controller json-schema. Signed-off-by: Yoshinori Sato --- .../bindings/pci/renesas,sh7751-pci.yaml | 89 +++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 Documentation/devicetree/bindings/pci/renesas,sh7751-pci.yaml diff --git a/Documentation/devicetree/bindings/pci/renesas,sh7751-pci.yaml b/Documentation/devicetree/bindings/pci/renesas,sh7751-pci.yaml new file mode 100644 index 000000000000..115c2bb67339 --- /dev/null +++ b/Documentation/devicetree/bindings/pci/renesas,sh7751-pci.yaml @@ -0,0 +1,89 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/pci/renesas,sh7751-pci.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Renesas SH7751 PCI Host controller + +maintainers: + - Yoshinori Sato + +allOf: + - $ref: /schemas/pci/pci-bus.yaml# + +properties: + compatible: + const: renesas,sh7751-pci + + reg: + minItems: 2 + maxItems: 2 + + reg-names: + items: + - const: PCI Controller + - const: Bus State Controller + + "#interrupt-cells": + const: 1 + + "#address-cells": + const: 3 + + "#size-cells": + const: 2 + + ranges: true + + dma-ranges: true + + interrupt-controller: true + + renesas,bus-arbit-round-robin: + $ref: /schemas/types.yaml#/definitions/flag + description: | + Set DMA bus arbitration to round robin. + +required: + - compatible + - reg + - "#interrupt-cells" + - "#address-cells" + - "#size-cells" + - ranges + - interrupt-map + - interrupt-map-mask + +unevaluatedProperties: false + +examples: + - | + #include + pci@fe200000 { + compatible = "renesas,sh7751-pci"; + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + interrupt-controller; + device_type = "pci"; + bus-range = <0 0>; + ranges = <0x02000000 0 0xfd000000 0xfd000000 0 0x01000000>, + <0x01000000 0 0x00000000 0xfe240000 0 0x00040000>; + dma-ranges = <0x02000000 0 0xc000000 0x0c000000 0 0x04000000>; + reg = <0xfe200000 0x0400>, + <0xff800000 0x0100>; + interrupt-map = <0x0000 0 0 1 &julianintc 5 IRQ_TYPE_LEVEL_LOW>, + <0x0000 0 0 2 &julianintc 6 IRQ_TYPE_LEVEL_LOW>, + <0x0000 0 0 3 &julianintc 7 IRQ_TYPE_LEVEL_LOW>, + <0x0000 0 0 4 &julianintc 8 IRQ_TYPE_LEVEL_LOW>, + <0x0800 0 0 1 &julianintc 6 IRQ_TYPE_LEVEL_LOW>, + <0x0800 0 0 2 &julianintc 7 IRQ_TYPE_LEVEL_LOW>, + <0x0800 0 0 3 &julianintc 8 IRQ_TYPE_LEVEL_LOW>, + <0x0800 0 0 4 &julianintc 5 IRQ_TYPE_LEVEL_LOW>, + <0x1000 0 0 1 &julianintc 7 IRQ_TYPE_LEVEL_LOW>, + <0x1000 0 0 2 &julianintc 8 IRQ_TYPE_LEVEL_LOW>, + <0x1000 0 0 3 &julianintc 5 IRQ_TYPE_LEVEL_LOW>, + <0x1000 0 0 4 &julianintc 6 IRQ_TYPE_LEVEL_LOW>; + interrupt-map-mask = <0x1800 0 0 7>; + }; From patchwork Thu Apr 4 04:59:40 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yoshinori Sato X-Patchwork-Id: 13616964 Received: from sakura.ysato.name (ik1-413-38519.vs.sakura.ne.jp [153.127.30.23]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 6CE0A5676F for ; Thu, 4 Apr 2024 05:00:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=153.127.30.23 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712206859; cv=none; b=nbjr75JQs53a0d0Ey1xpif38pyqtIAh64wntIRXd7WDRg/Eo1LKK6iNGCS5RMzFgbxWdbkGOno3BwobWQgsDQ3mSvGM+U5RL2VJ2OXOERrSX/YfpkpFgbY236s5gsBevWB3qn7ofarRb79ASvYf5tve4JknZWqqSH7JVSza9gBU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712206859; c=relaxed/simple; bh=1xMW4sZCG05RmqUl4sfWusbiwrMTmOWImJT9AqMcM98=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=MAWPBFPXbcDwmxj0ozFCD0iRtFnHUvqVYA0PWRHNQnXh24poqERhcUwdyzUdFL/zTsH+DNs96rL8yVr4V+Sc8el41AA2DJzu+gH4yjDcWOYy45A8yTh07CpsmFVkj8yXIYBzfcNiUN6noQ/oXdrNtITpcsaTe+BR6pIwqlRvJxc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=users.sourceforge.jp; spf=fail smtp.mailfrom=users.sourceforge.jp; arc=none smtp.client-ip=153.127.30.23 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=users.sourceforge.jp Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=users.sourceforge.jp Received: from SIOS1075.ysato.name (al128006.dynamic.ppp.asahi-net.or.jp [111.234.128.6]) by sakura.ysato.name (Postfix) with ESMTPSA id 1F1281C03BE; Thu, 4 Apr 2024 14:00:57 +0900 (JST) From: Yoshinori Sato To: linux-sh@vger.kernel.org Cc: Yoshinori Sato Subject: [DO NOT MERGE v7 12/36] dt-bindings: clock: sh7750-cpg: Add renesas,sh7750-cpg header. Date: Thu, 4 Apr 2024 13:59:40 +0900 Message-Id: X-Mailer: git-send-email 2.39.2 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-sh@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 SH7750 CPG Clock output define. Signed-off-by: Yoshinori Sato --- .../bindings/clock/renesas,sh7750-cpg.yaml | 105 ++++++++++++++++++ include/dt-bindings/clock/sh7750-cpg.h | 26 +++++ 2 files changed, 131 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/renesas,sh7750-cpg.yaml create mode 100644 include/dt-bindings/clock/sh7750-cpg.h diff --git a/Documentation/devicetree/bindings/clock/renesas,sh7750-cpg.yaml b/Documentation/devicetree/bindings/clock/renesas,sh7750-cpg.yaml new file mode 100644 index 000000000000..04c10b0834ee --- /dev/null +++ b/Documentation/devicetree/bindings/clock/renesas,sh7750-cpg.yaml @@ -0,0 +1,105 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/renesas,sh7750-cpg.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Renesas SH7750/7751 Clock Pulse Generator (CPG) + +maintainers: + - Yoshinori Sato + +description: + The Clock Pulse Generator (CPG) generates core clocks for the SoC. It + includes PLLs, and variable ratio dividers. + + The CPG may also provide a Clock Domain for SoC devices, in combination with + the CPG Module Stop (MSTP) Clocks. + +properties: + compatible: + enum: + - renesas,sh7750-cpg # SH7750 + - renesas,sh7750s-cpg # SH775S + - renesas,sh7750r-cpg # SH7750R + - renesas,sh7751-cpg # SH7751 + - renesas,sh7751r-cpg # SH7751R + + reg: true + + reg-names: true + + clocks: + maxItems: 1 + + clock-names: + const: extal + + '#clock-cells': + const: 1 + + renesas,mode: + description: Board-specific settings of the MD[0-2] pins on SoC + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 0 + maximum: 6 + + '#power-domain-cells': + const: 0 + +required: + - compatible + - reg + - reg-names + - clocks + - clock-names + - '#clock-cells' + +allOf: + - if: + properties: + compatible: + contains: + enum: + - renesas,sh7750-cpg + - renesas,sh7750s-cpg + then: + properties: + reg: + maxItems: 1 + reg-names: + items: + - const: FRQCR + + - if: + properties: + compatible: + contains: + enum: + - renesas,sh7750r-cpg + - renesas,sh7751-cpg + - renesas,sh7751r-cpg + then: + properties: + reg: + maxItems: 2 + reg-names: + items: + - const: FRQCR + - const: CLKSTP00 + +additionalProperties: false + +examples: + - | + #include + cpg: clock-controller@ffc00000 { + #clock-cells = <1>; + #power-domain-cells = <0>; + compatible = "renesas,sh7751r-cpg"; + clocks = <&extal>; + clock-names = "extal"; + reg = <0xffc00000 20>, <0xfe0a0000 16>; + reg-names = "FRQCR", "CLKSTP00"; + renesas,mode = <0>; + }; diff --git a/include/dt-bindings/clock/sh7750-cpg.h b/include/dt-bindings/clock/sh7750-cpg.h new file mode 100644 index 000000000000..ec267be91adf --- /dev/null +++ b/include/dt-bindings/clock/sh7750-cpg.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) + * + * Copyright 2023 Yoshinori Sato + */ + +#ifndef __DT_BINDINGS_CLOCK_SH7750_H__ +#define __DT_BINDINGS_CLOCK_SH7750_H__ + +#define SH7750_CPG_PLLOUT 0 + +#define SH7750_CPG_PCK 1 +#define SH7750_CPG_BCK 2 +#define SH7750_CPG_ICK 3 + +#define SH7750_MSTP_SCI 4 +#define SH7750_MSTP_RTC 5 +#define SH7750_MSTP_TMU012 6 +#define SH7750_MSTP_SCIF 7 +#define SH7750_MSTP_DMAC 8 +#define SH7750_MSTP_UBC 9 +#define SH7750_MSTP_SQ 10 +#define SH7750_CSTP_INTC 11 +#define SH7750_CSTP_TMU34 12 +#define SH7750_CSTP_PCIC 13 + +#endif From patchwork Thu Apr 4 04:59:42 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yoshinori Sato X-Patchwork-Id: 13616967 Received: from sakura.ysato.name (ik1-413-38519.vs.sakura.ne.jp [153.127.30.23]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 66A6B5810D for ; Thu, 4 Apr 2024 05:00:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=153.127.30.23 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712206861; cv=none; b=oj1tRdWlhofMqeS1PTURgaWWw6ibfq+s/MVrtdfq6efKpjYYH3rCzGafYj0p0/SeO0ndDVTlMrFtinDEv99JRCBjVpiBmoS2UPNQo91ub892Ez8nutkVzCyNgr/6LzXt6ggrxosXCrL7xUM+LFEGwD24CklMCZGabzm+G6D908k= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712206861; c=relaxed/simple; bh=Hz4pzC8dI8YsLdK/hgxwHgxaTjxeeWuYz5hIEbCWJbs=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=Vfy4JKNVZIFMjXrUPv84FP/MMonFUhacy7A1ZZxK8NSh2tbWFLcp+EPUGRNzAWMPt+vfHUuSaSFddZkCrKOXLg0iU494ZBhXDao5BNK1V1F7gFu2fIQ59WoBAUlgEWT8ytq6Hm7kC9r8IPvFDDLsZmRIfBfiCMEKFsrnGGpAjLg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=users.sourceforge.jp; spf=fail smtp.mailfrom=users.sourceforge.jp; arc=none smtp.client-ip=153.127.30.23 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=users.sourceforge.jp Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=users.sourceforge.jp Received: from SIOS1075.ysato.name (al128006.dynamic.ppp.asahi-net.or.jp [111.234.128.6]) by sakura.ysato.name (Postfix) with ESMTPSA id 177761C0914; Thu, 4 Apr 2024 14:00:59 +0900 (JST) From: Yoshinori Sato To: linux-sh@vger.kernel.org Cc: Yoshinori Sato Subject: [DO NOT MERGE v7 13/36] clk: Compatible with narrow registers Date: Thu, 4 Apr 2024 13:59:42 +0900 Message-Id: X-Mailer: git-send-email 2.39.2 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-sh@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 divider and gate only support 32-bit registers. Older hardware uses narrower registers, so I want to be able to handle 8-bit and 16-bit wide registers. Seven clk_divider flags are used, and if I add flags for 8bit access and 16bit access, 8bit will not be enough, so I expanded it to u16. Signed-off-by: Yoshinori Sato --- drivers/clk/clk-divider.c | 56 +++++++++++++++++++++----------- drivers/clk/clk-gate.c | 62 ++++++++++++++++++++++++++++-------- include/linux/clk-provider.h | 22 ++++++++++--- 3 files changed, 103 insertions(+), 37 deletions(-) diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c index a2c2b5203b0a..a1b5187cd63d 100644 --- a/drivers/clk/clk-divider.c +++ b/drivers/clk/clk-divider.c @@ -26,20 +26,38 @@ * parent - fixed parent. No clk_set_parent support */ -static inline u32 clk_div_readl(struct clk_divider *divider) -{ - if (divider->flags & CLK_DIVIDER_BIG_ENDIAN) - return ioread32be(divider->reg); - - return readl(divider->reg); +static inline u32 clk_div_read(struct clk_divider *divider) +{ + if (divider->flags & CLK_DIVIDER_REG_8BIT) + return readb(divider->reg); + else if (divider->flags & CLK_DIVIDER_REG_16BIT) { + if (divider->flags & CLK_DIVIDER_BIG_ENDIAN) + return ioread16be(divider->reg); + else + return readw(divider->reg); + } else { + if (divider->flags & CLK_DIVIDER_BIG_ENDIAN) + return ioread32be(divider->reg); + else + return readl(divider->reg); + } } -static inline void clk_div_writel(struct clk_divider *divider, u32 val) +static inline void clk_div_write(struct clk_divider *divider, u32 val) { - if (divider->flags & CLK_DIVIDER_BIG_ENDIAN) - iowrite32be(val, divider->reg); - else - writel(val, divider->reg); + if (divider->flags & CLK_DIVIDER_REG_8BIT) + writeb(val, divider->reg); + else if (divider->flags & CLK_DIVIDER_REG_16BIT) { + if (divider->flags & CLK_DIVIDER_BIG_ENDIAN) + iowrite16be(val, divider->reg); + else + writew(val, divider->reg); + } else { + if (divider->flags & CLK_DIVIDER_BIG_ENDIAN) + iowrite32be(val, divider->reg); + else + writel(val, divider->reg); + } } static unsigned int _get_table_maxdiv(const struct clk_div_table *table, @@ -152,7 +170,7 @@ static unsigned long clk_divider_recalc_rate(struct clk_hw *hw, struct clk_divider *divider = to_clk_divider(hw); unsigned int val; - val = clk_div_readl(divider) >> divider->shift; + val = clk_div_read(divider) >> divider->shift; val &= clk_div_mask(divider->width); return divider_recalc_rate(hw, parent_rate, val, divider->table, @@ -434,7 +452,7 @@ static long clk_divider_round_rate(struct clk_hw *hw, unsigned long rate, if (divider->flags & CLK_DIVIDER_READ_ONLY) { u32 val; - val = clk_div_readl(divider) >> divider->shift; + val = clk_div_read(divider) >> divider->shift; val &= clk_div_mask(divider->width); return divider_ro_round_rate(hw, rate, prate, divider->table, @@ -455,7 +473,7 @@ static int clk_divider_determine_rate(struct clk_hw *hw, if (divider->flags & CLK_DIVIDER_READ_ONLY) { u32 val; - val = clk_div_readl(divider) >> divider->shift; + val = clk_div_read(divider) >> divider->shift; val &= clk_div_mask(divider->width); return divider_ro_determine_rate(hw, req, divider->table, @@ -505,11 +523,11 @@ static int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate, if (divider->flags & CLK_DIVIDER_HIWORD_MASK) { val = clk_div_mask(divider->width) << (divider->shift + 16); } else { - val = clk_div_readl(divider); + val = clk_div_read(divider); val &= ~(clk_div_mask(divider->width) << divider->shift); } val |= (u32)value << divider->shift; - clk_div_writel(divider, val); + clk_div_write(divider, val); if (divider->lock) spin_unlock_irqrestore(divider->lock, flags); @@ -538,7 +556,7 @@ struct clk_hw *__clk_hw_register_divider(struct device *dev, struct device_node *np, const char *name, const char *parent_name, const struct clk_hw *parent_hw, const struct clk_parent_data *parent_data, unsigned long flags, - void __iomem *reg, u8 shift, u8 width, u8 clk_divider_flags, + void __iomem *reg, u8 shift, u8 width, u32 clk_divider_flags, const struct clk_div_table *table, spinlock_t *lock) { struct clk_divider *div; @@ -610,7 +628,7 @@ EXPORT_SYMBOL_GPL(__clk_hw_register_divider); struct clk *clk_register_divider_table(struct device *dev, const char *name, const char *parent_name, unsigned long flags, void __iomem *reg, u8 shift, u8 width, - u8 clk_divider_flags, const struct clk_div_table *table, + u32 clk_divider_flags, const struct clk_div_table *table, spinlock_t *lock) { struct clk_hw *hw; @@ -664,7 +682,7 @@ struct clk_hw *__devm_clk_hw_register_divider(struct device *dev, struct device_node *np, const char *name, const char *parent_name, const struct clk_hw *parent_hw, const struct clk_parent_data *parent_data, unsigned long flags, - void __iomem *reg, u8 shift, u8 width, u8 clk_divider_flags, + void __iomem *reg, u8 shift, u8 width, u32 clk_divider_flags, const struct clk_div_table *table, spinlock_t *lock) { struct clk_hw **ptr, *hw; diff --git a/drivers/clk/clk-gate.c b/drivers/clk/clk-gate.c index 68e585a02fd9..65191f9684ff 100644 --- a/drivers/clk/clk-gate.c +++ b/drivers/clk/clk-gate.c @@ -24,20 +24,38 @@ * parent - fixed parent. No clk_set_parent support */ -static inline u32 clk_gate_readl(struct clk_gate *gate) +static inline u32 clk_gate_read(struct clk_gate *gate) { - if (gate->flags & CLK_GATE_BIG_ENDIAN) - return ioread32be(gate->reg); - - return readl(gate->reg); + if (gate->flags & CLK_GATE_REG_8BIT) + return readb(gate->reg); + else if (gate->flags & CLK_GATE_REG_16BIT) { + if (gate->flags & CLK_GATE_BIG_ENDIAN) + return ioread16be(gate->reg); + else + return readw(gate->reg); + } else { + if (gate->flags & CLK_GATE_BIG_ENDIAN) + return ioread32be(gate->reg); + else + return readl(gate->reg); + } } -static inline void clk_gate_writel(struct clk_gate *gate, u32 val) +static inline void clk_gate_write(struct clk_gate *gate, u32 val) { - if (gate->flags & CLK_GATE_BIG_ENDIAN) - iowrite32be(val, gate->reg); - else - writel(val, gate->reg); + if (gate->flags & CLK_GATE_REG_8BIT) + writeb(val, gate->reg); + else if (gate->flags & CLK_GATE_REG_16BIT) { + if (gate->flags & CLK_GATE_BIG_ENDIAN) + iowrite16be(val, gate->reg); + else + writew(val, gate->reg); + } else { + if (gate->flags & CLK_GATE_BIG_ENDIAN) + iowrite32be(val, gate->reg); + else + writel(val, gate->reg); + } } /* @@ -72,7 +90,7 @@ static void clk_gate_endisable(struct clk_hw *hw, int enable) if (set) reg |= BIT(gate->bit_idx); } else { - reg = clk_gate_readl(gate); + reg = clk_gate_read(gate); if (set) reg |= BIT(gate->bit_idx); @@ -80,7 +98,7 @@ static void clk_gate_endisable(struct clk_hw *hw, int enable) reg &= ~BIT(gate->bit_idx); } - clk_gate_writel(gate, reg); + clk_gate_write(gate, reg); if (gate->lock) spin_unlock_irqrestore(gate->lock, flags); @@ -105,7 +123,7 @@ int clk_gate_is_enabled(struct clk_hw *hw) u32 reg; struct clk_gate *gate = to_clk_gate(hw); - reg = clk_gate_readl(gate); + reg = clk_gate_read(gate); /* if a set bit disables this clk, flip it before masking */ if (gate->flags & CLK_GATE_SET_TO_DISABLE) @@ -137,12 +155,30 @@ struct clk_hw *__clk_hw_register_gate(struct device *dev, struct clk_init_data init = {}; int ret = -EINVAL; + /* validate register size option and bit_idx */ if (clk_gate_flags & CLK_GATE_HIWORD_MASK) { if (bit_idx > 15) { pr_err("gate bit exceeds LOWORD field\n"); return ERR_PTR(-EINVAL); } } + if (clk_gate_flags & CLK_GATE_REG_16BIT) { + if (bit_idx > 15) { + pr_err("gate bit exceeds 16 bits\n"); + return ERR_PTR(-EINVAL); + } + } + if (clk_gate_flags & CLK_GATE_REG_8BIT) { + if (bit_idx > 7) { + pr_err("gate bit exceeds 8 bits\n"); + return ERR_PTR(-EINVAL); + } + } + if ((clk_gate_flags & CLK_GATE_HIWORD_MASK) && + clk_gate_flags & (CLK_GATE_REG_8BIT | CLK_GATE_REG_16BIT)) { + pr_err("HIWORD_MASK required 32-bit register\n"); + return ERR_PTR(-EINVAL); + } /* allocate the gate */ gate = kzalloc(sizeof(*gate), GFP_KERNEL); diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index 4a537260f655..eaa6ff1d0b2e 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -508,12 +508,16 @@ void of_fixed_clk_setup(struct device_node *np); * CLK_GATE_BIG_ENDIAN - by default little endian register accesses are used for * the gate register. Setting this flag makes the register accesses big * endian. + * CLK_GATE_REG_8BIT - by default 32bit register accesses are used for + * the gate register. Setting this flag makes the register accesses 8bit. + * CLK_GATE_REG_16BIT - by default 32bit register accesses are used for + * the gate register. Setting this flag makes the register accesses 16bit. */ struct clk_gate { struct clk_hw hw; void __iomem *reg; u8 bit_idx; - u8 flags; + u32 flags; spinlock_t *lock; }; @@ -522,6 +526,8 @@ struct clk_gate { #define CLK_GATE_SET_TO_DISABLE BIT(0) #define CLK_GATE_HIWORD_MASK BIT(1) #define CLK_GATE_BIG_ENDIAN BIT(2) +#define CLK_GATE_REG_8BIT BIT(3) +#define CLK_GATE_REG_16BIT BIT(4) extern const struct clk_ops clk_gate_ops; struct clk_hw *__clk_hw_register_gate(struct device *dev, @@ -675,13 +681,17 @@ struct clk_div_table { * CLK_DIVIDER_BIG_ENDIAN - By default little endian register accesses are used * for the divider register. Setting this flag makes the register accesses * big endian. + * CLK_DIVIDER_REG_8BIT - by default 32bit register accesses are used for + * the gate register. Setting this flag makes the register accesses 8bit. + * CLK_DIVIDER_REG_16BIT - by default 32bit register accesses are used for + * the gate register. Setting this flag makes the register accesses 16bit. */ struct clk_divider { struct clk_hw hw; void __iomem *reg; u8 shift; u8 width; - u8 flags; + u16 flags; const struct clk_div_table *table; spinlock_t *lock; }; @@ -697,6 +707,8 @@ struct clk_divider { #define CLK_DIVIDER_READ_ONLY BIT(5) #define CLK_DIVIDER_MAX_AT_ZERO BIT(6) #define CLK_DIVIDER_BIG_ENDIAN BIT(7) +#define CLK_DIVIDER_REG_8BIT BIT(8) +#define CLK_DIVIDER_REG_16BIT BIT(9) extern const struct clk_ops clk_divider_ops; extern const struct clk_ops clk_divider_ro_ops; @@ -726,18 +738,18 @@ struct clk_hw *__clk_hw_register_divider(struct device *dev, struct device_node *np, const char *name, const char *parent_name, const struct clk_hw *parent_hw, const struct clk_parent_data *parent_data, unsigned long flags, - void __iomem *reg, u8 shift, u8 width, u8 clk_divider_flags, + void __iomem *reg, u8 shift, u8 width, u32 clk_divider_flags, const struct clk_div_table *table, spinlock_t *lock); struct clk_hw *__devm_clk_hw_register_divider(struct device *dev, struct device_node *np, const char *name, const char *parent_name, const struct clk_hw *parent_hw, const struct clk_parent_data *parent_data, unsigned long flags, - void __iomem *reg, u8 shift, u8 width, u8 clk_divider_flags, + void __iomem *reg, u8 shift, u8 width, u32 clk_divider_flags, const struct clk_div_table *table, spinlock_t *lock); struct clk *clk_register_divider_table(struct device *dev, const char *name, const char *parent_name, unsigned long flags, void __iomem *reg, u8 shift, u8 width, - u8 clk_divider_flags, const struct clk_div_table *table, + u32 clk_divider_flags, const struct clk_div_table *table, spinlock_t *lock); /** * clk_register_divider - register a divider clock with the clock framework From patchwork Thu Apr 4 04:59:45 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yoshinori Sato X-Patchwork-Id: 13616970 Received: from sakura.ysato.name (ik1-413-38519.vs.sakura.ne.jp [153.127.30.23]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 5EE42634E2 for ; Thu, 4 Apr 2024 05:01:03 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=153.127.30.23 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712206865; cv=none; b=n2V46F451ADRPNZpagmg0zw67gpaClBbIK8PKU1zaQzLkgz7TXAHx/tOC8lI/8pXz60MoIObUDi3tovtdbLkAv8oEdOJjsCG4KAIoikbpI1+7JxiNG7iS8dLcrpEvI94Eu5D/mFHY3zR6/zRjk47t9gjy3RmKojvKhAfbYDLEd4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712206865; c=relaxed/simple; bh=lu04S1z5esVKIKbtLupdeTesyqNKCVwU4W+dAOV5/pg=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=tcfvGqjWzsWXjbemdzK+6du74xlywjkjxPtvanqwGzE5yzqtiVkEkUSXieI8GR4FV31UX8vhOIUQpze5boQq4lpIvfeomX+dVRoChL7Ek1OIPhKX2QgMlGTQIQsjjod8ZR/+7X6ibNQQERaI1XzqM2E+cuP9uYFgt8RitM9IKQo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=users.sourceforge.jp; spf=fail smtp.mailfrom=users.sourceforge.jp; arc=none smtp.client-ip=153.127.30.23 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=users.sourceforge.jp Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=users.sourceforge.jp Received: from SIOS1075.ysato.name (al128006.dynamic.ppp.asahi-net.or.jp [111.234.128.6]) by sakura.ysato.name (Postfix) with ESMTPSA id 011B31C089C; Thu, 4 Apr 2024 14:01:02 +0900 (JST) From: Yoshinori Sato To: linux-sh@vger.kernel.org Cc: Yoshinori Sato Subject: [DO NOT MERGE v7 14/36] clk: renesas: Add SH7750/7751 CPG Driver Date: Thu, 4 Apr 2024 13:59:45 +0900 Message-Id: <59459fd47e77a6978dc83804eba7cd5998016e75.1712041249.git.ysato@users.sourceforge.jp> X-Mailer: git-send-email 2.39.2 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-sh@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Renesas SH7750 and SH7751 series CPG driver. This driver supported frequency control and clock gating. Signed-off-by: Yoshinori Sato --- drivers/clk/renesas/Kconfig | 13 +- drivers/clk/renesas/Makefile | 1 + drivers/clk/renesas/clk-sh7750.c | 480 +++++++++++++++++++++++++++++++ 3 files changed, 491 insertions(+), 3 deletions(-) create mode 100644 drivers/clk/renesas/clk-sh7750.c diff --git a/drivers/clk/renesas/Kconfig b/drivers/clk/renesas/Kconfig index d252150402e8..482efcb6e76e 100644 --- a/drivers/clk/renesas/Kconfig +++ b/drivers/clk/renesas/Kconfig @@ -1,8 +1,8 @@ # SPDX-License-Identifier: GPL-2.0 config CLK_RENESAS - bool "Renesas SoC clock support" if COMPILE_TEST && !ARCH_RENESAS - default y if ARCH_RENESAS + bool "Renesas SoC clock support" if COMPILE_TEST && !ARCH_RENESAS && !SUPERH + default y if ARCH_RENESAS || SUPERH select CLK_EMEV2 if ARCH_EMEV2 select CLK_RZA1 if ARCH_R7S72100 select CLK_R7S9210 if ARCH_R7S9210 @@ -41,6 +41,9 @@ config CLK_RENESAS select CLK_R9A08G045 if ARCH_R9A08G045 select CLK_R9A09G011 if ARCH_R9A09G011 select CLK_SH73A0 if ARCH_SH73A0 + select CLK_SH7750 if CPU_SUBTYPE_SH7750 || CPU_SUBTYPE_SH7750S || \ + CPU_SUBTYPE_SH7750R || CPU_SUBTYPE_SH7751 || \ + CPU_SUBTYPE_SH7751R if CLK_RENESAS @@ -198,7 +201,6 @@ config CLK_SH73A0 select CLK_RENESAS_CPG_MSTP select CLK_RENESAS_DIV6 - # Family config CLK_RCAR_CPG_LIB bool "CPG/MSSR library functions" if COMPILE_TEST @@ -228,6 +230,11 @@ config CLK_RZG2L bool "Renesas RZ/{G2L,G2UL,G3S,V2L} family clock support" if COMPILE_TEST select RESET_CONTROLLER +config CLK_SH7750 + bool "Renesas SH7750/7751 family clock support" if COMPILE_TEST + help + This is a driver for SH7750 / SH7751 CPG. + # Generic config CLK_RENESAS_CPG_MSSR bool "CPG/MSSR clock support" if COMPILE_TEST diff --git a/drivers/clk/renesas/Makefile b/drivers/clk/renesas/Makefile index f7e18679c3b8..ea0ffa8d59c4 100644 --- a/drivers/clk/renesas/Makefile +++ b/drivers/clk/renesas/Makefile @@ -38,6 +38,7 @@ obj-$(CONFIG_CLK_R9A07G054) += r9a07g044-cpg.o obj-$(CONFIG_CLK_R9A08G045) += r9a08g045-cpg.o obj-$(CONFIG_CLK_R9A09G011) += r9a09g011-cpg.o obj-$(CONFIG_CLK_SH73A0) += clk-sh73a0.o +obj-$(CONFIG_CLK_SH7750) += clk-sh7750.o # Family obj-$(CONFIG_CLK_RCAR_CPG_LIB) += rcar-cpg-lib.o diff --git a/drivers/clk/renesas/clk-sh7750.c b/drivers/clk/renesas/clk-sh7750.c new file mode 100644 index 000000000000..043269d31200 --- /dev/null +++ b/drivers/clk/renesas/clk-sh7750.c @@ -0,0 +1,480 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Renesas SH7750/51 CPG driver + * + * Copyright 2023 Yoshinori Sato + */ + +#include +#include +#include +#include +#include +#include +#include + +/* PCLK divide rate selector */ +static const struct clk_div_table pdiv_table[] = { + { .val = 0, .div = 2, }, + { .val = 1, .div = 3, }, + { .val = 2, .div = 4, }, + { .val = 3, .div = 6, }, + { .val = 4, .div = 8, }, + { } +}; + +/* ICLK and BCLK divide rate selector */ +static const struct clk_div_table div_table[] = { + { .val = 0, .div = 1, }, + { .val = 1, .div = 2, }, + { .val = 2, .div = 3, }, + { .val = 3, .div = 4, }, + { .val = 4, .div = 6, }, + { .val = 5, .div = 8, }, + { } +}; + +struct cpg_priv { + struct clk_hw hw; + spinlock_t clklock; + void __iomem *frqcr; + void __iomem *clkstp00; + u32 mode; + u32 feat; +}; + +/* CPG feature flag */ +#define CPG_DIV1 BIT(0) /* 7750, 7750S, 7751 */ +#define MSTP_CR2 BIT(1) /* 7750S, 7750R, 7751, 7751R */ +#define MSTP_CLKSTP BIT(2) /* 7750R, 7751, 7751R */ +#define MSTP_CSTP2 BIT(3) /* 7751, 7751R */ + +enum { + CPG_SH7750, + CPG_SH7750S, + CPG_SH7750R, + CPG_SH7751, + CPG_SH7751R, +}; + +static const u32 cpg_feature[] = { + [CPG_SH7750] = CPG_DIV1, + [CPG_SH7750S] = CPG_DIV1 | MSTP_CR2, + [CPG_SH7750R] = MSTP_CR2 | MSTP_CLKSTP, + [CPG_SH7751] = CPG_DIV1 | MSTP_CR2 | MSTP_CLKSTP | MSTP_CSTP2, + [CPG_SH7751R] = MSTP_CR2 | MSTP_CLKSTP | MSTP_CSTP2, +}; + +enum clk_type {CLK_DIV, CLK_STBCR, CLK_STBCR2, CLK_CLKSTP00}; + +enum { + FRQCR = 0, + STBCR = 4, + WTCNT = 8, + WTCSR = 12, + STBCR2 = 16, + CLKSTP00 = 0, + CLKSTPCLR00 = 8, +}; + +static struct cpg_priv *cpg_data; + +#define to_priv(_hw) container_of(_hw, struct cpg_priv, hw) + +#define FRQCR_PLL1EN BIT(10) +static const unsigned int pll1mult[] = { 12, 12, 6, 12, 6, 12, 1}; + +static unsigned long pll_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct cpg_priv *cpg = to_priv(hw); + unsigned long rate = parent_rate; + u16 frqcr; + + frqcr = ioread16(cpg->frqcr); + if (frqcr & FRQCR_PLL1EN) { + rate *= pll1mult[cpg->mode]; + if (cpg->mode < 6 && (cpg->feat & CPG_DIV1)) + rate /= 2; + } + return rate; +} + +static void get_round_rate(struct cpg_priv *cpg, + unsigned long *out, bool *pllen, + unsigned long rate, unsigned long prate) +{ + long pllout, res; + bool pll; + + if (cpg->mode < 6 && (cpg->feat & CPG_DIV1)) + prate /= 2; + + pllout = prate * pll1mult[cpg->mode]; + if (abs(pllout - rate) > abs(prate - rate)) { + res = prate; + pll = false; + } else { + res = pllout; + pll = true; + } + if (out) + *out = res; + if (pllen) + *pllen = pll; +} + +static int pll_determine_rate(struct clk_hw *hw, struct clk_rate_request *req) +{ + struct cpg_priv *cpg = to_priv(hw); + + get_round_rate(cpg, &req->rate, NULL, req->rate, req->best_parent_rate); + return 0; +} + +static int pll_set_rate(struct clk_hw *hw, + unsigned long rate, unsigned long prate) +{ + struct cpg_priv *cpg = to_priv(hw); + bool oldpll, newpll; + u16 frqcr; + + frqcr = ioread16(cpg->frqcr); + get_round_rate(cpg, NULL, &newpll, rate, prate); + oldpll = frqcr & FRQCR_PLL1EN; + frqcr &= ~FRQCR_PLL1EN; + + if (newpll) { + frqcr |= FRQCR_PLL1EN; + if (!oldpll) { + /* set PLL wakeup delay time */ + iowrite16(0xa500, cpg->frqcr + WTCNT); + iowrite16(0xa507, cpg->frqcr + WTCNT); + iowrite16(0x5a00, cpg->frqcr + WTCSR); + } + } + iowrite16(frqcr, cpg->frqcr); + + /* Test for new PLL state */ + frqcr = ioread16(cpg->frqcr); + oldpll = frqcr & FRQCR_PLL1EN; + return !(oldpll == newpll); +} + +static const struct clk_ops pll_ops = { + .recalc_rate = pll_recalc_rate, + .determine_rate = pll_determine_rate, + .set_rate = pll_set_rate, +}; + +#define PLLOUT "pllout" + +static int register_pll(struct device_node *node, struct cpg_priv *cpg) +{ + const char *clk_name = node->name; + const char *parent_name; + struct clk_init_data init = { + .name = PLLOUT, + .ops = &pll_ops, + .flags = 0, + .num_parents = 1, + }; + int ret; + + parent_name = of_clk_get_parent_name(node, 0); + init.parent_names = &parent_name; + cpg->hw.init = &init; + + ret = of_clk_hw_register(node, &cpg->hw); + if (ret < 0) + pr_err("%pOF: failed to add provider %s (%d)\n", + node, clk_name, ret); + return ret; +} + +static void clkstp00_sw(struct clk_hw *hw, bool on) +{ + u32 val; + struct clk_gate *gate = to_clk_gate(hw); + + val = BIT(gate->bit_idx); + if (on) + writel(val, gate->reg + CLKSTPCLR00); + else + writel(val, gate->reg); +} + +static int clkstp00_enable(struct clk_hw *hw) +{ + clkstp00_sw(hw, true); + return 0; +} + +static void clkstp00_disable(struct clk_hw *hw) +{ + clkstp00_sw(hw, false); +} + +static int clkstp00_is_enabled(struct clk_hw *hw) +{ + u8 val; + struct clk_gate *gate = to_clk_gate(hw); + + val = readb(gate->reg); + val &= 1 << gate->bit_idx; + return val == 0; +} + +static const struct clk_ops gate_clkstp00_ops = { + .enable = clkstp00_enable, + .disable = clkstp00_disable, + .is_enabled = clkstp00_is_enabled, +}; + +static struct clk_hw *clk_hw_register_clkstp(struct device_node *node, + const char *name, + const char *parent, + void __iomem *reg, int bit, + spinlock_t *lock) +{ + struct clk_gate *gate; + struct clk_init_data init = { + .name = name, + .ops = &gate_clkstp00_ops, + .flags = 0, + .parent_names = &parent, + .num_parents = 1, + }; + struct clk_hw *hw; + int ret; + + gate = kzalloc(sizeof(*gate), GFP_KERNEL); + if (gate == NULL) + goto error; + gate->reg = reg; + gate->bit_idx = bit; + gate->flags = 0; + gate->lock = lock; + gate->hw.init = &init; + hw = &gate->hw; + ret = of_clk_hw_register(node, hw); + if (ret < 0) + goto error; + return hw; +error: + kfree(gate); + return ERR_PTR(ret); +} + +#define STBCR_BASE 5 +#define CLKSTP_BASE 2 +static int register_div(struct device_node *node, struct cpg_priv *cpg) +{ + static const char * const divout[] = { + "fck", "bck", "ick", + }; + static const char * const stbcrout[] = { + "sci_clk", "rtc_clk", "tmu012_clk", /* STBCR */ + "scif_clk", "dmac_clk", /* STBCR */ + "ubc_clk", "sq_clk", /* STBCR2 */ + }; + static const char * const clkstpout[] = { + "intc_clk", "tmu34_clk", "pcic_clk", /* CLKSTP00 */ + }; + + int num_clk = ARRAY_SIZE(divout) + ARRAY_SIZE(stbcrout) + ARRAY_SIZE(clkstpout); + struct clk_hw_onecell_data *data; + struct clk_hw *reg_hw; + unsigned int i, n; + int ret; + + data = kzalloc(struct_size(data, hws, num_clk + 1), GFP_KERNEL); + if (!data) + return -ENOMEM; + + num_clk = 0; + for (i = 0; i < ARRAY_SIZE(divout); i++) { + reg_hw = __clk_hw_register_divider(NULL, node, divout[i], + PLLOUT, NULL, NULL, + 0, cpg->frqcr, i * 3, 3, + CLK_DIVIDER_REG_16BIT, + (i == 0) ? pdiv_table : div_table, + &cpg->clklock); + if (IS_ERR(reg_hw)) { + ret = PTR_ERR(reg_hw); + goto error; + } + data->hws[num_clk++] = reg_hw; + } + + n = (cpg->feat & MSTP_CR2) ? ARRAY_SIZE(stbcrout) : STBCR_BASE; + for (i = 0; i < n; i++) { + u32 off = (i < (ARRAY_SIZE(stbcrout) - 2)) ? STBCR : STBCR2; + + reg_hw = __clk_hw_register_gate(NULL, node, stbcrout[i], + divout[0], NULL, NULL, + 0, cpg->frqcr + off, i % STBCR_BASE, + CLK_GATE_REG_8BIT | CLK_GATE_SET_TO_DISABLE, + &cpg->clklock); + if (IS_ERR(reg_hw)) { + ret = PTR_ERR(reg_hw); + goto error; + } + data->hws[num_clk++] = reg_hw; + } + + if (cpg->feat & MSTP_CLKSTP) { + n = (cpg->feat & MSTP_CSTP2) ? ARRAY_SIZE(clkstpout) : CLKSTP_BASE; + for (i = 0; i < n; i++) { + reg_hw = clk_hw_register_clkstp(node, clkstpout[i], + divout[0], cpg->clkstp00, + i, &cpg->clklock); + if (IS_ERR(reg_hw)) { + ret = PTR_ERR(reg_hw); + goto error; + } + data->hws[num_clk++] = reg_hw; + } + } + + data->num = num_clk; + ret = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, data); + if (ret < 0) + goto error; + return 0; + +error: + pr_err("%pOF: failed to register clock (%d)\n", + node, ret); + for (num_clk--; num_clk >= 0; num_clk--) + kfree(data->hws[num_clk]); + kfree(data); + return ret; +} + +#define NR_CLKMODE 7 +static int sh7750_cpg_setup(struct device_node *node, u32 feat) +{ + struct cpg_priv *cpg; + u32 mode = NR_CLKMODE; + int ret = 0; + + cpg_data = NULL; + + of_property_read_u32_index(node, "renesas,mode", 0, &mode); + if (mode >= NR_CLKMODE) { + pr_err("%s: Invalid clock mode setting (%u)\n", + node->name, mode); + return -EINVAL; + } + + cpg = kzalloc(sizeof(struct cpg_priv), GFP_KERNEL); + if (!cpg) + return -ENOMEM; + + cpg->frqcr = of_iomap(node, 0); + if (cpg->frqcr == NULL) { + pr_err("%pOF: failed to map divide register", node); + ret = -ENODEV; + goto cpg_free; + } + + if (feat & MSTP_CLKSTP) { + cpg->clkstp00 = of_iomap(node, 1); + if (cpg->clkstp00 == NULL) { + pr_err("%pOF: failed to map clkstp00 register", node); + ret = -ENODEV; + goto unmap_frqcr; + } + } + cpg->feat = feat; + cpg->mode = mode; + + ret = register_pll(node, cpg); + if (ret < 0) + goto unmap_clkstp00; + + ret = register_div(node, cpg); + if (ret < 0) + goto unmap_clkstp00; + + cpg_data = cpg; + return 0; + +unmap_clkstp00: + iounmap(cpg->clkstp00); +unmap_frqcr: + iounmap(cpg->frqcr); +cpg_free: + kfree(cpg); + return ret; +} + +static void __init sh7750_cpg_init(struct device_node *node) +{ + sh7750_cpg_setup(node, cpg_feature[CPG_SH7750]); +} + +static void __init sh7750s_cpg_init(struct device_node *node) +{ + sh7750_cpg_setup(node, cpg_feature[CPG_SH7750S]); +} + +static void __init sh7750r_cpg_init(struct device_node *node) +{ + sh7750_cpg_setup(node, cpg_feature[CPG_SH7750R]); +} + +static void __init sh7751_cpg_init(struct device_node *node) +{ + sh7750_cpg_setup(node, cpg_feature[CPG_SH7751]); +} + +static void __init sh7751r_cpg_init(struct device_node *node) +{ + sh7750_cpg_setup(node, cpg_feature[CPG_SH7751R]); +} + +CLK_OF_DECLARE_DRIVER(sh7750_cpg, "renesas,sh7750-cpg", + sh7750_cpg_init); +CLK_OF_DECLARE_DRIVER(sh7750s_cpg, "renesas,sh7750s-cpg", + sh7750s_cpg_init); +CLK_OF_DECLARE_DRIVER(sh7750r_cpg, "renesas,sh7750r-cpg", + sh7750r_cpg_init); +CLK_OF_DECLARE_DRIVER(sh7751_cpg, "renesas,sh7751-cpg", + sh7751_cpg_init); +CLK_OF_DECLARE_DRIVER(sh7751r_cpg, "renesas,sh7751r-cpg", + sh7751r_cpg_init); + +static int sh7750_cpg_probe(struct platform_device *pdev) +{ + u32 feature; + + if (cpg_data) + return 0; + feature = *(u32 *)of_device_get_match_data(&pdev->dev); + return sh7750_cpg_setup(pdev->dev.of_node, feature); +} + +static const struct of_device_id sh7750_cpg_of_match[] = { + { .compatible = "renesas,sh7750-cpg", + .data = &cpg_feature[CPG_SH7750] }, + { .compatible = "renesas,sh7750s-cpg", + .data = &cpg_feature[CPG_SH7750S] }, + { .compatible = "renesas,sh7750r-cpg", + .data = &cpg_feature[CPG_SH7750R] }, + { .compatible = "renesas,sh7751-cpg", + .data = &cpg_feature[CPG_SH7751] }, + { .compatible = "renesas,sh7751r-cpg", + .data = &cpg_feature[CPG_SH7751R] }, + { } +}; + +static struct platform_driver sh7750_cpg_driver = { + .probe = sh7750_cpg_probe, + .driver = { + .name = "sh7750-cpg", + .of_match_table = sh7750_cpg_of_match, + }, +}; +builtin_platform_driver(sh7750_cpg_driver); From patchwork Thu Apr 4 04:59:47 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yoshinori Sato X-Patchwork-Id: 13616972 Received: from sakura.ysato.name (ik1-413-38519.vs.sakura.ne.jp [153.127.30.23]) by smtp.subspace.kernel.org (Postfix) with ESMTP id DDDD46BFA1 for ; Thu, 4 Apr 2024 05:01:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=153.127.30.23 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712206867; cv=none; b=DTog5mISdA/2L+k1i5C/FuoMyIZn8oRVi3LgAzaCJejF0KDlvop+SPhmvVVBY6aYaH75tKMldD36DHUPoRf2L5PX6rPf9y1xEusmQ0oS4byQcxftu8OldPzDpkprZ2Y4fQabHxffVIY7p8ROYgCAuUv7GPskOSFb80HMAuXUmxg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712206867; c=relaxed/simple; bh=oCrxEmk2AZZ3QAEZghfuBRaq+IhD5YVLcxnsl2qregU=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=ZlL91IaS0ceNADlSFRdJK+g+NjjaKkZATlrRHKnywVZjxvqobtVm2ZsWVqdMqBOVRTSg5GB6vKT92Ggx8pNhx8D8idfxyF5hnk3bUwlbNPp/6yp3hRfTlAcvRhbvU490DC+buAI5eqyix0vw89cKTlPbJkXIuPyA6dpXm3Nr0vg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=users.sourceforge.jp; spf=fail smtp.mailfrom=users.sourceforge.jp; arc=none smtp.client-ip=153.127.30.23 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=users.sourceforge.jp Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=users.sourceforge.jp Received: from SIOS1075.ysato.name (al128006.dynamic.ppp.asahi-net.or.jp [111.234.128.6]) by sakura.ysato.name (Postfix) with ESMTPSA id EDABD1C016F; Thu, 4 Apr 2024 14:01:04 +0900 (JST) From: Yoshinori Sato To: linux-sh@vger.kernel.org Cc: Yoshinori Sato Subject: [DO NOT MERGE v7 15/36] irqchip: Add SH7751 INTC driver Date: Thu, 4 Apr 2024 13:59:47 +0900 Message-Id: X-Mailer: git-send-email 2.39.2 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-sh@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Renesas SH7751 Internal interrupt controller driver. Signed-off-by: Yoshinori Sato --- drivers/irqchip/Kconfig | 8 + drivers/irqchip/Makefile | 1 + drivers/irqchip/irq-renesas-sh7751.c | 282 +++++++++++++++++++++++++++ 3 files changed, 291 insertions(+) create mode 100644 drivers/irqchip/irq-renesas-sh7751.c diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig index 72c07a12f5e1..33badb5b4f00 100644 --- a/drivers/irqchip/Kconfig +++ b/drivers/irqchip/Kconfig @@ -690,4 +690,12 @@ config SUNPLUS_SP7021_INTC chained controller, routing all interrupt source in P-Chip to the primary controller on C-Chip. +config RENESAS_SH7751_INTC + bool "Renesas SH7751 Interrupt Controller" + depends on SH_DEVICE_TREE || COMPILE_TEST + select IRQ_DOMAIN_HIERARCHY + help + Support for the Renesas SH7751 On-chip interrupt controller. + And external interrupt encoder for some targets. + endmenu diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile index ec4a18380998..51855034a895 100644 --- a/drivers/irqchip/Makefile +++ b/drivers/irqchip/Makefile @@ -121,3 +121,4 @@ obj-$(CONFIG_IRQ_IDT3243X) += irq-idt3243x.o obj-$(CONFIG_APPLE_AIC) += irq-apple-aic.o obj-$(CONFIG_MCHP_EIC) += irq-mchp-eic.o obj-$(CONFIG_SUNPLUS_SP7021_INTC) += irq-sp7021-intc.o +obj-$(CONFIG_RENESAS_SH7751_INTC) += irq-renesas-sh7751.o diff --git a/drivers/irqchip/irq-renesas-sh7751.c b/drivers/irqchip/irq-renesas-sh7751.c new file mode 100644 index 000000000000..91d6dc3ed04c --- /dev/null +++ b/drivers/irqchip/irq-renesas-sh7751.c @@ -0,0 +1,282 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Renesas SH7751 interrupt controller driver + * + * Copyright 2023 Yoshinori Sato + */ + +#include +#include +#include +#include +#include +#include +#include + +struct ipr { + u16 off; + u16 idx; +}; + +struct sh7751_intc_priv { + const struct ipr *iprmap; + void __iomem *base; + void __iomem *intpri00; + bool irlm; +}; + +enum { + R_ICR = 0x00, + R_IPR = 0x04, + R_INTPRI00 = 0x00, + R_INTREQ00 = 0x20, + R_INTMSK00 = 0x40, + R_INTMSKCLR00 = 0x60, +}; + +#define ICR_IRLM BIT(7) + +/* + * SH7751 IRQ mapping + * IRQ16 - 63: Group0 - IPRA to IPRD + * IRQ16 - 31: external IRL input (ICR.IRLM is 0) + * IRQ80 - 92: Group1 - INTPRI00 + */ +#define IRQ_START 16 +#define MAX_IRL (IRQ_START + NR_IRL) +#define GRP0_IRQ_END 63 +#define GRP1_IRQ_START 80 +#define IRQ_END 92 + +#define NR_IPRMAP0 (GRP0_IRQ_END - IRQ_START + 1) +#define NR_IPRMAP1 (IRQ_END - GRP1_IRQ_START) +#define IPR_PRI_MASK 0x000f + +#define IPRA 0 +#define IPRB 4 +#define IPRC 8 +#define IPRD 12 +#define INTPRI00 256 +#define IPR_B12 12 +#define IPR_B8 8 +#define IPR_B4 4 +#define IPR_B0 0 + +/* SH7751 EVT to IPR mapping table */ +static const struct ipr sh7751_iprmap[] = { + [evt2irq(0x240)] = {IPRD, IPR_B12}, /* IRL0 (ICR.IRLM=1) */ + [evt2irq(0x2a0)] = {IPRD, IPR_B8}, /* IRL1 (ICR.IRLM=1) */ + [evt2irq(0x300)] = {IPRD, IPR_B4}, /* IRL2 (ICR.IRLM=1) */ + [evt2irq(0x360)] = {IPRD, IPR_B0}, /* IRL3 (ICR.IRLM=1) */ + [evt2irq(0x400)] = {IPRA, IPR_B12}, /* TMU0 */ + [evt2irq(0x420)] = {IPRA, IPR_B8}, /* TMU1 */ + [evt2irq(0x440)] = {IPRA, IPR_B4}, /* TMU2 TNUI */ + [evt2irq(0x460)] = {IPRA, IPR_B4}, /* TMU2 TICPI */ + [evt2irq(0x480)] = {IPRA, IPR_B0}, /* RTC ATI */ + [evt2irq(0x4a0)] = {IPRA, IPR_B0}, /* RTC PRI */ + [evt2irq(0x4c0)] = {IPRA, IPR_B0}, /* RTC CUI */ + [evt2irq(0x4e0)] = {IPRB, IPR_B4}, /* SCI ERI */ + [evt2irq(0x500)] = {IPRB, IPR_B4}, /* SCI RXI */ + [evt2irq(0x520)] = {IPRB, IPR_B4}, /* SCI TXI */ + [evt2irq(0x540)] = {IPRB, IPR_B4}, /* SCI TEI */ + [evt2irq(0x560)] = {IPRB, IPR_B12}, /* WDT */ + [evt2irq(0x580)] = {IPRB, IPR_B8}, /* REF RCMI */ + [evt2irq(0x5a0)] = {IPRB, IPR_B4}, /* REF ROVI */ + [evt2irq(0x600)] = {IPRC, IPR_B0}, /* H-UDI */ + [evt2irq(0x620)] = {IPRC, IPR_B12}, /* GPIO */ + [evt2irq(0x640)] = {IPRC, IPR_B8}, /* DMAC DMTE0 */ + [evt2irq(0x660)] = {IPRC, IPR_B8}, /* DMAC DMTE1 */ + [evt2irq(0x680)] = {IPRC, IPR_B8}, /* DMAC DMTE2 */ + [evt2irq(0x6a0)] = {IPRC, IPR_B8}, /* DMAC DMTE3 */ + [evt2irq(0x6c0)] = {IPRC, IPR_B8}, /* DMAC DMAE */ + [evt2irq(0x700)] = {IPRC, IPR_B4}, /* SCIF ERI */ + [evt2irq(0x720)] = {IPRC, IPR_B4}, /* SCIF RXI */ + [evt2irq(0x740)] = {IPRC, IPR_B4}, /* SCIF BRI */ + [evt2irq(0x760)] = {IPRC, IPR_B4}, /* SCIF TXI */ + [evt2irq(0x780)] = {IPRC, IPR_B8}, /* DMAC DMTE4 */ + [evt2irq(0x7a0)] = {IPRC, IPR_B8}, /* DMAC DMTE5 */ + [evt2irq(0x7c0)] = {IPRC, IPR_B8}, /* DMAC DMTE6 */ + [evt2irq(0x7e0)] = {IPRC, IPR_B8}, /* DMAC DMTE7 */ + [evt2irq(0xa00)] = {INTPRI00, IPR_B0}, /* PCIC PCISERR */ + [evt2irq(0xa20)] = {INTPRI00, IPR_B4}, /* PCIC PCIDMA3 */ + [evt2irq(0xa40)] = {INTPRI00, IPR_B4}, /* PCIC PCIDMA2 */ + [evt2irq(0xa60)] = {INTPRI00, IPR_B4}, /* PCIC PCIDMA1 */ + [evt2irq(0xa80)] = {INTPRI00, IPR_B4}, /* PCIC PCIDMA0 */ + [evt2irq(0xaa0)] = {INTPRI00, IPR_B4}, /* PCIC PCIPWON */ + [evt2irq(0xac0)] = {INTPRI00, IPR_B4}, /* PCIC PCIPWDWN */ + [evt2irq(0xae0)] = {INTPRI00, IPR_B4}, /* PCIC PCIERR */ + [evt2irq(0xb00)] = {INTPRI00, IPR_B8}, /* TMU3 */ + [evt2irq(0xb80)] = {INTPRI00, IPR_B12}, /* TMU4 */ +}; + +/* + * IPR registers have 4bit priority x 4 entry (16bits) + */ +static void update_ipr(struct sh7751_intc_priv *priv, unsigned int irq, u16 pri) +{ + const struct ipr *ipr = NULL; + void __iomem *ipr_base; + unsigned int offset; + u16 mask; + + ipr = priv->iprmap + irq; + if (irq < GRP1_IRQ_START) { + /* Group0 */ + ipr_base = priv->base + R_IPR; + offset = ipr->off; + } else { + /* Group1 */ + ipr_base = priv->intpri00; + offset = ipr->off - INTPRI00; + } + mask = ~(IPR_PRI_MASK << ipr->idx); + pri = (pri & IPR_PRI_MASK) << ipr->idx; + mask &= __raw_readw(ipr_base + offset); + __raw_writew(mask | pri, ipr_base + offset); +} + +static inline bool is_valid_irq(unsigned int irq) +{ + /* IRQ16 - 63 */ + if (irq >= IRQ_START && irq < IRQ_START + NR_IPRMAP0) + return true; + /* IRQ80 - 92 */ + if (irq >= GRP1_IRQ_START && irq <= IRQ_END) + return true; + return false; +} + +static inline struct sh7751_intc_priv *irq_data_to_priv(struct irq_data *data) +{ + return data->domain->host_data; +} + +/* Interrupt unmask priority is 1, mask priority is 0 */ +#define PRI_ENABLE 1 +#define PRI_DISABLE 0 +static void endisable_irq(struct irq_data *data, bool enable) +{ + struct sh7751_intc_priv *priv; + unsigned int irq; + + priv = irq_data_to_priv(data); + + irq = irqd_to_hwirq(data); + if (!is_valid_irq(irq)) { + /* IRQ out of range */ + pr_warn_once("%s: IRQ %u is out of range\n", __FILE__, irq); + return; + } + + if (irq <= MAX_IRL && !priv->irlm) { + /* IRL encoded external interrupt */ + /* enable and disable from SR.IMASK */ + update_sr_imask(irq - IRQ_START, enable); + } else { + /* Internal peripheral interrupt */ + /* enable and disable from interrupt priority */ + update_ipr(priv, irq, enable ? PRI_ENABLE : PRI_DISABLE); + } +} + +static void sh7751_mask_irq(struct irq_data *data) +{ + endisable_irq(data, false); +} + +static void sh7751_unmask_irq(struct irq_data *data) +{ + endisable_irq(data, true); +} + +static const struct irq_chip sh7751_irq_chip = { + .name = "SH7751-INTC", + .irq_unmask = sh7751_unmask_irq, + .irq_mask = sh7751_mask_irq, +}; + +static int irq_sh7751_map(struct irq_domain *h, unsigned int virq, + irq_hw_number_t hw_irq_num) +{ + irq_set_chip_and_handler(virq, &sh7751_irq_chip, handle_level_irq); + irq_get_irq_data(virq)->chip_data = h->host_data; + irq_modify_status(virq, IRQ_NOREQUEST, IRQ_NOPROBE); + return 0; +} + +static int irq_sh7751_xlate(struct irq_domain *d, struct device_node *ctrlr, + const u32 *intspec, unsigned int intsize, + unsigned long *out_hwirq, unsigned int *out_type) +{ + if (WARN_ON(intsize < 1)) + return -EINVAL; + *out_hwirq = evt2irq(intspec[0]); + *out_type = IRQ_TYPE_NONE; + return 0; +} + +static const struct irq_domain_ops irq_ops = { + .map = irq_sh7751_map, + .xlate = irq_sh7751_xlate, +}; + +static int __init shintc_of_init(struct device_node *intc, struct device_node *parent, + const struct ipr *iprmap) +{ + struct sh7751_intc_priv *priv; + void __iomem *base, *base2; + struct irq_domain *domain; + u16 icr; + int ret; + + priv = kzalloc(sizeof(struct sh7751_intc_priv), GFP_KERNEL); + if (priv == NULL) + return -ENOMEM; + + base = of_iomap(intc, 0); + base2 = of_iomap(intc, 1); + if (!base || !base2) { + pr_err("%pOFP: Invalid register definition\n", intc); + ret = -EINVAL; + goto error; + } + + priv->base = base; + priv->intpri00 = base2; + priv->iprmap = iprmap; + + if (of_property_read_bool(intc, "renesas,irlm")) { + priv->irlm = true; + icr = __raw_readw(priv->base + R_ICR); + icr |= ICR_IRLM; + __raw_writew(icr, priv->base + R_ICR); + } + + domain = irq_domain_add_linear(intc, NR_IRQS, &irq_ops, priv); + if (domain == NULL) { + pr_err("%pOFP: cannot initialize irq domain\n", intc); + ret = -ENOMEM; + goto error; + } + + irq_set_default_host(domain); + pr_info("%pOFP: SH7751 Interrupt controller (%s external IRQ)", + intc, priv->irlm ? "4 lines" : "15 level"); + return 0; + +error: + if (base) + iounmap(base); + if (base2) + iounmap(base); + kfree(priv); + return ret; +} + +static int __init sh7751_intc_of_init(struct device_node *intc, + struct device_node *parent) +{ + return shintc_of_init(intc, parent, sh7751_iprmap); +} + +IRQCHIP_DECLARE(sh_7751_intc, "renesas,sh7751-intc", sh7751_intc_of_init); From patchwork Thu Apr 4 04:59:48 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yoshinori Sato X-Patchwork-Id: 13616971 Received: from sakura.ysato.name (ik1-413-38519.vs.sakura.ne.jp [153.127.30.23]) by smtp.subspace.kernel.org (Postfix) with ESMTP id EA1E45B1FB for ; Thu, 4 Apr 2024 05:01:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=153.127.30.23 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712206867; cv=none; b=E3VQ2hyjmpIF1+dMVuO6Td7kpChCH2EtrrrXCY2Ux93jl9v3R2joonPCFhcTaHj1sL1gGJiILscAbT459GowM2BZJoECAGZlvaM0JL0OeaETTKqvJzQeP5WSyR5YQzP5Djw+MX8DfZIWMMpP+TXSCvTDHLJNCbVfSOGwE6axOMU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712206867; c=relaxed/simple; bh=D5ws4kol4ISHVGnY0BX2xqWsX9b4sW1yZaI0O/y/rdE=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=DX/nEhFTw5PR8u2jNdUlKPaVOyYSW8gCJnIzRnqcj4PUpFWorqPxCwSz+OnPHuMqPt0vOL1V2O87qVsFr5CvwSdxrfv8bRHsQkAVmOIVwdm2Vf1rUT4nqUwn7YdZN6fex71LnQm5mRs3u4q4NrdFbzNodIPBnkIt+FvvUk0n5ZE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=users.sourceforge.jp; spf=fail smtp.mailfrom=users.sourceforge.jp; arc=none smtp.client-ip=153.127.30.23 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=users.sourceforge.jp Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=users.sourceforge.jp Received: from SIOS1075.ysato.name (al128006.dynamic.ppp.asahi-net.or.jp [111.234.128.6]) by sakura.ysato.name (Postfix) with ESMTPSA id 1F4D91C092F; Thu, 4 Apr 2024 14:01:05 +0900 (JST) From: Yoshinori Sato To: linux-sh@vger.kernel.org Cc: Yoshinori Sato Subject: [DO NOT MERGE v7 16/36] dt-bindings: interrupt-controller: renesas,sh7751-intc: Add json-schema Date: Thu, 4 Apr 2024 13:59:48 +0900 Message-Id: X-Mailer: git-send-email 2.39.2 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-sh@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Renesas SH7751 INTC json-schema. Signed-off-by: Yoshinori Sato --- .../renesas,sh7751-intc.yaml | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 Documentation/devicetree/bindings/interrupt-controller/renesas,sh7751-intc.yaml diff --git a/Documentation/devicetree/bindings/interrupt-controller/renesas,sh7751-intc.yaml b/Documentation/devicetree/bindings/interrupt-controller/renesas,sh7751-intc.yaml new file mode 100644 index 000000000000..fb924eff465d --- /dev/null +++ b/Documentation/devicetree/bindings/interrupt-controller/renesas,sh7751-intc.yaml @@ -0,0 +1,53 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/interrupt-controller/renesas,sh7751-intc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Renesas SH7751 Interrupt Controller + +maintainers: + - Yoshinori Sato + +properties: + compatible: + items: + - const: renesas,sh7751-intc + + '#interrupt-cells': + const: 1 + + interrupt-controller: true + + reg: + maxItems: 2 + + reg-names: + items: + - const: ICR + - const: INTPRI00 + + renesas,icr-irlm: + $ref: /schemas/types.yaml#/definitions/flag + description: If true four independent interrupt requests mode (ICR.IRLM is 1). + +required: + - compatible + - reg + - reg-names + - '#interrupt-cells' + - interrupt-controller + +additionalProperties: false + +examples: + - | + #include + shintc: interrupt-controller@ffd00000 { + compatible = "renesas,sh7751-intc"; + reg = <0xffd00000 14>, <0xfe080000 128>; + reg-names = "ICR", "INTPRI00"; + #interrupt-cells = <1>; + interrupt-controller; + }; +... From patchwork Thu Apr 4 04:59:51 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yoshinori Sato X-Patchwork-Id: 13616976 Received: from sakura.ysato.name (ik1-413-38519.vs.sakura.ne.jp [153.127.30.23]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 293FA6CDAD for ; Thu, 4 Apr 2024 05:01:09 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=153.127.30.23 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712206871; cv=none; b=b9UYs/4kow8bpTGPx5ITVMZOGKlH46/1zRII30pdRGQWcIAfEmKggqGZFtif3ALUsEpd1Gj4MGZtJDMEdwv3Xu7FlCJljcKzoRRK/Y7ikr113sDTMvEtEHWRSeaQD2d/QTYlSxw5nlcaw2w9TvUoQv6WmJ1YBKF2XUHpJz0CK68= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712206871; c=relaxed/simple; bh=UJW1y/CNqaXMUaqUfQ32jgB+zVWcGE7dF8voaeMrWZE=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=ruFHuN3w3QQJX37BmwmFfjQn2aRdUygBak1WrStraUbh5PA/DF6tZ5QO4/MMC8hfYJmbFtSAa4lW2VK89bukcNrNzCweTpU24RN5FdmPALOFTTcMylXRwUdOC+2ErectHR42c/Af0runkevpkaU2JQLTZDeFpTk8bo5yjy+fYMI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=users.sourceforge.jp; spf=fail smtp.mailfrom=users.sourceforge.jp; arc=none smtp.client-ip=153.127.30.23 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=users.sourceforge.jp Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=users.sourceforge.jp Received: from SIOS1075.ysato.name (al128006.dynamic.ppp.asahi-net.or.jp [111.234.128.6]) by sakura.ysato.name (Postfix) with ESMTPSA id C6B7D1C092F; Thu, 4 Apr 2024 14:01:08 +0900 (JST) From: Yoshinori Sato To: linux-sh@vger.kernel.org Cc: Yoshinori Sato Subject: [DO NOT MERGE v7 17/36] irqchip: SH7751 external interrupt encoder with enable gate. Date: Thu, 4 Apr 2024 13:59:51 +0900 Message-Id: X-Mailer: git-send-email 2.39.2 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-sh@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 SH7751 have 15 level external interrupt. It is typically connected to the CPU through a priority encoder that can suppress requests. This driver provides a way to control those hardware with irqchip. Signed-off-by: Yoshinori Sato --- drivers/irqchip/Kconfig | 7 + drivers/irqchip/Makefile | 2 + drivers/irqchip/irq-renesas-sh7751irl.c | 221 ++++++++++++++++++++++++ 3 files changed, 230 insertions(+) create mode 100644 drivers/irqchip/irq-renesas-sh7751irl.c diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig index 33badb5b4f00..7670fcd6757d 100644 --- a/drivers/irqchip/Kconfig +++ b/drivers/irqchip/Kconfig @@ -698,4 +698,11 @@ config RENESAS_SH7751_INTC Support for the Renesas SH7751 On-chip interrupt controller. And external interrupt encoder for some targets. +config RENESAS_SH7751IRL_INTC + bool "Renesas SH7751 based target IRL encoder support." + depends on RENESAS_SH7751_INTC + help + Support for External Interrupt encoder + on the some Renesas SH7751 based target. + endmenu diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile index 51855034a895..bc21d65441f2 100644 --- a/drivers/irqchip/Makefile +++ b/drivers/irqchip/Makefile @@ -122,3 +122,5 @@ obj-$(CONFIG_APPLE_AIC) += irq-apple-aic.o obj-$(CONFIG_MCHP_EIC) += irq-mchp-eic.o obj-$(CONFIG_SUNPLUS_SP7021_INTC) += irq-sp7021-intc.o obj-$(CONFIG_RENESAS_SH7751_INTC) += irq-renesas-sh7751.o +obj-$(CONFIG_RENESAS_SH7751IRL_INTC) += irq-renesas-sh7751irl.o + diff --git a/drivers/irqchip/irq-renesas-sh7751irl.c b/drivers/irqchip/irq-renesas-sh7751irl.c new file mode 100644 index 000000000000..5990f2cd9a3d --- /dev/null +++ b/drivers/irqchip/irq-renesas-sh7751irl.c @@ -0,0 +1,221 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * SH7751 based board external interrupt level encoder driver + * (Renesas RTS7751R2D / IO DATA DEVICE LANDISK, USL-5P) + * + * Copyright (C) 2023 Yoshinori Sato + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct sh7751irl_intc_priv { + struct irq_domain *irq_domain; + void __iomem *base; + unsigned int width; + bool invert; + u32 enable_bit[NR_IRL]; +}; + +static inline unsigned long get_reg(void __iomem *addr, unsigned int w) +{ + switch (w) { + case 8: + return __raw_readb(addr); + case 16: + return __raw_readw(addr); + case 32: + return __raw_readl(addr); + default: + /* The size is checked when reading the properties. */ + pr_err("%s: Invalid width %d", __FILE__, w); + return 0; + } +} + +static inline void set_reg(void __iomem *addr, unsigned int w, unsigned long val) +{ + switch (w) { + case 8: + __raw_writeb(val, addr); + break; + case 16: + __raw_writew(val, addr); + break; + case 32: + __raw_writel(val, addr); + break; + default: + pr_err("%s: Invalid width %d", __FILE__, w); + } +} + +static inline struct sh7751irl_intc_priv *irq_data_to_priv(struct irq_data *data) +{ + return data->domain->host_data; +} + +static void irl_endisable(struct irq_data *data, unsigned int enable) +{ + struct sh7751irl_intc_priv *priv; + unsigned long val; + unsigned int irl; + + priv = irq_data_to_priv(data); + irl = irqd_to_hwirq(data) - IRL_BASE_IRQ; + + if (irl < NR_IRL && priv->enable_bit[irl] < priv->width) { + if (priv->invert) + enable = !enable; + + val = get_reg(priv->base, priv->width); + if (enable) + set_bit(priv->enable_bit[irl], &val); + else + clear_bit(priv->enable_bit[irl], &val); + set_reg(priv->base, priv->width, val); + } else { + pr_err("%s: Invalid register define in IRL %u", __FILE__, irl); + } +} + +static void sh7751irl_intc_disable_irq(struct irq_data *data) +{ + irl_endisable(data, 0); +} + +static void sh7751irl_intc_enable_irq(struct irq_data *data) +{ + irl_endisable(data, 1); +} + +static struct irq_chip sh7751irl_intc_chip = { + .name = "SH7751IRL-INTC", + .irq_enable = sh7751irl_intc_enable_irq, + .irq_disable = sh7751irl_intc_disable_irq, +}; + +static int sh7751irl_intc_map(struct irq_domain *h, unsigned int virq, + irq_hw_number_t hw_irq_num) +{ + irq_set_chip_and_handler(virq, &sh7751irl_intc_chip, handle_level_irq); + irq_get_irq_data(virq)->chip_data = h->host_data; + irq_modify_status(virq, IRQ_NOREQUEST, IRQ_NOPROBE); + return 0; +} + +static int sh7751irl_intc_translate(struct irq_domain *domain, + struct irq_fwspec *fwspec, unsigned long *hwirq, + unsigned int *type) +{ + if (fwspec->param[0] > NR_IRL) + return -EINVAL; + + switch (fwspec->param_count) { + case 2: + *type = fwspec->param[1]; + fallthrough; + case 1: + *hwirq = fwspec->param[0] + IRL_BASE_IRQ; + break; + default: + return -EINVAL; + } + return 0; +} + +static const struct irq_domain_ops sh7751irl_intc_domain_ops = { + .map = sh7751irl_intc_map, + .translate = sh7751irl_intc_translate, +}; + +static int __init load_irl_bit(struct device_node *node, struct sh7751irl_intc_priv *priv) +{ + struct property *enable_map; + const __be32 *p; + u32 nr_bits, bit; + u32 irl; + int ret; + + /* Fill in unused */ + memset(priv->enable_bit, ~0, sizeof(priv->enable_bit)); + + enable_map = of_find_property(node, "renesas,enable-reg", &nr_bits); + if (IS_ERR(enable_map)) + return PTR_ERR(enable_map); + + nr_bits /= sizeof(u32); + if (nr_bits > priv->width) + return -EINVAL; + + ret = nr_bits; + p = NULL; + for (bit = nr_bits; bit > 0; bit--) { + p = of_prop_next_u32(enable_map, p, &irl); + if (p == NULL || irl > NR_IRL) + return -EINVAL; + if (irl == NR_IRL) + /* IRL15 is unassined bit */ + continue; + priv->enable_bit[irl] = bit - 1; + } + return ret; +} + +static int __init sh7751irl_init(struct device_node *node, struct device_node *parent) +{ + struct sh7751irl_intc_priv *priv; + struct resource res; + struct irq_domain *d; + void __iomem *base; + int ret = 0; + + if (of_address_to_resource(node, 0, &res)) + return -EINVAL; + if (resource_size(&res) > 4) + return -EINVAL; + + base = ioremap(res.start, resource_size(&res)); + if (!base) + return -EINVAL; + + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->base = base; + priv->width = 8 << resource_size(&res); + + ret = load_irl_bit(node, priv); + if (ret < 0) { + pr_err("%pOFP: Invalid register define.\n", node); + goto error; + } + + d = irq_domain_add_tree(node, &sh7751irl_intc_domain_ops, priv); + if (d == NULL) { + pr_err("%pOFP: cannot initialize irq domain\n", node); + ret = -ENOMEM; + goto error; + } + + priv->irq_domain = d; + irq_domain_update_bus_token(d, DOMAIN_BUS_WIRED); + pr_info("%pOFP: SH7751 External Interrupt encoder (input=%d)", node, ret); + return 0; +error: + kfree(priv); + return ret; +} + +IRQCHIP_DECLARE(renesas_sh7751_irl, "renesas,sh7751-irl-ext", sh7751irl_init); From patchwork Thu Apr 4 04:59:52 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yoshinori Sato X-Patchwork-Id: 13616977 Received: from sakura.ysato.name (ik1-413-38519.vs.sakura.ne.jp [153.127.30.23]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 64FC143AB6 for ; Thu, 4 Apr 2024 05:01:09 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=153.127.30.23 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712206871; cv=none; b=KA7Oa/+cEb/6Fp4NsNySSuOl2nG0ezGVAmxadZniu1V1Dhn5ZTKlQ59upKT2HL0+0Sl4cPPVEDd4BroqWUDmXQYZByP2Dp14v7G9FHDSpCBPU5cFS8VzUk9OqY2KCqXF1fnlohUCrIMVshkGM2hv57vIdoWmmacqMuqP2z9HQTo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712206871; c=relaxed/simple; bh=7IdyKC16TiRcoV3/cW/Zd7MaUktUAv9ffK9AZ3hzcao=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=hr6OqgCugIAq/WqqRkVWOlQIVX2Tfiyihbaf93N7VpsFcXp6Bt8g8LULqbT+ie8DD8xRkCVgqqcq6fu6hxj2iMGNLtBihIq1Fn/9lwANTzSHLhZhl0LNvSZAEYopxLnI2M9/niPNDF1fKmnL4gXsFSz/d8JSE04J6wWkcL/ObaM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=users.sourceforge.jp; spf=fail smtp.mailfrom=users.sourceforge.jp; arc=none smtp.client-ip=153.127.30.23 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=users.sourceforge.jp Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=users.sourceforge.jp Received: from SIOS1075.ysato.name (al128006.dynamic.ppp.asahi-net.or.jp [111.234.128.6]) by sakura.ysato.name (Postfix) with ESMTPSA id EDD231C016F; Thu, 4 Apr 2024 14:01:08 +0900 (JST) From: Yoshinori Sato To: linux-sh@vger.kernel.org Cc: Yoshinori Sato Subject: [DO NOT MERGE v7 18/36] dt-bindings: interrupt-controller: renesas,sh7751-irl-ext: Add json-schema Date: Thu, 4 Apr 2024 13:59:52 +0900 Message-Id: <39bee5a5e2b8e30c072a69211983b723bd3ab98d.1712041249.git.ysato@users.sourceforge.jp> X-Mailer: git-send-email 2.39.2 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-sh@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Renesas SH7751 external interrupt encoder json-schema. Signed-off-by: Yoshinori Sato --- .../renesas,sh7751-irl-ext.yaml | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 Documentation/devicetree/bindings/interrupt-controller/renesas,sh7751-irl-ext.yaml diff --git a/Documentation/devicetree/bindings/interrupt-controller/renesas,sh7751-irl-ext.yaml b/Documentation/devicetree/bindings/interrupt-controller/renesas,sh7751-irl-ext.yaml new file mode 100644 index 000000000000..fc174c0467e7 --- /dev/null +++ b/Documentation/devicetree/bindings/interrupt-controller/renesas,sh7751-irl-ext.yaml @@ -0,0 +1,57 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/interrupt-controller/renesas,sh7751-irl-ext.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Renesas SH7751 external interrupt encoder with enable regs. + +maintainers: + - Yoshinori Sato + +description: + This is the generally used external interrupt encoder on SH7751 based boards. + +properties: + compatible: + items: + - const: renesas,sh7751-irl-ext + + reg: true + + interrupt-controller: true + + '#interrupt-cells': + const: 2 + + '#address-cells': + const: 0 + + renesas,set-to-disable: + $ref: /schemas/types.yaml#/definitions/flag + description: Invert enable registers. Setting the bit to 0 enables interrupts. + + renesas,enable-reg: + $ref: /schemas/types.yaml#/definitions/uint32-array + description: | + IRQ enable register bit mapping + +required: + - compatible + - reg + - interrupt-controller + - '#interrupt-cells' + - renesas,enable-reg + +additionalProperties: false + +examples: + - | + r2dintc: interrupt-controller@a4000000 { + compatible = "renesas,sh7751-irl-ext"; + reg = <0xa4000000 0x02>; + interrupt-controller; + #address-cells = <0>; + #interrupt-cells = <1>; + renesas,enable-reg = <12 9 10 3 0 4 1 2 8 5 6 7 15 15 15 11>; + }; From patchwork Thu Apr 4 04:59:55 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yoshinori Sato X-Patchwork-Id: 13616980 Received: from sakura.ysato.name (ik1-413-38519.vs.sakura.ne.jp [153.127.30.23]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 050CB6FE2B for ; Thu, 4 Apr 2024 05:01:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=153.127.30.23 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712206874; cv=none; b=QreaVvp4WO+pbip310Z4gR8xdAzN/Nr1n3vXPcPVgZbyE9aLsM8ej3Aq3rI93Y0AnkDlc1vbxS9RDqYOAyziq9UJxS8vpbyFU2e3ibLCuwIITKcZxwtaDhHJkKtwqmOpe4pZ4nTGucDfD8e8omyMOawYX7cmHVZs9zk8pQrKnGY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712206874; c=relaxed/simple; bh=/SVwW82/qqoafDX5rrWInlnHjQYhzm2Ysf1xX40RPDI=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=PP9A8mhyursWsoPwT/SHk0LdNavBx0RGarcOJkrS+y9U6YfRLGkLAKtm/sqWX0+s+1vCrFeQo3PAhkVUjuA8GtBKQVpiuzx+9ctyDItgr0a1u6gLiIwLPpIZQEWl+E4V/T9u7sfvBgXMogUNJjfaaFMOV9OtyECt8fib+Pvsc7E= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=users.sourceforge.jp; spf=fail smtp.mailfrom=users.sourceforge.jp; arc=none smtp.client-ip=153.127.30.23 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=users.sourceforge.jp Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=users.sourceforge.jp Received: from SIOS1075.ysato.name (al128006.dynamic.ppp.asahi-net.or.jp [111.234.128.6]) by sakura.ysato.name (Postfix) with ESMTPSA id 9DF6E1C09E7; Thu, 4 Apr 2024 14:01:12 +0900 (JST) From: Yoshinori Sato To: linux-sh@vger.kernel.org Cc: Yoshinori Sato , Geert Uytterhoeven Subject: [DO NOT MERGE v7 19/36] serial: sh-sci: fix SH4 OF support. Date: Thu, 4 Apr 2024 13:59:55 +0900 Message-Id: X-Mailer: git-send-email 2.39.2 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-sh@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 - fix earlycon name. - fix earlyprintk hung (NULL pointer reference). - fix SERIAL_SH_SCI_EARLYCON enablement Signed-off-by: Yoshinori Sato Reviewed-by: Geert Uytterhoeven --- drivers/tty/serial/Kconfig | 2 +- drivers/tty/serial/sh-sci.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index ffcf4882b25f..dfe5fd436816 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -661,7 +661,7 @@ config SERIAL_SH_SCI_EARLYCON depends on SERIAL_SH_SCI=y select SERIAL_CORE_CONSOLE select SERIAL_EARLYCON - default ARCH_RENESAS + default ARCH_RENESAS || SUPERH config SERIAL_SH_SCI_DMA bool "DMA support" if EXPERT diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index e512eaa57ed5..46466fb5a637 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -2717,7 +2717,7 @@ static int sci_remap_port(struct uart_port *port) if (port->membase) return 0; - if (port->dev->of_node || (port->flags & UPF_IOREMAP)) { + if ((port->dev && port->dev->of_node) || (port->flags & UPF_IOREMAP)) { port->membase = ioremap(port->mapbase, sport->reg_size); if (unlikely(!port->membase)) { dev_err(port->dev, "can't remap port#%d\n", port->line); @@ -3545,8 +3545,8 @@ static int __init hscif_early_console_setup(struct earlycon_device *device, OF_EARLYCON_DECLARE(sci, "renesas,sci", sci_early_console_setup); OF_EARLYCON_DECLARE(scif, "renesas,scif", scif_early_console_setup); -OF_EARLYCON_DECLARE(scif, "renesas,scif-r7s9210", rzscifa_early_console_setup); -OF_EARLYCON_DECLARE(scif, "renesas,scif-r9a07g044", rzscifa_early_console_setup); +OF_EARLYCON_DECLARE(rzscifa, "renesas,scif-r7s9210", rzscifa_early_console_setup); +OF_EARLYCON_DECLARE(rzscifa, "renesas,scif-r9a07g044", rzscifa_early_console_setup); OF_EARLYCON_DECLARE(scifa, "renesas,scifa", scifa_early_console_setup); OF_EARLYCON_DECLARE(scifb, "renesas,scifb", scifb_early_console_setup); OF_EARLYCON_DECLARE(hscif, "renesas,hscif", hscif_early_console_setup); From patchwork Thu Apr 4 04:59:56 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yoshinori Sato X-Patchwork-Id: 13616981 Received: from sakura.ysato.name (ik1-413-38519.vs.sakura.ne.jp [153.127.30.23]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 3DD3370CD7 for ; Thu, 4 Apr 2024 05:01:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=153.127.30.23 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712206874; cv=none; b=pq8DsQbQIJzjXYpnpqJE1P/UcwaxGibQAObaHoNlLRyohUvfwExTsIhaueKAOi8AgkL/u4ZsRteiB+x6YzuVYDyAr/mY4dSOjq25GjArilPCWwUC6ybQo5yHIWENO5Qjj+Ln0yyxy+IVm1iVaQZQAw/5VCQDOfJuiRnuhz0LAbk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712206874; c=relaxed/simple; bh=17MFAO8Mxxt2rDxlaE4c9eYzawZE+YNTNwC92zwVHm0=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=nzCPva4f92HnY7QZtwdTXLbgPIEVTHH8JcCEXTr7jA/vrxjPm4M88O1nRxJ/0OMLkKqVClCGai+kZQvQpbll/89zLm4P4OSep9A9QU4lmnakZfgOsCk/VFOm5OX7gRoHkNffZZ1A7ojMk69engEuzmU3PYhe7AVCeOiI41V2cwI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=users.sourceforge.jp; spf=fail smtp.mailfrom=users.sourceforge.jp; arc=none smtp.client-ip=153.127.30.23 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=users.sourceforge.jp Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=users.sourceforge.jp Received: from SIOS1075.ysato.name (al128006.dynamic.ppp.asahi-net.or.jp [111.234.128.6]) by sakura.ysato.name (Postfix) with ESMTPSA id CA3961C016F; Thu, 4 Apr 2024 14:01:12 +0900 (JST) From: Yoshinori Sato To: linux-sh@vger.kernel.org Cc: Yoshinori Sato , Geert Uytterhoeven Subject: [DO NOT MERGE v7 20/36] dt-bindings: serial: renesas,scif: Add scif-sh7751. Date: Thu, 4 Apr 2024 13:59:56 +0900 Message-Id: <31ee1a65b3636f8e496eb1bc84d4e35bcf979919.1712041249.git.ysato@users.sourceforge.jp> X-Mailer: git-send-email 2.39.2 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-sh@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Add Renesas SH7751 SCIF. Signed-off-by: Yoshinori Sato Reviewed-by: Geert Uytterhoeven --- Documentation/devicetree/bindings/serial/renesas,scif.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/serial/renesas,scif.yaml b/Documentation/devicetree/bindings/serial/renesas,scif.yaml index 4610a5bd580c..590f88e2ced9 100644 --- a/Documentation/devicetree/bindings/serial/renesas,scif.yaml +++ b/Documentation/devicetree/bindings/serial/renesas,scif.yaml @@ -18,6 +18,7 @@ properties: - items: - enum: - renesas,scif-r7s72100 # RZ/A1H + - renesas,scif-sh7751 # SH7751 - const: renesas,scif # generic SCIF compatible UART - items: From patchwork Thu Apr 4 04:59:58 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yoshinori Sato X-Patchwork-Id: 13616983 Received: from sakura.ysato.name (ik1-413-38519.vs.sakura.ne.jp [153.127.30.23]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 2457471B42 for ; Thu, 4 Apr 2024 05:01:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=153.127.30.23 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712206877; cv=none; b=o1J92INpyahI7wLMdbe7ylsoy5b5a5TOi+4z/EpboifADLPYlMR4XH/GIP+9z0woiBHc6umznu1Mtpu9d1T4RDMdmgyVKilm5ZoFTxnBAdIpqOz1w/lD91Sn8U4sE8FntaQAajryR7Qlj2CGfjgNdhPUiG38umePmsxcOF6mxL4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712206877; c=relaxed/simple; bh=MvQpdX/sSYmof7Bxa6HlKAVNZXKWVUfpsjYKfuvmB9k=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=rVl3F3Fzz1UyJSrMd9BZzBcltBvRhA/KxPjZBzCSjl5l/uGlOLRa3UxR5NoIlBhCi+WHoU6Fu21vvAeCG77GGreumJhuCxTcv19Oxra9FUq0JnpDoUAT1kBTP4q3ORU7T/CqVcq7GX+fT89f+uEoELyrBeFyqW17rO2j3iUQ3DA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=users.sourceforge.jp; spf=fail smtp.mailfrom=users.sourceforge.jp; arc=none smtp.client-ip=153.127.30.23 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=users.sourceforge.jp Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=users.sourceforge.jp Received: from SIOS1075.ysato.name (al128006.dynamic.ppp.asahi-net.or.jp [111.234.128.6]) by sakura.ysato.name (Postfix) with ESMTPSA id C988C1C0B84; Thu, 4 Apr 2024 14:01:14 +0900 (JST) From: Yoshinori Sato To: linux-sh@vger.kernel.org Cc: Yoshinori Sato Subject: [DO NOT MERGE v7 21/36] dt-bindings: display: smi,sm501: SMI SM501 binding json-schema Date: Thu, 4 Apr 2024 13:59:58 +0900 Message-Id: <0b5f29d51c75ef0aea2d302b60ca865b1ab3dc79.1712041249.git.ysato@users.sourceforge.jp> X-Mailer: git-send-email 2.39.2 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-sh@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Signed-off-by: Yoshinori Sato --- .../bindings/display/smi,sm501.yaml | 398 ++++++++++++++++++ 1 file changed, 398 insertions(+) create mode 100644 Documentation/devicetree/bindings/display/smi,sm501.yaml diff --git a/Documentation/devicetree/bindings/display/smi,sm501.yaml b/Documentation/devicetree/bindings/display/smi,sm501.yaml new file mode 100644 index 000000000000..06c6af4fa4a9 --- /dev/null +++ b/Documentation/devicetree/bindings/display/smi,sm501.yaml @@ -0,0 +1,398 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/display/smi,sm501.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Silicon Motion SM501 Mobile Multimedia Companion Chip + +maintainers: + - Yoshinori Sato + +description: | + These DT bindings describe the SM501. + +properties: + compatible: + const: + smi,sm501 + + reg: + maxItems: 2 + description: | + First entry: System Configuration register + Second entry: IO space (Display Controller register) + + interrupts: + description: SM501 interrupt to the cpu should be described here. + + mode: + $ref: /schemas/types.yaml#/definitions/string + description: select a video mode + + edid: + description: | + verbatim EDID data block describing attached display. + Data from the detailed timing descriptor will be used to + program the display controller. + + little-endian: + $ref: /schemas/types.yaml#/definitions/flag + description: available on big endian systems, to set different foreign endian. + big-endian: + $ref: /schemas/types.yaml#/definitions/flag + description: available on little endian systems, to set different foreign endian. + + swap-fb-endian: + $ref: /schemas/types.yaml#/definitions/flag + description: swap framebuffer byteorder. + + route-crt-panel: + $ref: /schemas/types.yaml#/definitions/flag + description: Panel output merge to CRT. + + crt: + type: object + description: CRT output control + properties: + edid: + $ref: /schemas/types.yaml#/definitions/uint8-array + description: | + verbatim EDID data block describing attached display. + Data from the detailed timing descriptor will be used to + program the display controller. + + smi,flags: + $ref: /schemas/types.yaml#/definitions/string-array + description: Display control flags. + items: + anyOf: + - const: use-init-done + - const: disable-at-exit + - const: use-hwcursor + - const: use-hwaccel + - const: panel-no-fpen + - const: panel-no-vbiasen + - const: panel-inv-fpen + - const: panel-inv-vbiasen + maxItems: 8 + + bpp: + $ref: /schemas/types.yaml#/definitions/uint32 + description: Color depth + + panel: + type: object + description: Panel output control + properties: + edid: + $ref: /schemas/types.yaml#/definitions/uint8-array + description: | + verbatim EDID data block describing attached display. + Data from the detailed timing descriptor will be used to + program the display controller. + + smi,flags: + $ref: /schemas/types.yaml#/definitions/string-array + description: Display control flags. + items: + anyOf: + - const: use-init-done + - const: disable-at-exit + - const: use-hwcursor + - const: use-hwaccel + - const: panel-no-fpen + - const: panel-no-vbiasen + - const: panel-inv-fpen + - const: panel-inv-vbiasen + maxItems: 8 + + bpp: + $ref: /schemas/types.yaml#/definitions/uint32 + description: Color depth + + smi,devices: + $ref: /schemas/types.yaml#/definitions/string-array + description: Select SM501 device functions. + items: + anyOf: + - const: usb-host + - const: usb-slave + - const: ssp0 + - const: ssp1 + - const: uart0 + - const: uart1 + - const: fbaccel + - const: ac97 + - const: i2s + - const: gpio + minItems: 1 + maxItems: 10 + + smi,mclk: + $ref: /schemas/types.yaml#/definitions/uint32 + description: mclk frequency. + + smi,m1xclk: + $ref: /schemas/types.yaml#/definitions/uint32 + description: m1xclk frequency. + + misc-timing: + type: object + description: Miscellaneous Timing register values. + properties: + ex: + $ref: /schemas/types.yaml#/definitions/uint32 + description: Extend bus holding time. + + xc: + $ref: /schemas/types.yaml#/definitions/uint32 + description: Xscale clock input select. + + usb-over-current-detect-disable: + $ref: /schemas/types.yaml#/definitions/flag + description: USB host current detection disable (Us=0). + + usb-over-current-detect-enable: + $ref: /schemas/types.yaml#/definitions/flag + description: USB host current detection disable (Us=1). + + sdram-clock-mode1-288mhz: + $ref: /schemas/types.yaml#/definitions/flag + description: SSM1 bit is clear. + + sdram-clock-mode1-div: + $ref: /schemas/types.yaml#/definitions/flag + description: SSM1 bit is set. + + sm1: + $ref: /schemas/types.yaml#/definitions/flag + description: SDRAM clock divider for PW mode 1. + + sdram-clock-mode0-288mhz: + $ref: /schemas/types.yaml#/definitions/flag + description: SSM0 bit is clear. + + sdram-clock-mode0-div: + $ref: /schemas/types.yaml#/definitions/flag + description: SSM0 bit is set. + + sm0: + $ref: /schemas/types.yaml#/definitions/uint32 + description: SDRAM clock divider for PW mode 0. + + pll-debug-input: + $ref: /schemas/types.yaml#/definitions/flag + description: 96MHz PLL debug input reference frequency (Deb=0). + + pll-debug-output: + $ref: /schemas/types.yaml#/definitions/flag + description: 96MHz PLL debug output frequency (Deb=1). + + no-acpi-control: + $ref: /schemas/types.yaml#/definitions/flag + description: No ACPI control (A=0). + + acpi-control: + $ref: /schemas/types.yaml#/definitions/flag + description: No ACPI control (A=1). + + divider: + $ref: /schemas/types.yaml#/definitions/uint32 + description: Second PLL output frequency. + + usb-host-normal: + $ref: /schemas/types.yaml#/definitions/flag + description: USB Host normal mode. + + usb-host-simulation: + $ref: /schemas/types.yaml#/definitions/flag + description: USB Host simulation mode. + + delay: + $ref: /schemas/types.yaml#/definitions/uint32 + description: Delay time to latch read data. Set the value to 10x. + + misc-control: + type: object + description: Miscellaneous Control register values. + properties: + pad: + $ref: /schemas/types.yaml#/definitions/uint32 + description: PCI Pad drive strength. + + usbclk: + $ref: /schemas/types.yaml#/definitions/uint32 + description: USB Clcok Select. + + uart1: + $ref: /schemas/types.yaml#/definitions/flag + description: UART1 (SSP=0) + + ssp1: + $ref: /schemas/types.yaml#/definitions/flag + description: SSP1 (SSP=1) + + latch-address-disable: + $ref: /schemas/types.yaml#/definitions/flag + description: 8051 Latch disable (Lat=0). + + latch-address-enable: + $ref: /schemas/types.yaml#/definitions/flag + description: 8051 Latch enable (Lat=1). + + panel-data-18bit: + $ref: /schemas/types.yaml#/definitions/flag + description: Flat Panel data 18bit (FP=0). + + panel-data-24bit: + $ref: /schemas/types.yaml#/definitions/flag + description: Flat Panel data 24bit (FP=1). + + xtal-freq-24mhz: + $ref: /schemas/types.yaml#/definitions/flag + description: Crystal frequency 24MHz (Freq=0). + + xtal-freq-12mhz: + $ref: /schemas/types.yaml#/definitions/flag + description: Crystal frequency 12MHz (Freq=1). + + refresh: + $ref: /schemas/types.yaml#/definitions/uint32 + description: Internal memory refresh timing. + + hold: + $ref: /schemas/types.yaml#/definitions/uint32 + description: BUS Hold time. + + sh-ready-low: + $ref: /schemas/types.yaml#/definitions/flag + description: SuperH ready polarity active low (SH=0). + + sh-ready-high: + $ref: /schemas/types.yaml#/definitions/flag + description: SuperH ready polarity active high (SH=1). + + interrupt-normal: + $ref: /schemas/types.yaml#/definitions/flag + description: Interrupt normal (II=0). + + interrupt-inverted: + $ref: /schemas/types.yaml#/definitions/flag + description: Interrupt Inverting (II=1). + + pll-clock-count-disable: + $ref: /schemas/types.yaml#/definitions/flag + description: PLL clock count disable. + + pll-clock-count-enaable: + $ref: /schemas/types.yaml#/definitions/flag + description: PLL clock count enable. + + dac-power-enable: + $ref: /schemas/types.yaml#/definitions/flag + description: DAC Power enable (DAC=0). + + dac-power-disable: + $ref: /schemas/types.yaml#/definitions/flag + description: DAC Power disable (DAC=1). + + usb-slave-cpu: + $ref: /schemas/types.yaml#/definitions/flag + description: USB slave controller cpu (MC=0). + + usb-slave-8051: + $ref: /schemas/types.yaml#/definitions/flag + description: USB slave controller 8051MCU (MC=1). + + burst-length-8: + $ref: /schemas/types.yaml#/definitions/flag + description: CPU Master burst length 8 (BL=0). + + burst-length-1: + $ref: /schemas/types.yaml#/definitions/flag + description: CPU Master burst length 1 (BL=1). + + usb-port-master: + $ref: /schemas/types.yaml#/definitions/flag + description: USB port master. + + usb-port-slave: + $ref: /schemas/types.yaml#/definitions/flag + description: USB port slave. + + vr-mmio-30mb: + $ref: /schemas/types.yaml#/definitions/flag + description: NEC VR Memory map MMIO locatedat 30MB (VR=0) + + vr-mmio-62mb: + $ref: /schemas/types.yaml#/definitions/flag + description: NEC VR Memory map MMIO locatedat 62MB (VR=1) + + gpio-pin-control: + type: object + description: GPIO control configuration. + properties: + pin: + type: object + properties: + gpio: + $ref: /schemas/types.yaml#/definitions/flag + description: pin in/out use GPIO. + function: + $ref: /schemas/types.yaml#/definitions/flag + description: pin in/out use function. + + gpio-i2c: + type: object + description: GPIO I2C definition. + properties: + i2c: + type: object + properties: + bus: + $ref: /schemas/types.yaml#/definitions/uint32 + description: I2C bus number. + + sda: + $ref: /schemas/types.yaml#/definitions/uint32 + description: I2C SDA pin port number. + + scl: + $ref: /schemas/types.yaml#/definitions/uint32 + description: I2C SCL pin port number. + + delay: + $ref: /schemas/types.yaml#/definitions/uint32 + description: bit transmission delay. + + timeout: + $ref: /schemas/types.yaml#/definitions/uint32 + description: transmission timeout. + +additionalProperties: false + +required: + - compatible + - reg + - interrupts + + +examples: + # MPC5200 + - | + display@1,0 { + compatible = "smi,sm501"; + reg = <0x00000000 0x00800000 + 0x03e00000 0x00200000>; + interrupts = <1 1 3>; + mode = "640x480-32@60"; + edid = [00 ff ff ff ff ff ff 00 00 00 00 00 00 00 00 00 + 00 00 01 04 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 f0 0a 80 fb 20 e0 25 10 32 60 + 02 00 00 00 00 00 00 06 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 bd]; + }; From patchwork Thu Apr 4 05:00:00 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yoshinori Sato X-Patchwork-Id: 13616985 Received: from sakura.ysato.name (ik1-413-38519.vs.sakura.ne.jp [153.127.30.23]) by smtp.subspace.kernel.org (Postfix) with ESMTP id B528C73535 for ; Thu, 4 Apr 2024 05:01:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=153.127.30.23 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712206879; cv=none; b=ikERKFcqDaHEQM/k2zTqGJioT6IODhsYTvuhzrL76jsgyTODKYYLJd2V/tvRKn4bF1Rz08IcTSs407S6pqehOMzv6HMHWS1rAE6AI6Lc4IEDYd7hAnOQnB+kp5HwWKLv06BGXQosf4VwQ5K/YZKzJAIELNYrOvpRSRzllJ/b2Ao= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712206879; c=relaxed/simple; bh=RfBIVerSVY5ro3iClkCuqoyBsbZfPpMYmGiZieoqKAU=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=ETXKmAn9tXVTQG/pcL2vnQztUAnUp+b/RHXuVxgx/GK5JFCK5zOF2Obef5qgnjltOgU0BAwEcdD6KqXt+Syr2dcpV2r/X0niOq6D340Sn8SFj18E/g56jaD1QDKLjgmhRQdvkvZyULwdXz/gQi7Gaz1UJk3Yxl1FCdUm57EhtaE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=users.sourceforge.jp; spf=fail smtp.mailfrom=users.sourceforge.jp; arc=none smtp.client-ip=153.127.30.23 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=users.sourceforge.jp Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=users.sourceforge.jp Received: from SIOS1075.ysato.name (al128006.dynamic.ppp.asahi-net.or.jp [111.234.128.6]) by sakura.ysato.name (Postfix) with ESMTPSA id AE36D1C0BD1; Thu, 4 Apr 2024 14:01:16 +0900 (JST) From: Yoshinori Sato To: linux-sh@vger.kernel.org Cc: Yoshinori Sato Subject: [DO NOT MERGE v7 22/36] dt-bindings: display: sm501 register definition helper Date: Thu, 4 Apr 2024 14:00:00 +0900 Message-Id: X-Mailer: git-send-email 2.39.2 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-sh@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Miscellaneous Timing and Miscellaneous Control registers definition. Signed-off-by: Yoshinori Sato --- include/dt-bindings/display/sm501.h | 76 +++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 include/dt-bindings/display/sm501.h diff --git a/include/dt-bindings/display/sm501.h b/include/dt-bindings/display/sm501.h new file mode 100644 index 000000000000..a6c6943642e4 --- /dev/null +++ b/include/dt-bindings/display/sm501.h @@ -0,0 +1,76 @@ +/* SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause */ +#ifndef __DT_BINDING_DISPALY_SM501__ +#define __DT_BINDING_DISPALY_SM501__ + +/* Miscellaneous Conntrol */ +#define SM501_MISC_CONTROL_PAD_24 0 +#define SM501_MISC_CONTROL_PAD_12 1 +#define SM501_MISC_CONTROL_PAD_8 2 + +#define SM501_MISC_CONTROL_USBCLK_XTAL 0 +#define SM501_MISC_CONTROL_USBCLK_96MHZ 1 +#define SM501_MISC_CONTROL_USBCLK_48MHZ 2 + +#define SM501_MISC_CONTROL_RFSH_8US 0 +#define SM501_MISC_CONTROL_RFSH_16US 1 +#define SM501_MISC_CONTROL_RFSH_32US 2 +#define SM501_MISC_CONTROL_RFSH_64US 3 + +#define SM501_MISC_CONTROL_HOLD_EMPTY 0 +#define SM501_MISC_CONTROL_HOLD_8TR 1 +#define SM501_MISC_CONTROL_HOLD_16TR 2 +#define SM501_MISC_CONTROL_HOLD_24TR 3 +#define SM501_MISC_CONTROL_HOLD_32TR 4 + +/* Miscellaneous timing */ +#define SM501_MISC_TIMING_EX_HOLD_0 0 +#define SM501_MISC_TIMING_EX_HOLD_16 1 +#define SM501_MISC_TIMING_EX_HOLD_32 2 +#define SM501_MISC_TIMING_EX_HOLD_48 3 +#define SM501_MISC_TIMING_EX_HOLD_64 4 +#define SM501_MISC_TIMING_EX_HOLD_80 5 +#define SM501_MISC_TIMING_EX_HOLD_96 6 +#define SM501_MISC_TIMING_EX_HOLD_112 7 +#define SM501_MISC_TIMING_EX_HOLD_128 8 +#define SM501_MISC_TIMING_EX_HOLD_144 9 +#define SM501_MISC_TIMING_EX_HOLD_160 10 +#define SM501_MISC_TIMING_EX_HOLD_176 11 +#define SM501_MISC_TIMING_EX_HOLD_192 12 +#define SM501_MISC_TIMING_EX_HOLD_208 13 +#define SM501_MISC_TIMING_EX_HOLD_224 14 +#define SM501_MISC_TIMING_EX_HOLD_240 15 + +#define SM501_MISC_TIMING_XC_INTERNAL 0 +#define SM501_MISC_TIMING_XC_HCLK 1 +#define SM501_MISC_TIMING_XC_GPIO 2 + +#define SM501_MISC_TIMING_SM_DIV1 0 +#define SM501_MISC_TIMING_SM_DIV2 1 +#define SM501_MISC_TIMING_SM_DIV4 2 +#define SM501_MISC_TIMING_SM_DIV8 3 +#define SM501_MISC_TIMING_SM_DIV16 4 +#define SM501_MISC_TIMING_SM_DIV32 5 +#define SM501_MISC_TIMING_SM_DIV64 6 +#define SM501_MISC_TIMING_SM_DIV128 7 +#define SM501_MISC_TIMING_SM_DIV3 8 +#define SM501_MISC_TIMING_SM_DIV6 9 +#define SM501_MISC_TIMING_SM_DIV12 10 +#define SM501_MISC_TIMING_SM_DIV24 11 +#define SM501_MISC_TIMING_SM_DIV48 12 +#define SM501_MISC_TIMING_SM_DIV96 13 +#define SM501_MISC_TIMING_SM_DIV192 14 +#define SM501_MISC_TIMING_SM_DIV384 15 + +#define SM501_MISC_TIMING_DIV336MHZ 0 +#define SM501_MISC_TIMING_DIV288MHZ 1 +#define SM501_MISC_TIMING_DIV240MHZ 2 +#define SM501_MISC_TIMING_DIV192MHZ 3 + +#define SM501_MISC_TIMING_DELAY_NONE 0 +#define SM501_MISC_TIMING_DELAY_0_5 1 +#define SM501_MISC_TIMING_DELAY_1_0 2 +#define SM501_MISC_TIMING_DELAY_1_5 3 +#define SM501_MISC_TIMING_DELAY_2_0 4 +#define SM501_MISC_TIMING_DELAY_2_5 5 + +#endif From patchwork Thu Apr 4 05:00:03 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yoshinori Sato X-Patchwork-Id: 13616989 Received: from sakura.ysato.name (ik1-413-38519.vs.sakura.ne.jp [153.127.30.23]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 8500574C17 for ; Thu, 4 Apr 2024 05:01:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=153.127.30.23 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712206883; cv=none; b=i28OPZApCiBFGmlVZU8fJABH8no7z9RVyypQAPNK0e+yWQNo8zb1bvDiN/puC2ZH8qzin/vLWTGHuTYl/RjpPTIBpHkx+sBWt+t/euuCFiOlADapeksdeH1UM0XkrnOHYklWjQXnF7E+QToMQDGUGpVt4EM3kG0kpBDONv0Iw8o= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712206883; c=relaxed/simple; bh=oR1VwjedA1FpuS2dt+TVchHyrMd1UPMPXbR4xhUxYIE=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=CqSt/+Yj0TzW4cENBYhvaXJ1hTkzhg081YkRGgbylu9eEjlxYZ87lVRvj44KC40arVXar98dl+fn+To8EfG/dMI3/2vaFtMbFKTyEd+JnXJNTAl+1aAJvRZBmyQxmL75XMSfwV6p0NMJxsTVIp5d6olzSExvXe7h+OLjGnr+qyo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=users.sourceforge.jp; spf=fail smtp.mailfrom=users.sourceforge.jp; arc=none smtp.client-ip=153.127.30.23 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=users.sourceforge.jp Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=users.sourceforge.jp Received: from SIOS1075.ysato.name (al128006.dynamic.ppp.asahi-net.or.jp [111.234.128.6]) by sakura.ysato.name (Postfix) with ESMTPSA id 7749C1C016F; Thu, 4 Apr 2024 14:01:20 +0900 (JST) From: Yoshinori Sato To: linux-sh@vger.kernel.org Cc: Yoshinori Sato Subject: [DO NOT MERGE v7 23/36] mfd: sm501: Convert platform_data to OF property Date: Thu, 4 Apr 2024 14:00:03 +0900 Message-Id: X-Mailer: git-send-email 2.39.2 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-sh@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Various parameters of SM501 can be set using platform_data, so parameters cannot be passed in the DeviceTree target. Expands the parameters set in platform_data so that they can be specified using DeviceTree properties. Signed-off-by: Yoshinori Sato --- drivers/mfd/sm501.c | 315 ++++++++++++++++++++++++++++++++++ drivers/video/fbdev/sm501fb.c | 106 ++++++++++++ 2 files changed, 421 insertions(+) diff --git a/drivers/mfd/sm501.c b/drivers/mfd/sm501.c index b3592982a83b..98a69e254f5f 100644 --- a/drivers/mfd/sm501.c +++ b/drivers/mfd/sm501.c @@ -82,6 +82,16 @@ struct sm501_devdata { unsigned int rev; }; +struct sm501_config_props_uint { + char *name; + u32 shift; +}; + +struct sm501_config_props_flag { + char *clr_name; + char *set_name; + u32 bit; +}; #define MHZ (1000 * 1000) @@ -1370,6 +1380,305 @@ static int sm501_init_dev(struct sm501_devdata *sm) return 0; } +static const struct sm501_config_props_uint misc_timing[] = { + {"delay", 0}, + {"-", 3}, + {"divider", 4}, + {"-", 6}, + {"sm0", 8}, + {"-", 12}, + {"sm1", 16}, + {"-", 20}, + {"xc", 24}, + {"-", 26}, + {"ex", 28}, + {NULL, 32}, +}; + +static const struct sm501_config_props_flag misc_timing_flag[] = { + {"usb-host-normal", "usb-host-simulation", 3}, + {"no-acpi-control", "acpi-control", 6}, + {"pll-debug-input", "pll-debug-output", 7}, + {"sdram-clock-mode0-288mhz", "sdram-clock-mode0-div", 12}, + {"sdram-clock-mode1-288mhz", "sdram-clock-mode1-div", 20}, + {"usb-over-current-detect-disable", + "usb-over-current-detect-enable", 23}, + {}, +}; + +static const struct sm501_config_props_uint misc_control[] = { + {"hold", 18}, + {"refresh", 21}, + {"-", 23}, + {"usbclk", 28}, + {"pad", 30}, + {NULL, 32}, +}; + +static const struct sm501_config_props_flag misc_control_flag[] = { + {"vr-mmio-30mb", "vr-mmio-62mb", 4}, + {"usb-port-master", "usb-port-slave", 9}, + {"burst-length-8", "burst-length-1", 10}, + {"usb-slave-cpu", "usb-slave-8051", 11}, + {"dac-power-enable", "dac-power-disable", 12}, + {"pll-clock-count-disable", "pll-clock-count-enable", 15}, + {"interrupt-normal", "interrupt-invarted", 16}, + {"sh-ready-low", "sh-ready-high", 17}, + {"xtal-freq-24mhz", "xtal-freq-12mhz", 24}, + {"panel-data-18bit", "panel-dtat-24bit", 25}, + {"latch-address-disable", "latch-address-enable", 26}, + {"uart1", "ssp1", 27}, + {}, +}; + +/* Read configuration values */ +static void sm501_of_read_config(struct device *dev, struct device_node *np, + const char *prefix, + const struct sm501_config_props_uint *props, + const struct sm501_config_props_flag *props_flag, + struct sm501_reg_init *ret) +{ + struct device_node *child; + char *name; + u32 shift; + u32 width; + u32 mask; + u32 val; + + ret->mask = ~0; + ret->set = 0; + + child = of_get_child_by_name(np, prefix); + if (!child) + return; + + while (props->name) { + name = props->name; + shift = props->shift; + props++; + + if (name[0] == '-' || + of_property_read_u32(child, name, &val)) + continue; + + width = props->shift - shift; + mask = (1 << width) - 1; + if (mask < val) { + dev_warn(dev, "%s invalid value %d", name, val); + continue; + } + mask = ~(mask << shift); + ret->mask &= mask; + ret->set |= val << shift; + } + while (props_flag->clr_name) { + val = ~0; + if (of_property_read_bool(child, props_flag->clr_name)) + val = 0; + else if (of_property_read_bool(child, props_flag->set_name)) + val = 1; + if (val != ~0) { + val <<= (props_flag->bit & 31); + mask = 1 << (props_flag->bit & 31); + ret->mask &= ~mask; + ret->set |= val; + } + props_flag++; + } +} + +/* Read GPIO control */ +/* + * DT example. + * gpio-pin-control { + * pin@0 { + * gpio-port; + * }; + * pin@1 { + * function; + * }; + * }; + */ +static void sm501_of_read_gpio(struct device *dev, struct device_node *np, + struct sm501_reg_init *hi, struct sm501_reg_init *low) +{ + struct device_node *gpio_group, *pin; + const char *prop_mode; + unsigned int pin_no; + int mode; + u64 mask; + u64 set; + + mask = ~0; + set = 0; + gpio_group = of_get_child_by_name(np, "gpio-pin-control"); + if (gpio_group) { + for_each_child_of_node(gpio_group, pin) { + mode = -1; + if (sscanf(pin->full_name, "pin@%u", &pin_no) == 1) { + if (of_property_read_bool(pin, "gpio-port")) + mode = 0; + else if (of_property_read_bool(pin, "function")) + mode = 1; + } + /* GPIO0 - 47 and 55 -63 */ + if (mode < 0 || + (pin_no >= 64 || (pin_no >= 48 && pin_no <= 54))) { + dev_warn(dev, + "%s mode %s is invalid.", pin->name, prop_mode); + } else { + mask &= ~(1 << pin_no); + set |= mode << pin_no; + } + } + } + hi->set = set >> 32; + low->set = set & 0xffffffff; + hi->mask = mask >> 32; + low->mask = mask & 0xffffffff; +} + +static inline int read_i2c_prop(struct device *dev, struct device_node *child, + const char *name, u32 *val) +{ + if (of_property_read_u32(child, name, val)) { + dev_warn(dev, "%s/%s not found. skip it.", of_node_full_name(child), name); + return -ENOENT; + } + return 0; +} + +/* Read GPIO I2C configuration */ +/* + * DT example. + * gpio-i2c { + * i2c@0 { + * sda = ; + * scl = ; + * delay = ; + * timeout = ; + * }; + * i2c@1 { + * : + * }; + * : + * }; + */ +static int sm501_parse_dt_gpio_i2c(struct device *dev, struct sm501_platdata *plat, + struct device_node *np) +{ + struct device_node *i2c_group, *child; + unsigned int i; + u32 i2c_nr; + int err; + + i2c_group = of_get_child_by_name(np, "gpio-i2c"); + if (!i2c_group) + return 0; + + i2c_nr = of_get_child_count(i2c_group); + plat->gpio_i2c = devm_kzalloc(dev, sizeof(*plat->gpio_i2c) * i2c_nr, + GFP_KERNEL); + if (!plat->gpio_i2c) + return -ENOMEM; + + plat->gpio_i2c_nr = i2c_nr; + i = 0; + for_each_child_of_node(i2c_group, child) { + u32 bus; + + if (sscanf(child->full_name, "i2c@%u", &bus) != 1) { + dev_warn(dev, "Unknown address %s\n", child->name); + continue; + } + + err = 0; + plat->gpio_i2c[i].bus_num = bus; + err += read_i2c_prop(dev, child, "sda", &plat->gpio_i2c[i].pin_sda); + err += read_i2c_prop(dev, child, "scl", &plat->gpio_i2c[i].pin_scl); + err += read_i2c_prop(dev, child, "delay", &plat->gpio_i2c[i].udelay); + err += read_i2c_prop(dev, child, "timeout", &plat->gpio_i2c[i].timeout); + if (err == 0) + i++; + } + + return 0; +} + +/* Read device functions */ +static u32 sm501_read_devices(struct device *dev, struct device_node *np) +{ + static const char * const funcname[] = { + "usb-host", "usb-slave", "ssp0", "ssp1", + "uart0", "uart1", "fbaccel", "ac97", + "i2s", "gpio", + }; + struct property *prop; + unsigned int i; + const char *s; + u32 ret = 0; + + of_property_for_each_string(np, "smi,devices", prop, s) { + for (i = 0; i < ARRAY_SIZE(funcname); i++) { + if (strcmp(s, funcname[i]) == 0) { + ret |= 1 << i; + goto next; + } + } + dev_warn(dev, "Unknown device function '%s'", s); +next: + } + if (!ret) + dev_warn(dev, "devices not defined. disable all functions."); + return ret; +} + +/* Build platform_data from OF property */ +struct plat_dt { + struct sm501_platdata plat; + struct sm501_initdata init; +}; + +static int sm501_parse_dt(struct sm501_devdata *sm, struct device_node *np) +{ + struct sm501_platdata *plat; + struct plat_dt *dt_p; + u32 word; + int ret; + + dt_p = devm_kzalloc(sm->dev, sizeof(*dt_p), GFP_KERNEL); + if (!dt_p) + return -ENOMEM; + + plat = &dt_p->plat; + plat->init = &dt_p->init; + + plat->init->devices = sm501_read_devices(sm->dev, np); + /* mclk and m1xclk are not u32, so convert between them using intermediate variables. */ + of_property_read_u32(np, "smi,mclk", &word); + plat->init->mclk = word; + of_property_read_u32(np, "smi,m1xclk", &word); + plat->init->m1xclk = word; + + sm501_of_read_config(sm->dev, np, "misc-timing", + misc_timing, misc_timing_flag, + &plat->init->misc_timing); + sm501_of_read_config(sm->dev, np, "misc-control", + misc_control, misc_control_flag, + &plat->init->misc_control); + sm501_of_read_gpio(sm->dev, np, + &plat->init->gpio_high, &plat->init->gpio_low); + + if (IS_ENABLED(CONFIG_MFD_SM501_GPIO) && + (plat->init->devices & SM501_USE_GPIO)) { + ret = sm501_parse_dt_gpio_i2c(sm->dev, plat, np); + if (ret) + return ret; + } + sm->platdata = plat; + return 0; +} + static int sm501_plat_probe(struct platform_device *dev) { struct sm501_devdata *sm; @@ -1406,6 +1715,12 @@ static int sm501_plat_probe(struct platform_device *dev) goto err_res; } + if (IS_ENABLED(CONFIG_OF) && dev->dev.of_node) { + ret = sm501_parse_dt(sm, dev->dev.of_node); + if (ret) + goto err_res; + } + platform_set_drvdata(dev, sm); sm->regs = ioremap(sm->io_res->start, resource_size(sm->io_res)); diff --git a/drivers/video/fbdev/sm501fb.c b/drivers/video/fbdev/sm501fb.c index d6fdc1737cd2..5de00f2570aa 100644 --- a/drivers/video/fbdev/sm501fb.c +++ b/drivers/video/fbdev/sm501fb.c @@ -1932,6 +1932,106 @@ static int sm501fb_start_one(struct sm501fb_info *info, return 0; } +#if defined(CONFIG_OF) +static u32 read_display_flags(struct device_node *np) +{ + static const char * const name[] = { + "use-init-done", "disable-at-exit", "use-hwcursor", "use-hwaccel", + "panel-no-fpen", "panel-no-vbiasen", "panel-inv-fpen", "panel-inv-vbiasen", + }; + + struct property *prop; + unsigned int i; + const char *s; + u32 ret = 0; + + of_property_for_each_string(np, "smi,flags", prop, s) { + for (i = 0; i < ARRAY_SIZE(name); i++) { + if (strcmp(s, name[i]) == 0) { + ret |= 1 << i; + break; + } + } + } + return ret; +} + +/* parse CRT / panel configuration */ +static struct sm501_platdata_fbsub *dt_fbsub(struct device *dev, + struct device_node *np, + const char *name) +{ + struct sm501_platdata_fbsub *fbsub = NULL; + struct fb_videomode *def_mode = NULL; + struct device_node *child; + const void *p_edid; + u32 flags = 0; + u32 bpp = 0; + int len; + + child = of_get_child_by_name(np, name); + if (child == NULL) + return NULL; + + p_edid = of_get_property(child, "edid", &len); + if (p_edid && len == EDID_LENGTH) { + struct fb_monspecs *specs; + u8 *edid; + + edid = kmemdup(p_edid, EDID_LENGTH, GFP_KERNEL); + if (edid) { + specs = kzalloc(sizeof(*specs), GFP_KERNEL); + if (specs) { + fb_edid_to_monspecs(edid, specs); + def_mode = specs->modedb; + } + } + kfree(edid); + } + + of_property_read_u32(child, "bpp", &bpp); + + /* If flags property is obtained, fbsub is returned. */ + flags = read_display_flags(child); + if (flags) { + fbsub = devm_kzalloc(dev, sizeof(*fbsub), GFP_KERNEL); + if (fbsub) { + fbsub->def_mode = def_mode; + fbsub->def_bpp = bpp; + fbsub->flags = flags; + } + } + return fbsub; +} + +/* Build platform_data from OF property */ +static struct sm501_platdata_fb *pdata_from_dt(struct device *dev, struct device_node *np) +{ + enum sm501_fb_routing fb_route = SM501_FB_OWN; + struct sm501_platdata_fb *pdata = NULL; + struct sm501_platdata_fbsub *fb_crt; + struct sm501_platdata_fbsub *fb_pnl; + unsigned int flags = 0; + + if (of_property_read_bool(np, "route-crt-panel")) + fb_route = SM501_FB_CRT_PANEL; + if (of_property_read_bool(np, "swap-fb-endian")) + flags = SM501_FBPD_SWAP_FB_ENDIAN; + fb_crt = dt_fbsub(dev, np, "crt"); + fb_pnl = dt_fbsub(dev, np, "panel"); + if (fb_crt || fb_pnl) { + pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); + if (pdata) { + pdata->fb_route = fb_route; + pdata->flags = flags; + pdata->fb_crt = fb_crt; + pdata->fb_pnl = fb_pnl; + } + } + return pdata; +} +#endif + static int sm501fb_probe(struct platform_device *pdev) { struct sm501fb_info *info; @@ -1974,6 +2074,12 @@ static int sm501fb_probe(struct platform_device *pdev) if (info->edid_data) found = 1; } + /* Get platform data compatible configuration */ + if (!found) { + info->pdata = pdata_from_dt(dev, np); + if (info->pdata) + found = 1; + } } #endif if (!found) { From patchwork Thu Apr 4 05:00:04 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yoshinori Sato X-Patchwork-Id: 13616988 Received: from sakura.ysato.name (ik1-413-38519.vs.sakura.ne.jp [153.127.30.23]) by smtp.subspace.kernel.org (Postfix) with ESMTP id ABA7574C1B for ; Thu, 4 Apr 2024 05:01:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=153.127.30.23 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712206883; cv=none; b=Yk6a927x/CGhT/QXov+Fn5bCdVh/gisJFi0ZNa6arq/epyXReg5c8WvWqQODl05LBDWgtXNxECruVGePtjk8od4IMhLl54l4U78Yp43EAUG11iv2zykDSIxlwZoLHmOMam44jDG6P/RSObVnM/lPRSb4s4JubrUuD0H9uity8fg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712206883; c=relaxed/simple; bh=yT32dw2MA1l/u3K8YlVvTRqYbgKjGsuCai8CvdMaens=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=mctPi8MqTfuHblF1V1Hgngnkj8zK3l0ph3C1QO0a+/6AKkf1Ih6DCAunpGb3IqStD4vBNo0kX7xy+u4NhYpKNN1lhBtAZk9jqNMzhIVagu3GOCF7ccXmD1jwmfA2MvpDTGzYQlCSuJ+SBxvYyhC7EtN9vB+ehRijkjduyx4jeM0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=users.sourceforge.jp; spf=fail smtp.mailfrom=users.sourceforge.jp; arc=none smtp.client-ip=153.127.30.23 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=users.sourceforge.jp Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=users.sourceforge.jp Received: from SIOS1075.ysato.name (al128006.dynamic.ppp.asahi-net.or.jp [111.234.128.6]) by sakura.ysato.name (Postfix) with ESMTPSA id 9CDD91C0DCB; Thu, 4 Apr 2024 14:01:20 +0900 (JST) From: Yoshinori Sato To: linux-sh@vger.kernel.org Cc: Yoshinori Sato Subject: [DO NOT MERGE v7 24/36] dt-binding: sh: cpus: Add SH CPUs json-schema Date: Thu, 4 Apr 2024 14:00:04 +0900 Message-Id: X-Mailer: git-send-email 2.39.2 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-sh@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Renesas SH series and compatible ISA CPUs. Signed-off-by: Yoshinori Sato --- .../devicetree/bindings/sh/cpus.yaml | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 Documentation/devicetree/bindings/sh/cpus.yaml diff --git a/Documentation/devicetree/bindings/sh/cpus.yaml b/Documentation/devicetree/bindings/sh/cpus.yaml new file mode 100644 index 000000000000..43e079b8753d --- /dev/null +++ b/Documentation/devicetree/bindings/sh/cpus.yaml @@ -0,0 +1,61 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sh/cpus.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Renesas SuperH CPUs + +maintainers: + - Yoshinori Sato + +description: |+ + Definition of CPU core with Renesas SuperH and compatible instruction set. + +properties: + compatible: + anyOf: + - items: + - enum: + - renesas,sh2a + - renesas,sh3 + - renesas,sh4 + - renesas,sh4a + - jcore,j2 + - const: renesas,sh2 + - const: renesas,sh2 + + clocks: + maxItems: 1 + + reg: + maxItems: 1 + + device_type: true + +required: + - compatible + - reg + - device_type + + +examples: + - | + #include + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu: cpu@0 { + compatible = "renesas,sh4", "renesas,sh2"; + device_type = "cpu"; + reg = <0>; + clocks = <&cpg SH7750_CPG_ICK>; + clock-names = "ick"; + icache-size = <16384>; + icache-line-size = <32>; + dcache-size = <32768>; + dcache-line-size = <32>; + }; + }; +...