mirror of
https://github.com/openwrt/openwrt.git
synced 2024-12-24 07:46:48 +00:00
brcm63xx: remove linux 4.4 support
Signed-off-by: Felix Fietkau <nbd@nbd.name>
This commit is contained in:
parent
1de74df8b9
commit
771f1ca3ff
@ -1,261 +0,0 @@
|
||||
CONFIG_ARCH_BINFMT_ELF_STATE=y
|
||||
CONFIG_ARCH_CLOCKSOURCE_DATA=y
|
||||
CONFIG_ARCH_DISCARD_MEMBLOCK=y
|
||||
CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y
|
||||
CONFIG_ARCH_HAS_ELF_RANDOMIZE=y
|
||||
# CONFIG_ARCH_HAS_GCOV_PROFILE_ALL is not set
|
||||
# CONFIG_ARCH_HAS_SG_CHAIN is not set
|
||||
CONFIG_ARCH_HIBERNATION_POSSIBLE=y
|
||||
CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y
|
||||
CONFIG_ARCH_MIGHT_HAVE_PC_SERIO=y
|
||||
CONFIG_ARCH_REQUIRE_GPIOLIB=y
|
||||
CONFIG_ARCH_SUPPORTS_UPROBES=y
|
||||
CONFIG_ARCH_SUSPEND_POSSIBLE=y
|
||||
CONFIG_ARCH_USE_BUILTIN_BSWAP=y
|
||||
CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y
|
||||
CONFIG_BCM6345_EXT_IRQ=y
|
||||
CONFIG_BCM6345_PERIPH_IRQ=y
|
||||
CONFIG_BCM63XX=y
|
||||
CONFIG_BCM63XX_CPU_3368=y
|
||||
CONFIG_BCM63XX_CPU_6318=y
|
||||
CONFIG_BCM63XX_CPU_63268=y
|
||||
CONFIG_BCM63XX_CPU_6328=y
|
||||
CONFIG_BCM63XX_CPU_6338=y
|
||||
CONFIG_BCM63XX_CPU_6345=y
|
||||
CONFIG_BCM63XX_CPU_6348=y
|
||||
CONFIG_BCM63XX_CPU_6358=y
|
||||
CONFIG_BCM63XX_CPU_6362=y
|
||||
CONFIG_BCM63XX_CPU_6368=y
|
||||
CONFIG_BCM63XX_EHCI=y
|
||||
CONFIG_BCM63XX_ENET=y
|
||||
CONFIG_BCM63XX_OHCI=y
|
||||
CONFIG_BCM63XX_PHY=y
|
||||
CONFIG_BCM63XX_WDT=y
|
||||
CONFIG_BCMA=y
|
||||
CONFIG_BCMA_BLOCKIO=y
|
||||
# CONFIG_BCMA_DEBUG is not set
|
||||
# CONFIG_BCMA_DRIVER_GMAC_CMN is not set
|
||||
# CONFIG_BCMA_DRIVER_MIPS is not set
|
||||
CONFIG_BCMA_DRIVER_PCI=y
|
||||
# CONFIG_BCMA_DRIVER_PCI_HOSTMODE is not set
|
||||
CONFIG_BCMA_HOST_PCI=y
|
||||
CONFIG_BCMA_HOST_PCI_POSSIBLE=y
|
||||
# CONFIG_BCMA_HOST_SOC is not set
|
||||
CONFIG_BCM_NET_PHYLIB=y
|
||||
CONFIG_BOARD_BCM63XX_DT=y
|
||||
CONFIG_BOARD_BCM963XX=y
|
||||
CONFIG_BOARD_LIVEBOX=y
|
||||
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
|
||||
CONFIG_CEVT_R4K=y
|
||||
CONFIG_CLKDEV_LOOKUP=y
|
||||
CONFIG_CLONE_BACKWARDS=y
|
||||
CONFIG_CPU_BIG_ENDIAN=y
|
||||
CONFIG_CPU_BMIPS=y
|
||||
CONFIG_CPU_BMIPS32_3300=y
|
||||
CONFIG_CPU_BMIPS4350=y
|
||||
CONFIG_CPU_GENERIC_DUMP_TLB=y
|
||||
CONFIG_CPU_HAS_PREFETCH=y
|
||||
CONFIG_CPU_HAS_SYNC=y
|
||||
CONFIG_CPU_MIPS32=y
|
||||
CONFIG_CPU_NEEDS_NO_SMARTMIPS_OR_MICROMIPS=y
|
||||
CONFIG_CPU_R4K_CACHE_TLB=y
|
||||
CONFIG_CPU_R4K_FPU=y
|
||||
CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
|
||||
CONFIG_CPU_SUPPORTS_HIGHMEM=y
|
||||
CONFIG_CRYPTO_RNG2=y
|
||||
CONFIG_CRYPTO_WORKQUEUE=y
|
||||
CONFIG_CSRC_R4K=y
|
||||
CONFIG_DMA_NONCOHERENT=y
|
||||
CONFIG_DTC=y
|
||||
CONFIG_EARLY_PRINTK=y
|
||||
CONFIG_FIRMWARE_IN_KERNEL=y
|
||||
CONFIG_GENERIC_ATOMIC64=y
|
||||
CONFIG_GENERIC_CLOCKEVENTS=y
|
||||
CONFIG_GENERIC_CMOS_UPDATE=y
|
||||
CONFIG_GENERIC_IO=y
|
||||
CONFIG_GENERIC_IRQ_CHIP=y
|
||||
CONFIG_GENERIC_IRQ_SHOW=y
|
||||
CONFIG_GENERIC_PCI_IOMAP=y
|
||||
CONFIG_GENERIC_PINCONF=y
|
||||
CONFIG_GENERIC_SCHED_CLOCK=y
|
||||
CONFIG_GENERIC_SMP_IDLE_THREAD=y
|
||||
CONFIG_GENERIC_TIME_VSYSCALL=y
|
||||
CONFIG_GPIOLIB=y
|
||||
CONFIG_GPIO_BCM63XX=y
|
||||
CONFIG_GPIO_DEVRES=y
|
||||
CONFIG_GPIO_GENERIC=y
|
||||
CONFIG_GPIO_SYSFS=y
|
||||
CONFIG_HAS_DMA=y
|
||||
CONFIG_HAS_IOMEM=y
|
||||
CONFIG_HAS_IOPORT_MAP=y
|
||||
# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set
|
||||
# CONFIG_HAVE_ARCH_BITREVERSE is not set
|
||||
CONFIG_HAVE_ARCH_JUMP_LABEL=y
|
||||
CONFIG_HAVE_ARCH_KGDB=y
|
||||
CONFIG_HAVE_ARCH_SECCOMP_FILTER=y
|
||||
CONFIG_HAVE_ARCH_TRACEHOOK=y
|
||||
# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set
|
||||
CONFIG_HAVE_BPF_JIT=y
|
||||
CONFIG_HAVE_CC_STACKPROTECTOR=y
|
||||
CONFIG_HAVE_CLK=y
|
||||
CONFIG_HAVE_CONTEXT_TRACKING=y
|
||||
CONFIG_HAVE_C_RECORDMCOUNT=y
|
||||
CONFIG_HAVE_DEBUG_KMEMLEAK=y
|
||||
CONFIG_HAVE_DEBUG_STACKOVERFLOW=y
|
||||
CONFIG_HAVE_DMA_API_DEBUG=y
|
||||
CONFIG_HAVE_DMA_ATTRS=y
|
||||
CONFIG_HAVE_DMA_CONTIGUOUS=y
|
||||
CONFIG_HAVE_DYNAMIC_FTRACE=y
|
||||
CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
|
||||
CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
|
||||
CONFIG_HAVE_FUNCTION_TRACER=y
|
||||
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
|
||||
CONFIG_HAVE_IDE=y
|
||||
CONFIG_HAVE_IRQ_EXIT_ON_IRQ_STACK=y
|
||||
CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y
|
||||
CONFIG_HAVE_LATENCYTOP_SUPPORT=y
|
||||
CONFIG_HAVE_MEMBLOCK=y
|
||||
CONFIG_HAVE_MEMBLOCK_NODE_MAP=y
|
||||
CONFIG_HAVE_MOD_ARCH_SPECIFIC=y
|
||||
CONFIG_HAVE_NET_DSA=y
|
||||
CONFIG_HAVE_OPROFILE=y
|
||||
CONFIG_HAVE_PERF_EVENTS=y
|
||||
CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
|
||||
CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y
|
||||
CONFIG_HW_HAS_PCI=y
|
||||
CONFIG_HW_RANDOM=y
|
||||
CONFIG_HW_RANDOM_BCM63XX=y
|
||||
CONFIG_HZ=250
|
||||
# CONFIG_HZ_100 is not set
|
||||
CONFIG_HZ_250=y
|
||||
CONFIG_HZ_PERIODIC=y
|
||||
CONFIG_INITRAMFS_SOURCE=""
|
||||
CONFIG_IP_PIMSM_V1=y
|
||||
CONFIG_IP_PIMSM_V2=y
|
||||
CONFIG_IRQCHIP=y
|
||||
CONFIG_IRQ_DOMAIN=y
|
||||
CONFIG_IRQ_FORCED_THREADING=y
|
||||
CONFIG_IRQ_MIPS_CPU=y
|
||||
CONFIG_IRQ_WORK=y
|
||||
CONFIG_KEXEC=y
|
||||
CONFIG_KEXEC_CORE=y
|
||||
CONFIG_LEDS_BCM6328=y
|
||||
CONFIG_LEDS_BCM6358=y
|
||||
CONFIG_LEDS_GPIO=y
|
||||
CONFIG_LIBFDT=y
|
||||
CONFIG_MDIO_BOARDINFO=y
|
||||
CONFIG_MFD_SYSCON=y
|
||||
CONFIG_MIPS=y
|
||||
CONFIG_MIPS_CLOCK_VSYSCALL=y
|
||||
# CONFIG_MIPS_CMDLINE_DTB_EXTEND is not set
|
||||
# CONFIG_MIPS_CMDLINE_FROM_BOOTLOADER is not set
|
||||
CONFIG_MIPS_CMDLINE_FROM_DTB=y
|
||||
# CONFIG_MIPS_ELF_APPENDED_DTB is not set
|
||||
# CONFIG_MIPS_HUGE_TLB_SUPPORT is not set
|
||||
CONFIG_MIPS_L1_CACHE_SHIFT=4
|
||||
CONFIG_MIPS_L1_CACHE_SHIFT_4=y
|
||||
# CONFIG_MIPS_MACHINE is not set
|
||||
# CONFIG_MIPS_NO_APPENDED_DTB is not set
|
||||
CONFIG_MIPS_RAW_APPENDED_DTB=y
|
||||
CONFIG_MODULES_USE_ELF_REL=y
|
||||
CONFIG_MODULE_FORCE_LOAD=y
|
||||
CONFIG_MODULE_FORCE_UNLOAD=y
|
||||
CONFIG_MTD_BCM63XX_PARTS=y
|
||||
CONFIG_MTD_CFI_ADV_OPTIONS=y
|
||||
CONFIG_MTD_CFI_BE_BYTE_SWAP=y
|
||||
# CONFIG_MTD_CFI_GEOMETRY is not set
|
||||
# CONFIG_MTD_CFI_NOSWAP is not set
|
||||
CONFIG_MTD_CFI_STAA=y
|
||||
# CONFIG_MTD_COMPLEX_MAPPINGS is not set
|
||||
CONFIG_MTD_JEDECPROBE=y
|
||||
CONFIG_MTD_M25P80=y
|
||||
CONFIG_MTD_PHYSMAP=y
|
||||
CONFIG_MTD_REDBOOT_PARTS=y
|
||||
CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y
|
||||
CONFIG_MTD_SPI_NOR=y
|
||||
CONFIG_NEED_DMA_MAP_STATE=y
|
||||
CONFIG_NEED_PER_CPU_KM=y
|
||||
CONFIG_NO_GENERIC_PCI_IOPORT_MAP=y
|
||||
# CONFIG_NO_IOPORT_MAP is not set
|
||||
CONFIG_OF=y
|
||||
CONFIG_OF_ADDRESS=y
|
||||
CONFIG_OF_ADDRESS_PCI=y
|
||||
CONFIG_OF_EARLY_FLATTREE=y
|
||||
CONFIG_OF_FLATTREE=y
|
||||
CONFIG_OF_GPIO=y
|
||||
CONFIG_OF_IRQ=y
|
||||
CONFIG_OF_MDIO=y
|
||||
CONFIG_OF_MTD=y
|
||||
CONFIG_OF_NET=y
|
||||
CONFIG_OF_PCI=y
|
||||
CONFIG_OF_PCI_IRQ=y
|
||||
CONFIG_PCI=y
|
||||
# CONFIG_PCIEAER is not set
|
||||
CONFIG_PCIEPORTBUS=y
|
||||
CONFIG_PCI_DOMAINS=y
|
||||
CONFIG_PERF_USE_VMALLOC=y
|
||||
CONFIG_PGTABLE_LEVELS=2
|
||||
CONFIG_PHYLIB=y
|
||||
CONFIG_PINCTRL=y
|
||||
CONFIG_PINCTRL_BCM6318=y
|
||||
CONFIG_PINCTRL_BCM63268=y
|
||||
CONFIG_PINCTRL_BCM6328=y
|
||||
CONFIG_PINCTRL_BCM6348=y
|
||||
CONFIG_PINCTRL_BCM6358=y
|
||||
CONFIG_PINCTRL_BCM6362=y
|
||||
CONFIG_PINCTRL_BCM6368=y
|
||||
CONFIG_PINCTRL_BCM63XX=y
|
||||
CONFIG_POSIX_MQUEUE=y
|
||||
CONFIG_POSIX_MQUEUE_SYSCTL=y
|
||||
# CONFIG_RCU_STALL_COMMON is not set
|
||||
CONFIG_REGMAP=y
|
||||
CONFIG_REGMAP_MMIO=y
|
||||
CONFIG_RELAY=y
|
||||
CONFIG_RTL8366_SMI=y
|
||||
CONFIG_RTL8367_PHY=y
|
||||
# CONFIG_SCHED_INFO is not set
|
||||
# CONFIG_SCSI_DMA is not set
|
||||
# CONFIG_SERIAL_8250 is not set
|
||||
CONFIG_SERIAL_BCM63XX=y
|
||||
CONFIG_SERIAL_BCM63XX_CONSOLE=y
|
||||
CONFIG_SPI=y
|
||||
CONFIG_SPI_BCM63XX=y
|
||||
CONFIG_SPI_BCM63XX_HSSPI=y
|
||||
CONFIG_SPI_MASTER=y
|
||||
CONFIG_SQUASHFS_EMBEDDED=y
|
||||
CONFIG_SRCU=y
|
||||
CONFIG_SSB=y
|
||||
CONFIG_SSB_B43_PCI_BRIDGE=y
|
||||
CONFIG_SSB_BLOCKIO=y
|
||||
# CONFIG_SSB_DRIVER_MIPS is not set
|
||||
CONFIG_SSB_DRIVER_PCICORE=y
|
||||
CONFIG_SSB_DRIVER_PCICORE_POSSIBLE=y
|
||||
CONFIG_SSB_PCIHOST=y
|
||||
CONFIG_SSB_PCIHOST_POSSIBLE=y
|
||||
CONFIG_SSB_SPROM=y
|
||||
CONFIG_SWAP_IO_SPACE=y
|
||||
CONFIG_SWCONFIG=y
|
||||
CONFIG_SWCONFIG_B53=y
|
||||
CONFIG_SWCONFIG_B53_MMAP_DRIVER=y
|
||||
CONFIG_SWCONFIG_B53_PHY_DRIVER=y
|
||||
CONFIG_SWCONFIG_B53_PHY_FIXUP=y
|
||||
CONFIG_SWCONFIG_B53_SPI_DRIVER=y
|
||||
# CONFIG_SWCONFIG_B53_SRAB_DRIVER is not set
|
||||
CONFIG_SYNC_R4K=y
|
||||
CONFIG_SYSCTL_EXCEPTION_TRACE=y
|
||||
CONFIG_SYS_HAS_CPU_BMIPS=y
|
||||
CONFIG_SYS_HAS_CPU_BMIPS32_3300=y
|
||||
CONFIG_SYS_HAS_CPU_BMIPS4350=y
|
||||
CONFIG_SYS_HAS_EARLY_PRINTK=y
|
||||
CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
|
||||
CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
|
||||
CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
|
||||
CONFIG_SYS_SUPPORTS_HOTPLUG_CPU=y
|
||||
CONFIG_SYS_SUPPORTS_SMP=y
|
||||
CONFIG_TICK_CPU_ACCOUNTING=y
|
||||
CONFIG_USB_SUPPORT=y
|
||||
CONFIG_USE_OF=y
|
||||
CONFIG_VM_EVENT_COUNTERS=y
|
||||
CONFIG_WATCHDOG_NOWAYOUT=y
|
||||
CONFIG_WEAK_ORDERING=y
|
||||
CONFIG_ZONE_DMA_FLAG=0
|
@ -1,78 +0,0 @@
|
||||
From 28b8b26b308e656edfa9467867d5f79212da2ec3 Mon Sep 17 00:00:00 2001
|
||||
From: Brian Norris <computersforpeace@gmail.com>
|
||||
Date: Fri, 30 Oct 2015 20:33:20 -0700
|
||||
Subject: [PATCH 01/11] mtd: add get/set of_node/flash_node helpers
|
||||
|
||||
We are going to begin using the mtd->dev.of_node field for MTD device
|
||||
nodes, so let's add helpers for it. Also, we'll be making some
|
||||
conversions on spi_nor (and nand_chip eventually) too, so get that ready
|
||||
with their own helpers.
|
||||
|
||||
Signed-off-by: Brian Norris <computersforpeace@gmail.com>
|
||||
Reviewed-by: Boris Brezillon <boris.brezillon@free-electrons.com>
|
||||
---
|
||||
include/linux/mtd/mtd.h | 11 +++++++++++
|
||||
include/linux/mtd/nand.h | 11 +++++++++++
|
||||
include/linux/mtd/spi-nor.h | 11 +++++++++++
|
||||
3 files changed, 33 insertions(+)
|
||||
|
||||
--- a/include/linux/mtd/mtd.h
|
||||
+++ b/include/linux/mtd/mtd.h
|
||||
@@ -258,6 +258,17 @@ struct mtd_info {
|
||||
int usecount;
|
||||
};
|
||||
|
||||
+static inline void mtd_set_of_node(struct mtd_info *mtd,
|
||||
+ struct device_node *np)
|
||||
+{
|
||||
+ mtd->dev.of_node = np;
|
||||
+}
|
||||
+
|
||||
+static inline struct device_node *mtd_get_of_node(struct mtd_info *mtd)
|
||||
+{
|
||||
+ return mtd->dev.of_node;
|
||||
+}
|
||||
+
|
||||
int mtd_erase(struct mtd_info *mtd, struct erase_info *instr);
|
||||
int mtd_point(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen,
|
||||
void **virt, resource_size_t *phys);
|
||||
--- a/include/linux/mtd/nand.h
|
||||
+++ b/include/linux/mtd/nand.h
|
||||
@@ -719,6 +719,17 @@ struct nand_chip {
|
||||
void *priv;
|
||||
};
|
||||
|
||||
+static inline void nand_set_flash_node(struct nand_chip *chip,
|
||||
+ struct device_node *np)
|
||||
+{
|
||||
+ chip->flash_node = np;
|
||||
+}
|
||||
+
|
||||
+static inline struct device_node *nand_get_flash_node(struct nand_chip *chip)
|
||||
+{
|
||||
+ return chip->flash_node;
|
||||
+}
|
||||
+
|
||||
/*
|
||||
* NAND Flash Manufacturer ID Codes
|
||||
*/
|
||||
--- a/include/linux/mtd/spi-nor.h
|
||||
+++ b/include/linux/mtd/spi-nor.h
|
||||
@@ -184,6 +184,17 @@ struct spi_nor {
|
||||
void *priv;
|
||||
};
|
||||
|
||||
+static inline void spi_nor_set_flash_node(struct spi_nor *nor,
|
||||
+ struct device_node *np)
|
||||
+{
|
||||
+ nor->flash_node = np;
|
||||
+}
|
||||
+
|
||||
+static inline struct device_node *spi_nor_get_flash_node(struct spi_nor *nor)
|
||||
+{
|
||||
+ return nor->flash_node;
|
||||
+}
|
||||
+
|
||||
/**
|
||||
* spi_nor_scan() - scan the SPI NOR
|
||||
* @nor: the spi_nor structure
|
@ -1,74 +0,0 @@
|
||||
From 3b6521eab0386a4854d47b1a01947d7dc46ec98d Mon Sep 17 00:00:00 2001
|
||||
From: Brian Norris <computersforpeace@gmail.com>
|
||||
Date: Fri, 30 Oct 2015 20:33:21 -0700
|
||||
Subject: [PATCH] mtd: ofpart: grab device tree node directly from master
|
||||
device node
|
||||
|
||||
It seems more logical to use a device node directly associated with the
|
||||
MTD master device (i.e., mtd->dev.of_node field) rather than requiring
|
||||
auxiliary partition parser information to be passed in by the driver in
|
||||
a separate struct.
|
||||
|
||||
This patch supports the mtd->dev.of_node field and deprecates the parser
|
||||
data 'of_node' field
|
||||
|
||||
Driver conversions may now follow.
|
||||
|
||||
Additional side benefit to assigning mtd->dev.of_node rather than using
|
||||
parser data: the driver core will automatically create a device -> node
|
||||
symlink for us.
|
||||
|
||||
Signed-off-by: Brian Norris <computersforpeace@gmail.com>
|
||||
Reviewed-by: Boris Brezillon <boris.brezillon@free-electrons.com>
|
||||
---
|
||||
drivers/mtd/ofpart.c | 18 ++++++++++--------
|
||||
include/linux/mtd/partitions.h | 4 +++-
|
||||
2 files changed, 13 insertions(+), 9 deletions(-)
|
||||
|
||||
--- a/drivers/mtd/ofpart.c
|
||||
+++ b/drivers/mtd/ofpart.c
|
||||
@@ -37,10 +37,11 @@ static int parse_ofpart_partitions(struc
|
||||
bool dedicated = true;
|
||||
|
||||
|
||||
- if (!data)
|
||||
- return 0;
|
||||
-
|
||||
- mtd_node = data->of_node;
|
||||
+ /*
|
||||
+ * of_node can be provided through auxiliary parser data or (preferred)
|
||||
+ * by assigning the master device node
|
||||
+ */
|
||||
+ mtd_node = data && data->of_node ? data->of_node : mtd_get_of_node(master);
|
||||
if (!mtd_node)
|
||||
return 0;
|
||||
|
||||
@@ -157,10 +158,11 @@ static int parse_ofoldpart_partitions(st
|
||||
} *part;
|
||||
const char *names;
|
||||
|
||||
- if (!data)
|
||||
- return 0;
|
||||
-
|
||||
- dp = data->of_node;
|
||||
+ /*
|
||||
+ * of_node can be provided through auxiliary parser data or (preferred)
|
||||
+ * by assigning the master device node
|
||||
+ */
|
||||
+ dp = data && data->of_node ? data->of_node : mtd_get_of_node(master);
|
||||
if (!dp)
|
||||
return 0;
|
||||
|
||||
--- a/include/linux/mtd/partitions.h
|
||||
+++ b/include/linux/mtd/partitions.h
|
||||
@@ -56,7 +56,9 @@ struct device_node;
|
||||
/**
|
||||
* struct mtd_part_parser_data - used to pass data to MTD partition parsers.
|
||||
* @origin: for RedBoot, start address of MTD device
|
||||
- * @of_node: for OF parsers, device node containing partitioning information
|
||||
+ * @of_node: for OF parsers, device node containing partitioning information.
|
||||
+ * This field is deprecated, as the device node should simply be
|
||||
+ * assigned to the master struct device.
|
||||
*/
|
||||
struct mtd_part_parser_data {
|
||||
unsigned long origin;
|
@ -1,37 +0,0 @@
|
||||
From 3e63b26bdd4069c3df2cd7ce7217a21d06801b41 Mon Sep 17 00:00:00 2001
|
||||
From: Brian Norris <computersforpeace@gmail.com>
|
||||
Date: Fri, 30 Oct 2015 20:33:22 -0700
|
||||
Subject: [PATCH 03/11] mtd: {nand,spi-nor}: assign MTD of_node
|
||||
|
||||
We should pass along our flash DT node to the MTD layer, so it can set
|
||||
up ofpart for us.
|
||||
|
||||
Signed-off-by: Brian Norris <computersforpeace@gmail.com>
|
||||
Reviewed-by: Boris Brezillon <boris.brezillon@free-electrons.com>
|
||||
---
|
||||
drivers/mtd/nand/nand_base.c | 3 +++
|
||||
drivers/mtd/spi-nor/spi-nor.c | 1 +
|
||||
2 files changed, 4 insertions(+)
|
||||
|
||||
--- a/drivers/mtd/nand/nand_base.c
|
||||
+++ b/drivers/mtd/nand/nand_base.c
|
||||
@@ -3995,6 +3995,9 @@ int nand_scan_ident(struct mtd_info *mtd
|
||||
int ret;
|
||||
|
||||
if (chip->flash_node) {
|
||||
+ /* MTD can automatically handle DT partitions, etc. */
|
||||
+ mtd_set_of_node(mtd, chip->flash_node);
|
||||
+
|
||||
ret = nand_dt_init(mtd, chip, chip->flash_node);
|
||||
if (ret)
|
||||
return ret;
|
||||
--- a/drivers/mtd/spi-nor/spi-nor.c
|
||||
+++ b/drivers/mtd/spi-nor/spi-nor.c
|
||||
@@ -1228,6 +1228,7 @@ int spi_nor_scan(struct spi_nor *nor, co
|
||||
mtd->flags |= MTD_NO_ERASE;
|
||||
|
||||
mtd->dev.parent = dev;
|
||||
+ mtd_set_of_node(mtd, np);
|
||||
nor->page_size = info->page_size;
|
||||
mtd->writebufsize = nor->page_size;
|
||||
|
@ -1,72 +0,0 @@
|
||||
From 6375219951a66047805ed977b674615d152001ee Mon Sep 17 00:00:00 2001
|
||||
From: Brian Norris <computersforpeace@gmail.com>
|
||||
Date: Fri, 30 Oct 2015 20:33:23 -0700
|
||||
Subject: [PATCH 04/11] mtd: nand: convert to nand_set_flash_node()
|
||||
|
||||
Used semantic patch with 'make coccicheck MODE=patch COCCI=script.cocci':
|
||||
|
||||
---8<----
|
||||
virtual patch
|
||||
|
||||
@@
|
||||
struct nand_chip *c;
|
||||
struct device_node *d;
|
||||
@@
|
||||
-(c)->flash_node = (d)
|
||||
+nand_set_flash_node(c, d)
|
||||
---8<----
|
||||
|
||||
Signed-off-by: Brian Norris <computersforpeace@gmail.com>
|
||||
Reviewed-by: Marek Vasut <marex@denx.de>
|
||||
Reviewed-by: Boris Brezillon <boris.brezillon@free-electrons.com>
|
||||
---
|
||||
drivers/mtd/nand/brcmnand/brcmnand.c | 2 +-
|
||||
drivers/mtd/nand/fsmc_nand.c | 2 +-
|
||||
drivers/mtd/nand/sunxi_nand.c | 2 +-
|
||||
drivers/mtd/nand/vf610_nfc.c | 2 +-
|
||||
4 files changed, 4 insertions(+), 4 deletions(-)
|
||||
|
||||
--- a/drivers/mtd/nand/brcmnand/brcmnand.c
|
||||
+++ b/drivers/mtd/nand/brcmnand/brcmnand.c
|
||||
@@ -1950,7 +1950,7 @@ static int brcmnand_init_cs(struct brcmn
|
||||
mtd = &host->mtd;
|
||||
chip = &host->chip;
|
||||
|
||||
- chip->flash_node = dn;
|
||||
+ nand_set_flash_node(chip, dn);
|
||||
chip->priv = host;
|
||||
mtd->priv = chip;
|
||||
mtd->name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "brcmnand.%d",
|
||||
--- a/drivers/mtd/nand/fsmc_nand.c
|
||||
+++ b/drivers/mtd/nand/fsmc_nand.c
|
||||
@@ -1033,7 +1033,7 @@ static int __init fsmc_nand_probe(struct
|
||||
nand->options = pdata->options;
|
||||
nand->select_chip = fsmc_select_chip;
|
||||
nand->badblockbits = 7;
|
||||
- nand->flash_node = np;
|
||||
+ nand_set_flash_node(nand, np);
|
||||
|
||||
if (pdata->width == FSMC_NAND_BW16)
|
||||
nand->options |= NAND_BUSWIDTH_16;
|
||||
--- a/drivers/mtd/nand/sunxi_nand.c
|
||||
+++ b/drivers/mtd/nand/sunxi_nand.c
|
||||
@@ -1336,7 +1336,7 @@ static int sunxi_nand_chip_init(struct d
|
||||
* in the DT.
|
||||
*/
|
||||
nand->ecc.mode = NAND_ECC_HW;
|
||||
- nand->flash_node = np;
|
||||
+ nand_set_flash_node(nand, np);
|
||||
nand->select_chip = sunxi_nfc_select_chip;
|
||||
nand->cmd_ctrl = sunxi_nfc_cmd_ctrl;
|
||||
nand->read_buf = sunxi_nfc_read_buf;
|
||||
--- a/drivers/mtd/nand/vf610_nfc.c
|
||||
+++ b/drivers/mtd/nand/vf610_nfc.c
|
||||
@@ -714,7 +714,7 @@ static int vf610_nfc_probe(struct platfo
|
||||
goto error;
|
||||
}
|
||||
|
||||
- chip->flash_node = child;
|
||||
+ nand_set_flash_node(chip, child);
|
||||
}
|
||||
}
|
||||
|
@ -1,79 +0,0 @@
|
||||
From 9c7d787508be6d68a6ec66de3c3466b24e820c71 Mon Sep 17 00:00:00 2001
|
||||
From: Brian Norris <computersforpeace@gmail.com>
|
||||
Date: Fri, 30 Oct 2015 20:33:24 -0700
|
||||
Subject: [PATCH] mtd: spi-nor: convert to spi_nor_{get, set}_flash_node()
|
||||
|
||||
Used semantic patch with 'make coccicheck MODE=patch COCCI=script.cocci':
|
||||
|
||||
---8<----
|
||||
virtual patch
|
||||
|
||||
@@
|
||||
struct spi_nor b;
|
||||
struct spi_nor *c;
|
||||
expression d;
|
||||
@@
|
||||
(
|
||||
-(b).flash_node = (d)
|
||||
+spi_nor_set_flash_node(&b, d)
|
||||
|
|
||||
-(c)->flash_node = (d)
|
||||
+spi_nor_set_flash_node(c, d)
|
||||
)
|
||||
---8<----
|
||||
|
||||
And a manual conversion for the one use of spi_nor_get_flash_node().
|
||||
|
||||
Signed-off-by: Brian Norris <computersforpeace@gmail.com>
|
||||
Reviewed-by: Boris Brezillon <boris.brezillon@free-electrons.com>
|
||||
---
|
||||
drivers/mtd/devices/m25p80.c | 2 +-
|
||||
drivers/mtd/spi-nor/fsl-quadspi.c | 2 +-
|
||||
drivers/mtd/spi-nor/nxp-spifi.c | 2 +-
|
||||
drivers/mtd/spi-nor/spi-nor.c | 2 +-
|
||||
4 files changed, 4 insertions(+), 4 deletions(-)
|
||||
|
||||
--- a/drivers/mtd/devices/m25p80.c
|
||||
+++ b/drivers/mtd/devices/m25p80.c
|
||||
@@ -221,7 +221,7 @@ static int m25p_probe(struct spi_device
|
||||
nor->read_reg = m25p80_read_reg;
|
||||
|
||||
nor->dev = &spi->dev;
|
||||
- nor->flash_node = spi->dev.of_node;
|
||||
+ spi_nor_set_flash_node(nor, spi->dev.of_node);
|
||||
nor->priv = flash;
|
||||
|
||||
spi_set_drvdata(spi, flash);
|
||||
--- a/drivers/mtd/spi-nor/fsl-quadspi.c
|
||||
+++ b/drivers/mtd/spi-nor/fsl-quadspi.c
|
||||
@@ -1013,7 +1013,7 @@ static int fsl_qspi_probe(struct platfor
|
||||
mtd = &nor->mtd;
|
||||
|
||||
nor->dev = dev;
|
||||
- nor->flash_node = np;
|
||||
+ spi_nor_set_flash_node(nor, np);
|
||||
nor->priv = q;
|
||||
|
||||
/* fill the hooks */
|
||||
--- a/drivers/mtd/spi-nor/nxp-spifi.c
|
||||
+++ b/drivers/mtd/spi-nor/nxp-spifi.c
|
||||
@@ -330,7 +330,7 @@ static int nxp_spifi_setup_flash(struct
|
||||
writel(ctrl, spifi->io_base + SPIFI_CTRL);
|
||||
|
||||
spifi->nor.dev = spifi->dev;
|
||||
- spifi->nor.flash_node = np;
|
||||
+ spi_nor_set_flash_node(&spifi->nor, np);
|
||||
spifi->nor.priv = spifi;
|
||||
spifi->nor.read = nxp_spifi_read;
|
||||
spifi->nor.write = nxp_spifi_write;
|
||||
--- a/drivers/mtd/spi-nor/spi-nor.c
|
||||
+++ b/drivers/mtd/spi-nor/spi-nor.c
|
||||
@@ -1120,7 +1120,7 @@ int spi_nor_scan(struct spi_nor *nor, co
|
||||
const struct flash_info *info = NULL;
|
||||
struct device *dev = nor->dev;
|
||||
struct mtd_info *mtd = &nor->mtd;
|
||||
- struct device_node *np = nor->flash_node;
|
||||
+ struct device_node *np = spi_nor_get_flash_node(nor);
|
||||
int ret;
|
||||
int i;
|
||||
|
@ -1,725 +0,0 @@
|
||||
From a61ae81a1907af1987ad4c77300508327bc48b23 Mon Sep 17 00:00:00 2001
|
||||
From: Brian Norris <computersforpeace@gmail.com>
|
||||
Date: Fri, 30 Oct 2015 20:33:25 -0700
|
||||
Subject: [PATCH 06/11] mtd: nand: drop unnecessary partition parser data
|
||||
|
||||
All of these drivers set up a parser data struct just to communicate DT
|
||||
partition data. This field has been deprecated and is instead supported
|
||||
by telling nand_scan_ident() about the 'flash_node'.
|
||||
|
||||
This patch:
|
||||
* sets chip->flash_node for those drivers that didn't already (but used
|
||||
OF partitioning)
|
||||
* drops the parser data
|
||||
* switches to the simpler mtd_device_register() where possible, now
|
||||
that we've eliminated one of the auxiliary parameters
|
||||
|
||||
Now that we've assigned chip->flash_node for these drivers, we can
|
||||
probably rely on nand_dt_init() to do more of the DT parsing for us, but
|
||||
for now, I don't want to fiddle with each of these drivers. The parsing
|
||||
is done in duplicate for now on some drivers. I don't think this should
|
||||
break things. (Famous last words.)
|
||||
|
||||
(Rolled in some changes by Boris Brezillon)
|
||||
|
||||
Signed-off-by: Brian Norris <computersforpeace@gmail.com>
|
||||
Reviewed-by: Boris Brezillon <boris.brezillon@free-electrons.com>
|
||||
---
|
||||
drivers/mtd/nand/atmel_nand.c | 7 +++----
|
||||
drivers/mtd/nand/brcmnand/brcmnand.c | 3 +--
|
||||
drivers/mtd/nand/davinci_nand.c | 10 +++-------
|
||||
drivers/mtd/nand/fsl_elbc_nand.c | 5 ++---
|
||||
drivers/mtd/nand/fsl_ifc_nand.c | 5 ++---
|
||||
drivers/mtd/nand/fsl_upm.c | 5 ++---
|
||||
drivers/mtd/nand/fsmc_nand.c | 7 +++----
|
||||
drivers/mtd/nand/gpio.c | 8 +++-----
|
||||
drivers/mtd/nand/gpmi-nand/gpmi-nand.c | 5 ++---
|
||||
drivers/mtd/nand/hisi504_nand.c | 5 ++---
|
||||
drivers/mtd/nand/lpc32xx_mlc.c | 7 +++----
|
||||
drivers/mtd/nand/lpc32xx_slc.c | 7 +++----
|
||||
drivers/mtd/nand/mpc5121_nfc.c | 5 ++---
|
||||
drivers/mtd/nand/mxc_nand.c | 5 ++---
|
||||
drivers/mtd/nand/ndfc.c | 5 ++---
|
||||
drivers/mtd/nand/omap2.c | 6 ++----
|
||||
drivers/mtd/nand/orion_nand.c | 6 ++----
|
||||
drivers/mtd/nand/plat_nand.c | 5 ++---
|
||||
drivers/mtd/nand/pxa3xx_nand.c | 10 +++++-----
|
||||
drivers/mtd/nand/sh_flctl.c | 6 ++----
|
||||
drivers/mtd/nand/socrates_nand.c | 5 ++---
|
||||
drivers/mtd/nand/sunxi_nand.c | 4 +---
|
||||
drivers/mtd/nand/vf610_nfc.c | 6 +-----
|
||||
drivers/staging/mt29f_spinand/mt29f_spinand.c | 5 ++---
|
||||
24 files changed, 54 insertions(+), 88 deletions(-)
|
||||
|
||||
--- a/drivers/mtd/nand/atmel_nand.c
|
||||
+++ b/drivers/mtd/nand/atmel_nand.c
|
||||
@@ -2093,7 +2093,6 @@ static int atmel_nand_probe(struct platf
|
||||
struct mtd_info *mtd;
|
||||
struct nand_chip *nand_chip;
|
||||
struct resource *mem;
|
||||
- struct mtd_part_parser_data ppdata = {};
|
||||
int res, irq;
|
||||
|
||||
/* Allocate memory for the device structure (and zero it) */
|
||||
@@ -2117,6 +2116,7 @@ static int atmel_nand_probe(struct platf
|
||||
nand_chip = &host->nand_chip;
|
||||
host->dev = &pdev->dev;
|
||||
if (IS_ENABLED(CONFIG_OF) && pdev->dev.of_node) {
|
||||
+ nand_set_flash_node(nand_chip, pdev->dev.of_node);
|
||||
/* Only when CONFIG_OF is enabled of_node can be parsed */
|
||||
res = atmel_of_init_port(host, pdev->dev.of_node);
|
||||
if (res)
|
||||
@@ -2259,9 +2259,8 @@ static int atmel_nand_probe(struct platf
|
||||
}
|
||||
|
||||
mtd->name = "atmel_nand";
|
||||
- ppdata.of_node = pdev->dev.of_node;
|
||||
- res = mtd_device_parse_register(mtd, NULL, &ppdata,
|
||||
- host->board.parts, host->board.num_parts);
|
||||
+ res = mtd_device_register(mtd, host->board.parts,
|
||||
+ host->board.num_parts);
|
||||
if (!res)
|
||||
return res;
|
||||
|
||||
--- a/drivers/mtd/nand/brcmnand/brcmnand.c
|
||||
+++ b/drivers/mtd/nand/brcmnand/brcmnand.c
|
||||
@@ -1939,7 +1939,6 @@ static int brcmnand_init_cs(struct brcmn
|
||||
struct nand_chip *chip;
|
||||
int ret;
|
||||
u16 cfg_offs;
|
||||
- struct mtd_part_parser_data ppdata = { .of_node = dn };
|
||||
|
||||
ret = of_property_read_u32(dn, "reg", &host->cs);
|
||||
if (ret) {
|
||||
@@ -2018,7 +2017,7 @@ static int brcmnand_init_cs(struct brcmn
|
||||
if (nand_scan_tail(mtd))
|
||||
return -ENXIO;
|
||||
|
||||
- return mtd_device_parse_register(mtd, NULL, &ppdata, NULL, 0);
|
||||
+ return mtd_device_register(mtd, NULL, 0);
|
||||
}
|
||||
|
||||
static void brcmnand_save_restore_cs_config(struct brcmnand_host *host,
|
||||
--- a/drivers/mtd/nand/davinci_nand.c
|
||||
+++ b/drivers/mtd/nand/davinci_nand.c
|
||||
@@ -687,6 +687,7 @@ static int nand_davinci_probe(struct pla
|
||||
|
||||
info->mtd.priv = &info->chip;
|
||||
info->mtd.dev.parent = &pdev->dev;
|
||||
+ nand_set_flash_node(&info->chip, pdev->dev.of_node);
|
||||
|
||||
info->chip.IO_ADDR_R = vaddr;
|
||||
info->chip.IO_ADDR_W = vaddr;
|
||||
@@ -842,13 +843,8 @@ syndrome_done:
|
||||
if (pdata->parts)
|
||||
ret = mtd_device_parse_register(&info->mtd, NULL, NULL,
|
||||
pdata->parts, pdata->nr_parts);
|
||||
- else {
|
||||
- struct mtd_part_parser_data ppdata;
|
||||
-
|
||||
- ppdata.of_node = pdev->dev.of_node;
|
||||
- ret = mtd_device_parse_register(&info->mtd, NULL, &ppdata,
|
||||
- NULL, 0);
|
||||
- }
|
||||
+ else
|
||||
+ ret = mtd_device_register(&info->mtd, NULL, 0);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
|
||||
--- a/drivers/mtd/nand/fsl_elbc_nand.c
|
||||
+++ b/drivers/mtd/nand/fsl_elbc_nand.c
|
||||
@@ -748,6 +748,7 @@ static int fsl_elbc_chip_init(struct fsl
|
||||
/* Fill in fsl_elbc_mtd structure */
|
||||
priv->mtd.priv = chip;
|
||||
priv->mtd.dev.parent = priv->dev;
|
||||
+ nand_set_flash_node(chip, priv->dev->of_node);
|
||||
|
||||
/* set timeout to maximum */
|
||||
priv->fmr = 15 << FMR_CWTO_SHIFT;
|
||||
@@ -823,9 +824,7 @@ static int fsl_elbc_nand_probe(struct pl
|
||||
int bank;
|
||||
struct device *dev;
|
||||
struct device_node *node = pdev->dev.of_node;
|
||||
- struct mtd_part_parser_data ppdata;
|
||||
|
||||
- ppdata.of_node = pdev->dev.of_node;
|
||||
if (!fsl_lbc_ctrl_dev || !fsl_lbc_ctrl_dev->regs)
|
||||
return -ENODEV;
|
||||
lbc = fsl_lbc_ctrl_dev->regs;
|
||||
@@ -911,7 +910,7 @@ static int fsl_elbc_nand_probe(struct pl
|
||||
|
||||
/* First look for RedBoot table or partitions on the command
|
||||
* line, these take precedence over device tree information */
|
||||
- mtd_device_parse_register(&priv->mtd, part_probe_types, &ppdata,
|
||||
+ mtd_device_parse_register(&priv->mtd, part_probe_types, NULL,
|
||||
NULL, 0);
|
||||
|
||||
printk(KERN_INFO "eLBC NAND device at 0x%llx, bank %d\n",
|
||||
--- a/drivers/mtd/nand/fsl_ifc_nand.c
|
||||
+++ b/drivers/mtd/nand/fsl_ifc_nand.c
|
||||
@@ -883,6 +883,7 @@ static int fsl_ifc_chip_init(struct fsl_
|
||||
/* Fill in fsl_ifc_mtd structure */
|
||||
priv->mtd.priv = chip;
|
||||
priv->mtd.dev.parent = priv->dev;
|
||||
+ nand_set_flash_node(chip, priv->dev->of_node);
|
||||
|
||||
/* fill in nand_chip structure */
|
||||
/* set up function call table */
|
||||
@@ -1030,9 +1031,7 @@ static int fsl_ifc_nand_probe(struct pla
|
||||
int ret;
|
||||
int bank;
|
||||
struct device_node *node = dev->dev.of_node;
|
||||
- struct mtd_part_parser_data ppdata;
|
||||
|
||||
- ppdata.of_node = dev->dev.of_node;
|
||||
if (!fsl_ifc_ctrl_dev || !fsl_ifc_ctrl_dev->regs)
|
||||
return -ENODEV;
|
||||
ifc = fsl_ifc_ctrl_dev->regs;
|
||||
@@ -1128,7 +1127,7 @@ static int fsl_ifc_nand_probe(struct pla
|
||||
|
||||
/* First look for RedBoot table or partitions on the command
|
||||
* line, these take precedence over device tree information */
|
||||
- mtd_device_parse_register(&priv->mtd, part_probe_types, &ppdata,
|
||||
+ mtd_device_parse_register(&priv->mtd, part_probe_types, NULL,
|
||||
NULL, 0);
|
||||
|
||||
dev_info(priv->dev, "IFC NAND device at 0x%llx, bank %d\n",
|
||||
--- a/drivers/mtd/nand/fsl_upm.c
|
||||
+++ b/drivers/mtd/nand/fsl_upm.c
|
||||
@@ -159,7 +159,6 @@ static int fun_chip_init(struct fsl_upm_
|
||||
{
|
||||
int ret;
|
||||
struct device_node *flash_np;
|
||||
- struct mtd_part_parser_data ppdata;
|
||||
|
||||
fun->chip.IO_ADDR_R = fun->io_base;
|
||||
fun->chip.IO_ADDR_W = fun->io_base;
|
||||
@@ -182,6 +181,7 @@ static int fun_chip_init(struct fsl_upm_
|
||||
if (!flash_np)
|
||||
return -ENODEV;
|
||||
|
||||
+ nand_set_flash_node(&fun->chip, flash_np);
|
||||
fun->mtd.name = kasprintf(GFP_KERNEL, "0x%llx.%s", (u64)io_res->start,
|
||||
flash_np->name);
|
||||
if (!fun->mtd.name) {
|
||||
@@ -193,8 +193,7 @@ static int fun_chip_init(struct fsl_upm_
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
- ppdata.of_node = flash_np;
|
||||
- ret = mtd_device_parse_register(&fun->mtd, NULL, &ppdata, NULL, 0);
|
||||
+ ret = mtd_device_register(&fun->mtd, NULL, 0);
|
||||
err:
|
||||
of_node_put(flash_np);
|
||||
if (ret)
|
||||
--- a/drivers/mtd/nand/fsmc_nand.c
|
||||
+++ b/drivers/mtd/nand/fsmc_nand.c
|
||||
@@ -926,7 +926,6 @@ static int __init fsmc_nand_probe(struct
|
||||
{
|
||||
struct fsmc_nand_platform_data *pdata = dev_get_platdata(&pdev->dev);
|
||||
struct device_node __maybe_unused *np = pdev->dev.of_node;
|
||||
- struct mtd_part_parser_data ppdata = {};
|
||||
struct fsmc_nand_data *host;
|
||||
struct mtd_info *mtd;
|
||||
struct nand_chip *nand;
|
||||
@@ -1016,6 +1015,7 @@ static int __init fsmc_nand_probe(struct
|
||||
nand = &host->nand;
|
||||
mtd->priv = nand;
|
||||
nand->priv = host;
|
||||
+ nand_set_flash_node(nand, np);
|
||||
|
||||
host->mtd.dev.parent = &pdev->dev;
|
||||
nand->IO_ADDR_R = host->data_va;
|
||||
@@ -1175,9 +1175,8 @@ static int __init fsmc_nand_probe(struct
|
||||
* Check for partition info passed
|
||||
*/
|
||||
host->mtd.name = "nand";
|
||||
- ppdata.of_node = np;
|
||||
- ret = mtd_device_parse_register(&host->mtd, NULL, &ppdata,
|
||||
- host->partitions, host->nr_partitions);
|
||||
+ ret = mtd_device_register(&host->mtd, host->partitions,
|
||||
+ host->nr_partitions);
|
||||
if (ret)
|
||||
goto err_probe;
|
||||
|
||||
--- a/drivers/mtd/nand/gpio.c
|
||||
+++ b/drivers/mtd/nand/gpio.c
|
||||
@@ -209,7 +209,6 @@ static int gpio_nand_probe(struct platfo
|
||||
struct gpiomtd *gpiomtd;
|
||||
struct nand_chip *chip;
|
||||
struct resource *res;
|
||||
- struct mtd_part_parser_data ppdata = {};
|
||||
int ret = 0;
|
||||
|
||||
if (!pdev->dev.of_node && !dev_get_platdata(&pdev->dev))
|
||||
@@ -268,6 +267,7 @@ static int gpio_nand_probe(struct platfo
|
||||
chip->dev_ready = gpio_nand_devready;
|
||||
}
|
||||
|
||||
+ nand_set_flash_node(chip, pdev->dev.of_node);
|
||||
chip->IO_ADDR_W = chip->IO_ADDR_R;
|
||||
chip->ecc.mode = NAND_ECC_SOFT;
|
||||
chip->options = gpiomtd->plat.options;
|
||||
@@ -291,10 +291,8 @@ static int gpio_nand_probe(struct platfo
|
||||
gpiomtd->plat.adjust_parts(&gpiomtd->plat,
|
||||
gpiomtd->mtd_info.size);
|
||||
|
||||
- ppdata.of_node = pdev->dev.of_node;
|
||||
- ret = mtd_device_parse_register(&gpiomtd->mtd_info, NULL, &ppdata,
|
||||
- gpiomtd->plat.parts,
|
||||
- gpiomtd->plat.num_parts);
|
||||
+ ret = mtd_device_register(&gpiomtd->mtd_info, gpiomtd->plat.parts,
|
||||
+ gpiomtd->plat.num_parts);
|
||||
if (!ret)
|
||||
return 0;
|
||||
|
||||
--- a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c
|
||||
+++ b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c
|
||||
@@ -1888,7 +1888,6 @@ static int gpmi_nand_init(struct gpmi_na
|
||||
{
|
||||
struct mtd_info *mtd = &this->mtd;
|
||||
struct nand_chip *chip = &this->nand;
|
||||
- struct mtd_part_parser_data ppdata = {};
|
||||
int ret;
|
||||
|
||||
/* init current chip */
|
||||
@@ -1901,6 +1900,7 @@ static int gpmi_nand_init(struct gpmi_na
|
||||
|
||||
/* init the nand_chip{}, we don't support a 16-bit NAND Flash bus. */
|
||||
chip->priv = this;
|
||||
+ nand_set_flash_node(chip, this->pdev->dev.of_node);
|
||||
chip->select_chip = gpmi_select_chip;
|
||||
chip->cmd_ctrl = gpmi_cmd_ctrl;
|
||||
chip->dev_ready = gpmi_dev_ready;
|
||||
@@ -1954,8 +1954,7 @@ static int gpmi_nand_init(struct gpmi_na
|
||||
if (ret)
|
||||
goto err_out;
|
||||
|
||||
- ppdata.of_node = this->pdev->dev.of_node;
|
||||
- ret = mtd_device_parse_register(mtd, NULL, &ppdata, NULL, 0);
|
||||
+ ret = mtd_device_register(mtd, NULL, 0);
|
||||
if (ret)
|
||||
goto err_out;
|
||||
return 0;
|
||||
--- a/drivers/mtd/nand/hisi504_nand.c
|
||||
+++ b/drivers/mtd/nand/hisi504_nand.c
|
||||
@@ -704,7 +704,6 @@ static int hisi_nfc_probe(struct platfor
|
||||
struct mtd_info *mtd;
|
||||
struct resource *res;
|
||||
struct device_node *np = dev->of_node;
|
||||
- struct mtd_part_parser_data ppdata;
|
||||
|
||||
host = devm_kzalloc(dev, sizeof(*host), GFP_KERNEL);
|
||||
if (!host)
|
||||
@@ -742,6 +741,7 @@ static int hisi_nfc_probe(struct platfor
|
||||
mtd->dev.parent = &pdev->dev;
|
||||
|
||||
chip->priv = host;
|
||||
+ nand_set_flash_node(chip, np);
|
||||
chip->cmdfunc = hisi_nfc_cmdfunc;
|
||||
chip->select_chip = hisi_nfc_select_chip;
|
||||
chip->read_byte = hisi_nfc_read_byte;
|
||||
@@ -805,8 +805,7 @@ static int hisi_nfc_probe(struct platfor
|
||||
goto err_res;
|
||||
}
|
||||
|
||||
- ppdata.of_node = np;
|
||||
- ret = mtd_device_parse_register(mtd, NULL, &ppdata, NULL, 0);
|
||||
+ ret = mtd_device_register(mtd, NULL, 0);
|
||||
if (ret) {
|
||||
dev_err(dev, "Err MTD partition=%d\n", ret);
|
||||
goto err_mtd;
|
||||
--- a/drivers/mtd/nand/lpc32xx_mlc.c
|
||||
+++ b/drivers/mtd/nand/lpc32xx_mlc.c
|
||||
@@ -647,7 +647,6 @@ static int lpc32xx_nand_probe(struct pla
|
||||
struct nand_chip *nand_chip;
|
||||
struct resource *rc;
|
||||
int res;
|
||||
- struct mtd_part_parser_data ppdata = {};
|
||||
|
||||
/* Allocate memory for the device structure (and zero it) */
|
||||
host = devm_kzalloc(&pdev->dev, sizeof(*host), GFP_KERNEL);
|
||||
@@ -682,6 +681,7 @@ static int lpc32xx_nand_probe(struct pla
|
||||
host->pdata = dev_get_platdata(&pdev->dev);
|
||||
|
||||
nand_chip->priv = host; /* link the private data structures */
|
||||
+ nand_set_flash_node(nand_chip, pdev->dev.of_node);
|
||||
mtd->priv = nand_chip;
|
||||
mtd->dev.parent = &pdev->dev;
|
||||
|
||||
@@ -786,9 +786,8 @@ static int lpc32xx_nand_probe(struct pla
|
||||
|
||||
mtd->name = DRV_NAME;
|
||||
|
||||
- ppdata.of_node = pdev->dev.of_node;
|
||||
- res = mtd_device_parse_register(mtd, NULL, &ppdata, host->ncfg->parts,
|
||||
- host->ncfg->num_parts);
|
||||
+ res = mtd_device_register(mtd, host->ncfg->parts,
|
||||
+ host->ncfg->num_parts);
|
||||
if (!res)
|
||||
return res;
|
||||
|
||||
--- a/drivers/mtd/nand/lpc32xx_slc.c
|
||||
+++ b/drivers/mtd/nand/lpc32xx_slc.c
|
||||
@@ -763,7 +763,6 @@ static int lpc32xx_nand_probe(struct pla
|
||||
struct mtd_info *mtd;
|
||||
struct nand_chip *chip;
|
||||
struct resource *rc;
|
||||
- struct mtd_part_parser_data ppdata = {};
|
||||
int res;
|
||||
|
||||
rc = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
@@ -803,6 +802,7 @@ static int lpc32xx_nand_probe(struct pla
|
||||
mtd = &host->mtd;
|
||||
chip = &host->nand_chip;
|
||||
chip->priv = host;
|
||||
+ nand_set_flash_node(chip, pdev->dev.of_node);
|
||||
mtd->priv = chip;
|
||||
mtd->owner = THIS_MODULE;
|
||||
mtd->dev.parent = &pdev->dev;
|
||||
@@ -908,9 +908,8 @@ static int lpc32xx_nand_probe(struct pla
|
||||
}
|
||||
|
||||
mtd->name = "nxp_lpc3220_slc";
|
||||
- ppdata.of_node = pdev->dev.of_node;
|
||||
- res = mtd_device_parse_register(mtd, NULL, &ppdata, host->ncfg->parts,
|
||||
- host->ncfg->num_parts);
|
||||
+ res = mtd_device_register(mtd, host->ncfg->parts,
|
||||
+ host->ncfg->num_parts);
|
||||
if (!res)
|
||||
return res;
|
||||
|
||||
--- a/drivers/mtd/nand/mpc5121_nfc.c
|
||||
+++ b/drivers/mtd/nand/mpc5121_nfc.c
|
||||
@@ -639,7 +639,6 @@ static int mpc5121_nfc_probe(struct plat
|
||||
int resettime = 0;
|
||||
int retval = 0;
|
||||
int rev, len;
|
||||
- struct mtd_part_parser_data ppdata;
|
||||
|
||||
/*
|
||||
* Check SoC revision. This driver supports only NFC
|
||||
@@ -661,6 +660,7 @@ static int mpc5121_nfc_probe(struct plat
|
||||
mtd->priv = chip;
|
||||
mtd->dev.parent = dev;
|
||||
chip->priv = prv;
|
||||
+ nand_set_flash_node(chip, dn);
|
||||
prv->dev = dev;
|
||||
|
||||
/* Read NFC configuration from Reset Config Word */
|
||||
@@ -703,7 +703,6 @@ static int mpc5121_nfc_probe(struct plat
|
||||
}
|
||||
|
||||
mtd->name = "MPC5121 NAND";
|
||||
- ppdata.of_node = dn;
|
||||
chip->dev_ready = mpc5121_nfc_dev_ready;
|
||||
chip->cmdfunc = mpc5121_nfc_command;
|
||||
chip->read_byte = mpc5121_nfc_read_byte;
|
||||
@@ -815,7 +814,7 @@ static int mpc5121_nfc_probe(struct plat
|
||||
dev_set_drvdata(dev, mtd);
|
||||
|
||||
/* Register device in MTD */
|
||||
- retval = mtd_device_parse_register(mtd, NULL, &ppdata, NULL, 0);
|
||||
+ retval = mtd_device_register(mtd, NULL, 0);
|
||||
if (retval) {
|
||||
dev_err(dev, "Error adding MTD device!\n");
|
||||
goto error;
|
||||
--- a/drivers/mtd/nand/mxc_nand.c
|
||||
+++ b/drivers/mtd/nand/mxc_nand.c
|
||||
@@ -1524,6 +1524,7 @@ static int mxcnd_probe(struct platform_d
|
||||
this->chip_delay = 5;
|
||||
|
||||
this->priv = host;
|
||||
+ nand_set_flash_node(this, pdev->dev.of_node),
|
||||
this->dev_ready = mxc_nand_dev_ready;
|
||||
this->cmdfunc = mxc_nand_command;
|
||||
this->read_byte = mxc_nand_read_byte;
|
||||
@@ -1683,9 +1684,7 @@ static int mxcnd_probe(struct platform_d
|
||||
|
||||
/* Register the partitions */
|
||||
mtd_device_parse_register(mtd, part_probes,
|
||||
- &(struct mtd_part_parser_data){
|
||||
- .of_node = pdev->dev.of_node,
|
||||
- },
|
||||
+ NULL,
|
||||
host->pdata.parts,
|
||||
host->pdata.nr_parts);
|
||||
|
||||
--- a/drivers/mtd/nand/ndfc.c
|
||||
+++ b/drivers/mtd/nand/ndfc.c
|
||||
@@ -147,7 +147,6 @@ static int ndfc_chip_init(struct ndfc_co
|
||||
{
|
||||
struct device_node *flash_np;
|
||||
struct nand_chip *chip = &ndfc->chip;
|
||||
- struct mtd_part_parser_data ppdata;
|
||||
int ret;
|
||||
|
||||
chip->IO_ADDR_R = ndfc->ndfcbase + NDFC_DATA;
|
||||
@@ -174,8 +173,8 @@ static int ndfc_chip_init(struct ndfc_co
|
||||
flash_np = of_get_next_child(node, NULL);
|
||||
if (!flash_np)
|
||||
return -ENODEV;
|
||||
+ nand_set_flash_node(chip, flash_np);
|
||||
|
||||
- ppdata.of_node = flash_np;
|
||||
ndfc->mtd.name = kasprintf(GFP_KERNEL, "%s.%s",
|
||||
dev_name(&ndfc->ofdev->dev), flash_np->name);
|
||||
if (!ndfc->mtd.name) {
|
||||
@@ -187,7 +186,7 @@ static int ndfc_chip_init(struct ndfc_co
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
- ret = mtd_device_parse_register(&ndfc->mtd, NULL, &ppdata, NULL, 0);
|
||||
+ ret = mtd_device_register(&ndfc->mtd, NULL, 0);
|
||||
|
||||
err:
|
||||
of_node_put(flash_np);
|
||||
--- a/drivers/mtd/nand/omap2.c
|
||||
+++ b/drivers/mtd/nand/omap2.c
|
||||
@@ -1663,7 +1663,6 @@ static int omap_nand_probe(struct platfo
|
||||
unsigned sig;
|
||||
unsigned oob_index;
|
||||
struct resource *res;
|
||||
- struct mtd_part_parser_data ppdata = {};
|
||||
|
||||
pdata = dev_get_platdata(&pdev->dev);
|
||||
if (pdata == NULL) {
|
||||
@@ -1688,6 +1687,7 @@ static int omap_nand_probe(struct platfo
|
||||
mtd->dev.parent = &pdev->dev;
|
||||
nand_chip = &info->nand;
|
||||
nand_chip->ecc.priv = NULL;
|
||||
+ nand_set_flash_node(nand_chip, pdata->of_node);
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
nand_chip->IO_ADDR_R = devm_ioremap_resource(&pdev->dev, res);
|
||||
@@ -2037,9 +2037,7 @@ scan_tail:
|
||||
goto return_error;
|
||||
}
|
||||
|
||||
- ppdata.of_node = pdata->of_node;
|
||||
- mtd_device_parse_register(mtd, NULL, &ppdata, pdata->parts,
|
||||
- pdata->nr_parts);
|
||||
+ mtd_device_register(mtd, pdata->parts, pdata->nr_parts);
|
||||
|
||||
platform_set_drvdata(pdev, mtd);
|
||||
|
||||
--- a/drivers/mtd/nand/orion_nand.c
|
||||
+++ b/drivers/mtd/nand/orion_nand.c
|
||||
@@ -76,7 +76,6 @@ static void orion_nand_read_buf(struct m
|
||||
static int __init orion_nand_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct mtd_info *mtd;
|
||||
- struct mtd_part_parser_data ppdata = {};
|
||||
struct nand_chip *nc;
|
||||
struct orion_nand_data *board;
|
||||
struct resource *res;
|
||||
@@ -127,6 +126,7 @@ static int __init orion_nand_probe(struc
|
||||
mtd->dev.parent = &pdev->dev;
|
||||
|
||||
nc->priv = board;
|
||||
+ nand_set_flash_node(nc, pdev->dev.of_node);
|
||||
nc->IO_ADDR_R = nc->IO_ADDR_W = io_base;
|
||||
nc->cmd_ctrl = orion_nand_cmd_ctrl;
|
||||
nc->read_buf = orion_nand_read_buf;
|
||||
@@ -161,9 +161,7 @@ static int __init orion_nand_probe(struc
|
||||
}
|
||||
|
||||
mtd->name = "orion_nand";
|
||||
- ppdata.of_node = pdev->dev.of_node;
|
||||
- ret = mtd_device_parse_register(mtd, NULL, &ppdata,
|
||||
- board->parts, board->nr_parts);
|
||||
+ ret = mtd_device_register(mtd, board->parts, board->nr_parts);
|
||||
if (ret) {
|
||||
nand_release(mtd);
|
||||
goto no_dev;
|
||||
--- a/drivers/mtd/nand/plat_nand.c
|
||||
+++ b/drivers/mtd/nand/plat_nand.c
|
||||
@@ -30,7 +30,6 @@ struct plat_nand_data {
|
||||
static int plat_nand_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct platform_nand_data *pdata = dev_get_platdata(&pdev->dev);
|
||||
- struct mtd_part_parser_data ppdata;
|
||||
struct plat_nand_data *data;
|
||||
struct resource *res;
|
||||
const char **part_types;
|
||||
@@ -58,6 +57,7 @@ static int plat_nand_probe(struct platfo
|
||||
return PTR_ERR(data->io_base);
|
||||
|
||||
data->chip.priv = &data;
|
||||
+ nand_set_flash_node(&data->chip, pdev->dev.of_node);
|
||||
data->mtd.priv = &data->chip;
|
||||
data->mtd.dev.parent = &pdev->dev;
|
||||
|
||||
@@ -105,8 +105,7 @@ static int plat_nand_probe(struct platfo
|
||||
|
||||
part_types = pdata->chip.part_probe_types;
|
||||
|
||||
- ppdata.of_node = pdev->dev.of_node;
|
||||
- err = mtd_device_parse_register(&data->mtd, part_types, &ppdata,
|
||||
+ err = mtd_device_parse_register(&data->mtd, part_types, NULL,
|
||||
pdata->chip.partitions,
|
||||
pdata->chip.nr_partitions);
|
||||
|
||||
--- a/drivers/mtd/nand/pxa3xx_nand.c
|
||||
+++ b/drivers/mtd/nand/pxa3xx_nand.c
|
||||
@@ -1697,6 +1697,7 @@ KEEP_CONFIG:
|
||||
|
||||
static int alloc_nand_resource(struct platform_device *pdev)
|
||||
{
|
||||
+ struct device_node *np = pdev->dev.of_node;
|
||||
struct pxa3xx_nand_platform_data *pdata;
|
||||
struct pxa3xx_nand_info *info;
|
||||
struct pxa3xx_nand_host *host;
|
||||
@@ -1725,6 +1726,8 @@ static int alloc_nand_resource(struct pl
|
||||
host->info_data = info;
|
||||
mtd->priv = host;
|
||||
mtd->dev.parent = &pdev->dev;
|
||||
+ /* FIXME: all chips use the same device tree partitions */
|
||||
+ nand_set_flash_node(chip, np);
|
||||
|
||||
chip->ecc.read_page = pxa3xx_nand_read_page_hwecc;
|
||||
chip->ecc.write_page = pxa3xx_nand_write_page_hwecc;
|
||||
@@ -1886,7 +1889,6 @@ static int pxa3xx_nand_probe_dt(struct p
|
||||
static int pxa3xx_nand_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct pxa3xx_nand_platform_data *pdata;
|
||||
- struct mtd_part_parser_data ppdata = {};
|
||||
struct pxa3xx_nand_info *info;
|
||||
int ret, cs, probe_success, dma_available;
|
||||
|
||||
@@ -1933,10 +1935,8 @@ static int pxa3xx_nand_probe(struct plat
|
||||
continue;
|
||||
}
|
||||
|
||||
- ppdata.of_node = pdev->dev.of_node;
|
||||
- ret = mtd_device_parse_register(mtd, NULL,
|
||||
- &ppdata, pdata->parts[cs],
|
||||
- pdata->nr_parts[cs]);
|
||||
+ ret = mtd_device_register(mtd, pdata->parts[cs],
|
||||
+ pdata->nr_parts[cs]);
|
||||
if (!ret)
|
||||
probe_success = 1;
|
||||
}
|
||||
--- a/drivers/mtd/nand/sh_flctl.c
|
||||
+++ b/drivers/mtd/nand/sh_flctl.c
|
||||
@@ -1086,7 +1086,6 @@ static int flctl_probe(struct platform_d
|
||||
struct sh_flctl_platform_data *pdata;
|
||||
int ret;
|
||||
int irq;
|
||||
- struct mtd_part_parser_data ppdata = {};
|
||||
|
||||
flctl = devm_kzalloc(&pdev->dev, sizeof(struct sh_flctl), GFP_KERNEL);
|
||||
if (!flctl)
|
||||
@@ -1124,6 +1123,7 @@ static int flctl_probe(struct platform_d
|
||||
platform_set_drvdata(pdev, flctl);
|
||||
flctl_mtd = &flctl->mtd;
|
||||
nand = &flctl->chip;
|
||||
+ nand_set_flash_node(nand, pdev->dev.of_node);
|
||||
flctl_mtd->priv = nand;
|
||||
flctl_mtd->dev.parent = &pdev->dev;
|
||||
flctl->pdev = pdev;
|
||||
@@ -1164,9 +1164,7 @@ static int flctl_probe(struct platform_d
|
||||
if (ret)
|
||||
goto err_chip;
|
||||
|
||||
- ppdata.of_node = pdev->dev.of_node;
|
||||
- ret = mtd_device_parse_register(flctl_mtd, NULL, &ppdata, pdata->parts,
|
||||
- pdata->nr_parts);
|
||||
+ ret = mtd_device_register(flctl_mtd, pdata->parts, pdata->nr_parts);
|
||||
|
||||
return 0;
|
||||
|
||||
--- a/drivers/mtd/nand/socrates_nand.c
|
||||
+++ b/drivers/mtd/nand/socrates_nand.c
|
||||
@@ -147,7 +147,6 @@ static int socrates_nand_probe(struct pl
|
||||
struct mtd_info *mtd;
|
||||
struct nand_chip *nand_chip;
|
||||
int res;
|
||||
- struct mtd_part_parser_data ppdata;
|
||||
|
||||
/* Allocate memory for the device structure (and zero it) */
|
||||
host = devm_kzalloc(&ofdev->dev, sizeof(*host), GFP_KERNEL);
|
||||
@@ -165,10 +164,10 @@ static int socrates_nand_probe(struct pl
|
||||
host->dev = &ofdev->dev;
|
||||
|
||||
nand_chip->priv = host; /* link the private data structures */
|
||||
+ nand_set_flash_node(nand_chip, ofdev->dev.of_node);
|
||||
mtd->priv = nand_chip;
|
||||
mtd->name = "socrates_nand";
|
||||
mtd->dev.parent = &ofdev->dev;
|
||||
- ppdata.of_node = ofdev->dev.of_node;
|
||||
|
||||
/*should never be accessed directly */
|
||||
nand_chip->IO_ADDR_R = (void *)0xdeadbeef;
|
||||
@@ -200,7 +199,7 @@ static int socrates_nand_probe(struct pl
|
||||
goto out;
|
||||
}
|
||||
|
||||
- res = mtd_device_parse_register(mtd, NULL, &ppdata, NULL, 0);
|
||||
+ res = mtd_device_register(mtd, NULL, 0);
|
||||
if (!res)
|
||||
return res;
|
||||
|
||||
--- a/drivers/mtd/nand/sunxi_nand.c
|
||||
+++ b/drivers/mtd/nand/sunxi_nand.c
|
||||
@@ -1238,7 +1238,6 @@ static int sunxi_nand_chip_init(struct d
|
||||
{
|
||||
const struct nand_sdr_timings *timings;
|
||||
struct sunxi_nand_chip *chip;
|
||||
- struct mtd_part_parser_data ppdata;
|
||||
struct mtd_info *mtd;
|
||||
struct nand_chip *nand;
|
||||
int nsels;
|
||||
@@ -1372,8 +1371,7 @@ static int sunxi_nand_chip_init(struct d
|
||||
return ret;
|
||||
}
|
||||
|
||||
- ppdata.of_node = np;
|
||||
- ret = mtd_device_parse_register(mtd, NULL, &ppdata, NULL, 0);
|
||||
+ ret = mtd_device_register(mtd, NULL, 0);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to register mtd device: %d\n", ret);
|
||||
nand_release(mtd);
|
||||
--- a/drivers/mtd/nand/vf610_nfc.c
|
||||
+++ b/drivers/mtd/nand/vf610_nfc.c
|
||||
@@ -811,11 +811,7 @@ static int vf610_nfc_probe(struct platfo
|
||||
platform_set_drvdata(pdev, mtd);
|
||||
|
||||
/* Register device in MTD */
|
||||
- return mtd_device_parse_register(mtd, NULL,
|
||||
- &(struct mtd_part_parser_data){
|
||||
- .of_node = chip->flash_node,
|
||||
- },
|
||||
- NULL, 0);
|
||||
+ return mtd_device_register(mtd, NULL, 0);
|
||||
|
||||
error:
|
||||
of_node_put(chip->flash_node);
|
||||
--- a/drivers/staging/mt29f_spinand/mt29f_spinand.c
|
||||
+++ b/drivers/staging/mt29f_spinand/mt29f_spinand.c
|
||||
@@ -850,7 +850,6 @@ static int spinand_probe(struct spi_devi
|
||||
struct nand_chip *chip;
|
||||
struct spinand_info *info;
|
||||
struct spinand_state *state;
|
||||
- struct mtd_part_parser_data ppdata;
|
||||
|
||||
info = devm_kzalloc(&spi_nand->dev, sizeof(struct spinand_info),
|
||||
GFP_KERNEL);
|
||||
@@ -894,6 +893,7 @@ static int spinand_probe(struct spi_devi
|
||||
pr_info("%s: disable ecc failed!\n", __func__);
|
||||
#endif
|
||||
|
||||
+ nand_set_flash_node(chip, spi_nand->dev.of_node);
|
||||
chip->priv = info;
|
||||
chip->read_buf = spinand_read_buf;
|
||||
chip->write_buf = spinand_write_buf;
|
||||
@@ -916,8 +916,7 @@ static int spinand_probe(struct spi_devi
|
||||
if (nand_scan(mtd, 1))
|
||||
return -ENXIO;
|
||||
|
||||
- ppdata.of_node = spi_nand->dev.of_node;
|
||||
- return mtd_device_parse_register(mtd, NULL, &ppdata, NULL, 0);
|
||||
+ return mtd_device_register(mtd, NULL, 0);
|
||||
}
|
||||
|
||||
/*
|
@ -1,83 +0,0 @@
|
||||
From df02c885f8697546da41665f28dde5e30ce99674 Mon Sep 17 00:00:00 2001
|
||||
From: Brian Norris <computersforpeace@gmail.com>
|
||||
Date: Fri, 30 Oct 2015 20:33:26 -0700
|
||||
Subject: [PATCH] mtd: spi-nor: drop unnecessary partition parser data
|
||||
|
||||
Now that the SPI-NOR/MTD framework pass the 'flash_node' through to the
|
||||
partition parsing code, we don't have to do it ourselves.
|
||||
|
||||
Also convert to mtd_device_register(), since we don't need the 2nd and
|
||||
3rd parameters anymore.
|
||||
|
||||
Signed-off-by: Brian Norris <computersforpeace@gmail.com>
|
||||
Reviewed-by: Boris Brezillon <boris.brezillon@free-electrons.com>
|
||||
---
|
||||
drivers/mtd/devices/m25p80.c | 8 ++------
|
||||
drivers/mtd/spi-nor/fsl-quadspi.c | 4 +---
|
||||
drivers/mtd/spi-nor/nxp-spifi.c | 4 +---
|
||||
3 files changed, 4 insertions(+), 12 deletions(-)
|
||||
|
||||
--- a/drivers/mtd/devices/m25p80.c
|
||||
+++ b/drivers/mtd/devices/m25p80.c
|
||||
@@ -197,7 +197,6 @@ static int m25p80_erase(struct spi_nor *
|
||||
*/
|
||||
static int m25p_probe(struct spi_device *spi)
|
||||
{
|
||||
- struct mtd_part_parser_data ppdata;
|
||||
struct flash_platform_data *data;
|
||||
struct m25p *flash;
|
||||
struct spi_nor *nor;
|
||||
@@ -249,11 +248,8 @@ static int m25p_probe(struct spi_device
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
- ppdata.of_node = spi->dev.of_node;
|
||||
-
|
||||
- return mtd_device_parse_register(&nor->mtd, NULL, &ppdata,
|
||||
- data ? data->parts : NULL,
|
||||
- data ? data->nr_parts : 0);
|
||||
+ return mtd_device_register(&nor->mtd, data ? data->parts : NULL,
|
||||
+ data ? data->nr_parts : 0);
|
||||
}
|
||||
|
||||
|
||||
--- a/drivers/mtd/spi-nor/fsl-quadspi.c
|
||||
+++ b/drivers/mtd/spi-nor/fsl-quadspi.c
|
||||
@@ -927,7 +927,6 @@ static void fsl_qspi_unprep(struct spi_n
|
||||
static int fsl_qspi_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
- struct mtd_part_parser_data ppdata;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct fsl_qspi *q;
|
||||
struct resource *res;
|
||||
@@ -1038,8 +1037,7 @@ static int fsl_qspi_probe(struct platfor
|
||||
if (ret)
|
||||
goto mutex_failed;
|
||||
|
||||
- ppdata.of_node = np;
|
||||
- ret = mtd_device_parse_register(mtd, NULL, &ppdata, NULL, 0);
|
||||
+ ret = mtd_device_register(mtd, NULL, 0);
|
||||
if (ret)
|
||||
goto mutex_failed;
|
||||
|
||||
--- a/drivers/mtd/spi-nor/nxp-spifi.c
|
||||
+++ b/drivers/mtd/spi-nor/nxp-spifi.c
|
||||
@@ -271,7 +271,6 @@ static void nxp_spifi_dummy_id_read(stru
|
||||
static int nxp_spifi_setup_flash(struct nxp_spifi *spifi,
|
||||
struct device_node *np)
|
||||
{
|
||||
- struct mtd_part_parser_data ppdata;
|
||||
enum read_mode flash_read;
|
||||
u32 ctrl, property;
|
||||
u16 mode = 0;
|
||||
@@ -361,8 +360,7 @@ static int nxp_spifi_setup_flash(struct
|
||||
return ret;
|
||||
}
|
||||
|
||||
- ppdata.of_node = np;
|
||||
- ret = mtd_device_parse_register(&spifi->nor.mtd, NULL, &ppdata, NULL, 0);
|
||||
+ ret = mtd_device_register(&spifi->nor.mtd, NULL, 0);
|
||||
if (ret) {
|
||||
dev_err(spifi->dev, "mtd device parse failed\n");
|
||||
return ret;
|
@ -1,57 +0,0 @@
|
||||
From 30069af7348b56eb8c5e1dda7788a531c5f24ca2 Mon Sep 17 00:00:00 2001
|
||||
From: Brian Norris <computersforpeace@gmail.com>
|
||||
Date: Fri, 30 Oct 2015 20:33:27 -0700
|
||||
Subject: [PATCH 08/11] mtd: spi-nor: drop flash_node field
|
||||
|
||||
We can just alias to the MTD of_node.
|
||||
|
||||
Signed-off-by: Brian Norris <computersforpeace@gmail.com>
|
||||
Reviewed-by: Boris Brezillon <boris.brezillon@free-electrons.com>
|
||||
---
|
||||
drivers/mtd/spi-nor/spi-nor.c | 1 -
|
||||
include/linux/mtd/spi-nor.h | 6 ++----
|
||||
2 files changed, 2 insertions(+), 5 deletions(-)
|
||||
|
||||
--- a/drivers/mtd/spi-nor/spi-nor.c
|
||||
+++ b/drivers/mtd/spi-nor/spi-nor.c
|
||||
@@ -1228,7 +1228,6 @@ int spi_nor_scan(struct spi_nor *nor, co
|
||||
mtd->flags |= MTD_NO_ERASE;
|
||||
|
||||
mtd->dev.parent = dev;
|
||||
- mtd_set_of_node(mtd, np);
|
||||
nor->page_size = info->page_size;
|
||||
mtd->writebufsize = nor->page_size;
|
||||
|
||||
--- a/include/linux/mtd/spi-nor.h
|
||||
+++ b/include/linux/mtd/spi-nor.h
|
||||
@@ -123,7 +123,6 @@ enum spi_nor_option_flags {
|
||||
* @mtd: point to a mtd_info structure
|
||||
* @lock: the lock for the read/write/erase/lock/unlock operations
|
||||
* @dev: point to a spi device, or a spi nor controller device.
|
||||
- * @flash_node: point to a device node describing this flash instance.
|
||||
* @page_size: the page size of the SPI NOR
|
||||
* @addr_width: number of address bytes
|
||||
* @erase_opcode: the opcode for erasing a sector
|
||||
@@ -154,7 +153,6 @@ struct spi_nor {
|
||||
struct mtd_info mtd;
|
||||
struct mutex lock;
|
||||
struct device *dev;
|
||||
- struct device_node *flash_node;
|
||||
u32 page_size;
|
||||
u8 addr_width;
|
||||
u8 erase_opcode;
|
||||
@@ -187,12 +185,12 @@ struct spi_nor {
|
||||
static inline void spi_nor_set_flash_node(struct spi_nor *nor,
|
||||
struct device_node *np)
|
||||
{
|
||||
- nor->flash_node = np;
|
||||
+ mtd_set_of_node(&nor->mtd, np);
|
||||
}
|
||||
|
||||
static inline struct device_node *spi_nor_get_flash_node(struct spi_nor *nor)
|
||||
{
|
||||
- return nor->flash_node;
|
||||
+ return mtd_get_of_node(&nor->mtd);
|
||||
}
|
||||
|
||||
/**
|
@ -1,195 +0,0 @@
|
||||
From 004b5e6031f4e9fd90d565fb213b74cd06d03718 Mon Sep 17 00:00:00 2001
|
||||
From: Brian Norris <computersforpeace@gmail.com>
|
||||
Date: Fri, 30 Oct 2015 20:33:28 -0700
|
||||
Subject: [PATCH] mtd: drop unnecessary partition parser data
|
||||
|
||||
We should assign the MTD dev.of_node instead of the parser data field.
|
||||
This gets us the equivalent partition parser behavior with fewer special
|
||||
fields and parameter passing.
|
||||
|
||||
Also convert several of these to mtd_device_register(), since we don't
|
||||
need the 2nd and 3rd parameters anymore.
|
||||
|
||||
Signed-off-by: Brian Norris <computersforpeace@gmail.com>
|
||||
Reviewed-by: Marek Vasut <marex@denx.de>
|
||||
Reviewed-by: Boris Brezillon <boris.brezillon@free-electrons.com>
|
||||
---
|
||||
drivers/mtd/devices/mtd_dataflash.c | 5 ++---
|
||||
drivers/mtd/devices/spear_smi.c | 6 ++----
|
||||
drivers/mtd/devices/st_spi_fsm.c | 5 ++---
|
||||
drivers/mtd/maps/lantiq-flash.c | 5 ++---
|
||||
drivers/mtd/maps/physmap_of.c | 5 ++---
|
||||
drivers/mtd/onenand/omap2.c | 8 +++-----
|
||||
6 files changed, 13 insertions(+), 21 deletions(-)
|
||||
|
||||
--- a/drivers/mtd/devices/mtd_dataflash.c
|
||||
+++ b/drivers/mtd/devices/mtd_dataflash.c
|
||||
@@ -624,7 +624,6 @@ static int add_dataflash_otp(struct spi_
|
||||
{
|
||||
struct dataflash *priv;
|
||||
struct mtd_info *device;
|
||||
- struct mtd_part_parser_data ppdata;
|
||||
struct flash_platform_data *pdata = dev_get_platdata(&spi->dev);
|
||||
char *otp_tag = "";
|
||||
int err = 0;
|
||||
@@ -656,6 +655,7 @@ static int add_dataflash_otp(struct spi_
|
||||
device->priv = priv;
|
||||
|
||||
device->dev.parent = &spi->dev;
|
||||
+ mtd_set_of_node(device, spi->dev.of_node);
|
||||
|
||||
if (revision >= 'c')
|
||||
otp_tag = otp_setup(device, revision);
|
||||
@@ -665,8 +665,7 @@ static int add_dataflash_otp(struct spi_
|
||||
pagesize, otp_tag);
|
||||
spi_set_drvdata(spi, priv);
|
||||
|
||||
- ppdata.of_node = spi->dev.of_node;
|
||||
- err = mtd_device_parse_register(device, NULL, &ppdata,
|
||||
+ err = mtd_device_register(device,
|
||||
pdata ? pdata->parts : NULL,
|
||||
pdata ? pdata->nr_parts : 0);
|
||||
|
||||
--- a/drivers/mtd/devices/spear_smi.c
|
||||
+++ b/drivers/mtd/devices/spear_smi.c
|
||||
@@ -810,7 +810,6 @@ static int spear_smi_setup_banks(struct
|
||||
u32 bank, struct device_node *np)
|
||||
{
|
||||
struct spear_smi *dev = platform_get_drvdata(pdev);
|
||||
- struct mtd_part_parser_data ppdata = {};
|
||||
struct spear_smi_flash_info *flash_info;
|
||||
struct spear_smi_plat_data *pdata;
|
||||
struct spear_snor_flash *flash;
|
||||
@@ -855,6 +854,7 @@ static int spear_smi_setup_banks(struct
|
||||
flash->mtd.name = flash_devices[flash_index].name;
|
||||
|
||||
flash->mtd.dev.parent = &pdev->dev;
|
||||
+ mtd_set_of_node(&flash->mtd, np);
|
||||
flash->mtd.type = MTD_NORFLASH;
|
||||
flash->mtd.writesize = 1;
|
||||
flash->mtd.flags = MTD_CAP_NORFLASH;
|
||||
@@ -881,10 +881,8 @@ static int spear_smi_setup_banks(struct
|
||||
count = flash_info->nr_partitions;
|
||||
}
|
||||
#endif
|
||||
- ppdata.of_node = np;
|
||||
|
||||
- ret = mtd_device_parse_register(&flash->mtd, NULL, &ppdata, parts,
|
||||
- count);
|
||||
+ ret = mtd_device_register(&flash->mtd, parts, count);
|
||||
if (ret) {
|
||||
dev_err(&dev->pdev->dev, "Err MTD partition=%d\n", ret);
|
||||
return ret;
|
||||
--- a/drivers/mtd/devices/st_spi_fsm.c
|
||||
+++ b/drivers/mtd/devices/st_spi_fsm.c
|
||||
@@ -2025,7 +2025,6 @@ boot_device_fail:
|
||||
static int stfsm_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
- struct mtd_part_parser_data ppdata;
|
||||
struct flash_info *info;
|
||||
struct resource *res;
|
||||
struct stfsm *fsm;
|
||||
@@ -2035,7 +2034,6 @@ static int stfsm_probe(struct platform_d
|
||||
dev_err(&pdev->dev, "No DT found\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
- ppdata.of_node = np;
|
||||
|
||||
fsm = devm_kzalloc(&pdev->dev, sizeof(*fsm), GFP_KERNEL);
|
||||
if (!fsm)
|
||||
@@ -2106,6 +2104,7 @@ static int stfsm_probe(struct platform_d
|
||||
|
||||
fsm->mtd.name = info->name;
|
||||
fsm->mtd.dev.parent = &pdev->dev;
|
||||
+ mtd_set_of_node(&fsm->mtd, np);
|
||||
fsm->mtd.type = MTD_NORFLASH;
|
||||
fsm->mtd.writesize = 4;
|
||||
fsm->mtd.writebufsize = fsm->mtd.writesize;
|
||||
@@ -2124,7 +2123,7 @@ static int stfsm_probe(struct platform_d
|
||||
(long long)fsm->mtd.size, (long long)(fsm->mtd.size >> 20),
|
||||
fsm->mtd.erasesize, (fsm->mtd.erasesize >> 10));
|
||||
|
||||
- return mtd_device_parse_register(&fsm->mtd, NULL, &ppdata, NULL, 0);
|
||||
+ return mtd_device_register(&fsm->mtd, NULL, 0);
|
||||
}
|
||||
|
||||
static int stfsm_remove(struct platform_device *pdev)
|
||||
--- a/drivers/mtd/maps/lantiq-flash.c
|
||||
+++ b/drivers/mtd/maps/lantiq-flash.c
|
||||
@@ -110,7 +110,6 @@ ltq_copy_to(struct map_info *map, unsign
|
||||
static int
|
||||
ltq_mtd_probe(struct platform_device *pdev)
|
||||
{
|
||||
- struct mtd_part_parser_data ppdata;
|
||||
struct ltq_mtd *ltq_mtd;
|
||||
struct cfi_private *cfi;
|
||||
int err;
|
||||
@@ -161,13 +160,13 @@ ltq_mtd_probe(struct platform_device *pd
|
||||
}
|
||||
|
||||
ltq_mtd->mtd->dev.parent = &pdev->dev;
|
||||
+ mtd_set_of_node(ltq_mtd->mtd, pdev->dev.of_node);
|
||||
|
||||
cfi = ltq_mtd->map->fldrv_priv;
|
||||
cfi->addr_unlock1 ^= 1;
|
||||
cfi->addr_unlock2 ^= 1;
|
||||
|
||||
- ppdata.of_node = pdev->dev.of_node;
|
||||
- err = mtd_device_parse_register(ltq_mtd->mtd, NULL, &ppdata, NULL, 0);
|
||||
+ err = mtd_device_register(ltq_mtd->mtd, NULL, 0);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "failed to add partitions\n");
|
||||
goto err_destroy;
|
||||
--- a/drivers/mtd/maps/physmap_of.c
|
||||
+++ b/drivers/mtd/maps/physmap_of.c
|
||||
@@ -128,7 +128,6 @@ static int of_flash_probe(struct platfor
|
||||
int reg_tuple_size;
|
||||
struct mtd_info **mtd_list = NULL;
|
||||
resource_size_t res_size;
|
||||
- struct mtd_part_parser_data ppdata;
|
||||
bool map_indirect;
|
||||
const char *mtd_name = NULL;
|
||||
|
||||
@@ -272,8 +271,8 @@ static int of_flash_probe(struct platfor
|
||||
if (err)
|
||||
goto err_out;
|
||||
|
||||
- ppdata.of_node = dp;
|
||||
- mtd_device_parse_register(info->cmtd, part_probe_types_def, &ppdata,
|
||||
+ mtd_set_of_node(info->cmtd, dp);
|
||||
+ mtd_device_parse_register(info->cmtd, part_probe_types_def, NULL,
|
||||
NULL, 0);
|
||||
|
||||
kfree(mtd_list);
|
||||
--- a/drivers/mtd/onenand/omap2.c
|
||||
+++ b/drivers/mtd/onenand/omap2.c
|
||||
@@ -614,7 +614,6 @@ static int omap2_onenand_probe(struct pl
|
||||
struct onenand_chip *this;
|
||||
int r;
|
||||
struct resource *res;
|
||||
- struct mtd_part_parser_data ppdata = {};
|
||||
|
||||
pdata = dev_get_platdata(&pdev->dev);
|
||||
if (pdata == NULL) {
|
||||
@@ -713,6 +712,7 @@ static int omap2_onenand_probe(struct pl
|
||||
c->mtd.priv = &c->onenand;
|
||||
|
||||
c->mtd.dev.parent = &pdev->dev;
|
||||
+ mtd_set_of_node(&c->mtd, pdata->of_node);
|
||||
|
||||
this = &c->onenand;
|
||||
if (c->dma_channel >= 0) {
|
||||
@@ -743,10 +743,8 @@ static int omap2_onenand_probe(struct pl
|
||||
if ((r = onenand_scan(&c->mtd, 1)) < 0)
|
||||
goto err_release_regulator;
|
||||
|
||||
- ppdata.of_node = pdata->of_node;
|
||||
- r = mtd_device_parse_register(&c->mtd, NULL, &ppdata,
|
||||
- pdata ? pdata->parts : NULL,
|
||||
- pdata ? pdata->nr_parts : 0);
|
||||
+ r = mtd_device_register(&c->mtd, pdata ? pdata->parts : NULL,
|
||||
+ pdata ? pdata->nr_parts : 0);
|
||||
if (r)
|
||||
goto err_release_onenand;
|
||||
|
@ -1,61 +0,0 @@
|
||||
From e270bca531b40cd0a143176eb093d173b9c6f418 Mon Sep 17 00:00:00 2001
|
||||
From: Brian Norris <computersforpeace@gmail.com>
|
||||
Date: Fri, 30 Oct 2015 20:33:29 -0700
|
||||
Subject: [PATCH 10/11] mtd: ofpart: drop 'of_node' partition parser data
|
||||
|
||||
This field is no longer used anywhere, as it is superseded by
|
||||
mtd->dev.of_node.
|
||||
|
||||
Signed-off-by: Brian Norris <computersforpeace@gmail.com>
|
||||
Reviewed-by: Boris Brezillon <boris.brezillon@free-electrons.com>
|
||||
---
|
||||
drivers/mtd/ofpart.c | 14 ++++----------
|
||||
include/linux/mtd/partitions.h | 4 ----
|
||||
2 files changed, 4 insertions(+), 14 deletions(-)
|
||||
|
||||
--- a/drivers/mtd/ofpart.c
|
||||
+++ b/drivers/mtd/ofpart.c
|
||||
@@ -37,11 +37,8 @@ static int parse_ofpart_partitions(struc
|
||||
bool dedicated = true;
|
||||
|
||||
|
||||
- /*
|
||||
- * of_node can be provided through auxiliary parser data or (preferred)
|
||||
- * by assigning the master device node
|
||||
- */
|
||||
- mtd_node = data && data->of_node ? data->of_node : mtd_get_of_node(master);
|
||||
+ /* Pull of_node from the master device node */
|
||||
+ mtd_node = mtd_get_of_node(master);
|
||||
if (!mtd_node)
|
||||
return 0;
|
||||
|
||||
@@ -158,11 +155,8 @@ static int parse_ofoldpart_partitions(st
|
||||
} *part;
|
||||
const char *names;
|
||||
|
||||
- /*
|
||||
- * of_node can be provided through auxiliary parser data or (preferred)
|
||||
- * by assigning the master device node
|
||||
- */
|
||||
- dp = data && data->of_node ? data->of_node : mtd_get_of_node(master);
|
||||
+ /* Pull of_node from the master device node */
|
||||
+ dp = mtd_get_of_node(master);
|
||||
if (!dp)
|
||||
return 0;
|
||||
|
||||
--- a/include/linux/mtd/partitions.h
|
||||
+++ b/include/linux/mtd/partitions.h
|
||||
@@ -56,13 +56,9 @@ struct device_node;
|
||||
/**
|
||||
* struct mtd_part_parser_data - used to pass data to MTD partition parsers.
|
||||
* @origin: for RedBoot, start address of MTD device
|
||||
- * @of_node: for OF parsers, device node containing partitioning information.
|
||||
- * This field is deprecated, as the device node should simply be
|
||||
- * assigned to the master struct device.
|
||||
*/
|
||||
struct mtd_part_parser_data {
|
||||
unsigned long origin;
|
||||
- struct device_node *of_node;
|
||||
};
|
||||
|
||||
|
@ -1,27 +0,0 @@
|
||||
From 8361a9b8cb6a9c71b7cf884a87b2532d8367c185 Mon Sep 17 00:00:00 2001
|
||||
From: Brian Norris <computersforpeace@gmail.com>
|
||||
Date: Fri, 30 Oct 2015 20:33:30 -0700
|
||||
Subject: [PATCH 11/11] mtd: physmap_of: assign parent for the concatenated MTD
|
||||
|
||||
If there is more than one map region for this device, then the
|
||||
concatenated MTD will not have a parent device assigned to it -- only
|
||||
the sub-devices (which are not actually registered with the framework)
|
||||
will have their parents assigned. Let's assign the concatenated device
|
||||
correctly.
|
||||
|
||||
Signed-off-by: Brian Norris <computersforpeace@gmail.com>
|
||||
Reviewed-by: Boris Brezillon <boris.brezillon@free-electrons.com>
|
||||
---
|
||||
drivers/mtd/maps/physmap_of.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
--- a/drivers/mtd/maps/physmap_of.c
|
||||
+++ b/drivers/mtd/maps/physmap_of.c
|
||||
@@ -271,6 +271,7 @@ static int of_flash_probe(struct platfor
|
||||
if (err)
|
||||
goto err_out;
|
||||
|
||||
+ info->cmtd->dev.parent = &dev->dev;
|
||||
mtd_set_of_node(info->cmtd, dp);
|
||||
mtd_device_parse_register(info->cmtd, part_probe_types_def, NULL,
|
||||
NULL, 0);
|
@ -1,51 +0,0 @@
|
||||
From 4acad4aae10d1fa79a075b38b5c73772c44f576c Mon Sep 17 00:00:00 2001
|
||||
From: Michal Suchanek <hramrach@gmail.com>
|
||||
Date: Wed, 2 Dec 2015 10:38:21 +0000
|
||||
Subject: [PATCH] spi: expose master transfer size limitation.
|
||||
|
||||
On some SPI controllers it is not feasible to transfer arbitrary amount
|
||||
of data at once.
|
||||
|
||||
When the limit on transfer size is a few kilobytes at least it makes
|
||||
sense to use the SPI hardware rather than reverting to gpio driver.
|
||||
|
||||
The protocol drivers need a way to check that they do not sent overly
|
||||
long messages, though.
|
||||
|
||||
Signed-off-by: Michal Suchanek <hramrach@gmail.com>
|
||||
Signed-off-by: Mark Brown <broonie@kernel.org>
|
||||
---
|
||||
include/linux/spi/spi.h | 15 +++++++++++++++
|
||||
1 file changed, 15 insertions(+)
|
||||
|
||||
--- a/include/linux/spi/spi.h
|
||||
+++ b/include/linux/spi/spi.h
|
||||
@@ -428,6 +428,12 @@ struct spi_master {
|
||||
#define SPI_MASTER_MUST_RX BIT(3) /* requires rx */
|
||||
#define SPI_MASTER_MUST_TX BIT(4) /* requires tx */
|
||||
|
||||
+ /*
|
||||
+ * on some hardware transfer size may be constrained
|
||||
+ * the limit may depend on device transfer settings
|
||||
+ */
|
||||
+ size_t (*max_transfer_size)(struct spi_device *spi);
|
||||
+
|
||||
/* lock and mutex for SPI bus locking */
|
||||
spinlock_t bus_lock_spinlock;
|
||||
struct mutex bus_lock_mutex;
|
||||
@@ -837,6 +843,15 @@ extern int spi_async(struct spi_device *
|
||||
extern int spi_async_locked(struct spi_device *spi,
|
||||
struct spi_message *message);
|
||||
|
||||
+static inline size_t
|
||||
+spi_max_transfer_size(struct spi_device *spi)
|
||||
+{
|
||||
+ struct spi_master *master = spi->master;
|
||||
+ if (!master->max_transfer_size)
|
||||
+ return SIZE_MAX;
|
||||
+ return master->max_transfer_size(spi);
|
||||
+}
|
||||
+
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
/* All these synchronous SPI transfer routines are utilities layered
|
@ -1,121 +0,0 @@
|
||||
From b08ea35a3296ee25c4cb53a977b752266dafa2c2 Mon Sep 17 00:00:00 2001
|
||||
From: Linus Walleij <linus.walleij@linaro.org>
|
||||
Date: Thu, 3 Dec 2015 15:14:13 +0100
|
||||
Subject: [PATCH] gpio: add a data pointer to gpio_chip
|
||||
|
||||
This adds a void * pointer to gpio_chip so that driver can
|
||||
assign and retrieve some states. This is done to get rid of
|
||||
container_of() calls for gpio_chips embedded inside state
|
||||
containers, so we can remove the need to have the gpio_chip
|
||||
or later (planned) struct gpio_device be dynamically allocated
|
||||
at registration time, so that its struct device can be properly
|
||||
reference counted and not bound to its parent device (e.g.
|
||||
a platform_device) but instead live on after unregistration
|
||||
if it is opened by e.g. a char device or sysfs.
|
||||
|
||||
The data is added with the new function gpiochip_add_data()
|
||||
and for compatibility we add static inline wrapper function
|
||||
gpiochip_add() that will call gpiochip_add_data() with
|
||||
NULL as argument. The latter will be removed once we have
|
||||
exorcised gpiochip_add() from the kernel.
|
||||
|
||||
gpiochip_get_data() is added as a static inline accessor
|
||||
for drivers to quickly get their data out.
|
||||
|
||||
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
|
||||
---
|
||||
drivers/gpio/gpiolib.c | 10 ++++++----
|
||||
include/linux/gpio/driver.h | 14 +++++++++++++-
|
||||
2 files changed, 19 insertions(+), 5 deletions(-)
|
||||
|
||||
--- a/drivers/gpio/gpiolib.c
|
||||
+++ b/drivers/gpio/gpiolib.c
|
||||
@@ -280,7 +280,7 @@ static int gpiochip_set_desc_names(struc
|
||||
}
|
||||
|
||||
/**
|
||||
- * gpiochip_add() - register a gpio_chip
|
||||
+ * gpiochip_add_data() - register a gpio_chip
|
||||
* @chip: the chip to register, with chip->base initialized
|
||||
* Context: potentially before irqs will work
|
||||
*
|
||||
@@ -288,7 +288,7 @@ static int gpiochip_set_desc_names(struc
|
||||
* because the chip->base is invalid or already associated with a
|
||||
* different chip. Otherwise it returns zero as a success code.
|
||||
*
|
||||
- * When gpiochip_add() is called very early during boot, so that GPIOs
|
||||
+ * When gpiochip_add_data() is called very early during boot, so that GPIOs
|
||||
* can be freely used, the chip->dev device must be registered before
|
||||
* the gpio framework's arch_initcall(). Otherwise sysfs initialization
|
||||
* for GPIOs will fail rudely.
|
||||
@@ -296,7 +296,7 @@ static int gpiochip_set_desc_names(struc
|
||||
* If chip->base is negative, this requests dynamic assignment of
|
||||
* a range of valid GPIOs.
|
||||
*/
|
||||
-int gpiochip_add(struct gpio_chip *chip)
|
||||
+int gpiochip_add_data(struct gpio_chip *chip, void *data)
|
||||
{
|
||||
unsigned long flags;
|
||||
int status = 0;
|
||||
@@ -308,6 +308,8 @@ int gpiochip_add(struct gpio_chip *chip)
|
||||
if (!descs)
|
||||
return -ENOMEM;
|
||||
|
||||
+ chip->data = data;
|
||||
+
|
||||
spin_lock_irqsave(&gpio_lock, flags);
|
||||
|
||||
if (base < 0) {
|
||||
@@ -389,7 +391,7 @@ err_free_descs:
|
||||
chip->label ? : "generic");
|
||||
return status;
|
||||
}
|
||||
-EXPORT_SYMBOL_GPL(gpiochip_add);
|
||||
+EXPORT_SYMBOL_GPL(gpiochip_add_data);
|
||||
|
||||
/**
|
||||
* gpiochip_remove() - unregister a gpio_chip
|
||||
--- a/include/linux/gpio/driver.h
|
||||
+++ b/include/linux/gpio/driver.h
|
||||
@@ -23,6 +23,7 @@ struct seq_file;
|
||||
* @dev: optional device providing the GPIOs
|
||||
* @cdev: class device used by sysfs interface (may be NULL)
|
||||
* @owner: helps prevent removal of modules exporting active GPIOs
|
||||
+ * @data: per-instance data assigned by the driver
|
||||
* @list: links gpio_chips together for traversal
|
||||
* @request: optional hook for chip-specific activation, such as
|
||||
* enabling module power and clock; may sleep
|
||||
@@ -92,6 +93,7 @@ struct gpio_chip {
|
||||
struct device *dev;
|
||||
struct device *cdev;
|
||||
struct module *owner;
|
||||
+ void *data;
|
||||
struct list_head list;
|
||||
|
||||
int (*request)(struct gpio_chip *chip,
|
||||
@@ -166,7 +168,11 @@ extern const char *gpiochip_is_requested
|
||||
unsigned offset);
|
||||
|
||||
/* add/remove chips */
|
||||
-extern int gpiochip_add(struct gpio_chip *chip);
|
||||
+extern int gpiochip_add_data(struct gpio_chip *chip, void *data);
|
||||
+static inline int gpiochip_add(struct gpio_chip *chip)
|
||||
+{
|
||||
+ return gpiochip_add_data(chip, NULL);
|
||||
+}
|
||||
extern void gpiochip_remove(struct gpio_chip *chip);
|
||||
extern struct gpio_chip *gpiochip_find(void *data,
|
||||
int (*match)(struct gpio_chip *chip, void *data));
|
||||
@@ -175,6 +181,12 @@ extern struct gpio_chip *gpiochip_find(v
|
||||
int gpiochip_lock_as_irq(struct gpio_chip *chip, unsigned int offset);
|
||||
void gpiochip_unlock_as_irq(struct gpio_chip *chip, unsigned int offset);
|
||||
|
||||
+/* get driver data */
|
||||
+static inline void *gpiochip_get_data(struct gpio_chip *chip)
|
||||
+{
|
||||
+ return chip->data;
|
||||
+}
|
||||
+
|
||||
struct gpio_chip *gpiod_to_chip(const struct gpio_desc *desc);
|
||||
|
||||
#ifdef CONFIG_GPIOLIB_IRQCHIP
|
File diff suppressed because it is too large
Load Diff
@ -1,115 +0,0 @@
|
||||
From 0cf3292cde22f8843ae5d1eeb8466d8121243c1a Mon Sep 17 00:00:00 2001
|
||||
From: Laxman Dewangan <ldewangan@nvidia.com>
|
||||
Date: Mon, 15 Feb 2016 16:32:09 +0530
|
||||
Subject: [PATCH] gpio: Add devm_ apis for gpiochip_add_data and
|
||||
gpiochip_remove
|
||||
|
||||
Add device managed APIs devm_gpiochip_add_data() and
|
||||
devm_gpiochip_remove() for the APIs gpiochip_add_data()
|
||||
and gpiochip_remove().
|
||||
|
||||
This helps in reducing code in error path and sometimes
|
||||
removal of .remove callback for driver unbind.
|
||||
|
||||
Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com>
|
||||
---
|
||||
drivers/gpio/gpiolib.c | 74 +++++++++++++++++++++++++++++++++++++++++++++
|
||||
include/linux/gpio/driver.h | 4 +++
|
||||
2 files changed, 78 insertions(+)
|
||||
|
||||
--- a/drivers/gpio/gpiolib.c
|
||||
+++ b/drivers/gpio/gpiolib.c
|
||||
@@ -433,6 +433,80 @@ void gpiochip_remove(struct gpio_chip *c
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(gpiochip_remove);
|
||||
|
||||
+static void devm_gpio_chip_release(struct device *dev, void *res)
|
||||
+{
|
||||
+ struct gpio_chip *chip = *(struct gpio_chip **)res;
|
||||
+
|
||||
+ gpiochip_remove(chip);
|
||||
+}
|
||||
+
|
||||
+static int devm_gpio_chip_match(struct device *dev, void *res, void *data)
|
||||
+
|
||||
+{
|
||||
+ struct gpio_chip **r = res;
|
||||
+
|
||||
+ if (!r || !*r) {
|
||||
+ WARN_ON(!r || !*r);
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ return *r == data;
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * devm_gpiochip_add_data() - Resource manager piochip_add_data()
|
||||
+ * @dev: the device pointer on which irq_chip belongs to.
|
||||
+ * @chip: the chip to register, with chip->base initialized
|
||||
+ * Context: potentially before irqs will work
|
||||
+ *
|
||||
+ * Returns a negative errno if the chip can't be registered, such as
|
||||
+ * because the chip->base is invalid or already associated with a
|
||||
+ * different chip. Otherwise it returns zero as a success code.
|
||||
+ *
|
||||
+ * The gpio chip automatically be released when the device is unbound.
|
||||
+ */
|
||||
+int devm_gpiochip_add_data(struct device *dev, struct gpio_chip *chip,
|
||||
+ void *data)
|
||||
+{
|
||||
+ struct gpio_chip **ptr;
|
||||
+ int ret;
|
||||
+
|
||||
+ ptr = devres_alloc(devm_gpio_chip_release, sizeof(*ptr),
|
||||
+ GFP_KERNEL);
|
||||
+ if (!ptr)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ ret = gpiochip_add_data(chip, data);
|
||||
+ if (ret < 0) {
|
||||
+ devres_free(ptr);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ *ptr = chip;
|
||||
+ devres_add(dev, ptr);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(devm_gpiochip_add_data);
|
||||
+
|
||||
+/**
|
||||
+ * devm_gpiochip_remove() - Resource manager of gpiochip_remove()
|
||||
+ * @dev: device for which which resource was allocated
|
||||
+ * @chip: the chip to remove
|
||||
+ *
|
||||
+ * A gpio_chip with any GPIOs still requested may not be removed.
|
||||
+ */
|
||||
+void devm_gpiochip_remove(struct device *dev, struct gpio_chip *chip)
|
||||
+{
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = devres_release(dev, devm_gpio_chip_release,
|
||||
+ devm_gpio_chip_match, chip);
|
||||
+ if (!ret)
|
||||
+ WARN_ON(ret);
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(devm_gpiochip_remove);
|
||||
+
|
||||
/**
|
||||
* gpiochip_find() - iterator for locating a specific gpio_chip
|
||||
* @data: data to pass to match function
|
||||
--- a/include/linux/gpio/driver.h
|
||||
+++ b/include/linux/gpio/driver.h
|
||||
@@ -206,6 +206,10 @@ static inline int gpiochip_add(struct gp
|
||||
return gpiochip_add_data(chip, NULL);
|
||||
}
|
||||
extern void gpiochip_remove(struct gpio_chip *chip);
|
||||
+extern int devm_gpiochip_add_data(struct device *dev, struct gpio_chip *chip,
|
||||
+ void *data);
|
||||
+extern void devm_gpiochip_remove(struct device *dev, struct gpio_chip *chip);
|
||||
+
|
||||
extern struct gpio_chip *gpiochip_find(void *data,
|
||||
int (*match)(struct gpio_chip *chip, void *data));
|
||||
|
@ -1,108 +0,0 @@
|
||||
From 80e0f8d94d3090f0f7bf3faf3e6180e920ee0d22 Mon Sep 17 00:00:00 2001
|
||||
From: Laxman Dewangan <ldewangan@nvidia.com>
|
||||
Date: Wed, 24 Feb 2016 14:12:59 +0530
|
||||
Subject: [PATCH] pinctrl: Add devm_ apis for pinctrl_{register, unregister}
|
||||
|
||||
Add device managed APIs devm_pinctrl_register() and
|
||||
devm_pinctrl_unregister() for the APIs pinctrl_register()
|
||||
and pinctrl_unregister().
|
||||
|
||||
This helps in reducing code in error path and sometimes
|
||||
removal of .remove callback for driver unbind.
|
||||
|
||||
Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com>
|
||||
Reviewed-by: Philipp Zabel <p.zabel@pengutronix.de>
|
||||
Acked-by: Bjorn Andersson <bjorn.andersson@linaro.org>
|
||||
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
|
||||
---
|
||||
drivers/pinctrl/core.c | 63 +++++++++++++++++++++++++++++++++++++++++
|
||||
include/linux/pinctrl/pinctrl.h | 6 ++++
|
||||
2 files changed, 69 insertions(+)
|
||||
|
||||
--- a/drivers/pinctrl/core.c
|
||||
+++ b/drivers/pinctrl/core.c
|
||||
@@ -1861,6 +1861,69 @@ void pinctrl_unregister(struct pinctrl_d
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pinctrl_unregister);
|
||||
|
||||
+static void devm_pinctrl_dev_release(struct device *dev, void *res)
|
||||
+{
|
||||
+ struct pinctrl_dev *pctldev = *(struct pinctrl_dev **)res;
|
||||
+
|
||||
+ pinctrl_unregister(pctldev);
|
||||
+}
|
||||
+
|
||||
+static int devm_pinctrl_dev_match(struct device *dev, void *res, void *data)
|
||||
+{
|
||||
+ struct pctldev **r = res;
|
||||
+
|
||||
+ if (WARN_ON(!r || !*r))
|
||||
+ return 0;
|
||||
+
|
||||
+ return *r == data;
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * devm_pinctrl_register() - Resource managed version of pinctrl_register().
|
||||
+ * @dev: parent device for this pin controller
|
||||
+ * @pctldesc: descriptor for this pin controller
|
||||
+ * @driver_data: private pin controller data for this pin controller
|
||||
+ *
|
||||
+ * Returns an error pointer if pincontrol register failed. Otherwise
|
||||
+ * it returns valid pinctrl handle.
|
||||
+ *
|
||||
+ * The pinctrl device will be automatically released when the device is unbound.
|
||||
+ */
|
||||
+struct pinctrl_dev *devm_pinctrl_register(struct device *dev,
|
||||
+ struct pinctrl_desc *pctldesc,
|
||||
+ void *driver_data)
|
||||
+{
|
||||
+ struct pinctrl_dev **ptr, *pctldev;
|
||||
+
|
||||
+ ptr = devres_alloc(devm_pinctrl_dev_release, sizeof(*ptr), GFP_KERNEL);
|
||||
+ if (!ptr)
|
||||
+ return ERR_PTR(-ENOMEM);
|
||||
+
|
||||
+ pctldev = pinctrl_register(pctldesc, dev, driver_data);
|
||||
+ if (IS_ERR(pctldev)) {
|
||||
+ devres_free(ptr);
|
||||
+ return pctldev;
|
||||
+ }
|
||||
+
|
||||
+ *ptr = pctldev;
|
||||
+ devres_add(dev, ptr);
|
||||
+
|
||||
+ return pctldev;
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(devm_pinctrl_register);
|
||||
+
|
||||
+/**
|
||||
+ * devm_pinctrl_unregister() - Resource managed version of pinctrl_unregister().
|
||||
+ * @dev: device for which which resource was allocated
|
||||
+ * @pctldev: the pinctrl device to unregister.
|
||||
+ */
|
||||
+void devm_pinctrl_unregister(struct device *dev, struct pinctrl_dev *pctldev)
|
||||
+{
|
||||
+ WARN_ON(devres_release(dev, devm_pinctrl_dev_release,
|
||||
+ devm_pinctrl_dev_match, pctldev));
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(devm_pinctrl_unregister);
|
||||
+
|
||||
static int __init pinctrl_init(void)
|
||||
{
|
||||
pr_info("initialized pinctrl subsystem\n");
|
||||
--- a/include/linux/pinctrl/pinctrl.h
|
||||
+++ b/include/linux/pinctrl/pinctrl.h
|
||||
@@ -144,6 +144,12 @@ struct pinctrl_desc {
|
||||
extern struct pinctrl_dev *pinctrl_register(struct pinctrl_desc *pctldesc,
|
||||
struct device *dev, void *driver_data);
|
||||
extern void pinctrl_unregister(struct pinctrl_dev *pctldev);
|
||||
+extern struct pinctrl_dev *devm_pinctrl_register(struct device *dev,
|
||||
+ struct pinctrl_desc *pctldesc,
|
||||
+ void *driver_data);
|
||||
+extern void devm_pinctrl_unregister(struct device *dev,
|
||||
+ struct pinctrl_dev *pctldev);
|
||||
+
|
||||
extern bool pin_is_valid(struct pinctrl_dev *pctldev, int pin);
|
||||
extern void pinctrl_add_gpio_range(struct pinctrl_dev *pctldev,
|
||||
struct pinctrl_gpio_range *range);
|
@ -1,59 +0,0 @@
|
||||
From d32f7fd3bbc32732b094d938b95169521503a9fb Mon Sep 17 00:00:00 2001
|
||||
From: Irina Tirdea <irina.tirdea@intel.com>
|
||||
Date: Thu, 31 Mar 2016 14:44:42 +0300
|
||||
Subject: [PATCH] pinctrl: Rename pinctrl_utils_dt_free_map to
|
||||
pinctrl_utils_free_map
|
||||
|
||||
Rename pinctrl_utils_dt_free_map to pinctrl_utils_free_map, since
|
||||
it does not depend on device tree despite the current name. This
|
||||
will enforce a consistent naming in pinctr-utils.c and will make
|
||||
it clear it can be called from outside device tree (e.g. from
|
||||
ACPI handling code).
|
||||
|
||||
Signed-off-by: Irina Tirdea <irina.tirdea@intel.com>
|
||||
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
|
||||
---
|
||||
drivers/pinctrl/pinconf-generic.c | 2 +-
|
||||
drivers/pinctrl/pinctrl-utils.c | 4 ++--
|
||||
drivers/pinctrl/pinctrl-utils.h | 2 +-
|
||||
3 files changed, 4 insertions(+), 4 deletions(-)
|
||||
|
||||
--- a/drivers/pinctrl/pinconf-generic.c
|
||||
+++ b/drivers/pinctrl/pinconf-generic.c
|
||||
@@ -385,7 +385,7 @@ int pinconf_generic_dt_node_to_map(struc
|
||||
return 0;
|
||||
|
||||
exit:
|
||||
- pinctrl_utils_dt_free_map(pctldev, *map, *num_maps);
|
||||
+ pinctrl_utils_free_map(pctldev, *map, *num_maps);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pinconf_generic_dt_node_to_map);
|
||||
--- a/drivers/pinctrl/pinctrl-utils.c
|
||||
+++ b/drivers/pinctrl/pinctrl-utils.c
|
||||
@@ -122,7 +122,7 @@ int pinctrl_utils_add_config(struct pinc
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pinctrl_utils_add_config);
|
||||
|
||||
-void pinctrl_utils_dt_free_map(struct pinctrl_dev *pctldev,
|
||||
+void pinctrl_utils_free_map(struct pinctrl_dev *pctldev,
|
||||
struct pinctrl_map *map, unsigned num_maps)
|
||||
{
|
||||
int i;
|
||||
@@ -139,4 +139,4 @@ void pinctrl_utils_dt_free_map(struct pi
|
||||
}
|
||||
kfree(map);
|
||||
}
|
||||
-EXPORT_SYMBOL_GPL(pinctrl_utils_dt_free_map);
|
||||
+EXPORT_SYMBOL_GPL(pinctrl_utils_free_map);
|
||||
--- a/drivers/pinctrl/pinctrl-utils.h
|
||||
+++ b/drivers/pinctrl/pinctrl-utils.h
|
||||
@@ -37,7 +37,7 @@ int pinctrl_utils_add_map_configs(struct
|
||||
int pinctrl_utils_add_config(struct pinctrl_dev *pctldev,
|
||||
unsigned long **configs, unsigned *num_configs,
|
||||
unsigned long config);
|
||||
-void pinctrl_utils_dt_free_map(struct pinctrl_dev *pctldev,
|
||||
+void pinctrl_utils_free_map(struct pinctrl_dev *pctldev,
|
||||
struct pinctrl_map *map, unsigned num_maps);
|
||||
|
||||
#endif /* __PINCTRL_UTILS_H__ */
|
@ -1,149 +0,0 @@
|
||||
From 59451e1233bd315c5379a631838a03d80e689581 Mon Sep 17 00:00:00 2001
|
||||
From: Michal Suchanek <hramrach@gmail.com>
|
||||
Date: Thu, 5 May 2016 17:31:47 -0700
|
||||
Subject: [PATCH 01/10] mtd: spi-nor: change return value of read/write
|
||||
|
||||
Change the return value of spi-nor device read and write methods to
|
||||
allow returning amount of data transferred and errors as
|
||||
read(2)/write(2) does.
|
||||
|
||||
Also, start handling positive returns in spi_nor_read(), since we want
|
||||
to convert drivers to start returning the read-length both via *retlen
|
||||
and the return code. (We don't need to do the same transition process
|
||||
for spi_nor_write(), since ->write() didn't used to have a return code
|
||||
at all.)
|
||||
|
||||
Signed-off-by: Michal Suchanek <hramrach@gmail.com>
|
||||
Signed-off-by: Brian Norris <computersforpeace@gmail.com>
|
||||
Tested-by Cyrille Pitchen <cyrille.pitchen@atmel.com>
|
||||
Acked-by: Michal Suchanek <hramrach@gmail.com>
|
||||
Tested-by: Michal Suchanek <hramrach@gmail.com>
|
||||
---
|
||||
drivers/mtd/devices/m25p80.c | 5 +++--
|
||||
drivers/mtd/spi-nor/fsl-quadspi.c | 5 +++--
|
||||
drivers/mtd/spi-nor/nxp-spifi.c | 12 ++++++------
|
||||
drivers/mtd/spi-nor/spi-nor.c | 5 ++++-
|
||||
include/linux/mtd/spi-nor.h | 4 ++--
|
||||
6 files changed, 36 insertions(+), 21 deletions(-)
|
||||
|
||||
--- a/drivers/mtd/devices/m25p80.c
|
||||
+++ b/drivers/mtd/devices/m25p80.c
|
||||
@@ -73,7 +73,7 @@ static int m25p80_write_reg(struct spi_n
|
||||
return spi_write(spi, flash->command, len + 1);
|
||||
}
|
||||
|
||||
-static void m25p80_write(struct spi_nor *nor, loff_t to, size_t len,
|
||||
+static ssize_t m25p80_write(struct spi_nor *nor, loff_t to, size_t len,
|
||||
size_t *retlen, const u_char *buf)
|
||||
{
|
||||
struct m25p *flash = nor->priv;
|
||||
@@ -101,6 +101,7 @@ static void m25p80_write(struct spi_nor
|
||||
spi_sync(spi, &m);
|
||||
|
||||
*retlen += m.actual_length - cmd_sz;
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
static inline unsigned int m25p80_rx_nbits(struct spi_nor *nor)
|
||||
@@ -119,7 +120,7 @@ static inline unsigned int m25p80_rx_nbi
|
||||
* Read an address range from the nor chip. The address range
|
||||
* may be any size provided it is within the physical boundaries.
|
||||
*/
|
||||
-static int m25p80_read(struct spi_nor *nor, loff_t from, size_t len,
|
||||
+static ssize_t m25p80_read(struct spi_nor *nor, loff_t from, size_t len,
|
||||
size_t *retlen, u_char *buf)
|
||||
{
|
||||
struct m25p *flash = nor->priv;
|
||||
--- a/drivers/mtd/spi-nor/fsl-quadspi.c
|
||||
+++ b/drivers/mtd/spi-nor/fsl-quadspi.c
|
||||
@@ -822,7 +822,7 @@ static int fsl_qspi_write_reg(struct spi
|
||||
return ret;
|
||||
}
|
||||
|
||||
-static void fsl_qspi_write(struct spi_nor *nor, loff_t to,
|
||||
+static ssize_t fsl_qspi_write(struct spi_nor *nor, loff_t to,
|
||||
size_t len, size_t *retlen, const u_char *buf)
|
||||
{
|
||||
struct fsl_qspi *q = nor->priv;
|
||||
@@ -832,9 +832,10 @@ static void fsl_qspi_write(struct spi_no
|
||||
|
||||
/* invalid the data in the AHB buffer. */
|
||||
fsl_qspi_invalid(q);
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
-static int fsl_qspi_read(struct spi_nor *nor, loff_t from,
|
||||
+static ssize_t fsl_qspi_read(struct spi_nor *nor, loff_t from,
|
||||
size_t len, size_t *retlen, u_char *buf)
|
||||
{
|
||||
struct fsl_qspi *q = nor->priv;
|
||||
--- a/drivers/mtd/spi-nor/nxp-spifi.c
|
||||
+++ b/drivers/mtd/spi-nor/nxp-spifi.c
|
||||
@@ -172,8 +172,8 @@ static int nxp_spifi_write_reg(struct sp
|
||||
return nxp_spifi_wait_for_cmd(spifi);
|
||||
}
|
||||
|
||||
-static int nxp_spifi_read(struct spi_nor *nor, loff_t from, size_t len,
|
||||
- size_t *retlen, u_char *buf)
|
||||
+static ssize_t nxp_spifi_read(struct spi_nor *nor, loff_t from, size_t len,
|
||||
+ size_t *retlen, u_char *buf)
|
||||
{
|
||||
struct nxp_spifi *spifi = nor->priv;
|
||||
int ret;
|
||||
@@ -188,8 +188,8 @@ static int nxp_spifi_read(struct spi_nor
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static void nxp_spifi_write(struct spi_nor *nor, loff_t to, size_t len,
|
||||
- size_t *retlen, const u_char *buf)
|
||||
+static ssize_t nxp_spifi_write(struct spi_nor *nor, loff_t to, size_t len,
|
||||
+ size_t *retlen, const u_char *buf)
|
||||
{
|
||||
struct nxp_spifi *spifi = nor->priv;
|
||||
u32 cmd;
|
||||
@@ -197,7 +197,7 @@ static void nxp_spifi_write(struct spi_n
|
||||
|
||||
ret = nxp_spifi_set_memory_mode_off(spifi);
|
||||
if (ret)
|
||||
- return;
|
||||
+ return ret;
|
||||
|
||||
writel(to, spifi->io_base + SPIFI_ADDR);
|
||||
*retlen += len;
|
||||
@@ -212,7 +212,7 @@ static void nxp_spifi_write(struct spi_n
|
||||
while (len--)
|
||||
writeb(*buf++, spifi->io_base + SPIFI_DATA);
|
||||
|
||||
- nxp_spifi_wait_for_cmd(spifi);
|
||||
+ return nxp_spifi_wait_for_cmd(spifi);
|
||||
}
|
||||
|
||||
static int nxp_spifi_erase(struct spi_nor *nor, loff_t offs)
|
||||
--- a/drivers/mtd/spi-nor/spi-nor.c
|
||||
+++ b/drivers/mtd/spi-nor/spi-nor.c
|
||||
@@ -893,7 +893,10 @@ static int spi_nor_read(struct mtd_info
|
||||
ret = nor->read(nor, from, len, retlen, buf);
|
||||
|
||||
spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_READ);
|
||||
- return ret;
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
static int sst_write(struct mtd_info *mtd, loff_t to, size_t len,
|
||||
--- a/include/linux/mtd/spi-nor.h
|
||||
+++ b/include/linux/mtd/spi-nor.h
|
||||
@@ -169,9 +169,9 @@ struct spi_nor {
|
||||
int (*read_reg)(struct spi_nor *nor, u8 opcode, u8 *buf, int len);
|
||||
int (*write_reg)(struct spi_nor *nor, u8 opcode, u8 *buf, int len);
|
||||
|
||||
- int (*read)(struct spi_nor *nor, loff_t from,
|
||||
+ ssize_t (*read)(struct spi_nor *nor, loff_t from,
|
||||
size_t len, size_t *retlen, u_char *read_buf);
|
||||
- void (*write)(struct spi_nor *nor, loff_t to,
|
||||
+ ssize_t (*write)(struct spi_nor *nor, loff_t to,
|
||||
size_t len, size_t *retlen, const u_char *write_buf);
|
||||
int (*erase)(struct spi_nor *nor, loff_t offs);
|
||||
|
@ -1,91 +0,0 @@
|
||||
From 1992297b0810a42d78ec7b4de15304eb0489fd97 Mon Sep 17 00:00:00 2001
|
||||
From: Michal Suchanek <hramrach@gmail.com>
|
||||
Date: Thu, 5 May 2016 17:31:48 -0700
|
||||
Subject: [PATCH 02/10] mtd: m25p80: return amount of data transferred or error
|
||||
in read/write
|
||||
|
||||
Add checking of SPI transfer errors and return them from read/write
|
||||
functions. Also return the amount of data transferred.
|
||||
|
||||
Signed-off-by: Michal Suchanek <hramrach@gmail.com>
|
||||
Signed-off-by: Brian Norris <computersforpeace@gmail.com>
|
||||
Acked-by: Michal Suchanek <hramrach@gmail.com>
|
||||
Tested-by: Michal Suchanek <hramrach@gmail.com>
|
||||
---
|
||||
drivers/mtd/devices/m25p80.c | 29 +++++++++++++++++++++--------
|
||||
1 file changed, 21 insertions(+), 8 deletions(-)
|
||||
|
||||
--- a/drivers/mtd/devices/m25p80.c
|
||||
+++ b/drivers/mtd/devices/m25p80.c
|
||||
@@ -81,6 +81,7 @@ static ssize_t m25p80_write(struct spi_n
|
||||
struct spi_transfer t[2] = {};
|
||||
struct spi_message m;
|
||||
int cmd_sz = m25p_cmdsz(nor);
|
||||
+ ssize_t ret;
|
||||
|
||||
spi_message_init(&m);
|
||||
|
||||
@@ -98,10 +99,15 @@ static ssize_t m25p80_write(struct spi_n
|
||||
t[1].len = len;
|
||||
spi_message_add_tail(&t[1], &m);
|
||||
|
||||
- spi_sync(spi, &m);
|
||||
+ ret = spi_sync(spi, &m);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
|
||||
- *retlen += m.actual_length - cmd_sz;
|
||||
- return 0;
|
||||
+ ret = m.actual_length - cmd_sz;
|
||||
+ if (ret < 0)
|
||||
+ return -EIO;
|
||||
+ *retlen += ret;
|
||||
+ return ret;
|
||||
}
|
||||
|
||||
static inline unsigned int m25p80_rx_nbits(struct spi_nor *nor)
|
||||
@@ -128,13 +134,13 @@ static ssize_t m25p80_read(struct spi_no
|
||||
struct spi_transfer t[2];
|
||||
struct spi_message m;
|
||||
unsigned int dummy = nor->read_dummy;
|
||||
+ ssize_t ret;
|
||||
|
||||
/* convert the dummy cycles to the number of bytes */
|
||||
dummy /= 8;
|
||||
|
||||
if (spi_flash_read_supported(spi)) {
|
||||
struct spi_flash_read_message msg;
|
||||
- int ret;
|
||||
|
||||
memset(&msg, 0, sizeof(msg));
|
||||
|
||||
@@ -151,7 +157,9 @@ static ssize_t m25p80_read(struct spi_no
|
||||
|
||||
ret = spi_flash_read(spi, &msg);
|
||||
*retlen = msg.retlen;
|
||||
- return ret;
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+ return msg.retlen;
|
||||
}
|
||||
|
||||
spi_message_init(&m);
|
||||
@@ -169,10 +177,15 @@ static ssize_t m25p80_read(struct spi_no
|
||||
t[1].len = len;
|
||||
spi_message_add_tail(&t[1], &m);
|
||||
|
||||
- spi_sync(spi, &m);
|
||||
+ ret = spi_sync(spi, &m);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
|
||||
- *retlen = m.actual_length - m25p_cmdsz(nor) - dummy;
|
||||
- return 0;
|
||||
+ ret = m.actual_length - m25p_cmdsz(nor) - dummy;
|
||||
+ if (ret < 0)
|
||||
+ return -EIO;
|
||||
+ *retlen += ret;
|
||||
+ return ret;
|
||||
}
|
||||
|
||||
static int m25p80_erase(struct spi_nor *nor, loff_t offset)
|
@ -1,72 +0,0 @@
|
||||
From fc0d7e542a0d4193521899d15f8f4999dc295323 Mon Sep 17 00:00:00 2001
|
||||
From: Michal Suchanek <hramrach@gmail.com>
|
||||
Date: Thu, 5 May 2016 17:31:49 -0700
|
||||
Subject: [PATCH 03/10] mtd: fsl-quadspi: return amount of data read/written or
|
||||
error
|
||||
|
||||
Return amount of data read/written or error as read(2)/write(2) does.
|
||||
|
||||
Signed-off-by: Michal Suchanek <hramrach@gmail.com>
|
||||
Signed-off-by: Brian Norris <computersforpeace@gmail.com>
|
||||
---
|
||||
drivers/mtd/spi-nor/fsl-quadspi.c | 17 +++++++++++------
|
||||
1 file changed, 11 insertions(+), 6 deletions(-)
|
||||
|
||||
--- a/drivers/mtd/spi-nor/fsl-quadspi.c
|
||||
+++ b/drivers/mtd/spi-nor/fsl-quadspi.c
|
||||
@@ -575,7 +575,7 @@ static inline void fsl_qspi_invalid(stru
|
||||
writel(reg, q->iobase + QUADSPI_MCR);
|
||||
}
|
||||
|
||||
-static int fsl_qspi_nor_write(struct fsl_qspi *q, struct spi_nor *nor,
|
||||
+static ssize_t fsl_qspi_nor_write(struct fsl_qspi *q, struct spi_nor *nor,
|
||||
u8 opcode, unsigned int to, u32 *txbuf,
|
||||
unsigned count, size_t *retlen)
|
||||
{
|
||||
@@ -604,8 +604,11 @@ static int fsl_qspi_nor_write(struct fsl
|
||||
/* Trigger it */
|
||||
ret = fsl_qspi_runcmd(q, opcode, to, count);
|
||||
|
||||
- if (ret == 0 && retlen)
|
||||
- *retlen += count;
|
||||
+ if (ret == 0) {
|
||||
+ if (retlen)
|
||||
+ *retlen += count;
|
||||
+ return count;
|
||||
+ }
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -814,6 +817,8 @@ static int fsl_qspi_write_reg(struct spi
|
||||
} else if (len > 0) {
|
||||
ret = fsl_qspi_nor_write(q, nor, opcode, 0,
|
||||
(u32 *)buf, len, NULL);
|
||||
+ if (ret > 0)
|
||||
+ return 0;
|
||||
} else {
|
||||
dev_err(q->dev, "invalid cmd %d\n", opcode);
|
||||
ret = -EINVAL;
|
||||
@@ -827,12 +832,12 @@ static ssize_t fsl_qspi_write(struct spi
|
||||
{
|
||||
struct fsl_qspi *q = nor->priv;
|
||||
|
||||
- fsl_qspi_nor_write(q, nor, nor->program_opcode, to,
|
||||
+ ssize_t ret = fsl_qspi_nor_write(q, nor, nor->program_opcode, to,
|
||||
(u32 *)buf, len, retlen);
|
||||
|
||||
/* invalid the data in the AHB buffer. */
|
||||
fsl_qspi_invalid(q);
|
||||
- return 0;
|
||||
+ return ret;
|
||||
}
|
||||
|
||||
static ssize_t fsl_qspi_read(struct spi_nor *nor, loff_t from,
|
||||
@@ -879,7 +884,7 @@ static ssize_t fsl_qspi_read(struct spi_
|
||||
len);
|
||||
|
||||
*retlen += len;
|
||||
- return 0;
|
||||
+ return len;
|
||||
}
|
||||
|
||||
static int fsl_qspi_erase(struct spi_nor *nor, loff_t offs)
|
@ -1,51 +0,0 @@
|
||||
From bc418cd2652f47a327e27f978caa3d85f9558b09 Mon Sep 17 00:00:00 2001
|
||||
From: Brian Norris <computersforpeace@gmail.com>
|
||||
Date: Thu, 5 May 2016 17:31:51 -0700
|
||||
Subject: [PATCH 05/10] mtd: nxp-spifi: return amount of data transferred or
|
||||
error in read/write
|
||||
|
||||
Add checking of SPI transfer errors and return them from read/write
|
||||
functions. Also return the amount of data transferred.
|
||||
|
||||
Signed-off-by: Brian Norris <computersforpeace@gmail.com>
|
||||
---
|
||||
drivers/mtd/spi-nor/nxp-spifi.c | 13 +++++++++----
|
||||
1 file changed, 9 insertions(+), 4 deletions(-)
|
||||
|
||||
--- a/drivers/mtd/spi-nor/nxp-spifi.c
|
||||
+++ b/drivers/mtd/spi-nor/nxp-spifi.c
|
||||
@@ -185,7 +185,7 @@ static ssize_t nxp_spifi_read(struct spi
|
||||
memcpy_fromio(buf, spifi->flash_base + from, len);
|
||||
*retlen += len;
|
||||
|
||||
- return 0;
|
||||
+ return len;
|
||||
}
|
||||
|
||||
static ssize_t nxp_spifi_write(struct spi_nor *nor, loff_t to, size_t len,
|
||||
@@ -194,6 +194,7 @@ static ssize_t nxp_spifi_write(struct sp
|
||||
struct nxp_spifi *spifi = nor->priv;
|
||||
u32 cmd;
|
||||
int ret;
|
||||
+ size_t i;
|
||||
|
||||
ret = nxp_spifi_set_memory_mode_off(spifi);
|
||||
if (ret)
|
||||
@@ -209,10 +210,14 @@ static ssize_t nxp_spifi_write(struct sp
|
||||
SPIFI_CMD_FRAMEFORM(spifi->nor.addr_width + 1);
|
||||
writel(cmd, spifi->io_base + SPIFI_CMD);
|
||||
|
||||
- while (len--)
|
||||
- writeb(*buf++, spifi->io_base + SPIFI_DATA);
|
||||
+ for (i = 0; i < len; i++)
|
||||
+ writeb(buf[i], spifi->io_base + SPIFI_DATA);
|
||||
|
||||
- return nxp_spifi_wait_for_cmd(spifi);
|
||||
+ ret = nxp_spifi_wait_for_cmd(spifi);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ return len;
|
||||
}
|
||||
|
||||
static int nxp_spifi_erase(struct spi_nor *nor, loff_t offs)
|
@ -1,118 +0,0 @@
|
||||
From 0bad7b9304d543dd7627f4cd564aea5d7338b950 Mon Sep 17 00:00:00 2001
|
||||
From: Michal Suchanek <hramrach@gmail.com>
|
||||
Date: Thu, 5 May 2016 17:31:52 -0700
|
||||
Subject: [PATCH 06/10] mtd: spi-nor: check return value from write
|
||||
|
||||
SPI NOR hardware drivers now return useful value from their write
|
||||
functions so check them.
|
||||
|
||||
Signed-off-by: Michal Suchanek <hramrach@gmail.com>
|
||||
Signed-off-by: Brian Norris <computersforpeace@gmail.com>
|
||||
Tested-by Cyrille Pitchen <cyrille.pitchen@atmel.com>
|
||||
Acked-by: Michal Suchanek <hramrach@gmail.com>
|
||||
Tested-by: Michal Suchanek <hramrach@gmail.com>
|
||||
---
|
||||
drivers/mtd/spi-nor/spi-nor.c | 45 ++++++++++++++++++++++++++++++-------------
|
||||
1 file changed, 32 insertions(+), 13 deletions(-)
|
||||
|
||||
--- a/drivers/mtd/spi-nor/spi-nor.c
|
||||
+++ b/drivers/mtd/spi-nor/spi-nor.c
|
||||
@@ -922,10 +922,14 @@ static int sst_write(struct mtd_info *mt
|
||||
nor->program_opcode = SPINOR_OP_BP;
|
||||
|
||||
/* write one byte. */
|
||||
- nor->write(nor, to, 1, retlen, buf);
|
||||
+ ret = nor->write(nor, to, 1, retlen, buf);
|
||||
+ if (ret < 0)
|
||||
+ goto sst_write_err;
|
||||
+ WARN(ret != 1, "While writing 1 byte written %i bytes\n",
|
||||
+ (int)ret);
|
||||
ret = spi_nor_wait_till_ready(nor);
|
||||
if (ret)
|
||||
- goto time_out;
|
||||
+ goto sst_write_err;
|
||||
}
|
||||
to += actual;
|
||||
|
||||
@@ -934,10 +938,14 @@ static int sst_write(struct mtd_info *mt
|
||||
nor->program_opcode = SPINOR_OP_AAI_WP;
|
||||
|
||||
/* write two bytes. */
|
||||
- nor->write(nor, to, 2, retlen, buf + actual);
|
||||
+ ret = nor->write(nor, to, 2, retlen, buf + actual);
|
||||
+ if (ret < 0)
|
||||
+ goto sst_write_err;
|
||||
+ WARN(ret != 2, "While writing 2 bytes written %i bytes\n",
|
||||
+ (int)ret);
|
||||
ret = spi_nor_wait_till_ready(nor);
|
||||
if (ret)
|
||||
- goto time_out;
|
||||
+ goto sst_write_err;
|
||||
to += 2;
|
||||
nor->sst_write_second = true;
|
||||
}
|
||||
@@ -946,21 +954,24 @@ static int sst_write(struct mtd_info *mt
|
||||
write_disable(nor);
|
||||
ret = spi_nor_wait_till_ready(nor);
|
||||
if (ret)
|
||||
- goto time_out;
|
||||
+ goto sst_write_err;
|
||||
|
||||
/* Write out trailing byte if it exists. */
|
||||
if (actual != len) {
|
||||
write_enable(nor);
|
||||
|
||||
nor->program_opcode = SPINOR_OP_BP;
|
||||
- nor->write(nor, to, 1, retlen, buf + actual);
|
||||
-
|
||||
+ ret = nor->write(nor, to, 1, retlen, buf + actual);
|
||||
+ if (ret < 0)
|
||||
+ goto sst_write_err;
|
||||
+ WARN(ret != 1, "While writing 1 byte written %i bytes\n",
|
||||
+ (int)ret);
|
||||
ret = spi_nor_wait_till_ready(nor);
|
||||
if (ret)
|
||||
- goto time_out;
|
||||
+ goto sst_write_err;
|
||||
write_disable(nor);
|
||||
}
|
||||
-time_out:
|
||||
+sst_write_err:
|
||||
spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_WRITE);
|
||||
return ret;
|
||||
}
|
||||
@@ -989,14 +1000,18 @@ static int spi_nor_write(struct mtd_info
|
||||
|
||||
/* do all the bytes fit onto one page? */
|
||||
if (page_offset + len <= nor->page_size) {
|
||||
- nor->write(nor, to, len, retlen, buf);
|
||||
+ ret = nor->write(nor, to, len, retlen, buf);
|
||||
+ if (ret < 0)
|
||||
+ goto write_err;
|
||||
} else {
|
||||
/* the size of data remaining on the first page */
|
||||
page_size = nor->page_size - page_offset;
|
||||
- nor->write(nor, to, page_size, retlen, buf);
|
||||
+ ret = nor->write(nor, to, page_size, retlen, buf);
|
||||
+ if (ret < 0)
|
||||
+ goto write_err;
|
||||
|
||||
/* write everything in nor->page_size chunks */
|
||||
- for (i = page_size; i < len; i += page_size) {
|
||||
+ for (i = ret; i < len; ) {
|
||||
page_size = len - i;
|
||||
if (page_size > nor->page_size)
|
||||
page_size = nor->page_size;
|
||||
@@ -1007,7 +1022,11 @@ static int spi_nor_write(struct mtd_info
|
||||
|
||||
write_enable(nor);
|
||||
|
||||
- nor->write(nor, to + i, page_size, retlen, buf + i);
|
||||
+ ret = nor->write(nor, to + i, page_size, retlen,
|
||||
+ buf + i);
|
||||
+ if (ret < 0)
|
||||
+ goto write_err;
|
||||
+ i += ret;
|
||||
}
|
||||
}
|
||||
|
@ -1,266 +0,0 @@
|
||||
From 2dd087b16946cf168f401526adf26afa771bb740 Mon Sep 17 00:00:00 2001
|
||||
From: Michal Suchanek <hramrach@gmail.com>
|
||||
Date: Thu, 5 May 2016 17:31:53 -0700
|
||||
Subject: [PATCH 07/10] mtd: spi-nor: stop passing around retlen
|
||||
|
||||
Do not pass retlen to hardware driver read/write functions. Update it in
|
||||
spi-nor generic driver instead.
|
||||
|
||||
Signed-off-by: Michal Suchanek <hramrach@gmail.com>
|
||||
Signed-off-by: Brian Norris <computersforpeace@gmail.com>
|
||||
Tested-by Cyrille Pitchen <cyrille.pitchen@atmel.com>
|
||||
Acked-by: Michal Suchanek <hramrach@gmail.com>
|
||||
Tested-by: Michal Suchanek <hramrach@gmail.com>
|
||||
---
|
||||
drivers/mtd/devices/m25p80.c | 7 ++-----
|
||||
drivers/mtd/spi-nor/fsl-quadspi.c | 17 ++++++-----------
|
||||
drivers/mtd/spi-nor/nxp-spifi.c | 6 ++----
|
||||
drivers/mtd/spi-nor/spi-nor.c | 21 +++++++++++++--------
|
||||
include/linux/mtd/spi-nor.h | 4 ++--
|
||||
6 files changed, 28 insertions(+), 35 deletions(-)
|
||||
|
||||
--- a/drivers/mtd/devices/m25p80.c
|
||||
+++ b/drivers/mtd/devices/m25p80.c
|
||||
@@ -74,7 +74,7 @@ static int m25p80_write_reg(struct spi_n
|
||||
}
|
||||
|
||||
static ssize_t m25p80_write(struct spi_nor *nor, loff_t to, size_t len,
|
||||
- size_t *retlen, const u_char *buf)
|
||||
+ const u_char *buf)
|
||||
{
|
||||
struct m25p *flash = nor->priv;
|
||||
struct spi_device *spi = flash->spi;
|
||||
@@ -106,7 +106,6 @@ static ssize_t m25p80_write(struct spi_n
|
||||
ret = m.actual_length - cmd_sz;
|
||||
if (ret < 0)
|
||||
return -EIO;
|
||||
- *retlen += ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -127,7 +126,7 @@ static inline unsigned int m25p80_rx_nbi
|
||||
* may be any size provided it is within the physical boundaries.
|
||||
*/
|
||||
static ssize_t m25p80_read(struct spi_nor *nor, loff_t from, size_t len,
|
||||
- size_t *retlen, u_char *buf)
|
||||
+ u_char *buf)
|
||||
{
|
||||
struct m25p *flash = nor->priv;
|
||||
struct spi_device *spi = flash->spi;
|
||||
@@ -156,7 +155,6 @@ static ssize_t m25p80_read(struct spi_no
|
||||
msg.data_nbits = m25p80_rx_nbits(nor);
|
||||
|
||||
ret = spi_flash_read(spi, &msg);
|
||||
- *retlen = msg.retlen;
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
return msg.retlen;
|
||||
@@ -184,7 +182,6 @@ static ssize_t m25p80_read(struct spi_no
|
||||
ret = m.actual_length - m25p_cmdsz(nor) - dummy;
|
||||
if (ret < 0)
|
||||
return -EIO;
|
||||
- *retlen += ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
--- a/drivers/mtd/spi-nor/fsl-quadspi.c
|
||||
+++ b/drivers/mtd/spi-nor/fsl-quadspi.c
|
||||
@@ -577,7 +577,7 @@ static inline void fsl_qspi_invalid(stru
|
||||
|
||||
static ssize_t fsl_qspi_nor_write(struct fsl_qspi *q, struct spi_nor *nor,
|
||||
u8 opcode, unsigned int to, u32 *txbuf,
|
||||
- unsigned count, size_t *retlen)
|
||||
+ unsigned count)
|
||||
{
|
||||
int ret, i, j;
|
||||
u32 tmp;
|
||||
@@ -604,11 +604,8 @@ static ssize_t fsl_qspi_nor_write(struct
|
||||
/* Trigger it */
|
||||
ret = fsl_qspi_runcmd(q, opcode, to, count);
|
||||
|
||||
- if (ret == 0) {
|
||||
- if (retlen)
|
||||
- *retlen += count;
|
||||
+ if (ret == 0)
|
||||
return count;
|
||||
- }
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -816,7 +813,7 @@ static int fsl_qspi_write_reg(struct spi
|
||||
|
||||
} else if (len > 0) {
|
||||
ret = fsl_qspi_nor_write(q, nor, opcode, 0,
|
||||
- (u32 *)buf, len, NULL);
|
||||
+ (u32 *)buf, len);
|
||||
if (ret > 0)
|
||||
return 0;
|
||||
} else {
|
||||
@@ -828,12 +825,11 @@ static int fsl_qspi_write_reg(struct spi
|
||||
}
|
||||
|
||||
static ssize_t fsl_qspi_write(struct spi_nor *nor, loff_t to,
|
||||
- size_t len, size_t *retlen, const u_char *buf)
|
||||
+ size_t len, const u_char *buf)
|
||||
{
|
||||
struct fsl_qspi *q = nor->priv;
|
||||
-
|
||||
ssize_t ret = fsl_qspi_nor_write(q, nor, nor->program_opcode, to,
|
||||
- (u32 *)buf, len, retlen);
|
||||
+ (u32 *)buf, len);
|
||||
|
||||
/* invalid the data in the AHB buffer. */
|
||||
fsl_qspi_invalid(q);
|
||||
@@ -841,7 +837,7 @@ static ssize_t fsl_qspi_write(struct spi
|
||||
}
|
||||
|
||||
static ssize_t fsl_qspi_read(struct spi_nor *nor, loff_t from,
|
||||
- size_t len, size_t *retlen, u_char *buf)
|
||||
+ size_t len, u_char *buf)
|
||||
{
|
||||
struct fsl_qspi *q = nor->priv;
|
||||
u8 cmd = nor->read_opcode;
|
||||
@@ -883,7 +879,6 @@ static ssize_t fsl_qspi_read(struct spi_
|
||||
memcpy(buf, q->ahb_addr + q->chip_base_addr + from - q->memmap_offs,
|
||||
len);
|
||||
|
||||
- *retlen += len;
|
||||
return len;
|
||||
}
|
||||
|
||||
--- a/drivers/mtd/spi-nor/nxp-spifi.c
|
||||
+++ b/drivers/mtd/spi-nor/nxp-spifi.c
|
||||
@@ -173,7 +173,7 @@ static int nxp_spifi_write_reg(struct sp
|
||||
}
|
||||
|
||||
static ssize_t nxp_spifi_read(struct spi_nor *nor, loff_t from, size_t len,
|
||||
- size_t *retlen, u_char *buf)
|
||||
+ u_char *buf)
|
||||
{
|
||||
struct nxp_spifi *spifi = nor->priv;
|
||||
int ret;
|
||||
@@ -183,13 +183,12 @@ static ssize_t nxp_spifi_read(struct spi
|
||||
return ret;
|
||||
|
||||
memcpy_fromio(buf, spifi->flash_base + from, len);
|
||||
- *retlen += len;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static ssize_t nxp_spifi_write(struct spi_nor *nor, loff_t to, size_t len,
|
||||
- size_t *retlen, const u_char *buf)
|
||||
+ const u_char *buf)
|
||||
{
|
||||
struct nxp_spifi *spifi = nor->priv;
|
||||
u32 cmd;
|
||||
@@ -201,7 +200,6 @@ static ssize_t nxp_spifi_write(struct sp
|
||||
return ret;
|
||||
|
||||
writel(to, spifi->io_base + SPIFI_ADDR);
|
||||
- *retlen += len;
|
||||
|
||||
cmd = SPIFI_CMD_DOUT |
|
||||
SPIFI_CMD_DATALEN(len) |
|
||||
--- a/drivers/mtd/spi-nor/spi-nor.c
|
||||
+++ b/drivers/mtd/spi-nor/spi-nor.c
|
||||
@@ -890,12 +890,13 @@ static int spi_nor_read(struct mtd_info
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
- ret = nor->read(nor, from, len, retlen, buf);
|
||||
+ ret = nor->read(nor, from, len, buf);
|
||||
|
||||
spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_READ);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
+ *retlen += ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -922,7 +923,7 @@ static int sst_write(struct mtd_info *mt
|
||||
nor->program_opcode = SPINOR_OP_BP;
|
||||
|
||||
/* write one byte. */
|
||||
- ret = nor->write(nor, to, 1, retlen, buf);
|
||||
+ ret = nor->write(nor, to, 1, buf);
|
||||
if (ret < 0)
|
||||
goto sst_write_err;
|
||||
WARN(ret != 1, "While writing 1 byte written %i bytes\n",
|
||||
@@ -938,7 +939,7 @@ static int sst_write(struct mtd_info *mt
|
||||
nor->program_opcode = SPINOR_OP_AAI_WP;
|
||||
|
||||
/* write two bytes. */
|
||||
- ret = nor->write(nor, to, 2, retlen, buf + actual);
|
||||
+ ret = nor->write(nor, to, 2, buf + actual);
|
||||
if (ret < 0)
|
||||
goto sst_write_err;
|
||||
WARN(ret != 2, "While writing 2 bytes written %i bytes\n",
|
||||
@@ -961,7 +962,7 @@ static int sst_write(struct mtd_info *mt
|
||||
write_enable(nor);
|
||||
|
||||
nor->program_opcode = SPINOR_OP_BP;
|
||||
- ret = nor->write(nor, to, 1, retlen, buf + actual);
|
||||
+ ret = nor->write(nor, to, 1, buf + actual);
|
||||
if (ret < 0)
|
||||
goto sst_write_err;
|
||||
WARN(ret != 1, "While writing 1 byte written %i bytes\n",
|
||||
@@ -970,8 +971,10 @@ static int sst_write(struct mtd_info *mt
|
||||
if (ret)
|
||||
goto sst_write_err;
|
||||
write_disable(nor);
|
||||
+ actual += 1;
|
||||
}
|
||||
sst_write_err:
|
||||
+ *retlen += actual;
|
||||
spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_WRITE);
|
||||
return ret;
|
||||
}
|
||||
@@ -1000,15 +1003,17 @@ static int spi_nor_write(struct mtd_info
|
||||
|
||||
/* do all the bytes fit onto one page? */
|
||||
if (page_offset + len <= nor->page_size) {
|
||||
- ret = nor->write(nor, to, len, retlen, buf);
|
||||
+ ret = nor->write(nor, to, len, buf);
|
||||
if (ret < 0)
|
||||
goto write_err;
|
||||
+ *retlen += ret;
|
||||
} else {
|
||||
/* the size of data remaining on the first page */
|
||||
page_size = nor->page_size - page_offset;
|
||||
- ret = nor->write(nor, to, page_size, retlen, buf);
|
||||
+ ret = nor->write(nor, to, page_size, buf);
|
||||
if (ret < 0)
|
||||
goto write_err;
|
||||
+ *retlen += ret;
|
||||
|
||||
/* write everything in nor->page_size chunks */
|
||||
for (i = ret; i < len; ) {
|
||||
@@ -1022,10 +1027,10 @@ static int spi_nor_write(struct mtd_info
|
||||
|
||||
write_enable(nor);
|
||||
|
||||
- ret = nor->write(nor, to + i, page_size, retlen,
|
||||
- buf + i);
|
||||
+ ret = nor->write(nor, to + i, page_size, buf + i);
|
||||
if (ret < 0)
|
||||
goto write_err;
|
||||
+ *retlen += ret;
|
||||
i += ret;
|
||||
}
|
||||
}
|
||||
--- a/include/linux/mtd/spi-nor.h
|
||||
+++ b/include/linux/mtd/spi-nor.h
|
||||
@@ -170,9 +170,9 @@ struct spi_nor {
|
||||
int (*write_reg)(struct spi_nor *nor, u8 opcode, u8 *buf, int len);
|
||||
|
||||
ssize_t (*read)(struct spi_nor *nor, loff_t from,
|
||||
- size_t len, size_t *retlen, u_char *read_buf);
|
||||
+ size_t len, u_char *read_buf);
|
||||
ssize_t (*write)(struct spi_nor *nor, loff_t to,
|
||||
- size_t len, size_t *retlen, const u_char *write_buf);
|
||||
+ size_t len, const u_char *write_buf);
|
||||
int (*erase)(struct spi_nor *nor, loff_t offs);
|
||||
|
||||
int (*flash_lock)(struct spi_nor *nor, loff_t ofs, uint64_t len);
|
@ -1,103 +0,0 @@
|
||||
From e5d05cbd6d8b01f08c95c427a36c66aac769af4f Mon Sep 17 00:00:00 2001
|
||||
From: Michal Suchanek <hramrach@gmail.com>
|
||||
Date: Thu, 5 May 2016 17:31:54 -0700
|
||||
Subject: [PATCH 08/10] mtd: spi-nor: simplify write loop
|
||||
|
||||
The spi-nor write loop assumes that what is passed to the hardware
|
||||
driver write() is what gets written.
|
||||
|
||||
When write() writes less than page size at once data is dropped on the
|
||||
floor. Check the amount of data writen and exit if it does not match
|
||||
requested amount.
|
||||
|
||||
Signed-off-by: Michal Suchanek <hramrach@gmail.com>
|
||||
Signed-off-by: Brian Norris <computersforpeace@gmail.com>
|
||||
Tested-by Cyrille Pitchen <cyrille.pitchen@atmel.com>
|
||||
Acked-by: Michal Suchanek <hramrach@gmail.com>
|
||||
Tested-by: Michal Suchanek <hramrach@gmail.com>
|
||||
---
|
||||
drivers/mtd/spi-nor/spi-nor.c | 58 +++++++++++++++++++------------------------
|
||||
1 file changed, 25 insertions(+), 33 deletions(-)
|
||||
|
||||
--- a/drivers/mtd/spi-nor/spi-nor.c
|
||||
+++ b/drivers/mtd/spi-nor/spi-nor.c
|
||||
@@ -988,8 +988,8 @@ static int spi_nor_write(struct mtd_info
|
||||
size_t *retlen, const u_char *buf)
|
||||
{
|
||||
struct spi_nor *nor = mtd_to_spi_nor(mtd);
|
||||
- u32 page_offset, page_size, i;
|
||||
- int ret;
|
||||
+ size_t page_offset, page_remain, i;
|
||||
+ ssize_t ret;
|
||||
|
||||
dev_dbg(nor->dev, "to 0x%08x, len %zd\n", (u32)to, len);
|
||||
|
||||
@@ -997,45 +997,37 @@ static int spi_nor_write(struct mtd_info
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
- write_enable(nor);
|
||||
+ for (i = 0; i < len; ) {
|
||||
+ ssize_t written;
|
||||
|
||||
- page_offset = to & (nor->page_size - 1);
|
||||
-
|
||||
- /* do all the bytes fit onto one page? */
|
||||
- if (page_offset + len <= nor->page_size) {
|
||||
- ret = nor->write(nor, to, len, buf);
|
||||
- if (ret < 0)
|
||||
- goto write_err;
|
||||
- *retlen += ret;
|
||||
- } else {
|
||||
+ page_offset = (to + i) & (nor->page_size - 1);
|
||||
+ WARN_ONCE(page_offset,
|
||||
+ "Writing at offset %zu into a NOR page. Writing partial pages may decrease reliability and increase wear of NOR flash.",
|
||||
+ page_offset);
|
||||
/* the size of data remaining on the first page */
|
||||
- page_size = nor->page_size - page_offset;
|
||||
- ret = nor->write(nor, to, page_size, buf);
|
||||
+ page_remain = min_t(size_t,
|
||||
+ nor->page_size - page_offset, len - i);
|
||||
+
|
||||
+ write_enable(nor);
|
||||
+ ret = nor->write(nor, to + i, page_remain, buf + i);
|
||||
if (ret < 0)
|
||||
goto write_err;
|
||||
- *retlen += ret;
|
||||
+ written = ret;
|
||||
|
||||
- /* write everything in nor->page_size chunks */
|
||||
- for (i = ret; i < len; ) {
|
||||
- page_size = len - i;
|
||||
- if (page_size > nor->page_size)
|
||||
- page_size = nor->page_size;
|
||||
-
|
||||
- ret = spi_nor_wait_till_ready(nor);
|
||||
- if (ret)
|
||||
- goto write_err;
|
||||
-
|
||||
- write_enable(nor);
|
||||
-
|
||||
- ret = nor->write(nor, to + i, page_size, buf + i);
|
||||
- if (ret < 0)
|
||||
- goto write_err;
|
||||
- *retlen += ret;
|
||||
- i += ret;
|
||||
+ ret = spi_nor_wait_till_ready(nor);
|
||||
+ if (ret)
|
||||
+ goto write_err;
|
||||
+ *retlen += written;
|
||||
+ i += written;
|
||||
+ if (written != page_remain) {
|
||||
+ dev_err(nor->dev,
|
||||
+ "While writing %zu bytes written %zd bytes\n",
|
||||
+ page_remain, written);
|
||||
+ ret = -EIO;
|
||||
+ goto write_err;
|
||||
}
|
||||
}
|
||||
|
||||
- ret = spi_nor_wait_till_ready(nor);
|
||||
write_err:
|
||||
spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_WRITE);
|
||||
return ret;
|
@ -1,54 +0,0 @@
|
||||
From 26f9bcad29a6c240881bd4efc90f16a9990dd6c2 Mon Sep 17 00:00:00 2001
|
||||
From: Michal Suchanek <hramrach@gmail.com>
|
||||
Date: Thu, 5 May 2016 17:31:55 -0700
|
||||
Subject: [PATCH 09/10] mtd: spi-nor: add read loop
|
||||
|
||||
mtdblock and ubi do not handle the situation when read returns less data
|
||||
than requested. Loop in spi-nor until buffer is filled or an error is
|
||||
returned.
|
||||
|
||||
Signed-off-by: Michal Suchanek <hramrach@gmail.com>
|
||||
Signed-off-by: Brian Norris <computersforpeace@gmail.com>
|
||||
Tested-by Cyrille Pitchen <cyrille.pitchen@atmel.com>
|
||||
Acked-by: Michal Suchanek <hramrach@gmail.com>
|
||||
Tested-by: Michal Suchanek <hramrach@gmail.com>
|
||||
---
|
||||
drivers/mtd/spi-nor/spi-nor.c | 25 +++++++++++++++++++------
|
||||
1 file changed, 19 insertions(+), 6 deletions(-)
|
||||
|
||||
--- a/drivers/mtd/spi-nor/spi-nor.c
|
||||
+++ b/drivers/mtd/spi-nor/spi-nor.c
|
||||
@@ -890,14 +890,27 @@ static int spi_nor_read(struct mtd_info
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
- ret = nor->read(nor, from, len, buf);
|
||||
+ while (len) {
|
||||
+ ret = nor->read(nor, from, len, buf);
|
||||
+ if (ret == 0) {
|
||||
+ /* We shouldn't see 0-length reads */
|
||||
+ ret = -EIO;
|
||||
+ goto read_err;
|
||||
+ }
|
||||
+ if (ret < 0)
|
||||
+ goto read_err;
|
||||
|
||||
- spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_READ);
|
||||
- if (ret < 0)
|
||||
- return ret;
|
||||
+ WARN_ON(ret > len);
|
||||
+ *retlen += ret;
|
||||
+ buf += ret;
|
||||
+ from += ret;
|
||||
+ len -= ret;
|
||||
+ }
|
||||
+ ret = 0;
|
||||
|
||||
- *retlen += ret;
|
||||
- return 0;
|
||||
+read_err:
|
||||
+ spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_READ);
|
||||
+ return ret;
|
||||
}
|
||||
|
||||
static int sst_write(struct mtd_info *mtd, loff_t to, size_t len,
|
@ -1,26 +0,0 @@
|
||||
From 95193796256cfce16e5d881318e15b6b04062c15 Mon Sep 17 00:00:00 2001
|
||||
From: Michal Suchanek <hramrach@gmail.com>
|
||||
Date: Thu, 5 May 2016 17:31:56 -0700
|
||||
Subject: [PATCH 10/10] mtd: m25p80: read in spi_max_transfer_size chunks
|
||||
|
||||
Take into account transfer size limitation of SPI master.
|
||||
|
||||
Signed-off-by: Michal Suchanek <hramrach@gmail.com>
|
||||
Signed-off-by: Brian Norris <computersforpeace@gmail.com>
|
||||
Acked-by: Michal Suchanek <hramrach@gmail.com>
|
||||
Tested-by: Michal Suchanek <hramrach@gmail.com>
|
||||
---
|
||||
drivers/mtd/devices/m25p80.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/mtd/devices/m25p80.c
|
||||
+++ b/drivers/mtd/devices/m25p80.c
|
||||
@@ -172,7 +172,7 @@ static ssize_t m25p80_read(struct spi_no
|
||||
|
||||
t[1].rx_buf = buf;
|
||||
t[1].rx_nbits = m25p80_rx_nbits(nor);
|
||||
- t[1].len = len;
|
||||
+ t[1].len = min(len, spi_max_transfer_size(spi));
|
||||
spi_message_add_tail(&t[1], &m);
|
||||
|
||||
ret = spi_sync(spi, &m);
|
@ -1,37 +0,0 @@
|
||||
From a59388668d0ce19dadea909e09f4eb905a27b1ce Mon Sep 17 00:00:00 2001
|
||||
From: Jonas Gorski <jogo@openwrt.org>
|
||||
Date: Wed, 8 Jun 2016 12:08:43 +0200
|
||||
Subject: [PATCH] serial/bcm63xx_uart: use correct alias naming
|
||||
|
||||
The bcm63xx_uart driver uses the of alias for determing its id. Recent
|
||||
changes in dts files changed the expected 'uartX' to the recommended
|
||||
'serialX', breaking serial output. Fix this by checking for a 'serialX'
|
||||
alias as well.
|
||||
|
||||
Fixes: e3b992d028f8 ("MIPS: BMIPS: Improve BCM6328 device tree")
|
||||
Fixes: 2d52ee82b475 ("MIPS: BMIPS: Improve BCM6368 device tree")
|
||||
Fixes: 7537d273e2f3 ("MIPS: BMIPS: Add device tree example for BCM6358")
|
||||
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
|
||||
Acked-by: Florian Fainelli <f.fainelli@gmail.com>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/tty/serial/bcm63xx_uart.c | 8 ++++++--
|
||||
1 file changed, 6 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/tty/serial/bcm63xx_uart.c
|
||||
+++ b/drivers/tty/serial/bcm63xx_uart.c
|
||||
@@ -813,8 +813,12 @@ static int bcm_uart_probe(struct platfor
|
||||
struct clk *clk;
|
||||
int ret;
|
||||
|
||||
- if (pdev->dev.of_node)
|
||||
- pdev->id = of_alias_get_id(pdev->dev.of_node, "uart");
|
||||
+ if (pdev->dev.of_node) {
|
||||
+ pdev->id = of_alias_get_id(pdev->dev.of_node, "serial");
|
||||
+
|
||||
+ if (pdev->id < 0)
|
||||
+ pdev->id = of_alias_get_id(pdev->dev.of_node, "uart");
|
||||
+ }
|
||||
|
||||
if (pdev->id < 0 || pdev->id >= BCM63XX_NR_UARTS)
|
||||
return -EINVAL;
|
@ -1,73 +0,0 @@
|
||||
From 5090cc6ae2f79ee779e5faf7c8a28edf42b7d738 Mon Sep 17 00:00:00 2001
|
||||
From: Heiner Kallweit <hkallweit1@gmail.com>
|
||||
Date: Wed, 17 Aug 2016 21:08:01 +0200
|
||||
Subject: [PATCH] spi: introduce max_message_size hook in spi_master
|
||||
|
||||
Recently a maximum transfer size was was introduced in struct spi_master.
|
||||
However there are also spi controllers with a maximum message size, e.g.
|
||||
fsl-espi has a max message size of 64KB.
|
||||
Introduce a hook max_message_size to deal with such limitations.
|
||||
|
||||
Also make sure that spi_max_transfer_size doesn't return greater values
|
||||
than spi_max_message_size, even if hook max_transfer_size is not set.
|
||||
|
||||
Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
|
||||
Signed-off-by: Mark Brown <broonie@kernel.org>
|
||||
---
|
||||
include/linux/spi/spi.h | 25 +++++++++++++++++++++----
|
||||
1 file changed, 21 insertions(+), 4 deletions(-)
|
||||
|
||||
--- a/include/linux/spi/spi.h
|
||||
+++ b/include/linux/spi/spi.h
|
||||
@@ -304,6 +304,8 @@ static inline void spi_unregister_driver
|
||||
* @min_speed_hz: Lowest supported transfer speed
|
||||
* @max_speed_hz: Highest supported transfer speed
|
||||
* @flags: other constraints relevant to this driver
|
||||
+ * @max_message_size: function that returns the max message size for
|
||||
+ * a &spi_device; may be %NULL, so the default %SIZE_MAX will be used.
|
||||
* @bus_lock_spinlock: spinlock for SPI bus locking
|
||||
* @bus_lock_mutex: mutex for SPI bus locking
|
||||
* @bus_lock_flag: indicates that the SPI bus is locked for exclusive use
|
||||
@@ -429,10 +431,11 @@ struct spi_master {
|
||||
#define SPI_MASTER_MUST_TX BIT(4) /* requires tx */
|
||||
|
||||
/*
|
||||
- * on some hardware transfer size may be constrained
|
||||
+ * on some hardware transfer / message size may be constrained
|
||||
* the limit may depend on device transfer settings
|
||||
*/
|
||||
size_t (*max_transfer_size)(struct spi_device *spi);
|
||||
+ size_t (*max_message_size)(struct spi_device *spi);
|
||||
|
||||
/* lock and mutex for SPI bus locking */
|
||||
spinlock_t bus_lock_spinlock;
|
||||
@@ -844,12 +847,26 @@ extern int spi_async_locked(struct spi_d
|
||||
struct spi_message *message);
|
||||
|
||||
static inline size_t
|
||||
-spi_max_transfer_size(struct spi_device *spi)
|
||||
+spi_max_message_size(struct spi_device *spi)
|
||||
{
|
||||
struct spi_master *master = spi->master;
|
||||
- if (!master->max_transfer_size)
|
||||
+ if (!master->max_message_size)
|
||||
return SIZE_MAX;
|
||||
- return master->max_transfer_size(spi);
|
||||
+ return master->max_message_size(spi);
|
||||
+}
|
||||
+
|
||||
+static inline size_t
|
||||
+spi_max_transfer_size(struct spi_device *spi)
|
||||
+{
|
||||
+ struct spi_master *master = spi->master;
|
||||
+ size_t tr_max = SIZE_MAX;
|
||||
+ size_t msg_max = spi_max_message_size(spi);
|
||||
+
|
||||
+ if (master->max_transfer_size)
|
||||
+ tr_max = master->max_transfer_size(spi);
|
||||
+
|
||||
+ /* transfer size limit must not be greater than messsage size limit */
|
||||
+ return min(tr_max, msg_max);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
@ -1,30 +0,0 @@
|
||||
From 80a79a889ce5df16c5261ab2f1e8e63b94b78102 Mon Sep 17 00:00:00 2001
|
||||
From: Heiner Kallweit <hkallweit1@gmail.com>
|
||||
Date: Fri, 28 Oct 2016 07:58:46 +0200
|
||||
Subject: [PATCH 1/8] mtd: m25p80: consider max message size in m25p80_read
|
||||
|
||||
Consider a message size limit when calculating the maximum amount
|
||||
of data that can be read.
|
||||
|
||||
The message size limit has been introduced with 4.9, so cc it
|
||||
to stable.
|
||||
|
||||
Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
|
||||
Cc: <stable@vger.kernel.org> # 4.9.x
|
||||
Signed-off-by: Cyrille Pitchen <cyrille.pitchen@atmel.com>
|
||||
---
|
||||
drivers/mtd/devices/m25p80.c | 3 ++-
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/mtd/devices/m25p80.c
|
||||
+++ b/drivers/mtd/devices/m25p80.c
|
||||
@@ -172,7 +172,8 @@ static ssize_t m25p80_read(struct spi_no
|
||||
|
||||
t[1].rx_buf = buf;
|
||||
t[1].rx_nbits = m25p80_rx_nbits(nor);
|
||||
- t[1].len = min(len, spi_max_transfer_size(spi));
|
||||
+ t[1].len = min3(len, spi_max_transfer_size(spi),
|
||||
+ spi_max_message_size(spi) - t[0].len);
|
||||
spi_message_add_tail(&t[1], &m);
|
||||
|
||||
ret = spi_sync(spi, &m);
|
@ -1,33 +0,0 @@
|
||||
From bc0e151514d09cadb56e473a10c783e64e48ce0b Mon Sep 17 00:00:00 2001
|
||||
From: Cyrille Pitchen <cyrille.pitchen@atmel.com>
|
||||
Date: Tue, 6 Dec 2016 18:14:24 +0100
|
||||
Subject: [PATCH] mtd: spi-nor: remove WARN_ONCE() message in spi_nor_write()
|
||||
|
||||
This patch removes the WARN_ONCE() test in spi_nor_write().
|
||||
This macro triggers the display of a warning message almost every time we
|
||||
use a UBI file-system because a write operation is performed at offset 64,
|
||||
which is in the middle of the SPI NOR memory page. This is a valid
|
||||
operation for ubifs.
|
||||
|
||||
Hence this warning is pretty annoying and useless so we just remove it.
|
||||
|
||||
Signed-off-by: Cyrille Pitchen <cyrille.pitchen@atmel.com>
|
||||
Suggested-by: Richard Weinberger <richard@nod.at>
|
||||
Suggested-by: Andras Szemzo <szemzo.andras@gmail.com>
|
||||
Acked-by: Boris Brezillon <boris.brezillon@free-electrons.com>
|
||||
---
|
||||
drivers/mtd/spi-nor/spi-nor.c | 3 ---
|
||||
1 file changed, 3 deletions(-)
|
||||
|
||||
--- a/drivers/mtd/spi-nor/spi-nor.c
|
||||
+++ b/drivers/mtd/spi-nor/spi-nor.c
|
||||
@@ -1014,9 +1014,6 @@ static int spi_nor_write(struct mtd_info
|
||||
ssize_t written;
|
||||
|
||||
page_offset = (to + i) & (nor->page_size - 1);
|
||||
- WARN_ONCE(page_offset,
|
||||
- "Writing at offset %zu into a NOR page. Writing partial pages may decrease reliability and increase wear of NOR flash.",
|
||||
- page_offset);
|
||||
/* the size of data remaining on the first page */
|
||||
page_remain = min_t(size_t,
|
||||
nor->page_size - page_offset, len - i);
|
@ -1,42 +0,0 @@
|
||||
From 3fcc36962c32ad0af2d5904103e2b2b824b6b1aa Mon Sep 17 00:00:00 2001
|
||||
From: Jonas Gorski <jonas.gorski@gmail.com>
|
||||
Date: Sat, 4 Feb 2017 12:32:59 +0100
|
||||
Subject: [PATCH 2/8] spi/bcm63xx: make spi subsystem aware of message size
|
||||
limits
|
||||
|
||||
The bcm63xx LS SPI controller does not allow manual control of the CS
|
||||
lines and will toggle it automatically before after sending data, so we
|
||||
are limited to messages that fit in the FIFO buffer. Since the CS lines
|
||||
aren't available as GPIOs either, we will need to make slave drivers
|
||||
aware of this limitation and handle it accordingly.
|
||||
|
||||
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
|
||||
---
|
||||
drivers/spi/spi-bcm63xx.c | 9 +++++++++
|
||||
1 file changed, 9 insertions(+)
|
||||
|
||||
--- a/drivers/spi/spi-bcm63xx.c
|
||||
+++ b/drivers/spi/spi-bcm63xx.c
|
||||
@@ -429,6 +429,13 @@ static irqreturn_t bcm63xx_spi_interrupt
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
+static size_t bcm63xx_spi_max_length(struct spi_device *spi)
|
||||
+{
|
||||
+ struct bcm63xx_spi *bs = spi_master_get_devdata(spi->master);
|
||||
+
|
||||
+ return bs->fifo_size;
|
||||
+}
|
||||
+
|
||||
static const unsigned long bcm6348_spi_reg_offsets[] = {
|
||||
[SPI_CMD] = SPI_6348_CMD,
|
||||
[SPI_INT_STATUS] = SPI_6348_INT_STATUS,
|
||||
@@ -542,6 +549,8 @@ static int bcm63xx_spi_probe(struct plat
|
||||
master->transfer_one_message = bcm63xx_spi_transfer_one;
|
||||
master->mode_bits = MODEBITS;
|
||||
master->bits_per_word_mask = SPI_BPW_MASK(8);
|
||||
+ master->max_transfer_size = bcm63xx_spi_max_length;
|
||||
+ master->max_message_size = bcm63xx_spi_max_length;
|
||||
master->auto_runtime_pm = true;
|
||||
bs->msg_type_shift = bs->reg_offsets[SPI_MSG_TYPE_SHIFT];
|
||||
bs->msg_ctl_width = bs->reg_offsets[SPI_MSG_CTL_WIDTH];
|
@ -1,50 +0,0 @@
|
||||
From 0a0c39044332a75eaf4a3c5654079df953b0d839 Mon Sep 17 00:00:00 2001
|
||||
From: Jonas Gorski <jogo@openwrt.org>
|
||||
Date: Mon, 7 Sep 2015 21:00:38 +0200
|
||||
Subject: [PATCH 3/8] spi/bcm63xx: document device tree bindings
|
||||
|
||||
Add documentation for the bindings of the low speed SPI controller found
|
||||
on most bcm63xx SoCs.
|
||||
|
||||
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
|
||||
---
|
||||
.../devicetree/bindings/spi/spi-bcm63xx.txt | 33 ++++++++++++++++++++++
|
||||
1 file changed, 33 insertions(+)
|
||||
create mode 100644 Documentation/devicetree/bindings/spi/spi-bcm63xx.txt
|
||||
|
||||
--- /dev/null
|
||||
+++ b/Documentation/devicetree/bindings/spi/spi-bcm63xx.txt
|
||||
@@ -0,0 +1,33 @@
|
||||
+Binding for Broadcom BCM6348/BCM6358 SPI controller
|
||||
+
|
||||
+Required properties:
|
||||
+- compatible: must contain one of "brcm,bcm6348-spi", "brcm,bcm6358-spi".
|
||||
+- reg: Base address and size of the controllers memory area.
|
||||
+- interrupts: Interrupt for the SPI block.
|
||||
+- clocks: phandle of the SPI clock.
|
||||
+- clock-names: has to be "spi".
|
||||
+- #address-cells: <1>, as required by generic SPI binding.
|
||||
+- #size-cells: <0>, also as required by generic SPI binding.
|
||||
+
|
||||
+Optional properties:
|
||||
+- num-cs: some controllers have less than 8 cs signals. Defaults to 8
|
||||
+ if absent.
|
||||
+
|
||||
+Child nodes as per the generic SPI binding.
|
||||
+
|
||||
+Example:
|
||||
+
|
||||
+ spi@10000800 {
|
||||
+ compatible = "brcm,bcm6368-spi", "brcm,bcm6358-spi";
|
||||
+ reg = <0x10000800 0x70c>;
|
||||
+
|
||||
+ interrupts = <1>;
|
||||
+
|
||||
+ clocks = <&clkctl 9>;
|
||||
+ clock-names = "spi";
|
||||
+
|
||||
+ num-cs = <5>;
|
||||
+
|
||||
+ #address-cells = <1>;
|
||||
+ #size-cells = <0>;
|
||||
+ };
|
@ -1,98 +0,0 @@
|
||||
From 3353228a04a004ec67073871f40cf58dc4e209aa Mon Sep 17 00:00:00 2001
|
||||
From: Jonas Gorski <jonas.gorski@gmail.com>
|
||||
Date: Mon, 7 Sep 2015 21:01:38 +0200
|
||||
Subject: [PATCH 4/8] spi/bcm63xx: add support for probing through devicetree
|
||||
|
||||
Add required binding support to probe through device tree.
|
||||
|
||||
Use the compatible instead of the resource size for identifiying the
|
||||
block type, and allow reducing the number of cs lines through OF.
|
||||
|
||||
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
|
||||
---
|
||||
drivers/spi/spi-bcm63xx.c | 42 ++++++++++++++++++++++++++++++++++++------
|
||||
1 file changed, 36 insertions(+), 6 deletions(-)
|
||||
|
||||
--- a/drivers/spi/spi-bcm63xx.c
|
||||
+++ b/drivers/spi/spi-bcm63xx.c
|
||||
@@ -26,6 +26,7 @@
|
||||
#include <linux/completion.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
+#include <linux/of.h>
|
||||
|
||||
/* BCM 6338/6348 SPI core */
|
||||
#define SPI_6348_RSET_SIZE 64
|
||||
@@ -485,21 +486,48 @@ static const struct platform_device_id b
|
||||
},
|
||||
};
|
||||
|
||||
+static const struct of_device_id bcm63xx_spi_of_match[] = {
|
||||
+ { .compatible = "brcm,bcm6348-spi", .data = &bcm6348_spi_reg_offsets },
|
||||
+ { .compatible = "brcm,bcm6358-spi", .data = &bcm6358_spi_reg_offsets },
|
||||
+ { },
|
||||
+};
|
||||
+
|
||||
static int bcm63xx_spi_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct resource *r;
|
||||
const unsigned long *bcm63xx_spireg;
|
||||
struct device *dev = &pdev->dev;
|
||||
- int irq;
|
||||
+ int irq, bus_num;
|
||||
struct spi_master *master;
|
||||
struct clk *clk;
|
||||
struct bcm63xx_spi *bs;
|
||||
int ret;
|
||||
+ u32 num_cs = BCM63XX_SPI_MAX_CS;
|
||||
|
||||
- if (!pdev->id_entry->driver_data)
|
||||
- return -EINVAL;
|
||||
+ if (dev->of_node) {
|
||||
+ const struct of_device_id *match;
|
||||
|
||||
- bcm63xx_spireg = (const unsigned long *)pdev->id_entry->driver_data;
|
||||
+ match = of_match_node(bcm63xx_spi_of_match, dev->of_node);
|
||||
+ if (!match)
|
||||
+ return -EINVAL;
|
||||
+ bcm63xx_spireg = match->data;
|
||||
+
|
||||
+ of_property_read_u32(dev->of_node, "num-cs", &num_cs);
|
||||
+ if (num_cs > BCM63XX_SPI_MAX_CS) {
|
||||
+ dev_warn(dev, "unsupported number of cs (%i), reducing to 8\n",
|
||||
+ num_cs);
|
||||
+ num_cs = BCM63XX_SPI_MAX_CS;
|
||||
+ }
|
||||
+
|
||||
+ bus_num = -1;
|
||||
+ } else if (pdev->id_entry->driver_data) {
|
||||
+ const struct platform_device_id *match = pdev->id_entry;
|
||||
+
|
||||
+ bcm63xx_spireg = (const unsigned long *)match->driver_data;
|
||||
+ bus_num = BCM63XX_SPI_BUS_NUM;
|
||||
+ } else {
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq < 0) {
|
||||
@@ -544,8 +572,9 @@ static int bcm63xx_spi_probe(struct plat
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
- master->bus_num = BCM63XX_SPI_BUS_NUM;
|
||||
- master->num_chipselect = BCM63XX_SPI_MAX_CS;
|
||||
+ master->dev.of_node = dev->of_node;
|
||||
+ master->bus_num = bus_num;
|
||||
+ master->num_chipselect = num_cs;
|
||||
master->transfer_one_message = bcm63xx_spi_transfer_one;
|
||||
master->mode_bits = MODEBITS;
|
||||
master->bits_per_word_mask = SPI_BPW_MASK(8);
|
||||
@@ -634,6 +663,7 @@ static struct platform_driver bcm63xx_sp
|
||||
.driver = {
|
||||
.name = "bcm63xx-spi",
|
||||
.pm = &bcm63xx_spi_pm_ops,
|
||||
+ .of_match_table = bcm63xx_spi_of_match,
|
||||
},
|
||||
.id_table = bcm63xx_spi_dev_match,
|
||||
.probe = bcm63xx_spi_probe,
|
@ -1,35 +0,0 @@
|
||||
From d03f23df6ff47898d76f06b3aa5dadcfa1ec8f4f Mon Sep 17 00:00:00 2001
|
||||
From: Jonas Gorski <jonas.gorski@gmail.com>
|
||||
Date: Sun, 19 Feb 2017 23:40:22 +0100
|
||||
Subject: [PATCH 1/3] spi/bcm63xx-hsspi: allow providing clock rate through a
|
||||
second clock
|
||||
|
||||
Instead of requiring the hsspi clock to have a rate, allow using a second
|
||||
clock for providing the Hz rate, which is probably more correct anyway.
|
||||
|
||||
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
|
||||
---
|
||||
drivers/spi/spi-bcm63xx-hsspi.c | 12 ++++++++++--
|
||||
1 file changed, 10 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/spi/spi-bcm63xx-hsspi.c
|
||||
+++ b/drivers/spi/spi-bcm63xx-hsspi.c
|
||||
@@ -351,8 +351,16 @@ static int bcm63xx_hsspi_probe(struct pl
|
||||
return PTR_ERR(clk);
|
||||
|
||||
rate = clk_get_rate(clk);
|
||||
- if (!rate)
|
||||
- return -EINVAL;
|
||||
+ if (!rate) {
|
||||
+ struct clk *pll_clk = devm_clk_get(dev, "pll");
|
||||
+
|
||||
+ if (IS_ERR(pll_clk))
|
||||
+ return PTR_ERR(pll_clk);
|
||||
+
|
||||
+ rate = clk_get_rate(pll_clk);
|
||||
+ if (!rate)
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
|
||||
ret = clk_prepare_enable(clk);
|
||||
if (ret)
|
@ -1,51 +0,0 @@
|
||||
From ff759cc25db31bbb3469abb16a0306f110c4c7fa Mon Sep 17 00:00:00 2001
|
||||
From: Jonas Gorski <jonas.gorski@gmail.com>
|
||||
Date: Thu, 10 Sep 2015 14:52:32 +0200
|
||||
Subject: [PATCH 2/3] dt-bindings: spi: document bcm63xx HS SPI devicetree
|
||||
bindings
|
||||
|
||||
Add documentation for the bindings of the high speed SPI controller found
|
||||
on newer bcm63xx SoCs.
|
||||
|
||||
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
|
||||
---
|
||||
.../devicetree/bindings/spi/spi-bcm63xx-hsspi.txt | 33 ++++++++++++++++++++++
|
||||
1 file changed, 33 insertions(+)
|
||||
create mode 100644 Documentation/devicetree/bindings/spi/spi-bcm63xx-hsspi.txt
|
||||
|
||||
--- /dev/null
|
||||
+++ b/Documentation/devicetree/bindings/spi/spi-bcm63xx-hsspi.txt
|
||||
@@ -0,0 +1,33 @@
|
||||
+Binding for Broadcom BCM6328 High Speed SPI controller
|
||||
+
|
||||
+Required properties:
|
||||
+- compatible: must contain of "brcm,bcm6328-hsspi".
|
||||
+- reg: Base address and size of the controllers memory area.
|
||||
+- interrupts: Interrupt for the SPI block.
|
||||
+- clocks: phandles of the SPI clock and the PLL clock.
|
||||
+- clock-names: must be "hsspi", "pll".
|
||||
+- #address-cells: <1>, as required by generic SPI binding.
|
||||
+- #size-cells: <0>, also as required by generic SPI binding.
|
||||
+
|
||||
+Optional properties:
|
||||
+- num-cs: some controllers have less than 8 cs signals. Defaults to 8
|
||||
+ if absent.
|
||||
+
|
||||
+Child nodes as per the generic SPI binding.
|
||||
+
|
||||
+Example:
|
||||
+
|
||||
+ spi@10001000 {
|
||||
+ compatible = "brcm,bcm6328-hsspi";
|
||||
+ reg = <0x10001000 0x600>;
|
||||
+
|
||||
+ interrupts = <29>;
|
||||
+
|
||||
+ clocks = <&clkctl 9>, <&hsspi_pll>;
|
||||
+ clock-names = "hsspi", "pll";
|
||||
+
|
||||
+ num-cs = <2>;
|
||||
+
|
||||
+ #address-cells = <1>;
|
||||
+ #size-cells = <0>;
|
||||
+ };
|
@ -1,76 +0,0 @@
|
||||
From 776041498c2b285a7f745c924e10fc11ef720eae Mon Sep 17 00:00:00 2001
|
||||
From: Jonas Gorski <jonas.gorski@gmail.com>
|
||||
Date: Thu, 10 Sep 2015 14:53:53 +0200
|
||||
Subject: [PATCH 3/3] spi/bcm63xx-hsspi: allow for probing through devicetree
|
||||
|
||||
Add required binding support to probe through device tree.
|
||||
|
||||
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
|
||||
---
|
||||
drivers/spi/spi-bcm63xx-hsspi.c | 23 ++++++++++++++++++++---
|
||||
1 file changed, 20 insertions(+), 3 deletions(-)
|
||||
|
||||
--- a/drivers/spi/spi-bcm63xx-hsspi.c
|
||||
+++ b/drivers/spi/spi-bcm63xx-hsspi.c
|
||||
@@ -19,6 +19,7 @@
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/mutex.h>
|
||||
+#include <linux/of.h>
|
||||
|
||||
#define HSSPI_GLOBAL_CTRL_REG 0x0
|
||||
#define GLOBAL_CTRL_CS_POLARITY_SHIFT 0
|
||||
@@ -91,6 +92,7 @@
|
||||
|
||||
#define HSSPI_MAX_SYNC_CLOCK 30000000
|
||||
|
||||
+#define HSSPI_SPI_MAX_CS 8
|
||||
#define HSSPI_BUS_NUM 1 /* 0 is legacy SPI */
|
||||
|
||||
struct bcm63xx_hsspi {
|
||||
@@ -332,7 +334,7 @@ static int bcm63xx_hsspi_probe(struct pl
|
||||
struct device *dev = &pdev->dev;
|
||||
struct clk *clk;
|
||||
int irq, ret;
|
||||
- u32 reg, rate;
|
||||
+ u32 reg, rate, num_cs = HSSPI_SPI_MAX_CS;
|
||||
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq < 0) {
|
||||
@@ -382,8 +384,17 @@ static int bcm63xx_hsspi_probe(struct pl
|
||||
mutex_init(&bs->bus_mutex);
|
||||
init_completion(&bs->done);
|
||||
|
||||
- master->bus_num = HSSPI_BUS_NUM;
|
||||
- master->num_chipselect = 8;
|
||||
+ master->dev.of_node = dev->of_node;
|
||||
+ if (!dev->of_node)
|
||||
+ master->bus_num = HSSPI_BUS_NUM;
|
||||
+
|
||||
+ of_property_read_u32(dev->of_node, "num-cs", &num_cs);
|
||||
+ if (num_cs > 8) {
|
||||
+ dev_warn(dev, "unsupported number of cs (%i), reducing to 8\n",
|
||||
+ num_cs);
|
||||
+ num_cs = HSSPI_SPI_MAX_CS;
|
||||
+ }
|
||||
+ master->num_chipselect = num_cs;
|
||||
master->setup = bcm63xx_hsspi_setup;
|
||||
master->transfer_one_message = bcm63xx_hsspi_transfer_one;
|
||||
master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH |
|
||||
@@ -469,10 +480,16 @@ static int bcm63xx_hsspi_resume(struct d
|
||||
static SIMPLE_DEV_PM_OPS(bcm63xx_hsspi_pm_ops, bcm63xx_hsspi_suspend,
|
||||
bcm63xx_hsspi_resume);
|
||||
|
||||
+static const struct of_device_id bcm63xx_hsspi_of_match[] = {
|
||||
+ { .compatible = "brcm,bcm6328-hsspi", },
|
||||
+ { },
|
||||
+};
|
||||
+
|
||||
static struct platform_driver bcm63xx_hsspi_driver = {
|
||||
.driver = {
|
||||
.name = "bcm63xx-hsspi",
|
||||
.pm = &bcm63xx_hsspi_pm_ops,
|
||||
+ .of_match_table = bcm63xx_hsspi_of_match,
|
||||
},
|
||||
.probe = bcm63xx_hsspi_probe,
|
||||
.remove = bcm63xx_hsspi_remove,
|
@ -1,192 +0,0 @@
|
||||
From 69226896ad636b94f6d2e55d75ff21a29c4de83b Mon Sep 17 00:00:00 2001
|
||||
From: Roger Quadros <rogerq@ti.com>
|
||||
Date: Fri, 21 Apr 2017 16:15:38 +0300
|
||||
Subject: [PATCH] mdio_bus: Issue GPIO RESET to PHYs.
|
||||
|
||||
Some boards [1] leave the PHYs at an invalid state
|
||||
during system power-up or reset thus causing unreliability
|
||||
issues with the PHY which manifests as PHY not being detected
|
||||
or link not functional. To fix this, these PHYs need to be RESET
|
||||
via a GPIO connected to the PHY's RESET pin.
|
||||
|
||||
Some boards have a single GPIO controlling the PHY RESET pin of all
|
||||
PHYs on the bus whereas some others have separate GPIOs controlling
|
||||
individual PHY RESETs.
|
||||
|
||||
In both cases, the RESET de-assertion cannot be done in the PHY driver
|
||||
as the PHY will not probe till its reset is de-asserted.
|
||||
So do the RESET de-assertion in the MDIO bus driver.
|
||||
|
||||
[1] - am572x-idk, am571x-idk, a437x-idk
|
||||
|
||||
Signed-off-by: Roger Quadros <rogerq@ti.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
Documentation/devicetree/bindings/net/mdio.txt | 33 ++++++++++++++++++
|
||||
drivers/net/phy/mdio_bus.c | 47 ++++++++++++++++++++++++++
|
||||
drivers/of/of_mdio.c | 7 ++++
|
||||
include/linux/phy.h | 7 ++++
|
||||
4 files changed, 94 insertions(+)
|
||||
create mode 100644 Documentation/devicetree/bindings/net/mdio.txt
|
||||
|
||||
--- /dev/null
|
||||
+++ b/Documentation/devicetree/bindings/net/mdio.txt
|
||||
@@ -0,0 +1,33 @@
|
||||
+Common MDIO bus properties.
|
||||
+
|
||||
+These are generic properties that can apply to any MDIO bus.
|
||||
+
|
||||
+Optional properties:
|
||||
+- reset-gpios: List of one or more GPIOs that control the RESET lines
|
||||
+ of the PHYs on that MDIO bus.
|
||||
+- reset-delay-us: RESET pulse width in microseconds as per PHY datasheet.
|
||||
+
|
||||
+A list of child nodes, one per device on the bus is expected. These
|
||||
+should follow the generic phy.txt, or a device specific binding document.
|
||||
+
|
||||
+Example :
|
||||
+This example shows these optional properties, plus other properties
|
||||
+required for the TI Davinci MDIO driver.
|
||||
+
|
||||
+ davinci_mdio: ethernet@0x5c030000 {
|
||||
+ compatible = "ti,davinci_mdio";
|
||||
+ reg = <0x5c030000 0x1000>;
|
||||
+ #address-cells = <1>;
|
||||
+ #size-cells = <0>;
|
||||
+
|
||||
+ reset-gpios = <&gpio2 5 GPIO_ACTIVE_LOW>;
|
||||
+ reset-delay-us = <2>; /* PHY datasheet states 1us min */
|
||||
+
|
||||
+ ethphy0: ethernet-phy@1 {
|
||||
+ reg = <1>;
|
||||
+ };
|
||||
+
|
||||
+ ethphy1: ethernet-phy@3 {
|
||||
+ reg = <3>;
|
||||
+ };
|
||||
+ };
|
||||
--- a/drivers/net/phy/mdio_bus.c
|
||||
+++ b/drivers/net/phy/mdio_bus.c
|
||||
@@ -22,8 +22,11 @@
|
||||
#include <linux/init.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/device.h>
|
||||
+#include <linux/gpio.h>
|
||||
+#include <linux/gpio/consumer.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_mdio.h>
|
||||
+#include <linux/of_gpio.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/skbuff.h>
|
||||
@@ -252,6 +255,7 @@ static inline void of_mdiobus_link_phyde
|
||||
int __mdiobus_register(struct mii_bus *bus, struct module *owner)
|
||||
{
|
||||
int i, err;
|
||||
+ struct gpio_desc *gpiod;
|
||||
|
||||
if (NULL == bus || NULL == bus->name ||
|
||||
NULL == bus->read || NULL == bus->write)
|
||||
@@ -278,6 +282,35 @@ int __mdiobus_register(struct mii_bus *b
|
||||
if (bus->reset)
|
||||
bus->reset(bus);
|
||||
|
||||
+ /* de-assert bus level PHY GPIO resets */
|
||||
+ if (bus->num_reset_gpios > 0) {
|
||||
+ bus->reset_gpiod = devm_kcalloc(&bus->dev,
|
||||
+ bus->num_reset_gpios,
|
||||
+ sizeof(struct gpio_desc *),
|
||||
+ GFP_KERNEL);
|
||||
+ if (!bus->reset_gpiod)
|
||||
+ return -ENOMEM;
|
||||
+ }
|
||||
+
|
||||
+ for (i = 0; i < bus->num_reset_gpios; i++) {
|
||||
+ gpiod = devm_gpiod_get_index(&bus->dev, "reset", i,
|
||||
+ GPIOD_OUT_LOW);
|
||||
+ if (IS_ERR(gpiod)) {
|
||||
+ err = PTR_ERR(gpiod);
|
||||
+ if (err != -ENOENT) {
|
||||
+ dev_err(&bus->dev,
|
||||
+ "mii_bus %s couldn't get reset GPIO\n",
|
||||
+ bus->id);
|
||||
+ return err;
|
||||
+ }
|
||||
+ } else {
|
||||
+ bus->reset_gpiod[i] = gpiod;
|
||||
+ gpiod_set_value_cansleep(gpiod, 1);
|
||||
+ udelay(bus->reset_delay_us);
|
||||
+ gpiod_set_value_cansleep(gpiod, 0);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
for (i = 0; i < PHY_MAX_ADDR; i++) {
|
||||
if ((bus->phy_mask & (1 << i)) == 0) {
|
||||
struct phy_device *phydev;
|
||||
@@ -302,6 +335,13 @@ error:
|
||||
phy_device_free(phydev);
|
||||
}
|
||||
}
|
||||
+
|
||||
+ /* Put PHYs in RESET to save power */
|
||||
+ for (i = 0; i < bus->num_reset_gpios; i++) {
|
||||
+ if (bus->reset_gpiod[i])
|
||||
+ gpiod_set_value_cansleep(bus->reset_gpiod[i], 1);
|
||||
+ }
|
||||
+
|
||||
device_del(&bus->dev);
|
||||
return err;
|
||||
}
|
||||
@@ -321,6 +361,13 @@ void mdiobus_unregister(struct mii_bus *
|
||||
phy_device_free(phydev);
|
||||
}
|
||||
}
|
||||
+
|
||||
+ /* Put PHYs in RESET to save power */
|
||||
+ for (i = 0; i < bus->num_reset_gpios; i++) {
|
||||
+ if (bus->reset_gpiod[i])
|
||||
+ gpiod_set_value_cansleep(bus->reset_gpiod[i], 1);
|
||||
+ }
|
||||
+
|
||||
device_del(&bus->dev);
|
||||
}
|
||||
EXPORT_SYMBOL(mdiobus_unregister);
|
||||
--- a/drivers/of/of_mdio.c
|
||||
+++ b/drivers/of/of_mdio.c
|
||||
@@ -21,6 +21,8 @@
|
||||
#include <linux/of_mdio.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
+#define DEFAULT_GPIO_RESET_DELAY 10 /* in microseconds */
|
||||
+
|
||||
MODULE_AUTHOR("Grant Likely <grant.likely@secretlab.ca>");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
@@ -140,6 +142,11 @@ int of_mdiobus_register(struct mii_bus *
|
||||
|
||||
mdio->dev.of_node = np;
|
||||
|
||||
+ /* Get bus level PHY reset GPIO details */
|
||||
+ mdio->reset_delay_us = DEFAULT_GPIO_RESET_DELAY;
|
||||
+ of_property_read_u32(np, "reset-delay-us", &mdio->reset_delay_us);
|
||||
+ mdio->num_reset_gpios = of_gpio_named_count(np, "reset-gpios");
|
||||
+
|
||||
/* Register the MDIO bus */
|
||||
rc = mdiobus_register(mdio);
|
||||
if (rc)
|
||||
--- a/include/linux/phy.h
|
||||
+++ b/include/linux/phy.h
|
||||
@@ -187,6 +187,13 @@ struct mii_bus {
|
||||
* interrupt at the index matching its address
|
||||
*/
|
||||
int *irq;
|
||||
+
|
||||
+ /* GPIO reset pulse width in microseconds */
|
||||
+ int reset_delay_us;
|
||||
+ /* Number of reset GPIOs */
|
||||
+ int num_reset_gpios;
|
||||
+ /* Array of RESET GPIO descriptors */
|
||||
+ struct gpio_desc **reset_gpiod;
|
||||
};
|
||||
#define to_mii_bus(d) container_of(d, struct mii_bus, dev)
|
||||
|
@ -1,43 +0,0 @@
|
||||
From df0c8d911abf6ba97b2c2fc3c5a12769e0b081a3 Mon Sep 17 00:00:00 2001
|
||||
From: Florian Fainelli <f.fainelli@gmail.com>
|
||||
Date: Thu, 11 May 2017 11:24:16 -0700
|
||||
Subject: [PATCH] net: phy: Call bus->reset() after releasing PHYs from reset
|
||||
|
||||
The API convention makes it that a given MDIO bus reset should be able
|
||||
to access PHY devices in its reset() callback and perform additional
|
||||
MDIO accesses in order to bring the bus and PHYs in a working state.
|
||||
|
||||
Commit 69226896ad63 ("mdio_bus: Issue GPIO RESET to PHYs.") broke that
|
||||
contract by first calling bus->reset() and then release all PHYs from
|
||||
reset using their shared GPIO line, so restore the expected
|
||||
functionality here.
|
||||
|
||||
Fixes: 69226896ad63 ("mdio_bus: Issue GPIO RESET to PHYs.")
|
||||
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/phy/mdio_bus.c | 6 +++---
|
||||
1 file changed, 3 insertions(+), 3 deletions(-)
|
||||
|
||||
--- a/drivers/net/phy/mdio_bus.c
|
||||
+++ b/drivers/net/phy/mdio_bus.c
|
||||
@@ -279,9 +279,6 @@ int __mdiobus_register(struct mii_bus *b
|
||||
|
||||
mutex_init(&bus->mdio_lock);
|
||||
|
||||
- if (bus->reset)
|
||||
- bus->reset(bus);
|
||||
-
|
||||
/* de-assert bus level PHY GPIO resets */
|
||||
if (bus->num_reset_gpios > 0) {
|
||||
bus->reset_gpiod = devm_kcalloc(&bus->dev,
|
||||
@@ -311,6 +308,9 @@ int __mdiobus_register(struct mii_bus *b
|
||||
}
|
||||
}
|
||||
|
||||
+ if (bus->reset)
|
||||
+ bus->reset(bus);
|
||||
+
|
||||
for (i = 0; i < PHY_MAX_ADDR; i++) {
|
||||
if ((bus->phy_mask & (1 << i)) == 0) {
|
||||
struct phy_device *phydev;
|
@ -1,34 +0,0 @@
|
||||
From dc90895d776d7b8017bc3b14f588d569d8edbe1f Mon Sep 17 00:00:00 2001
|
||||
From: Jonas Gorski <jonas.gorski@gmail.com>
|
||||
Date: Thu, 11 May 2017 13:36:52 +0200
|
||||
Subject: [PATCH] leds: bcm6328: fix signal source assignment for high leds
|
||||
|
||||
Each nibble represents 4 LEDs, and in case of the higher register, bit 0
|
||||
represents LED 4, so we need to use modulus for the LED number as well.
|
||||
|
||||
Fixes: fd7b025a238d0a5440bfa26c585eb78097bf48dc ("leds: add BCM6328 LED driver")
|
||||
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
|
||||
---
|
||||
drivers/leds/leds-bcm6328.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/leds/leds-bcm6328.c
|
||||
+++ b/drivers/leds/leds-bcm6328.c
|
||||
@@ -224,7 +224,7 @@ static int bcm6328_hwled(struct device *
|
||||
|
||||
spin_lock_irqsave(lock, flags);
|
||||
val = bcm6328_led_read(addr);
|
||||
- val |= (BIT(reg) << (((sel % 4) * 4) + 16));
|
||||
+ val |= (BIT(reg % 4) << (((sel % 4) * 4) + 16));
|
||||
bcm6328_led_write(addr, val);
|
||||
spin_unlock_irqrestore(lock, flags);
|
||||
}
|
||||
@@ -251,7 +251,7 @@ static int bcm6328_hwled(struct device *
|
||||
|
||||
spin_lock_irqsave(lock, flags);
|
||||
val = bcm6328_led_read(addr);
|
||||
- val |= (BIT(reg) << ((sel % 4) * 4));
|
||||
+ val |= (BIT(reg % 4) << ((sel % 4) * 4));
|
||||
bcm6328_led_write(addr, val);
|
||||
spin_unlock_irqrestore(lock, flags);
|
||||
}
|
@ -1,120 +0,0 @@
|
||||
From d396e84c56047b303cac378dde4b2e5cc430b336 Mon Sep 17 00:00:00 2001
|
||||
From: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
|
||||
Date: Mon, 12 Jun 2017 23:55:38 +0300
|
||||
Subject: [PATCH] mdio_bus: handle only single PHY reset GPIO
|
||||
|
||||
Commit 4c5e7a2c0501 ("dt-bindings: mdio: Clarify binding document")
|
||||
declared that a MDIO reset GPIO property should have only a single GPIO
|
||||
reference/specifier, however the supporting code was left intact, still
|
||||
burdening the kernel with now apparently useless loops -- get rid of them.
|
||||
|
||||
Signed-off-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/phy/mdio_bus.c | 53 +++++++++++++++++-----------------------------
|
||||
drivers/of/of_mdio.c | 1 -
|
||||
include/linux/phy.h | 6 ++----
|
||||
3 files changed, 21 insertions(+), 39 deletions(-)
|
||||
|
||||
--- a/drivers/net/phy/mdio_bus.c
|
||||
+++ b/drivers/net/phy/mdio_bus.c
|
||||
@@ -279,33 +279,22 @@ int __mdiobus_register(struct mii_bus *b
|
||||
|
||||
mutex_init(&bus->mdio_lock);
|
||||
|
||||
- /* de-assert bus level PHY GPIO resets */
|
||||
- if (bus->num_reset_gpios > 0) {
|
||||
- bus->reset_gpiod = devm_kcalloc(&bus->dev,
|
||||
- bus->num_reset_gpios,
|
||||
- sizeof(struct gpio_desc *),
|
||||
- GFP_KERNEL);
|
||||
- if (!bus->reset_gpiod)
|
||||
- return -ENOMEM;
|
||||
- }
|
||||
-
|
||||
- for (i = 0; i < bus->num_reset_gpios; i++) {
|
||||
- gpiod = devm_gpiod_get_index(&bus->dev, "reset", i,
|
||||
- GPIOD_OUT_LOW);
|
||||
- if (IS_ERR(gpiod)) {
|
||||
- err = PTR_ERR(gpiod);
|
||||
- if (err != -ENOENT) {
|
||||
- dev_err(&bus->dev,
|
||||
- "mii_bus %s couldn't get reset GPIO\n",
|
||||
- bus->id);
|
||||
- return err;
|
||||
- }
|
||||
- } else {
|
||||
- bus->reset_gpiod[i] = gpiod;
|
||||
- gpiod_set_value_cansleep(gpiod, 1);
|
||||
- udelay(bus->reset_delay_us);
|
||||
- gpiod_set_value_cansleep(gpiod, 0);
|
||||
+ /* de-assert bus level PHY GPIO reset */
|
||||
+ gpiod = devm_gpiod_get(&bus->dev, "reset", GPIOD_OUT_LOW);
|
||||
+ if (IS_ERR(gpiod)) {
|
||||
+ err = PTR_ERR(gpiod);
|
||||
+ if (err != -ENOENT) {
|
||||
+ dev_err(&bus->dev,
|
||||
+ "mii_bus %s couldn't get reset GPIO\n",
|
||||
+ bus->id);
|
||||
+ return err;
|
||||
}
|
||||
+ } else {
|
||||
+ bus->reset_gpiod = gpiod;
|
||||
+
|
||||
+ gpiod_set_value_cansleep(gpiod, 1);
|
||||
+ udelay(bus->reset_delay_us);
|
||||
+ gpiod_set_value_cansleep(gpiod, 0);
|
||||
}
|
||||
|
||||
if (bus->reset)
|
||||
@@ -337,10 +326,8 @@ error:
|
||||
}
|
||||
|
||||
/* Put PHYs in RESET to save power */
|
||||
- for (i = 0; i < bus->num_reset_gpios; i++) {
|
||||
- if (bus->reset_gpiod[i])
|
||||
- gpiod_set_value_cansleep(bus->reset_gpiod[i], 1);
|
||||
- }
|
||||
+ if (bus->reset_gpiod)
|
||||
+ gpiod_set_value_cansleep(bus->reset_gpiod, 1);
|
||||
|
||||
device_del(&bus->dev);
|
||||
return err;
|
||||
@@ -363,10 +350,8 @@ void mdiobus_unregister(struct mii_bus *
|
||||
}
|
||||
|
||||
/* Put PHYs in RESET to save power */
|
||||
- for (i = 0; i < bus->num_reset_gpios; i++) {
|
||||
- if (bus->reset_gpiod[i])
|
||||
- gpiod_set_value_cansleep(bus->reset_gpiod[i], 1);
|
||||
- }
|
||||
+ if (bus->reset_gpiod)
|
||||
+ gpiod_set_value_cansleep(bus->reset_gpiod, 1);
|
||||
|
||||
device_del(&bus->dev);
|
||||
}
|
||||
--- a/drivers/of/of_mdio.c
|
||||
+++ b/drivers/of/of_mdio.c
|
||||
@@ -145,7 +145,6 @@ int of_mdiobus_register(struct mii_bus *
|
||||
/* Get bus level PHY reset GPIO details */
|
||||
mdio->reset_delay_us = DEFAULT_GPIO_RESET_DELAY;
|
||||
of_property_read_u32(np, "reset-delay-us", &mdio->reset_delay_us);
|
||||
- mdio->num_reset_gpios = of_gpio_named_count(np, "reset-gpios");
|
||||
|
||||
/* Register the MDIO bus */
|
||||
rc = mdiobus_register(mdio);
|
||||
--- a/include/linux/phy.h
|
||||
+++ b/include/linux/phy.h
|
||||
@@ -190,10 +190,8 @@ struct mii_bus {
|
||||
|
||||
/* GPIO reset pulse width in microseconds */
|
||||
int reset_delay_us;
|
||||
- /* Number of reset GPIOs */
|
||||
- int num_reset_gpios;
|
||||
- /* Array of RESET GPIO descriptors */
|
||||
- struct gpio_desc **reset_gpiod;
|
||||
+ /* RESET GPIO descriptor pointer */
|
||||
+ struct gpio_desc *reset_gpiod;
|
||||
};
|
||||
#define to_mii_bus(d) container_of(d, struct mii_bus, dev)
|
||||
|
@ -1,39 +0,0 @@
|
||||
From fe0e4052fb11d5c713961ab7e136520be40052a3 Mon Sep 17 00:00:00 2001
|
||||
From: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
|
||||
Date: Mon, 12 Jun 2017 23:55:39 +0300
|
||||
Subject: [PATCH] mdio_bus: use devm_gpiod_get_optional()
|
||||
|
||||
The MDIO reset GPIO is really a classical optional GPIO property case,
|
||||
so devm_gpiod_get_optional() should have been used, not devm_gpiod_get().
|
||||
Doing this saves several LoCs...
|
||||
|
||||
Signed-off-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/phy/mdio_bus.c | 14 +++++---------
|
||||
1 file changed, 5 insertions(+), 9 deletions(-)
|
||||
|
||||
--- a/drivers/net/phy/mdio_bus.c
|
||||
+++ b/drivers/net/phy/mdio_bus.c
|
||||
@@ -280,16 +280,12 @@ int __mdiobus_register(struct mii_bus *b
|
||||
mutex_init(&bus->mdio_lock);
|
||||
|
||||
/* de-assert bus level PHY GPIO reset */
|
||||
- gpiod = devm_gpiod_get(&bus->dev, "reset", GPIOD_OUT_LOW);
|
||||
+ gpiod = devm_gpiod_get_optional(&bus->dev, "reset", GPIOD_OUT_LOW);
|
||||
if (IS_ERR(gpiod)) {
|
||||
- err = PTR_ERR(gpiod);
|
||||
- if (err != -ENOENT) {
|
||||
- dev_err(&bus->dev,
|
||||
- "mii_bus %s couldn't get reset GPIO\n",
|
||||
- bus->id);
|
||||
- return err;
|
||||
- }
|
||||
- } else {
|
||||
+ dev_err(&bus->dev, "mii_bus %s couldn't get reset GPIO\n",
|
||||
+ bus->id);
|
||||
+ return PTR_ERR(gpiod);
|
||||
+ } else if (gpiod) {
|
||||
bus->reset_gpiod = gpiod;
|
||||
|
||||
gpiod_set_value_cansleep(gpiod, 1);
|
@ -1,210 +0,0 @@
|
||||
From e74caf41aec5338b8cbbd0a1483650848f16f532 Mon Sep 17 00:00:00 2001
|
||||
From: Jonas Gorski <jonas.gorski@gmail.com>
|
||||
Date: Sun, 16 Jul 2017 12:23:47 +0200
|
||||
Subject: [PATCH V2 1/8] MIPS: BCM63XX: add clkdev lookup support
|
||||
|
||||
Enable clkdev lookup support to allow us providing clocks under
|
||||
different names to devices more easily, so we don't need to care
|
||||
about clock name clashes anymore.
|
||||
|
||||
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
|
||||
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
|
||||
---
|
||||
arch/mips/Kconfig | 1 +
|
||||
arch/mips/bcm63xx/clk.c | 150 +++++++++++++++++++++++++++++++++++++-----------
|
||||
2 files changed, 116 insertions(+), 35 deletions(-)
|
||||
|
||||
--- a/arch/mips/Kconfig
|
||||
+++ b/arch/mips/Kconfig
|
||||
@@ -214,6 +214,7 @@ config BCM63XX
|
||||
select ARCH_REQUIRE_GPIOLIB
|
||||
select HAVE_CLK
|
||||
select MIPS_L1_CACHE_SHIFT_4
|
||||
+ select CLKDEV_LOOKUP
|
||||
help
|
||||
Support for BCM63XX based boards
|
||||
|
||||
--- a/arch/mips/bcm63xx/clk.c
|
||||
+++ b/arch/mips/bcm63xx/clk.c
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/clk.h>
|
||||
+#include <linux/clkdev.h>
|
||||
#include <linux/delay.h>
|
||||
#include <bcm63xx_cpu.h>
|
||||
#include <bcm63xx_io.h>
|
||||
@@ -352,44 +353,103 @@ long clk_round_rate(struct clk *clk, uns
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(clk_round_rate);
|
||||
|
||||
-struct clk *clk_get(struct device *dev, const char *id)
|
||||
-{
|
||||
- if (!strcmp(id, "enet0"))
|
||||
- return &clk_enet0;
|
||||
- if (!strcmp(id, "enet1"))
|
||||
- return &clk_enet1;
|
||||
- if (!strcmp(id, "enetsw"))
|
||||
- return &clk_enetsw;
|
||||
- if (!strcmp(id, "ephy"))
|
||||
- return &clk_ephy;
|
||||
- if (!strcmp(id, "usbh"))
|
||||
- return &clk_usbh;
|
||||
- if (!strcmp(id, "usbd"))
|
||||
- return &clk_usbd;
|
||||
- if (!strcmp(id, "spi"))
|
||||
- return &clk_spi;
|
||||
- if (!strcmp(id, "hsspi"))
|
||||
- return &clk_hsspi;
|
||||
- if (!strcmp(id, "xtm"))
|
||||
- return &clk_xtm;
|
||||
- if (!strcmp(id, "periph"))
|
||||
- return &clk_periph;
|
||||
- if ((BCMCPU_IS_3368() || BCMCPU_IS_6358()) && !strcmp(id, "pcm"))
|
||||
- return &clk_pcm;
|
||||
- if ((BCMCPU_IS_6362() || BCMCPU_IS_6368()) && !strcmp(id, "ipsec"))
|
||||
- return &clk_ipsec;
|
||||
- if ((BCMCPU_IS_6328() || BCMCPU_IS_6362()) && !strcmp(id, "pcie"))
|
||||
- return &clk_pcie;
|
||||
- return ERR_PTR(-ENOENT);
|
||||
-}
|
||||
-
|
||||
-EXPORT_SYMBOL(clk_get);
|
||||
-
|
||||
-void clk_put(struct clk *clk)
|
||||
-{
|
||||
-}
|
||||
-
|
||||
-EXPORT_SYMBOL(clk_put);
|
||||
+static struct clk_lookup bcm3368_clks[] = {
|
||||
+ /* fixed rate clocks */
|
||||
+ CLKDEV_INIT(NULL, "periph", &clk_periph),
|
||||
+ /* gated clocks */
|
||||
+ CLKDEV_INIT(NULL, "enet0", &clk_enet0),
|
||||
+ CLKDEV_INIT(NULL, "enet1", &clk_enet1),
|
||||
+ CLKDEV_INIT(NULL, "ephy", &clk_ephy),
|
||||
+ CLKDEV_INIT(NULL, "usbh", &clk_usbh),
|
||||
+ CLKDEV_INIT(NULL, "usbd", &clk_usbd),
|
||||
+ CLKDEV_INIT(NULL, "spi", &clk_spi),
|
||||
+ CLKDEV_INIT(NULL, "pcm", &clk_pcm),
|
||||
+};
|
||||
+
|
||||
+static struct clk_lookup bcm6328_clks[] = {
|
||||
+ /* fixed rate clocks */
|
||||
+ CLKDEV_INIT(NULL, "periph", &clk_periph),
|
||||
+ /* gated clocks */
|
||||
+ CLKDEV_INIT(NULL, "enetsw", &clk_enetsw),
|
||||
+ CLKDEV_INIT(NULL, "usbh", &clk_usbh),
|
||||
+ CLKDEV_INIT(NULL, "usbd", &clk_usbd),
|
||||
+ CLKDEV_INIT(NULL, "hsspi", &clk_hsspi),
|
||||
+ CLKDEV_INIT(NULL, "pcie", &clk_pcie),
|
||||
+};
|
||||
+
|
||||
+static struct clk_lookup bcm6338_clks[] = {
|
||||
+ /* fixed rate clocks */
|
||||
+ CLKDEV_INIT(NULL, "periph", &clk_periph),
|
||||
+ /* gated clocks */
|
||||
+ CLKDEV_INIT(NULL, "enet0", &clk_enet0),
|
||||
+ CLKDEV_INIT(NULL, "enet1", &clk_enet1),
|
||||
+ CLKDEV_INIT(NULL, "ephy", &clk_ephy),
|
||||
+ CLKDEV_INIT(NULL, "usbh", &clk_usbh),
|
||||
+ CLKDEV_INIT(NULL, "usbd", &clk_usbd),
|
||||
+ CLKDEV_INIT(NULL, "spi", &clk_spi),
|
||||
+};
|
||||
+
|
||||
+static struct clk_lookup bcm6345_clks[] = {
|
||||
+ /* fixed rate clocks */
|
||||
+ CLKDEV_INIT(NULL, "periph", &clk_periph),
|
||||
+ /* gated clocks */
|
||||
+ CLKDEV_INIT(NULL, "enet0", &clk_enet0),
|
||||
+ CLKDEV_INIT(NULL, "enet1", &clk_enet1),
|
||||
+ CLKDEV_INIT(NULL, "ephy", &clk_ephy),
|
||||
+ CLKDEV_INIT(NULL, "usbh", &clk_usbh),
|
||||
+ CLKDEV_INIT(NULL, "usbd", &clk_usbd),
|
||||
+ CLKDEV_INIT(NULL, "spi", &clk_spi),
|
||||
+};
|
||||
+
|
||||
+static struct clk_lookup bcm6348_clks[] = {
|
||||
+ /* fixed rate clocks */
|
||||
+ CLKDEV_INIT(NULL, "periph", &clk_periph),
|
||||
+ /* gated clocks */
|
||||
+ CLKDEV_INIT(NULL, "enet0", &clk_enet0),
|
||||
+ CLKDEV_INIT(NULL, "enet1", &clk_enet1),
|
||||
+ CLKDEV_INIT(NULL, "ephy", &clk_ephy),
|
||||
+ CLKDEV_INIT(NULL, "usbh", &clk_usbh),
|
||||
+ CLKDEV_INIT(NULL, "usbd", &clk_usbd),
|
||||
+ CLKDEV_INIT(NULL, "spi", &clk_spi),
|
||||
+};
|
||||
+
|
||||
+static struct clk_lookup bcm6358_clks[] = {
|
||||
+ /* fixed rate clocks */
|
||||
+ CLKDEV_INIT(NULL, "periph", &clk_periph),
|
||||
+ /* gated clocks */
|
||||
+ CLKDEV_INIT(NULL, "enet0", &clk_enet0),
|
||||
+ CLKDEV_INIT(NULL, "enet1", &clk_enet1),
|
||||
+ CLKDEV_INIT(NULL, "ephy", &clk_ephy),
|
||||
+ CLKDEV_INIT(NULL, "usbh", &clk_usbh),
|
||||
+ CLKDEV_INIT(NULL, "usbd", &clk_usbd),
|
||||
+ CLKDEV_INIT(NULL, "spi", &clk_spi),
|
||||
+ CLKDEV_INIT(NULL, "pcm", &clk_pcm),
|
||||
+};
|
||||
+
|
||||
+static struct clk_lookup bcm6362_clks[] = {
|
||||
+ /* fixed rate clocks */
|
||||
+ CLKDEV_INIT(NULL, "periph", &clk_periph),
|
||||
+ /* gated clocks */
|
||||
+ CLKDEV_INIT(NULL, "enetsw", &clk_enetsw),
|
||||
+ CLKDEV_INIT(NULL, "usbh", &clk_usbh),
|
||||
+ CLKDEV_INIT(NULL, "usbd", &clk_usbd),
|
||||
+ CLKDEV_INIT(NULL, "spi", &clk_spi),
|
||||
+ CLKDEV_INIT(NULL, "hsspi", &clk_hsspi),
|
||||
+ CLKDEV_INIT(NULL, "pcie", &clk_pcie),
|
||||
+ CLKDEV_INIT(NULL, "ipsec", &clk_ipsec),
|
||||
+};
|
||||
+
|
||||
+static struct clk_lookup bcm6368_clks[] = {
|
||||
+ /* fixed rate clocks */
|
||||
+ CLKDEV_INIT(NULL, "periph", &clk_periph),
|
||||
+ /* gated clocks */
|
||||
+ CLKDEV_INIT(NULL, "enetsw", &clk_enetsw),
|
||||
+ CLKDEV_INIT(NULL, "usbh", &clk_usbh),
|
||||
+ CLKDEV_INIT(NULL, "usbd", &clk_usbd),
|
||||
+ CLKDEV_INIT(NULL, "spi", &clk_spi),
|
||||
+ CLKDEV_INIT(NULL, "xtm", &clk_xtm),
|
||||
+ CLKDEV_INIT(NULL, "ipsec", &clk_ipsec),
|
||||
+};
|
||||
|
||||
#define HSSPI_PLL_HZ_6328 133333333
|
||||
#define HSSPI_PLL_HZ_6362 400000000
|
||||
@@ -397,11 +457,31 @@ EXPORT_SYMBOL(clk_put);
|
||||
static int __init bcm63xx_clk_init(void)
|
||||
{
|
||||
switch (bcm63xx_get_cpu_id()) {
|
||||
+ case BCM3368_CPU_ID:
|
||||
+ clkdev_add_table(bcm3368_clks, ARRAY_SIZE(bcm3368_clks));
|
||||
+ break;
|
||||
case BCM6328_CPU_ID:
|
||||
clk_hsspi.rate = HSSPI_PLL_HZ_6328;
|
||||
+ clkdev_add_table(bcm6328_clks, ARRAY_SIZE(bcm6328_clks));
|
||||
+ break;
|
||||
+ case BCM6338_CPU_ID:
|
||||
+ clkdev_add_table(bcm6338_clks, ARRAY_SIZE(bcm6338_clks));
|
||||
+ break;
|
||||
+ case BCM6345_CPU_ID:
|
||||
+ clkdev_add_table(bcm6345_clks, ARRAY_SIZE(bcm6345_clks));
|
||||
+ break;
|
||||
+ case BCM6348_CPU_ID:
|
||||
+ clkdev_add_table(bcm6348_clks, ARRAY_SIZE(bcm6348_clks));
|
||||
+ break;
|
||||
+ case BCM6358_CPU_ID:
|
||||
+ clkdev_add_table(bcm6358_clks, ARRAY_SIZE(bcm6358_clks));
|
||||
break;
|
||||
case BCM6362_CPU_ID:
|
||||
clk_hsspi.rate = HSSPI_PLL_HZ_6362;
|
||||
+ clkdev_add_table(bcm6362_clks, ARRAY_SIZE(bcm6362_clks));
|
||||
+ break;
|
||||
+ case BCM6368_CPU_ID:
|
||||
+ clkdev_add_table(bcm6368_clks, ARRAY_SIZE(bcm6368_clks));
|
||||
break;
|
||||
}
|
||||
|
@ -1,84 +0,0 @@
|
||||
From d0322bf7bebe87012b4f95c85be6b5ba0cb6f344 Mon Sep 17 00:00:00 2001
|
||||
From: Jonas Gorski <jonas.gorski@gmail.com>
|
||||
Date: Sun, 16 Jul 2017 12:31:44 +0200
|
||||
Subject: [PATCH V2 2/8] MIPS: BCM63XX: provide periph clock as refclk for uart
|
||||
|
||||
Add a lookup as "refclk" to describe its function for the uarts.
|
||||
|
||||
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
|
||||
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
|
||||
---
|
||||
arch/mips/bcm63xx/clk.c | 13 +++++++++++++
|
||||
1 file changed, 13 insertions(+)
|
||||
|
||||
--- a/arch/mips/bcm63xx/clk.c
|
||||
+++ b/arch/mips/bcm63xx/clk.c
|
||||
@@ -356,6 +356,8 @@ EXPORT_SYMBOL_GPL(clk_round_rate);
|
||||
static struct clk_lookup bcm3368_clks[] = {
|
||||
/* fixed rate clocks */
|
||||
CLKDEV_INIT(NULL, "periph", &clk_periph),
|
||||
+ CLKDEV_INIT("bcm63xx_uart.0", "refclk", &clk_periph),
|
||||
+ CLKDEV_INIT("bcm63xx_uart.1", "refclk", &clk_periph),
|
||||
/* gated clocks */
|
||||
CLKDEV_INIT(NULL, "enet0", &clk_enet0),
|
||||
CLKDEV_INIT(NULL, "enet1", &clk_enet1),
|
||||
@@ -369,6 +371,8 @@ static struct clk_lookup bcm3368_clks[]
|
||||
static struct clk_lookup bcm6328_clks[] = {
|
||||
/* fixed rate clocks */
|
||||
CLKDEV_INIT(NULL, "periph", &clk_periph),
|
||||
+ CLKDEV_INIT("bcm63xx_uart.0", "refclk", &clk_periph),
|
||||
+ CLKDEV_INIT("bcm63xx_uart.1", "refclk", &clk_periph),
|
||||
/* gated clocks */
|
||||
CLKDEV_INIT(NULL, "enetsw", &clk_enetsw),
|
||||
CLKDEV_INIT(NULL, "usbh", &clk_usbh),
|
||||
@@ -380,6 +384,7 @@ static struct clk_lookup bcm6328_clks[]
|
||||
static struct clk_lookup bcm6338_clks[] = {
|
||||
/* fixed rate clocks */
|
||||
CLKDEV_INIT(NULL, "periph", &clk_periph),
|
||||
+ CLKDEV_INIT("bcm63xx_uart.0", "refclk", &clk_periph),
|
||||
/* gated clocks */
|
||||
CLKDEV_INIT(NULL, "enet0", &clk_enet0),
|
||||
CLKDEV_INIT(NULL, "enet1", &clk_enet1),
|
||||
@@ -392,6 +397,7 @@ static struct clk_lookup bcm6338_clks[]
|
||||
static struct clk_lookup bcm6345_clks[] = {
|
||||
/* fixed rate clocks */
|
||||
CLKDEV_INIT(NULL, "periph", &clk_periph),
|
||||
+ CLKDEV_INIT("bcm63xx_uart.0", "refclk", &clk_periph),
|
||||
/* gated clocks */
|
||||
CLKDEV_INIT(NULL, "enet0", &clk_enet0),
|
||||
CLKDEV_INIT(NULL, "enet1", &clk_enet1),
|
||||
@@ -404,6 +410,7 @@ static struct clk_lookup bcm6345_clks[]
|
||||
static struct clk_lookup bcm6348_clks[] = {
|
||||
/* fixed rate clocks */
|
||||
CLKDEV_INIT(NULL, "periph", &clk_periph),
|
||||
+ CLKDEV_INIT("bcm63xx_uart.0", "refclk", &clk_periph),
|
||||
/* gated clocks */
|
||||
CLKDEV_INIT(NULL, "enet0", &clk_enet0),
|
||||
CLKDEV_INIT(NULL, "enet1", &clk_enet1),
|
||||
@@ -416,6 +423,8 @@ static struct clk_lookup bcm6348_clks[]
|
||||
static struct clk_lookup bcm6358_clks[] = {
|
||||
/* fixed rate clocks */
|
||||
CLKDEV_INIT(NULL, "periph", &clk_periph),
|
||||
+ CLKDEV_INIT("bcm63xx_uart.0", "refclk", &clk_periph),
|
||||
+ CLKDEV_INIT("bcm63xx_uart.1", "refclk", &clk_periph),
|
||||
/* gated clocks */
|
||||
CLKDEV_INIT(NULL, "enet0", &clk_enet0),
|
||||
CLKDEV_INIT(NULL, "enet1", &clk_enet1),
|
||||
@@ -429,6 +438,8 @@ static struct clk_lookup bcm6358_clks[]
|
||||
static struct clk_lookup bcm6362_clks[] = {
|
||||
/* fixed rate clocks */
|
||||
CLKDEV_INIT(NULL, "periph", &clk_periph),
|
||||
+ CLKDEV_INIT("bcm63xx_uart.0", "refclk", &clk_periph),
|
||||
+ CLKDEV_INIT("bcm63xx_uart.1", "refclk", &clk_periph),
|
||||
/* gated clocks */
|
||||
CLKDEV_INIT(NULL, "enetsw", &clk_enetsw),
|
||||
CLKDEV_INIT(NULL, "usbh", &clk_usbh),
|
||||
@@ -442,6 +453,8 @@ static struct clk_lookup bcm6362_clks[]
|
||||
static struct clk_lookup bcm6368_clks[] = {
|
||||
/* fixed rate clocks */
|
||||
CLKDEV_INIT(NULL, "periph", &clk_periph),
|
||||
+ CLKDEV_INIT("bcm63xx_uart.0", "refclk", &clk_periph),
|
||||
+ CLKDEV_INIT("bcm63xx_uart.1", "refclk", &clk_periph),
|
||||
/* gated clocks */
|
||||
CLKDEV_INIT(NULL, "enetsw", &clk_enetsw),
|
||||
CLKDEV_INIT(NULL, "usbh", &clk_usbh),
|
@ -1,26 +0,0 @@
|
||||
From 8124706e6040b1cf0d2dd3a05759df6cec4bddfb Mon Sep 17 00:00:00 2001
|
||||
From: Jonas Gorski <jonas.gorski@gmail.com>
|
||||
Date: Sun, 16 Jul 2017 12:32:37 +0200
|
||||
Subject: [PATCH V2 3/8] tty/bcm63xx_uart: use refclk for the expected clock
|
||||
name
|
||||
|
||||
We now have the clock available under refclk, so use that.
|
||||
|
||||
Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
|
||||
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
|
||||
---
|
||||
drivers/tty/serial/bcm63xx_uart.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/tty/serial/bcm63xx_uart.c
|
||||
+++ b/drivers/tty/serial/bcm63xx_uart.c
|
||||
@@ -842,7 +842,7 @@ static int bcm_uart_probe(struct platfor
|
||||
return -ENODEV;
|
||||
|
||||
clk = pdev->dev.of_node ? of_clk_get(pdev->dev.of_node, 0) :
|
||||
- clk_get(&pdev->dev, "periph");
|
||||
+ clk_get(&pdev->dev, "refclk");
|
||||
if (IS_ERR(clk))
|
||||
return -ENODEV;
|
||||
|
@ -1,55 +0,0 @@
|
||||
From 317f8659bba01b307cbe4e9902d4e3d333fd7164 Mon Sep 17 00:00:00 2001
|
||||
From: Jonas Gorski <jonas.gorski@gmail.com>
|
||||
Date: Sun, 16 Jul 2017 12:39:17 +0200
|
||||
Subject: [PATCH V2 4/8] tty/bcm63xx_uart: allow naming clock in device tree
|
||||
|
||||
Codify using a named clock for the refclk of the uart. This makes it
|
||||
easier if we might need to add a gating clock (like present on the
|
||||
BCM6345).
|
||||
|
||||
Acked-by: Rob Herring <robh@kernel.org>
|
||||
Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
|
||||
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
|
||||
---
|
||||
Documentation/devicetree/bindings/serial/brcm,bcm6345-uart.txt | 6 ++++++
|
||||
drivers/tty/serial/bcm63xx_uart.c | 6 ++++--
|
||||
2 files changed, 10 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/Documentation/devicetree/bindings/serial/brcm,bcm6345-uart.txt
|
||||
+++ b/Documentation/devicetree/bindings/serial/brcm,bcm6345-uart.txt
|
||||
@@ -11,6 +11,11 @@ Required properties:
|
||||
- clocks: Clock driving the hardware; used to figure out the baud rate
|
||||
divisor.
|
||||
|
||||
+
|
||||
+Optional properties:
|
||||
+
|
||||
+- clock-names: Should be "refclk".
|
||||
+
|
||||
Example:
|
||||
|
||||
uart0: serial@14e00520 {
|
||||
@@ -19,6 +24,7 @@ Example:
|
||||
interrupt-parent = <&periph_intc>;
|
||||
interrupts = <2>;
|
||||
clocks = <&periph_clk>;
|
||||
+ clock-names = "refclk";
|
||||
};
|
||||
|
||||
clocks {
|
||||
--- a/drivers/tty/serial/bcm63xx_uart.c
|
||||
+++ b/drivers/tty/serial/bcm63xx_uart.c
|
||||
@@ -841,8 +841,10 @@ static int bcm_uart_probe(struct platfor
|
||||
if (!res_irq)
|
||||
return -ENODEV;
|
||||
|
||||
- clk = pdev->dev.of_node ? of_clk_get(pdev->dev.of_node, 0) :
|
||||
- clk_get(&pdev->dev, "refclk");
|
||||
+ clk = clk_get(&pdev->dev, "refclk");
|
||||
+ if (IS_ERR(clk) && pdev->dev.of_node)
|
||||
+ clk = of_clk_get(pdev->dev.of_node, 0);
|
||||
+
|
||||
if (IS_ERR(clk))
|
||||
return -ENODEV;
|
||||
|
@ -1,62 +0,0 @@
|
||||
From cb86630379c8f3432c916d62045b5176f17f4123 Mon Sep 17 00:00:00 2001
|
||||
From: Jonas Gorski <jonas.gorski@gmail.com>
|
||||
Date: Sun, 16 Jul 2017 12:57:21 +0200
|
||||
Subject: [PATCH V2 6/8] MIPS: BCM63XX: move the HSSPI PLL HZ into its own
|
||||
clock
|
||||
|
||||
Split up the HSSPL clock into rate and a gate clock, to more closely
|
||||
match the actual hardware.
|
||||
|
||||
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
|
||||
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
|
||||
---
|
||||
arch/mips/bcm63xx/clk.c | 10 ++++++++--
|
||||
1 file changed, 8 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/arch/mips/bcm63xx/clk.c
|
||||
+++ b/arch/mips/bcm63xx/clk.c
|
||||
@@ -247,6 +247,10 @@ static struct clk clk_hsspi = {
|
||||
.set = hsspi_set,
|
||||
};
|
||||
|
||||
+/*
|
||||
+ * HSSPI PLL
|
||||
+ */
|
||||
+static struct clk clk_hsspi_pll;
|
||||
|
||||
/*
|
||||
* XTM clock
|
||||
@@ -373,6 +377,7 @@ static struct clk_lookup bcm6328_clks[]
|
||||
CLKDEV_INIT(NULL, "periph", &clk_periph),
|
||||
CLKDEV_INIT("bcm63xx_uart.0", "refclk", &clk_periph),
|
||||
CLKDEV_INIT("bcm63xx_uart.1", "refclk", &clk_periph),
|
||||
+ CLKDEV_INIT("bcm63xx-hsspi.0", "pll", &clk_hsspi_pll),
|
||||
/* gated clocks */
|
||||
CLKDEV_INIT(NULL, "enetsw", &clk_enetsw),
|
||||
CLKDEV_INIT(NULL, "usbh", &clk_usbh),
|
||||
@@ -440,6 +445,7 @@ static struct clk_lookup bcm6362_clks[]
|
||||
CLKDEV_INIT(NULL, "periph", &clk_periph),
|
||||
CLKDEV_INIT("bcm63xx_uart.0", "refclk", &clk_periph),
|
||||
CLKDEV_INIT("bcm63xx_uart.1", "refclk", &clk_periph),
|
||||
+ CLKDEV_INIT("bcm63xx-hsspi.0", "pll", &clk_hsspi_pll),
|
||||
/* gated clocks */
|
||||
CLKDEV_INIT(NULL, "enetsw", &clk_enetsw),
|
||||
CLKDEV_INIT(NULL, "usbh", &clk_usbh),
|
||||
@@ -474,7 +480,7 @@ static int __init bcm63xx_clk_init(void)
|
||||
clkdev_add_table(bcm3368_clks, ARRAY_SIZE(bcm3368_clks));
|
||||
break;
|
||||
case BCM6328_CPU_ID:
|
||||
- clk_hsspi.rate = HSSPI_PLL_HZ_6328;
|
||||
+ clk_hsspi_pll.rate = HSSPI_PLL_HZ_6328;
|
||||
clkdev_add_table(bcm6328_clks, ARRAY_SIZE(bcm6328_clks));
|
||||
break;
|
||||
case BCM6338_CPU_ID:
|
||||
@@ -490,7 +496,7 @@ static int __init bcm63xx_clk_init(void)
|
||||
clkdev_add_table(bcm6358_clks, ARRAY_SIZE(bcm6358_clks));
|
||||
break;
|
||||
case BCM6362_CPU_ID:
|
||||
- clk_hsspi.rate = HSSPI_PLL_HZ_6362;
|
||||
+ clk_hsspi_pll.rate = HSSPI_PLL_HZ_6362;
|
||||
clkdev_add_table(bcm6362_clks, ARRAY_SIZE(bcm6362_clks));
|
||||
break;
|
||||
case BCM6368_CPU_ID:
|
@ -1,60 +0,0 @@
|
||||
From 6d43970a2eb1c7ee88caf7328d201f9c001262e9 Mon Sep 17 00:00:00 2001
|
||||
From: Jonas Gorski <jonas.gorski@gmail.com>
|
||||
Date: Sun, 16 Jul 2017 12:48:41 +0200
|
||||
Subject: [PATCH V2 7/8] MIPS: BCM63XX: provide enet clocks as "enet" to the
|
||||
ethernet devices
|
||||
|
||||
Add lookups to provide the appropriate enetX clocks as just "enet" to
|
||||
the ethernet devices.
|
||||
|
||||
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
|
||||
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
|
||||
---
|
||||
arch/mips/bcm63xx/clk.c | 8 ++++++++
|
||||
1 file changed, 8 insertions(+)
|
||||
|
||||
--- a/arch/mips/bcm63xx/clk.c
|
||||
+++ b/arch/mips/bcm63xx/clk.c
|
||||
@@ -370,6 +370,8 @@ static struct clk_lookup bcm3368_clks[]
|
||||
CLKDEV_INIT(NULL, "usbd", &clk_usbd),
|
||||
CLKDEV_INIT(NULL, "spi", &clk_spi),
|
||||
CLKDEV_INIT(NULL, "pcm", &clk_pcm),
|
||||
+ CLKDEV_INIT("bcm63xx_enet.0", "enet", &clk_enet0),
|
||||
+ CLKDEV_INIT("bcm63xx_enet.1", "enet", &clk_enet1),
|
||||
};
|
||||
|
||||
static struct clk_lookup bcm6328_clks[] = {
|
||||
@@ -397,6 +399,7 @@ static struct clk_lookup bcm6338_clks[]
|
||||
CLKDEV_INIT(NULL, "usbh", &clk_usbh),
|
||||
CLKDEV_INIT(NULL, "usbd", &clk_usbd),
|
||||
CLKDEV_INIT(NULL, "spi", &clk_spi),
|
||||
+ CLKDEV_INIT("bcm63xx_enet.0", "enet", &clk_enet_misc),
|
||||
};
|
||||
|
||||
static struct clk_lookup bcm6345_clks[] = {
|
||||
@@ -410,6 +413,7 @@ static struct clk_lookup bcm6345_clks[]
|
||||
CLKDEV_INIT(NULL, "usbh", &clk_usbh),
|
||||
CLKDEV_INIT(NULL, "usbd", &clk_usbd),
|
||||
CLKDEV_INIT(NULL, "spi", &clk_spi),
|
||||
+ CLKDEV_INIT("bcm63xx_enet.0", "enet", &clk_enet_misc),
|
||||
};
|
||||
|
||||
static struct clk_lookup bcm6348_clks[] = {
|
||||
@@ -423,6 +427,8 @@ static struct clk_lookup bcm6348_clks[]
|
||||
CLKDEV_INIT(NULL, "usbh", &clk_usbh),
|
||||
CLKDEV_INIT(NULL, "usbd", &clk_usbd),
|
||||
CLKDEV_INIT(NULL, "spi", &clk_spi),
|
||||
+ CLKDEV_INIT("bcm63xx_enet.0", "enet", &clk_enet_misc),
|
||||
+ CLKDEV_INIT("bcm63xx_enet.1", "enet", &clk_enet_misc),
|
||||
};
|
||||
|
||||
static struct clk_lookup bcm6358_clks[] = {
|
||||
@@ -438,6 +444,8 @@ static struct clk_lookup bcm6358_clks[]
|
||||
CLKDEV_INIT(NULL, "usbd", &clk_usbd),
|
||||
CLKDEV_INIT(NULL, "spi", &clk_spi),
|
||||
CLKDEV_INIT(NULL, "pcm", &clk_pcm),
|
||||
+ CLKDEV_INIT("bcm63xx_enet.0", "enet", &clk_enet0),
|
||||
+ CLKDEV_INIT("bcm63xx_enet.1", "enet", &clk_enet1),
|
||||
};
|
||||
|
||||
static struct clk_lookup bcm6362_clks[] = {
|
@ -1,105 +0,0 @@
|
||||
From b98027285bd1fa95da0645a4234a5fc1f1a83f92 Mon Sep 17 00:00:00 2001
|
||||
From: Jonas Gorski <jonas.gorski@gmail.com>
|
||||
Date: Sun, 26 Feb 2017 11:59:52 +0100
|
||||
Subject: [PATCH V2 8/8] MIPS: BCM63XX: split out swpkt_sar/usb clocks
|
||||
|
||||
Make the secondary switch clocks their own clocks. This allows proper
|
||||
enable reference counting between SAR/XTM and the main switch clocks,
|
||||
and controlling them individually from drivers.
|
||||
|
||||
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
|
||||
---
|
||||
arch/mips/bcm63xx/clk.c | 61 +++++++++++++++++++++++++++++++++++++++++--------
|
||||
1 file changed, 51 insertions(+), 10 deletions(-)
|
||||
|
||||
--- a/arch/mips/bcm63xx/clk.c
|
||||
+++ b/arch/mips/bcm63xx/clk.c
|
||||
@@ -121,21 +121,56 @@ static struct clk clk_ephy = {
|
||||
};
|
||||
|
||||
/*
|
||||
+ * Ethernet switch SAR clock
|
||||
+ */
|
||||
+static void swpkt_sar_set(struct clk *clk, int enable)
|
||||
+{
|
||||
+ if (BCMCPU_IS_6368())
|
||||
+ bcm_hwclock_set(CKCTL_6368_SWPKT_SAR_EN, enable);
|
||||
+ else
|
||||
+ return;
|
||||
+}
|
||||
+
|
||||
+static struct clk clk_swpkt_sar = {
|
||||
+ .set = swpkt_sar_set,
|
||||
+};
|
||||
+
|
||||
+/*
|
||||
+ * Ethernet switch USB clock
|
||||
+ */
|
||||
+static void swpkt_usb_set(struct clk *clk, int enable)
|
||||
+{
|
||||
+ if (BCMCPU_IS_6368())
|
||||
+ bcm_hwclock_set(CKCTL_6368_SWPKT_USB_EN, enable);
|
||||
+ else
|
||||
+ return;
|
||||
+}
|
||||
+
|
||||
+static struct clk clk_swpkt_usb = {
|
||||
+ .set = swpkt_usb_set,
|
||||
+};
|
||||
+
|
||||
+/*
|
||||
* Ethernet switch clock
|
||||
*/
|
||||
static void enetsw_set(struct clk *clk, int enable)
|
||||
{
|
||||
- if (BCMCPU_IS_6328())
|
||||
+ if (BCMCPU_IS_6328()) {
|
||||
bcm_hwclock_set(CKCTL_6328_ROBOSW_EN, enable);
|
||||
- else if (BCMCPU_IS_6362())
|
||||
+ } else if (BCMCPU_IS_6362()) {
|
||||
bcm_hwclock_set(CKCTL_6362_ROBOSW_EN, enable);
|
||||
- else if (BCMCPU_IS_6368())
|
||||
- bcm_hwclock_set(CKCTL_6368_ROBOSW_EN |
|
||||
- CKCTL_6368_SWPKT_USB_EN |
|
||||
- CKCTL_6368_SWPKT_SAR_EN,
|
||||
- enable);
|
||||
- else
|
||||
+ } else if (BCMCPU_IS_6368()) {
|
||||
+ if (enable) {
|
||||
+ clk_enable_unlocked(&clk_swpkt_sar);
|
||||
+ clk_enable_unlocked(&clk_swpkt_usb);
|
||||
+ } else {
|
||||
+ clk_disable_unlocked(&clk_swpkt_usb);
|
||||
+ clk_disable_unlocked(&clk_swpkt_sar);
|
||||
+ }
|
||||
+ bcm_hwclock_set(CKCTL_6368_ROBOSW_EN, enable);
|
||||
+ } else {
|
||||
return;
|
||||
+ }
|
||||
|
||||
if (enable) {
|
||||
/* reset switch core afer clock change */
|
||||
@@ -260,8 +295,12 @@ static void xtm_set(struct clk *clk, int
|
||||
if (!BCMCPU_IS_6368())
|
||||
return;
|
||||
|
||||
- bcm_hwclock_set(CKCTL_6368_SAR_EN |
|
||||
- CKCTL_6368_SWPKT_SAR_EN, enable);
|
||||
+ if (enable)
|
||||
+ clk_enable_unlocked(&clk_swpkt_sar);
|
||||
+ else
|
||||
+ clk_disable_unlocked(&clk_swpkt_sar);
|
||||
+
|
||||
+ bcm_hwclock_set(CKCTL_6368_SAR_EN, enable);
|
||||
|
||||
if (enable) {
|
||||
/* reset sar core afer clock change */
|
||||
@@ -444,6 +483,8 @@ static struct clk_lookup bcm6358_clks[]
|
||||
CLKDEV_INIT(NULL, "usbd", &clk_usbd),
|
||||
CLKDEV_INIT(NULL, "spi", &clk_spi),
|
||||
CLKDEV_INIT(NULL, "pcm", &clk_pcm),
|
||||
+ CLKDEV_INIT(NULL, "swpkt_sar", &clk_swpkt_sar),
|
||||
+ CLKDEV_INIT(NULL, "swpkt_usb", &clk_swpkt_usb),
|
||||
CLKDEV_INIT("bcm63xx_enet.0", "enet", &clk_enet0),
|
||||
CLKDEV_INIT("bcm63xx_enet.1", "enet", &clk_enet1),
|
||||
};
|
@ -1,101 +0,0 @@
|
||||
From d0423d3e4fa7ae305729cb50369427f075ccb279 Mon Sep 17 00:00:00 2001
|
||||
From: Jonas Gorski <jonas.gorski@gmail.com>
|
||||
Date: Sat, 25 Feb 2017 12:41:28 +0100
|
||||
Subject: [PATCH 1/6] bcm63xx_enet: correct clock usage
|
||||
|
||||
Check the return code of prepare_enable and change one last instance of
|
||||
enable only to prepare_enable. Also properly disable and release the
|
||||
clock in error paths and on remove for enetsw.
|
||||
|
||||
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
|
||||
---
|
||||
drivers/net/ethernet/broadcom/bcm63xx_enet.c | 31 +++++++++++++++++++++-------
|
||||
1 file changed, 23 insertions(+), 8 deletions(-)
|
||||
|
||||
--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c
|
||||
+++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
|
||||
@@ -1787,7 +1787,9 @@ static int bcm_enet_probe(struct platfor
|
||||
ret = PTR_ERR(priv->mac_clk);
|
||||
goto out;
|
||||
}
|
||||
- clk_prepare_enable(priv->mac_clk);
|
||||
+ ret = clk_prepare_enable(priv->mac_clk);
|
||||
+ if (ret)
|
||||
+ goto out_put_clk_mac;
|
||||
|
||||
/* initialize default and fetch platform data */
|
||||
priv->rx_ring_size = BCMENET_DEF_RX_DESC;
|
||||
@@ -1819,9 +1821,11 @@ static int bcm_enet_probe(struct platfor
|
||||
if (IS_ERR(priv->phy_clk)) {
|
||||
ret = PTR_ERR(priv->phy_clk);
|
||||
priv->phy_clk = NULL;
|
||||
- goto out_put_clk_mac;
|
||||
+ goto out_disable_clk_mac;
|
||||
}
|
||||
- clk_prepare_enable(priv->phy_clk);
|
||||
+ ret = clk_prepare_enable(priv->phy_clk);
|
||||
+ if (ret)
|
||||
+ goto out_put_clk_phy;
|
||||
}
|
||||
|
||||
/* do minimal hardware init to be able to probe mii bus */
|
||||
@@ -1921,13 +1925,16 @@ out_free_mdio:
|
||||
out_uninit_hw:
|
||||
/* turn off mdc clock */
|
||||
enet_writel(priv, 0, ENET_MIISC_REG);
|
||||
- if (priv->phy_clk) {
|
||||
+ if (priv->phy_clk)
|
||||
clk_disable_unprepare(priv->phy_clk);
|
||||
+
|
||||
+out_put_clk_phy:
|
||||
+ if (priv->phy_clk)
|
||||
clk_put(priv->phy_clk);
|
||||
- }
|
||||
|
||||
-out_put_clk_mac:
|
||||
+out_disable_clk_mac:
|
||||
clk_disable_unprepare(priv->mac_clk);
|
||||
+out_put_clk_mac:
|
||||
clk_put(priv->mac_clk);
|
||||
out:
|
||||
free_netdev(dev);
|
||||
@@ -2772,7 +2779,9 @@ static int bcm_enetsw_probe(struct platf
|
||||
ret = PTR_ERR(priv->mac_clk);
|
||||
goto out_unmap;
|
||||
}
|
||||
- clk_enable(priv->mac_clk);
|
||||
+ ret = clk_prepare_enable(priv->mac_clk);
|
||||
+ if (ret)
|
||||
+ goto out_put_clk;
|
||||
|
||||
priv->rx_chan = 0;
|
||||
priv->tx_chan = 1;
|
||||
@@ -2793,7 +2802,7 @@ static int bcm_enetsw_probe(struct platf
|
||||
|
||||
ret = register_netdev(dev);
|
||||
if (ret)
|
||||
- goto out_put_clk;
|
||||
+ goto out_disable_clk;
|
||||
|
||||
netif_carrier_off(dev);
|
||||
platform_set_drvdata(pdev, dev);
|
||||
@@ -2802,6 +2811,9 @@ static int bcm_enetsw_probe(struct platf
|
||||
|
||||
return 0;
|
||||
|
||||
+out_disable_clk:
|
||||
+ clk_disable_unprepare(priv->mac_clk);
|
||||
+
|
||||
out_put_clk:
|
||||
clk_put(priv->mac_clk);
|
||||
|
||||
@@ -2833,6 +2845,9 @@ static int bcm_enetsw_remove(struct plat
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
release_mem_region(res->start, resource_size(res));
|
||||
|
||||
+ clk_disable_unprepare(priv->mac_clk);
|
||||
+ clk_put(priv->mac_clk);
|
||||
+
|
||||
free_netdev(dev);
|
||||
return 0;
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
From 23d94cb855b6f4f0ee1c01679224472104ac6440 Mon Sep 17 00:00:00 2001
|
||||
From: Jonas Gorski <jonas.gorski@gmail.com>
|
||||
Date: Sat, 30 Sep 2017 14:10:18 +0200
|
||||
Subject: [PATCH 2/6] bcm63xx_enet: do not write to random DMA channel on
|
||||
BCM6345
|
||||
|
||||
The DMA controller regs actually point to DMA channel 0, so the write to
|
||||
ENETDMA_CFG_REG will actually modify a random DMA channel.
|
||||
|
||||
Since DMA controller registers do not exist on BCM6345, guard the write
|
||||
with the usual check for dma_has_sram.
|
||||
|
||||
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
|
||||
---
|
||||
drivers/net/ethernet/broadcom/bcm63xx_enet.c | 3 ++-
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c
|
||||
+++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
|
||||
@@ -1063,7 +1063,8 @@ static int bcm_enet_open(struct net_devi
|
||||
val = enet_readl(priv, ENET_CTL_REG);
|
||||
val |= ENET_CTL_ENABLE_MASK;
|
||||
enet_writel(priv, val, ENET_CTL_REG);
|
||||
- enet_dma_writel(priv, ENETDMA_CFG_EN_MASK, ENETDMA_CFG_REG);
|
||||
+ if (priv->dma_has_sram)
|
||||
+ enet_dma_writel(priv, ENETDMA_CFG_EN_MASK, ENETDMA_CFG_REG);
|
||||
enet_dmac_writel(priv, priv->dma_chan_en_mask,
|
||||
ENETDMAC_CHANCFG, priv->rx_chan);
|
||||
|
@ -1,41 +0,0 @@
|
||||
From 71710bb6cbc82f411a4e5faafa0c3178e48e7137 Mon Sep 17 00:00:00 2001
|
||||
From: Jonas Gorski <jonas.gorski@gmail.com>
|
||||
Date: Tue, 30 May 2017 13:31:45 +0200
|
||||
Subject: [PATCH 3/6] bcm63xx_enet: do not rely on probe order
|
||||
|
||||
Do not rely on the shared device being probed before the enet(sw)
|
||||
devices. This makes it easier to eventually move out the shared
|
||||
device as a dma controller driver (what it should be).
|
||||
|
||||
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
|
||||
---
|
||||
drivers/net/ethernet/broadcom/bcm63xx_enet.c | 9 ++-------
|
||||
1 file changed, 2 insertions(+), 7 deletions(-)
|
||||
|
||||
--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c
|
||||
+++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
|
||||
@@ -1736,10 +1736,8 @@ static int bcm_enet_probe(struct platfor
|
||||
const char *clk_name;
|
||||
int i, ret;
|
||||
|
||||
- /* stop if shared driver failed, assume driver->probe will be
|
||||
- * called in the same order we register devices (correct ?) */
|
||||
if (!bcm_enet_shared_base[0])
|
||||
- return -ENODEV;
|
||||
+ return -EPROBE_DEFER;
|
||||
|
||||
res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
|
||||
res_irq_rx = platform_get_resource(pdev, IORESOURCE_IRQ, 1);
|
||||
@@ -2720,11 +2718,8 @@ static int bcm_enetsw_probe(struct platf
|
||||
struct resource *res_mem;
|
||||
int ret, irq_rx, irq_tx;
|
||||
|
||||
- /* stop if shared driver failed, assume driver->probe will be
|
||||
- * called in the same order we register devices (correct ?)
|
||||
- */
|
||||
if (!bcm_enet_shared_base[0])
|
||||
- return -ENODEV;
|
||||
+ return -EPROBE_DEFER;
|
||||
|
||||
res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
irq_rx = platform_get_irq(pdev, 0);
|
@ -1,150 +0,0 @@
|
||||
From 179a445ae4ef36ec44f4aea18e5f42d21334d186 Mon Sep 17 00:00:00 2001
|
||||
From: Jonas Gorski <jonas.gorski@gmail.com>
|
||||
Date: Sat, 25 Feb 2017 12:39:25 +0100
|
||||
Subject: [PATCH 4/6] bcm63xx_enet: use managed functions for clock/ioremap
|
||||
|
||||
Use managed functions where possible to reduce the amount of resource
|
||||
handling on error and remove paths.
|
||||
|
||||
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
|
||||
---
|
||||
drivers/net/ethernet/broadcom/bcm63xx_enet.c | 54 +++++++---------------------
|
||||
1 file changed, 12 insertions(+), 42 deletions(-)
|
||||
|
||||
--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c
|
||||
+++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
|
||||
@@ -1781,14 +1781,14 @@ static int bcm_enet_probe(struct platfor
|
||||
clk_name = "enet1";
|
||||
}
|
||||
|
||||
- priv->mac_clk = clk_get(&pdev->dev, clk_name);
|
||||
+ priv->mac_clk = devm_clk_get(&pdev->dev, clk_name);
|
||||
if (IS_ERR(priv->mac_clk)) {
|
||||
ret = PTR_ERR(priv->mac_clk);
|
||||
goto out;
|
||||
}
|
||||
ret = clk_prepare_enable(priv->mac_clk);
|
||||
if (ret)
|
||||
- goto out_put_clk_mac;
|
||||
+ goto out;
|
||||
|
||||
/* initialize default and fetch platform data */
|
||||
priv->rx_ring_size = BCMENET_DEF_RX_DESC;
|
||||
@@ -1816,7 +1816,7 @@ static int bcm_enet_probe(struct platfor
|
||||
|
||||
if (priv->mac_id == 0 && priv->has_phy && !priv->use_external_mii) {
|
||||
/* using internal PHY, enable clock */
|
||||
- priv->phy_clk = clk_get(&pdev->dev, "ephy");
|
||||
+ priv->phy_clk = devm_clk_get(&pdev->dev, "ephy");
|
||||
if (IS_ERR(priv->phy_clk)) {
|
||||
ret = PTR_ERR(priv->phy_clk);
|
||||
priv->phy_clk = NULL;
|
||||
@@ -1824,7 +1824,7 @@ static int bcm_enet_probe(struct platfor
|
||||
}
|
||||
ret = clk_prepare_enable(priv->phy_clk);
|
||||
if (ret)
|
||||
- goto out_put_clk_phy;
|
||||
+ goto out_disable_clk_mac;
|
||||
}
|
||||
|
||||
/* do minimal hardware init to be able to probe mii bus */
|
||||
@@ -1927,14 +1927,8 @@ out_uninit_hw:
|
||||
if (priv->phy_clk)
|
||||
clk_disable_unprepare(priv->phy_clk);
|
||||
|
||||
-out_put_clk_phy:
|
||||
- if (priv->phy_clk)
|
||||
- clk_put(priv->phy_clk);
|
||||
-
|
||||
out_disable_clk_mac:
|
||||
clk_disable_unprepare(priv->mac_clk);
|
||||
-out_put_clk_mac:
|
||||
- clk_put(priv->mac_clk);
|
||||
out:
|
||||
free_netdev(dev);
|
||||
return ret;
|
||||
@@ -1970,12 +1964,10 @@ static int bcm_enet_remove(struct platfo
|
||||
}
|
||||
|
||||
/* disable hw block clocks */
|
||||
- if (priv->phy_clk) {
|
||||
+ if (priv->phy_clk)
|
||||
clk_disable_unprepare(priv->phy_clk);
|
||||
- clk_put(priv->phy_clk);
|
||||
- }
|
||||
+
|
||||
clk_disable_unprepare(priv->mac_clk);
|
||||
- clk_put(priv->mac_clk);
|
||||
|
||||
free_netdev(dev);
|
||||
return 0;
|
||||
@@ -2758,26 +2750,20 @@ static int bcm_enetsw_probe(struct platf
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
- if (!request_mem_region(res_mem->start, resource_size(res_mem),
|
||||
- "bcm63xx_enetsw")) {
|
||||
- ret = -EBUSY;
|
||||
+ priv->base = devm_ioremap_resource(&pdev->dev, res_mem);
|
||||
+ if (IS_ERR(priv->base)) {
|
||||
+ ret = PTR_ERR(priv->base);
|
||||
goto out;
|
||||
}
|
||||
|
||||
- priv->base = ioremap(res_mem->start, resource_size(res_mem));
|
||||
- if (priv->base == NULL) {
|
||||
- ret = -ENOMEM;
|
||||
- goto out_release_mem;
|
||||
- }
|
||||
-
|
||||
- priv->mac_clk = clk_get(&pdev->dev, "enetsw");
|
||||
+ priv->mac_clk = devm_clk_get(&pdev->dev, "enetsw");
|
||||
if (IS_ERR(priv->mac_clk)) {
|
||||
ret = PTR_ERR(priv->mac_clk);
|
||||
- goto out_unmap;
|
||||
+ goto out;
|
||||
}
|
||||
ret = clk_prepare_enable(priv->mac_clk);
|
||||
if (ret)
|
||||
- goto out_put_clk;
|
||||
+ goto out;
|
||||
|
||||
priv->rx_chan = 0;
|
||||
priv->tx_chan = 1;
|
||||
@@ -2809,15 +2795,6 @@ static int bcm_enetsw_probe(struct platf
|
||||
|
||||
out_disable_clk:
|
||||
clk_disable_unprepare(priv->mac_clk);
|
||||
-
|
||||
-out_put_clk:
|
||||
- clk_put(priv->mac_clk);
|
||||
-
|
||||
-out_unmap:
|
||||
- iounmap(priv->base);
|
||||
-
|
||||
-out_release_mem:
|
||||
- release_mem_region(res_mem->start, resource_size(res_mem));
|
||||
out:
|
||||
free_netdev(dev);
|
||||
return ret;
|
||||
@@ -2829,20 +2806,13 @@ static int bcm_enetsw_remove(struct plat
|
||||
{
|
||||
struct bcm_enet_priv *priv;
|
||||
struct net_device *dev;
|
||||
- struct resource *res;
|
||||
|
||||
/* stop netdevice */
|
||||
dev = platform_get_drvdata(pdev);
|
||||
priv = netdev_priv(dev);
|
||||
unregister_netdev(dev);
|
||||
|
||||
- /* release device resources */
|
||||
- iounmap(priv->base);
|
||||
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
- release_mem_region(res->start, resource_size(res));
|
||||
-
|
||||
clk_disable_unprepare(priv->mac_clk);
|
||||
- clk_put(priv->mac_clk);
|
||||
|
||||
free_netdev(dev);
|
||||
return 0;
|
@ -1,36 +0,0 @@
|
||||
From 555baec974ede81e616ca88ac6d3fca09239368f Mon Sep 17 00:00:00 2001
|
||||
From: Jonas Gorski <jonas.gorski@gmail.com>
|
||||
Date: Tue, 18 Jul 2017 13:18:01 +0200
|
||||
Subject: [PATCH 5/6] bcm63xx_enet: drop unneeded NULL phy_clk check
|
||||
|
||||
clk_disable and clk_unprepare are NULL-safe, so need to duplicate the
|
||||
NULL check of the functions.
|
||||
|
||||
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
|
||||
---
|
||||
drivers/net/ethernet/broadcom/bcm63xx_enet.c | 7 ++-----
|
||||
1 file changed, 2 insertions(+), 5 deletions(-)
|
||||
|
||||
--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c
|
||||
+++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
|
||||
@@ -1924,8 +1924,7 @@ out_free_mdio:
|
||||
out_uninit_hw:
|
||||
/* turn off mdc clock */
|
||||
enet_writel(priv, 0, ENET_MIISC_REG);
|
||||
- if (priv->phy_clk)
|
||||
- clk_disable_unprepare(priv->phy_clk);
|
||||
+ clk_disable_unprepare(priv->phy_clk);
|
||||
|
||||
out_disable_clk_mac:
|
||||
clk_disable_unprepare(priv->mac_clk);
|
||||
@@ -1964,9 +1963,7 @@ static int bcm_enet_remove(struct platfo
|
||||
}
|
||||
|
||||
/* disable hw block clocks */
|
||||
- if (priv->phy_clk)
|
||||
- clk_disable_unprepare(priv->phy_clk);
|
||||
-
|
||||
+ clk_disable_unprepare(priv->phy_clk);
|
||||
clk_disable_unprepare(priv->mac_clk);
|
||||
|
||||
free_netdev(dev);
|
@ -1,22 +0,0 @@
|
||||
From 77364ce98037972fb1c57d0ee0418eb1c2b26521 Mon Sep 17 00:00:00 2001
|
||||
From: Jonas Gorski <jonas.gorski@gmail.com>
|
||||
Date: Mon, 29 May 2017 13:11:14 +0200
|
||||
Subject: [PATCH 6/6] bcm63xx_enet: remove unneeded include
|
||||
|
||||
We don't use anyhing from that file, so drop it.
|
||||
|
||||
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
|
||||
---
|
||||
drivers/net/ethernet/broadcom/bcm63xx_enet.h | 1 -
|
||||
1 file changed, 1 deletion(-)
|
||||
|
||||
--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.h
|
||||
+++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.h
|
||||
@@ -8,7 +8,6 @@
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include <bcm63xx_regs.h>
|
||||
-#include <bcm63xx_irq.h>
|
||||
#include <bcm63xx_io.h>
|
||||
#include <bcm63xx_iudma.h>
|
||||
|
@ -1,39 +0,0 @@
|
||||
From 943b0832e0cf3afe5bd40ffb1885d06106122c5d Mon Sep 17 00:00:00 2001
|
||||
From: Jonas Gorski <jonas.gorski@gmail.com>
|
||||
Date: Sun, 16 Jul 2017 12:49:49 +0200
|
||||
Subject: [PATCH 1/4] bcm63xx_enet: just use "enet" as the clock name
|
||||
|
||||
Now that we have the individual clocks available as "enet" we
|
||||
don't need to rely on the device id for them anymore.
|
||||
|
||||
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
|
||||
---
|
||||
drivers/net/ethernet/broadcom/bcm63xx_enet.c | 5 +----
|
||||
1 file changed, 1 insertion(+), 4 deletions(-)
|
||||
|
||||
--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c
|
||||
+++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
|
||||
@@ -1733,7 +1733,6 @@ static int bcm_enet_probe(struct platfor
|
||||
struct bcm63xx_enet_platform_data *pd;
|
||||
struct resource *res_mem, *res_irq, *res_irq_rx, *res_irq_tx;
|
||||
struct mii_bus *bus;
|
||||
- const char *clk_name;
|
||||
int i, ret;
|
||||
|
||||
if (!bcm_enet_shared_base[0])
|
||||
@@ -1774,14 +1773,12 @@ static int bcm_enet_probe(struct platfor
|
||||
if (priv->mac_id == 0) {
|
||||
priv->rx_chan = 0;
|
||||
priv->tx_chan = 1;
|
||||
- clk_name = "enet0";
|
||||
} else {
|
||||
priv->rx_chan = 2;
|
||||
priv->tx_chan = 3;
|
||||
- clk_name = "enet1";
|
||||
}
|
||||
|
||||
- priv->mac_clk = devm_clk_get(&pdev->dev, clk_name);
|
||||
+ priv->mac_clk = devm_clk_get(&pdev->dev, "enet");
|
||||
if (IS_ERR(priv->mac_clk)) {
|
||||
ret = PTR_ERR(priv->mac_clk);
|
||||
goto out;
|
@ -1,72 +0,0 @@
|
||||
From b7d1d1f345bb3b25c360c1df812d98866e2ee7fb Mon Sep 17 00:00:00 2001
|
||||
From: Jonas Gorski <jonas.gorski@gmail.com>
|
||||
Date: Sat, 30 Sep 2017 13:50:03 +0200
|
||||
Subject: [PATCH 2/4] bcm63xx_enet: use platform data for dma channel numbers
|
||||
|
||||
To reduce the reliance on device ids, pass the dma channel numbers to
|
||||
the enet devices as platform data.
|
||||
|
||||
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
|
||||
---
|
||||
arch/mips/bcm63xx/dev-enet.c | 8 ++++++++
|
||||
arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_enet.h | 4 ++++
|
||||
drivers/net/ethernet/broadcom/bcm63xx_enet.c | 11 ++---------
|
||||
3 files changed, 14 insertions(+), 9 deletions(-)
|
||||
|
||||
--- a/arch/mips/bcm63xx/dev-enet.c
|
||||
+++ b/arch/mips/bcm63xx/dev-enet.c
|
||||
@@ -265,6 +265,14 @@ int __init bcm63xx_enet_register(int uni
|
||||
dpd->dma_chan_width = ENETDMA_CHAN_WIDTH;
|
||||
}
|
||||
|
||||
+ if (unit == 0) {
|
||||
+ dpd->rx_chan = 0;
|
||||
+ dpd->tx_chan = 1;
|
||||
+ } else {
|
||||
+ dpd->rx_chan = 2;
|
||||
+ dpd->tx_chan = 3;
|
||||
+ }
|
||||
+
|
||||
ret = platform_device_register(pdev);
|
||||
if (ret)
|
||||
return ret;
|
||||
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_enet.h
|
||||
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_enet.h
|
||||
@@ -54,6 +54,10 @@ struct bcm63xx_enet_platform_data {
|
||||
|
||||
/* DMA descriptor shift */
|
||||
unsigned int dma_desc_shift;
|
||||
+
|
||||
+ /* dma channel ids */
|
||||
+ int rx_chan;
|
||||
+ int tx_chan;
|
||||
};
|
||||
|
||||
/*
|
||||
--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c
|
||||
+++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
|
||||
@@ -1769,15 +1769,6 @@ static int bcm_enet_probe(struct platfor
|
||||
priv->irq_tx = res_irq_tx->start;
|
||||
priv->mac_id = pdev->id;
|
||||
|
||||
- /* get rx & tx dma channel id for this mac */
|
||||
- if (priv->mac_id == 0) {
|
||||
- priv->rx_chan = 0;
|
||||
- priv->tx_chan = 1;
|
||||
- } else {
|
||||
- priv->rx_chan = 2;
|
||||
- priv->tx_chan = 3;
|
||||
- }
|
||||
-
|
||||
priv->mac_clk = devm_clk_get(&pdev->dev, "enet");
|
||||
if (IS_ERR(priv->mac_clk)) {
|
||||
ret = PTR_ERR(priv->mac_clk);
|
||||
@@ -1809,6 +1800,8 @@ static int bcm_enet_probe(struct platfor
|
||||
priv->dma_chan_width = pd->dma_chan_width;
|
||||
priv->dma_has_sram = pd->dma_has_sram;
|
||||
priv->dma_desc_shift = pd->dma_desc_shift;
|
||||
+ priv->rx_chan = pd->rx_chan;
|
||||
+ priv->tx_chan = pd->tx_chan;
|
||||
}
|
||||
|
||||
if (priv->mac_id == 0 && priv->has_phy && !priv->use_external_mii) {
|
@ -1,25 +0,0 @@
|
||||
From 8c61608e5dd2e15575c171ee9cd558ddc3b94962 Mon Sep 17 00:00:00 2001
|
||||
From: Jonas Gorski <jonas.gorski@gmail.com>
|
||||
Date: Sun, 17 Dec 2017 12:54:30 +0100
|
||||
Subject: [PATCH 3/4] bcm63xx_enet: remove pointless mac_id check
|
||||
|
||||
Enabling the ephy clock for mac 1 is harmless, and the actual usage of
|
||||
the ephy is not restricted to mac 0, so we might as well remove the
|
||||
check.
|
||||
|
||||
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
|
||||
---
|
||||
drivers/net/ethernet/broadcom/bcm63xx_enet.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c
|
||||
+++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
|
||||
@@ -1804,7 +1804,7 @@ static int bcm_enet_probe(struct platfor
|
||||
priv->tx_chan = pd->tx_chan;
|
||||
}
|
||||
|
||||
- if (priv->mac_id == 0 && priv->has_phy && !priv->use_external_mii) {
|
||||
+ if (priv->has_phy && !priv->use_external_mii) {
|
||||
/* using internal PHY, enable clock */
|
||||
priv->phy_clk = devm_clk_get(&pdev->dev, "ephy");
|
||||
if (IS_ERR(priv->phy_clk)) {
|
@ -1,46 +0,0 @@
|
||||
From faea89cd893a1a7af81185f026a64dad603ef72f Mon Sep 17 00:00:00 2001
|
||||
From: Jonas Gorski <jonas.gorski@gmail.com>
|
||||
Date: Sun, 17 Dec 2017 12:58:12 +0100
|
||||
Subject: [PATCH 4/4] bcm63xx_enet: use platform device id directly for miibus
|
||||
name
|
||||
|
||||
Directly use the platform device for generating the miibus name. This removes
|
||||
the last user of bcm_enet_priv::mac_id and we can remove the field.
|
||||
|
||||
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
|
||||
---
|
||||
drivers/net/ethernet/broadcom/bcm63xx_enet.c | 3 +--
|
||||
drivers/net/ethernet/broadcom/bcm63xx_enet.h | 3 ---
|
||||
2 files changed, 1 insertion(+), 5 deletions(-)
|
||||
|
||||
--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c
|
||||
+++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
|
||||
@@ -1767,7 +1767,6 @@ static int bcm_enet_probe(struct platfor
|
||||
dev->irq = priv->irq = res_irq->start;
|
||||
priv->irq_rx = res_irq_rx->start;
|
||||
priv->irq_tx = res_irq_tx->start;
|
||||
- priv->mac_id = pdev->id;
|
||||
|
||||
priv->mac_clk = devm_clk_get(&pdev->dev, "enet");
|
||||
if (IS_ERR(priv->mac_clk)) {
|
||||
@@ -1835,7 +1834,7 @@ static int bcm_enet_probe(struct platfor
|
||||
bus->priv = priv;
|
||||
bus->read = bcm_enet_mdio_read_phylib;
|
||||
bus->write = bcm_enet_mdio_write_phylib;
|
||||
- sprintf(bus->id, "%s-%d", pdev->name, priv->mac_id);
|
||||
+ sprintf(bus->id, "%s-%d", pdev->name, pdev->id);
|
||||
|
||||
/* only probe bus where we think the PHY is, because
|
||||
* the mdio read operation return 0 instead of 0xffff
|
||||
--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.h
|
||||
+++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.h
|
||||
@@ -192,9 +192,6 @@ struct bcm_enet_mib_counters {
|
||||
|
||||
struct bcm_enet_priv {
|
||||
|
||||
- /* mac id (from platform device id) */
|
||||
- int mac_id;
|
||||
-
|
||||
/* base remapped address of device */
|
||||
void __iomem *base;
|
||||
|
@ -1,28 +0,0 @@
|
||||
From 80a2f983e9f44dbc3e01ae31c62d877846a7f791 Mon Sep 17 00:00:00 2001
|
||||
From: Florian Fainelli <florian@openwrt.org>
|
||||
Date: Mon, 28 Jan 2013 20:06:19 +0100
|
||||
Subject: [PATCH 01/11] MIPS: BCM63XX: add USB host clock enable delay
|
||||
|
||||
Knowledge of the clock setup delay should remain at the clock level (so
|
||||
it can be clock specific and CPU specific). Add the 100 milliseconds
|
||||
required clock delay for the USB host clock when it gets enabled.
|
||||
|
||||
Signed-off-by: Florian Fainelli <florian@openwrt.org>
|
||||
---
|
||||
arch/mips/bcm63xx/clk.c | 5 +++++
|
||||
1 file changed, 5 insertions(+)
|
||||
|
||||
--- a/arch/mips/bcm63xx/clk.c
|
||||
+++ b/arch/mips/bcm63xx/clk.c
|
||||
@@ -213,6 +213,11 @@ static void usbh_set(struct clk *clk, in
|
||||
bcm_hwclock_set(CKCTL_6362_USBH_EN, enable);
|
||||
else if (BCMCPU_IS_6368())
|
||||
bcm_hwclock_set(CKCTL_6368_USBH_EN, enable);
|
||||
+ else
|
||||
+ return;
|
||||
+
|
||||
+ if (enable)
|
||||
+ msleep(100);
|
||||
}
|
||||
|
||||
static struct clk clk_usbh = {
|
@ -1,41 +0,0 @@
|
||||
From 8e9bf528a122741f0171b89c297b63041116d704 Mon Sep 17 00:00:00 2001
|
||||
From: Florian Fainelli <florian@openwrt.org>
|
||||
Date: Mon, 28 Jan 2013 20:06:20 +0100
|
||||
Subject: [PATCH 02/11] MIPS: BCM63XX: add USB device clock enable delay to
|
||||
clock code
|
||||
|
||||
This patch adds the required 10 micro seconds delay to the USB device
|
||||
clock enable operation. Put this where the correct clock knowledege is,
|
||||
which is in the clock code, and remove this delay from the bcm63xx_udc
|
||||
gadget driver where it was before.
|
||||
|
||||
Signed-off-by: Florian Fainelli <florian@openwrt.org>
|
||||
---
|
||||
arch/mips/bcm63xx/clk.c | 5 +++++
|
||||
drivers/usb/gadget/bcm63xx_udc.c | 1 -
|
||||
2 files changed, 5 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/arch/mips/bcm63xx/clk.c
|
||||
+++ b/arch/mips/bcm63xx/clk.c
|
||||
@@ -235,6 +235,11 @@ static void usbd_set(struct clk *clk, in
|
||||
bcm_hwclock_set(CKCTL_6362_USBD_EN, enable);
|
||||
else if (BCMCPU_IS_6368())
|
||||
bcm_hwclock_set(CKCTL_6368_USBD_EN, enable);
|
||||
+ else
|
||||
+ return;
|
||||
+
|
||||
+ if (enable)
|
||||
+ udelay(10);
|
||||
}
|
||||
|
||||
static struct clk clk_usbd = {
|
||||
--- a/drivers/usb/gadget/udc/bcm63xx_udc.c
|
||||
+++ b/drivers/usb/gadget/udc/bcm63xx_udc.c
|
||||
@@ -411,7 +411,6 @@ static inline void set_clocks(struct bcm
|
||||
if (is_enabled) {
|
||||
clk_enable(udc->usbh_clk);
|
||||
clk_enable(udc->usbd_clk);
|
||||
- udelay(10);
|
||||
} else {
|
||||
clk_disable(udc->usbd_clk);
|
||||
clk_disable(udc->usbh_clk);
|
@ -1,151 +0,0 @@
|
||||
From ac9b0b574d54be28b300bf99ffe092a2c589484f Mon Sep 17 00:00:00 2001
|
||||
From: Florian Fainelli <florian@openwrt.org>
|
||||
Date: Mon, 28 Jan 2013 20:06:21 +0100
|
||||
Subject: [PATCH 03/11] MIPS: BCM63XX: move code touching the USB private
|
||||
register
|
||||
|
||||
This patch moves the code touching the USB private register in the
|
||||
bcm63xx USB gadget driver to arch/mips/bcm63xx/usb-common.c in
|
||||
preparation for adding support for OHCI and EHCI host controllers which
|
||||
will also touch the USB private register.
|
||||
|
||||
Signed-off-by: Florian Fainelli <florian@openwrt.org>
|
||||
---
|
||||
arch/mips/bcm63xx/Makefile | 2 +-
|
||||
arch/mips/bcm63xx/usb-common.c | 53 ++++++++++++++++++++
|
||||
.../include/asm/mach-bcm63xx/bcm63xx_usb_priv.h | 9 ++++
|
||||
drivers/usb/gadget/bcm63xx_udc.c | 27 ++--------
|
||||
4 files changed, 67 insertions(+), 24 deletions(-)
|
||||
create mode 100644 arch/mips/bcm63xx/usb-common.c
|
||||
create mode 100644 arch/mips/include/asm/mach-bcm63xx/bcm63xx_usb_priv.h
|
||||
|
||||
--- a/arch/mips/bcm63xx/Makefile
|
||||
+++ b/arch/mips/bcm63xx/Makefile
|
||||
@@ -1,7 +1,7 @@
|
||||
obj-y += clk.o cpu.o cs.o gpio.o irq.o nvram.o prom.o reset.o \
|
||||
setup.o timer.o dev-dsp.o dev-enet.o dev-flash.o \
|
||||
dev-pcmcia.o dev-rng.o dev-spi.o dev-hsspi.o dev-uart.o \
|
||||
- dev-wdt.o dev-usb-usbd.o
|
||||
+ dev-wdt.o dev-usb-usbd.o usb-common.o
|
||||
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
|
||||
|
||||
obj-y += boards/
|
||||
--- /dev/null
|
||||
+++ b/arch/mips/bcm63xx/usb-common.c
|
||||
@@ -0,0 +1,53 @@
|
||||
+/*
|
||||
+ * Broadcom BCM63xx common USB device configuration code
|
||||
+ *
|
||||
+ * This file is subject to the terms and conditions of the GNU General Public
|
||||
+ * License. See the file "COPYING" in the main directory of this archive
|
||||
+ * for more details.
|
||||
+ *
|
||||
+ * Copyright (C) 2012 Kevin Cernekee <cernekee@gmail.com>
|
||||
+ * Copyright (C) 2012 Broadcom Corporation
|
||||
+ *
|
||||
+ */
|
||||
+#include <linux/export.h>
|
||||
+
|
||||
+#include <bcm63xx_cpu.h>
|
||||
+#include <bcm63xx_regs.h>
|
||||
+#include <bcm63xx_io.h>
|
||||
+#include <bcm63xx_usb_priv.h>
|
||||
+
|
||||
+void bcm63xx_usb_priv_select_phy_mode(u32 portmask, bool is_device)
|
||||
+{
|
||||
+ u32 val;
|
||||
+
|
||||
+ val = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_UTMI_CTL_6368_REG);
|
||||
+ if (is_device) {
|
||||
+ val |= (portmask << USBH_PRIV_UTMI_CTL_HOSTB_SHIFT);
|
||||
+ val |= (portmask << USBH_PRIV_UTMI_CTL_NODRIV_SHIFT);
|
||||
+ } else {
|
||||
+ val &= ~(portmask << USBH_PRIV_UTMI_CTL_HOSTB_SHIFT);
|
||||
+ val &= ~(portmask << USBH_PRIV_UTMI_CTL_NODRIV_SHIFT);
|
||||
+ }
|
||||
+ bcm_rset_writel(RSET_USBH_PRIV, val, USBH_PRIV_UTMI_CTL_6368_REG);
|
||||
+
|
||||
+ val = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_SWAP_6368_REG);
|
||||
+ if (is_device)
|
||||
+ val |= USBH_PRIV_SWAP_USBD_MASK;
|
||||
+ else
|
||||
+ val &= ~USBH_PRIV_SWAP_USBD_MASK;
|
||||
+ bcm_rset_writel(RSET_USBH_PRIV, val, USBH_PRIV_SWAP_6368_REG);
|
||||
+}
|
||||
+EXPORT_SYMBOL(bcm63xx_usb_priv_select_phy_mode);
|
||||
+
|
||||
+void bcm63xx_usb_priv_select_pullup(u32 portmask, bool is_on)
|
||||
+{
|
||||
+ u32 val;
|
||||
+
|
||||
+ val = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_UTMI_CTL_6368_REG);
|
||||
+ if (is_on)
|
||||
+ val &= ~(portmask << USBH_PRIV_UTMI_CTL_NODRIV_SHIFT);
|
||||
+ else
|
||||
+ val |= (portmask << USBH_PRIV_UTMI_CTL_NODRIV_SHIFT);
|
||||
+ bcm_rset_writel(RSET_USBH_PRIV, val, USBH_PRIV_UTMI_CTL_6368_REG);
|
||||
+}
|
||||
+EXPORT_SYMBOL(bcm63xx_usb_priv_select_pullup);
|
||||
--- /dev/null
|
||||
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_usb_priv.h
|
||||
@@ -0,0 +1,9 @@
|
||||
+#ifndef BCM63XX_USB_PRIV_H_
|
||||
+#define BCM63XX_USB_PRIV_H_
|
||||
+
|
||||
+#include <linux/types.h>
|
||||
+
|
||||
+void bcm63xx_usb_priv_select_phy_mode(u32 portmask, bool is_device);
|
||||
+void bcm63xx_usb_priv_select_pullup(u32 portmask, bool is_on);
|
||||
+
|
||||
+#endif /* BCM63XX_USB_PRIV_H_ */
|
||||
--- a/drivers/usb/gadget/udc/bcm63xx_udc.c
|
||||
+++ b/drivers/usb/gadget/udc/bcm63xx_udc.c
|
||||
@@ -40,6 +40,7 @@
|
||||
#include <bcm63xx_dev_usb_usbd.h>
|
||||
#include <bcm63xx_io.h>
|
||||
#include <bcm63xx_regs.h>
|
||||
+#include <bcm63xx_usb_priv.h>
|
||||
|
||||
#define DRV_MODULE_NAME "bcm63xx_udc"
|
||||
|
||||
@@ -888,22 +889,7 @@ static void bcm63xx_select_phy_mode(stru
|
||||
bcm_gpio_writel(val, GPIO_PINMUX_OTHR_REG);
|
||||
}
|
||||
|
||||
- val = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_UTMI_CTL_6368_REG);
|
||||
- if (is_device) {
|
||||
- val |= (portmask << USBH_PRIV_UTMI_CTL_HOSTB_SHIFT);
|
||||
- val |= (portmask << USBH_PRIV_UTMI_CTL_NODRIV_SHIFT);
|
||||
- } else {
|
||||
- val &= ~(portmask << USBH_PRIV_UTMI_CTL_HOSTB_SHIFT);
|
||||
- val &= ~(portmask << USBH_PRIV_UTMI_CTL_NODRIV_SHIFT);
|
||||
- }
|
||||
- bcm_rset_writel(RSET_USBH_PRIV, val, USBH_PRIV_UTMI_CTL_6368_REG);
|
||||
-
|
||||
- val = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_SWAP_6368_REG);
|
||||
- if (is_device)
|
||||
- val |= USBH_PRIV_SWAP_USBD_MASK;
|
||||
- else
|
||||
- val &= ~USBH_PRIV_SWAP_USBD_MASK;
|
||||
- bcm_rset_writel(RSET_USBH_PRIV, val, USBH_PRIV_SWAP_6368_REG);
|
||||
+ bcm63xx_usb_priv_select_phy_mode(portmask, is_device);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -917,14 +903,9 @@ static void bcm63xx_select_phy_mode(stru
|
||||
*/
|
||||
static void bcm63xx_select_pullup(struct bcm63xx_udc *udc, bool is_on)
|
||||
{
|
||||
- u32 val, portmask = BIT(udc->pd->port_no);
|
||||
+ u32 portmask = BIT(udc->pd->port_no);
|
||||
|
||||
- val = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_UTMI_CTL_6368_REG);
|
||||
- if (is_on)
|
||||
- val &= ~(portmask << USBH_PRIV_UTMI_CTL_NODRIV_SHIFT);
|
||||
- else
|
||||
- val |= (portmask << USBH_PRIV_UTMI_CTL_NODRIV_SHIFT);
|
||||
- bcm_rset_writel(RSET_USBH_PRIV, val, USBH_PRIV_UTMI_CTL_6368_REG);
|
||||
+ bcm63xx_usb_priv_select_pullup(portmask, is_on);
|
||||
}
|
||||
|
||||
/**
|
@ -1,169 +0,0 @@
|
||||
From 28758a9da77954ed323f86123ef448c6a563c037 Mon Sep 17 00:00:00 2001
|
||||
From: Florian Fainelli <florian@openwrt.org>
|
||||
Date: Mon, 28 Jan 2013 20:06:22 +0100
|
||||
Subject: [PATCH 04/11] MIPS: BCM63XX: add OHCI/EHCI configuration bits to
|
||||
common USB code
|
||||
|
||||
This patch updates the common USB code touching the USB private
|
||||
registers with the specific bits to properly enable OHCI and EHCI
|
||||
controllers on BCM63xx SoCs. As a result we now need to protect access
|
||||
to Read Modify Write sequences using a spinlock because we cannot
|
||||
guarantee that any of the exposed helper will not be called
|
||||
concurrently.
|
||||
|
||||
Signed-off-by: Maxime Bizon <mbizon@freebox.fr>
|
||||
Signed-off-by: Florian Fainelli <florian@openwrt.org>
|
||||
---
|
||||
arch/mips/bcm63xx/usb-common.c | 97 ++++++++++++++++++++
|
||||
.../include/asm/mach-bcm63xx/bcm63xx_usb_priv.h | 2 +
|
||||
2 files changed, 99 insertions(+)
|
||||
|
||||
--- a/arch/mips/bcm63xx/usb-common.c
|
||||
+++ b/arch/mips/bcm63xx/usb-common.c
|
||||
@@ -5,10 +5,12 @@
|
||||
* License. See the file "COPYING" in the main directory of this archive
|
||||
* for more details.
|
||||
*
|
||||
+ * Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
|
||||
* Copyright (C) 2012 Kevin Cernekee <cernekee@gmail.com>
|
||||
* Copyright (C) 2012 Broadcom Corporation
|
||||
*
|
||||
*/
|
||||
+#include <linux/spinlock.h>
|
||||
#include <linux/export.h>
|
||||
|
||||
#include <bcm63xx_cpu.h>
|
||||
@@ -16,9 +18,14 @@
|
||||
#include <bcm63xx_io.h>
|
||||
#include <bcm63xx_usb_priv.h>
|
||||
|
||||
+static DEFINE_SPINLOCK(usb_priv_reg_lock);
|
||||
+
|
||||
void bcm63xx_usb_priv_select_phy_mode(u32 portmask, bool is_device)
|
||||
{
|
||||
u32 val;
|
||||
+ unsigned long flags;
|
||||
+
|
||||
+ spin_lock_irqsave(&usb_priv_reg_lock, flags);
|
||||
|
||||
val = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_UTMI_CTL_6368_REG);
|
||||
if (is_device) {
|
||||
@@ -36,12 +43,17 @@ void bcm63xx_usb_priv_select_phy_mode(u3
|
||||
else
|
||||
val &= ~USBH_PRIV_SWAP_USBD_MASK;
|
||||
bcm_rset_writel(RSET_USBH_PRIV, val, USBH_PRIV_SWAP_6368_REG);
|
||||
+
|
||||
+ spin_unlock_irqrestore(&usb_priv_reg_lock, flags);
|
||||
}
|
||||
EXPORT_SYMBOL(bcm63xx_usb_priv_select_phy_mode);
|
||||
|
||||
void bcm63xx_usb_priv_select_pullup(u32 portmask, bool is_on)
|
||||
{
|
||||
u32 val;
|
||||
+ unsigned long flags;
|
||||
+
|
||||
+ spin_lock_irqsave(&usb_priv_reg_lock, flags);
|
||||
|
||||
val = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_UTMI_CTL_6368_REG);
|
||||
if (is_on)
|
||||
@@ -49,5 +61,90 @@ void bcm63xx_usb_priv_select_pullup(u32
|
||||
else
|
||||
val |= (portmask << USBH_PRIV_UTMI_CTL_NODRIV_SHIFT);
|
||||
bcm_rset_writel(RSET_USBH_PRIV, val, USBH_PRIV_UTMI_CTL_6368_REG);
|
||||
+
|
||||
+ spin_unlock_irqrestore(&usb_priv_reg_lock, flags);
|
||||
}
|
||||
EXPORT_SYMBOL(bcm63xx_usb_priv_select_pullup);
|
||||
+
|
||||
+/* The following array represents the meaning of the DESC/DATA
|
||||
+ * endian swapping with respect to the CPU configured endianness
|
||||
+ *
|
||||
+ * DATA ENDN mmio descriptor
|
||||
+ * 0 0 BE invalid
|
||||
+ * 0 1 BE LE
|
||||
+ * 1 0 BE BE
|
||||
+ * 1 1 BE invalid
|
||||
+ *
|
||||
+ * Since BCM63XX SoCs are configured to be in big-endian mode
|
||||
+ * we want configuration at line 3.
|
||||
+ */
|
||||
+void bcm63xx_usb_priv_ohci_cfg_set(void)
|
||||
+{
|
||||
+ u32 reg;
|
||||
+ unsigned long flags;
|
||||
+
|
||||
+ spin_lock_irqsave(&usb_priv_reg_lock, flags);
|
||||
+
|
||||
+ if (BCMCPU_IS_6348())
|
||||
+ bcm_rset_writel(RSET_OHCI_PRIV, 0, OHCI_PRIV_REG);
|
||||
+ else if (BCMCPU_IS_6358()) {
|
||||
+ reg = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_SWAP_6358_REG);
|
||||
+ reg &= ~USBH_PRIV_SWAP_OHCI_ENDN_MASK;
|
||||
+ reg |= USBH_PRIV_SWAP_OHCI_DATA_MASK;
|
||||
+ bcm_rset_writel(RSET_USBH_PRIV, reg, USBH_PRIV_SWAP_6358_REG);
|
||||
+ /*
|
||||
+ * The magic value comes for the original vendor BSP
|
||||
+ * and is needed for USB to work. Datasheet does not
|
||||
+ * help, so the magic value is used as-is.
|
||||
+ */
|
||||
+ bcm_rset_writel(RSET_USBH_PRIV, 0x1c0020,
|
||||
+ USBH_PRIV_TEST_6358_REG);
|
||||
+
|
||||
+ } else if (BCMCPU_IS_6328() || BCMCPU_IS_6362() || BCMCPU_IS_6368()) {
|
||||
+ reg = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_SWAP_6368_REG);
|
||||
+ reg &= ~USBH_PRIV_SWAP_OHCI_ENDN_MASK;
|
||||
+ reg |= USBH_PRIV_SWAP_OHCI_DATA_MASK;
|
||||
+ bcm_rset_writel(RSET_USBH_PRIV, reg, USBH_PRIV_SWAP_6368_REG);
|
||||
+
|
||||
+ reg = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_SETUP_6368_REG);
|
||||
+ reg |= USBH_PRIV_SETUP_IOC_MASK;
|
||||
+ bcm_rset_writel(RSET_USBH_PRIV, reg, USBH_PRIV_SETUP_6368_REG);
|
||||
+ }
|
||||
+
|
||||
+ spin_unlock_irqrestore(&usb_priv_reg_lock, flags);
|
||||
+}
|
||||
+
|
||||
+void bcm63xx_usb_priv_ehci_cfg_set(void)
|
||||
+{
|
||||
+ u32 reg;
|
||||
+ unsigned long flags;
|
||||
+
|
||||
+ spin_lock_irqsave(&usb_priv_reg_lock, flags);
|
||||
+
|
||||
+ if (BCMCPU_IS_6358()) {
|
||||
+ reg = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_SWAP_6358_REG);
|
||||
+ reg &= ~USBH_PRIV_SWAP_EHCI_ENDN_MASK;
|
||||
+ reg |= USBH_PRIV_SWAP_EHCI_DATA_MASK;
|
||||
+ bcm_rset_writel(RSET_USBH_PRIV, reg, USBH_PRIV_SWAP_6358_REG);
|
||||
+
|
||||
+ /*
|
||||
+ * The magic value comes for the original vendor BSP
|
||||
+ * and is needed for USB to work. Datasheet does not
|
||||
+ * help, so the magic value is used as-is.
|
||||
+ */
|
||||
+ bcm_rset_writel(RSET_USBH_PRIV, 0x1c0020,
|
||||
+ USBH_PRIV_TEST_6358_REG);
|
||||
+
|
||||
+ } else if (BCMCPU_IS_6328() || BCMCPU_IS_6362() || BCMCPU_IS_6368()) {
|
||||
+ reg = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_SWAP_6368_REG);
|
||||
+ reg &= ~USBH_PRIV_SWAP_EHCI_ENDN_MASK;
|
||||
+ reg |= USBH_PRIV_SWAP_EHCI_DATA_MASK;
|
||||
+ bcm_rset_writel(RSET_USBH_PRIV, reg, USBH_PRIV_SWAP_6368_REG);
|
||||
+
|
||||
+ reg = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_SETUP_6368_REG);
|
||||
+ reg |= USBH_PRIV_SETUP_IOC_MASK;
|
||||
+ bcm_rset_writel(RSET_USBH_PRIV, reg, USBH_PRIV_SETUP_6368_REG);
|
||||
+ }
|
||||
+
|
||||
+ spin_unlock_irqrestore(&usb_priv_reg_lock, flags);
|
||||
+}
|
||||
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_usb_priv.h
|
||||
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_usb_priv.h
|
||||
@@ -5,5 +5,7 @@
|
||||
|
||||
void bcm63xx_usb_priv_select_phy_mode(u32 portmask, bool is_device);
|
||||
void bcm63xx_usb_priv_select_pullup(u32 portmask, bool is_on);
|
||||
+void bcm63xx_usb_priv_ohci_cfg_set(void);
|
||||
+void bcm63xx_usb_priv_ehci_cfg_set(void);
|
||||
|
||||
#endif /* BCM63XX_USB_PRIV_H_ */
|
@ -1,62 +0,0 @@
|
||||
From 94ec618bd1a6b07fafbbfc9bcc54e7f9360ff9a0 Mon Sep 17 00:00:00 2001
|
||||
From: Florian Fainelli <florian@openwrt.org>
|
||||
Date: Mon, 28 Jan 2013 20:06:23 +0100
|
||||
Subject: [PATCH 05/11] MIPS: BCM63XX: introduce BCM63XX_OHCI configuration
|
||||
symbol
|
||||
|
||||
This configuration symbol can be used by CPUs supporting the on-chip
|
||||
OHCI controller, and ensures that all relevant OHCI-related
|
||||
configuration options are correctly selected. So far, OHCI support is
|
||||
available for the 6328, 6348, 6358 and 6358 SoCs.
|
||||
|
||||
Signed-off-by: Florian Fainelli <florian@openwrt.org>
|
||||
---
|
||||
arch/mips/bcm63xx/Kconfig | 15 ++++++++++-----
|
||||
1 file changed, 10 insertions(+), 5 deletions(-)
|
||||
|
||||
--- a/arch/mips/bcm63xx/Kconfig
|
||||
+++ b/arch/mips/bcm63xx/Kconfig
|
||||
@@ -6,10 +6,17 @@ config BCM63XX_CPU_3368
|
||||
select SYS_HAS_CPU_BMIPS4350
|
||||
select HW_HAS_PCI
|
||||
|
||||
+config BCM63XX_OHCI
|
||||
+ bool
|
||||
+ select USB_ARCH_HAS_OHCI
|
||||
+ select USB_OHCI_BIG_ENDIAN_DESC if USB_OHCI_HCD
|
||||
+ select USB_OHCI_BIG_ENDIAN_MMIO if USB_OHCI_HCD
|
||||
+
|
||||
config BCM63XX_CPU_6328
|
||||
bool "support 6328 CPU"
|
||||
select SYS_HAS_CPU_BMIPS4350
|
||||
select HW_HAS_PCI
|
||||
+ select BCM63XX_OHCI
|
||||
|
||||
config BCM63XX_CPU_6338
|
||||
bool "support 6338 CPU"
|
||||
@@ -24,21 +31,25 @@ config BCM63XX_CPU_6348
|
||||
bool "support 6348 CPU"
|
||||
select SYS_HAS_CPU_BMIPS32_3300
|
||||
select HW_HAS_PCI
|
||||
+ select BCM63XX_OHCI
|
||||
|
||||
config BCM63XX_CPU_6358
|
||||
bool "support 6358 CPU"
|
||||
select SYS_HAS_CPU_BMIPS4350
|
||||
select HW_HAS_PCI
|
||||
+ select BCM63XX_OHCI
|
||||
|
||||
config BCM63XX_CPU_6362
|
||||
bool "support 6362 CPU"
|
||||
select SYS_HAS_CPU_BMIPS4350
|
||||
select HW_HAS_PCI
|
||||
+ select BCM63XX_OHCI
|
||||
|
||||
config BCM63XX_CPU_6368
|
||||
bool "support 6368 CPU"
|
||||
select SYS_HAS_CPU_BMIPS4350
|
||||
select HW_HAS_PCI
|
||||
+ select BCM63XX_OHCI
|
||||
endmenu
|
||||
|
||||
source "arch/mips/bcm63xx/boards/Kconfig"
|
@ -1,138 +0,0 @@
|
||||
From 30d22baef255c99a12c4858ce4ab0d45f0d8c9ae Mon Sep 17 00:00:00 2001
|
||||
From: Florian Fainelli <florian@openwrt.org>
|
||||
Date: Mon, 28 Jan 2013 20:06:24 +0100
|
||||
Subject: [PATCH 06/11] MIPS: BCM63XX: add support for the on-chip OHCI
|
||||
controller
|
||||
|
||||
Broadcom BCM63XX SoCs include an on-chip OHCI controller which can be
|
||||
driven by the ohci-platform generic driver by using specific power
|
||||
on/off/suspend callback to manage clocks and hardware specific
|
||||
configuration.
|
||||
|
||||
Signed-off-by: Maxime Bizon <mbizon@freebox.fr>
|
||||
Signed-off-by: Florian Fainelli <florian@openwrt.org>
|
||||
---
|
||||
arch/mips/bcm63xx/Makefile | 2 +-
|
||||
arch/mips/bcm63xx/dev-usb-ohci.c | 94 ++++++++++++++++++++
|
||||
.../asm/mach-bcm63xx/bcm63xx_dev_usb_ohci.h | 6 ++
|
||||
3 files changed, 101 insertions(+), 1 deletion(-)
|
||||
create mode 100644 arch/mips/bcm63xx/dev-usb-ohci.c
|
||||
create mode 100644 arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_usb_ohci.h
|
||||
|
||||
--- a/arch/mips/bcm63xx/Makefile
|
||||
+++ b/arch/mips/bcm63xx/Makefile
|
||||
@@ -1,7 +1,7 @@
|
||||
obj-y += clk.o cpu.o cs.o gpio.o irq.o nvram.o prom.o reset.o \
|
||||
setup.o timer.o dev-dsp.o dev-enet.o dev-flash.o \
|
||||
dev-pcmcia.o dev-rng.o dev-spi.o dev-hsspi.o dev-uart.o \
|
||||
- dev-wdt.o dev-usb-usbd.o usb-common.o
|
||||
+ dev-wdt.o dev-usb-ohci.o dev-usb-usbd.o usb-common.o
|
||||
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
|
||||
|
||||
obj-y += boards/
|
||||
--- /dev/null
|
||||
+++ b/arch/mips/bcm63xx/dev-usb-ohci.c
|
||||
@@ -0,0 +1,94 @@
|
||||
+/*
|
||||
+ * This file is subject to the terms and conditions of the GNU General Public
|
||||
+ * License. See the file "COPYING" in the main directory of this archive
|
||||
+ * for more details.
|
||||
+ *
|
||||
+ * Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
|
||||
+ * Copyright (C) 2013 Florian Fainelli <florian@openwrt.org>
|
||||
+ */
|
||||
+
|
||||
+#include <linux/init.h>
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+#include <linux/usb/ohci_pdriver.h>
|
||||
+#include <linux/dma-mapping.h>
|
||||
+#include <linux/clk.h>
|
||||
+#include <linux/delay.h>
|
||||
+
|
||||
+#include <bcm63xx_cpu.h>
|
||||
+#include <bcm63xx_regs.h>
|
||||
+#include <bcm63xx_io.h>
|
||||
+#include <bcm63xx_usb_priv.h>
|
||||
+#include <bcm63xx_dev_usb_ohci.h>
|
||||
+
|
||||
+static struct resource ohci_resources[] = {
|
||||
+ {
|
||||
+ .start = -1, /* filled at runtime */
|
||||
+ .end = -1, /* filled at runtime */
|
||||
+ .flags = IORESOURCE_MEM,
|
||||
+ },
|
||||
+ {
|
||||
+ .start = -1, /* filled at runtime */
|
||||
+ .flags = IORESOURCE_IRQ,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static u64 ohci_dmamask = DMA_BIT_MASK(32);
|
||||
+
|
||||
+static struct clk *usb_host_clock;
|
||||
+
|
||||
+static int bcm63xx_ohci_power_on(struct platform_device *pdev)
|
||||
+{
|
||||
+ usb_host_clock = clk_get(&pdev->dev, "usbh");
|
||||
+ if (IS_ERR_OR_NULL(usb_host_clock))
|
||||
+ return -ENODEV;
|
||||
+
|
||||
+ clk_prepare_enable(usb_host_clock);
|
||||
+
|
||||
+ bcm63xx_usb_priv_ohci_cfg_set();
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void bcm63xx_ohci_power_off(struct platform_device *pdev)
|
||||
+{
|
||||
+ if (!IS_ERR_OR_NULL(usb_host_clock)) {
|
||||
+ clk_disable_unprepare(usb_host_clock);
|
||||
+ clk_put(usb_host_clock);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static struct usb_ohci_pdata bcm63xx_ohci_pdata = {
|
||||
+ .big_endian_desc = 1,
|
||||
+ .big_endian_mmio = 1,
|
||||
+ .no_big_frame_no = 1,
|
||||
+ .num_ports = 1,
|
||||
+ .power_on = bcm63xx_ohci_power_on,
|
||||
+ .power_off = bcm63xx_ohci_power_off,
|
||||
+ .power_suspend = bcm63xx_ohci_power_off,
|
||||
+};
|
||||
+
|
||||
+static struct platform_device bcm63xx_ohci_device = {
|
||||
+ .name = "ohci-platform",
|
||||
+ .id = -1,
|
||||
+ .num_resources = ARRAY_SIZE(ohci_resources),
|
||||
+ .resource = ohci_resources,
|
||||
+ .dev = {
|
||||
+ .platform_data = &bcm63xx_ohci_pdata,
|
||||
+ .dma_mask = &ohci_dmamask,
|
||||
+ .coherent_dma_mask = DMA_BIT_MASK(32),
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+int __init bcm63xx_ohci_register(void)
|
||||
+{
|
||||
+ if (BCMCPU_IS_6345() || BCMCPU_IS_6338())
|
||||
+ return -ENODEV;
|
||||
+
|
||||
+ ohci_resources[0].start = bcm63xx_regset_address(RSET_OHCI0);
|
||||
+ ohci_resources[0].end = ohci_resources[0].start;
|
||||
+ ohci_resources[0].end += RSET_OHCI_SIZE - 1;
|
||||
+ ohci_resources[1].start = bcm63xx_get_irq_number(IRQ_OHCI0);
|
||||
+
|
||||
+ return platform_device_register(&bcm63xx_ohci_device);
|
||||
+}
|
||||
--- /dev/null
|
||||
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_usb_ohci.h
|
||||
@@ -0,0 +1,6 @@
|
||||
+#ifndef BCM63XX_DEV_USB_OHCI_H_
|
||||
+#define BCM63XX_DEV_USB_OHCI_H_
|
||||
+
|
||||
+int bcm63xx_ohci_register(void);
|
||||
+
|
||||
+#endif /* BCM63XX_DEV_USB_OHCI_H_ */
|
@ -1,36 +0,0 @@
|
||||
From 33ef960aed15f9a98a2c51d8d794cd72418e0be4 Mon Sep 17 00:00:00 2001
|
||||
From: Florian Fainelli <florian@openwrt.org>
|
||||
Date: Mon, 28 Jan 2013 20:06:25 +0100
|
||||
Subject: [PATCH 07/11] MIPS: BCM63XX: register OHCI controller if board
|
||||
enables it
|
||||
|
||||
BCM63XX-based boards can control the registration of the OHCI controller
|
||||
by setting their has_ohci0 flag to 1. Handle this in the generic
|
||||
code dealing with board registration and call the actual helper to
|
||||
register the OHCI controller.
|
||||
|
||||
Signed-off-by: Florian Fainelli <florian@openwrt.org>
|
||||
---
|
||||
arch/mips/bcm63xx/boards/board_bcm963xx.c | 4 ++++
|
||||
1 file changed, 4 insertions(+)
|
||||
|
||||
--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
|
||||
+++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
|
||||
@@ -28,6 +28,7 @@
|
||||
#include <bcm63xx_dev_hsspi.h>
|
||||
#include <bcm63xx_dev_pcmcia.h>
|
||||
#include <bcm63xx_dev_spi.h>
|
||||
+#include <bcm63xx_dev_usb_ohci.h>
|
||||
#include <bcm63xx_dev_usb_usbd.h>
|
||||
#include <board_bcm963xx.h>
|
||||
|
||||
@@ -898,6 +899,9 @@ int __init board_register_devices(void)
|
||||
if (board.has_usbd)
|
||||
bcm63xx_usbd_register(&board.usbd);
|
||||
|
||||
+ if (board.has_ohci0)
|
||||
+ bcm63xx_ohci_register();
|
||||
+
|
||||
if (board.has_dsp)
|
||||
bcm63xx_dsp_register(&board.dsp);
|
||||
|
@ -1,62 +0,0 @@
|
||||
From 00da1683364e58c6430a4577123d01037f8faddc Mon Sep 17 00:00:00 2001
|
||||
From: Florian Fainelli <florian@openwrt.org>
|
||||
Date: Mon, 28 Jan 2013 20:06:26 +0100
|
||||
Subject: [PATCH 08/11] MIPS: BCM63XX: introduce BCM63XX_EHCI configuration
|
||||
symbol
|
||||
|
||||
This configuration symbol can be used by CPUs supporting the on-chip
|
||||
EHCI controller, and ensures that all relevant EHCI-related
|
||||
configuration options are selected. So far BCM6328, BCM6358 and BCM6368
|
||||
have an EHCI controller and do select this symbol. Update
|
||||
drivers/usb/host/Kconfig with BCM63XX to update direct unmet
|
||||
dependencies.
|
||||
|
||||
Signed-off-by: Florian Fainelli <florian@openwrt.org>
|
||||
---
|
||||
arch/mips/bcm63xx/Kconfig | 9 +++++++++
|
||||
drivers/usb/host/Kconfig | 5 +++--
|
||||
2 files changed, 12 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/arch/mips/bcm63xx/Kconfig
|
||||
+++ b/arch/mips/bcm63xx/Kconfig
|
||||
@@ -12,11 +12,18 @@ config BCM63XX_OHCI
|
||||
select USB_OHCI_BIG_ENDIAN_DESC if USB_OHCI_HCD
|
||||
select USB_OHCI_BIG_ENDIAN_MMIO if USB_OHCI_HCD
|
||||
|
||||
+config BCM63XX_EHCI
|
||||
+ bool
|
||||
+ select USB_ARCH_HAS_EHCI
|
||||
+ select USB_EHCI_BIG_ENDIAN_DESC if USB_EHCI_HCD
|
||||
+ select USB_EHCI_BIG_ENDIAN_MMIO if USB_EHCI_HCD
|
||||
+
|
||||
config BCM63XX_CPU_6328
|
||||
bool "support 6328 CPU"
|
||||
select SYS_HAS_CPU_BMIPS4350
|
||||
select HW_HAS_PCI
|
||||
select BCM63XX_OHCI
|
||||
+ select BCM63XX_EHCI
|
||||
|
||||
config BCM63XX_CPU_6338
|
||||
bool "support 6338 CPU"
|
||||
@@ -38,18 +45,21 @@ config BCM63XX_CPU_6358
|
||||
select SYS_HAS_CPU_BMIPS4350
|
||||
select HW_HAS_PCI
|
||||
select BCM63XX_OHCI
|
||||
+ select BCM63XX_EHCI
|
||||
|
||||
config BCM63XX_CPU_6362
|
||||
bool "support 6362 CPU"
|
||||
select SYS_HAS_CPU_BMIPS4350
|
||||
select HW_HAS_PCI
|
||||
select BCM63XX_OHCI
|
||||
+ select BCM63XX_EHCI
|
||||
|
||||
config BCM63XX_CPU_6368
|
||||
bool "support 6368 CPU"
|
||||
select SYS_HAS_CPU_BMIPS4350
|
||||
select HW_HAS_PCI
|
||||
select BCM63XX_OHCI
|
||||
+ select BCM63XX_EHCI
|
||||
endmenu
|
||||
|
||||
source "arch/mips/bcm63xx/boards/Kconfig"
|
@ -1,137 +0,0 @@
|
||||
From e38f13bd6408769c0b565bb1079024f496eee121 Mon Sep 17 00:00:00 2001
|
||||
From: Florian Fainelli <florian@openwrt.org>
|
||||
Date: Mon, 28 Jan 2013 20:06:27 +0100
|
||||
Subject: [PATCH 09/11] MIPS: BCM63XX: add support for the on-chip EHCI
|
||||
controller
|
||||
|
||||
Broadcom BCM63XX SoCs include an on-chip EHCI controller which can be
|
||||
driven by the generic ehci-platform driver by using specific power
|
||||
on/off/suspend callbacks to manage clocks and hardware specific
|
||||
configuration.
|
||||
|
||||
Signed-off-by: Maxime Bizon <mbizon@freebox.fr>
|
||||
Signed-off-by: Florian Fainelli <florian@openwrt.org>
|
||||
---
|
||||
arch/mips/bcm63xx/Makefile | 2 +-
|
||||
arch/mips/bcm63xx/dev-usb-ehci.c | 92 ++++++++++++++++++++
|
||||
.../asm/mach-bcm63xx/bcm63xx_dev_usb_ehci.h | 6 ++
|
||||
3 files changed, 99 insertions(+), 1 deletion(-)
|
||||
create mode 100644 arch/mips/bcm63xx/dev-usb-ehci.c
|
||||
create mode 100644 arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_usb_ehci.h
|
||||
|
||||
--- a/arch/mips/bcm63xx/Makefile
|
||||
+++ b/arch/mips/bcm63xx/Makefile
|
||||
@@ -1,7 +1,8 @@
|
||||
obj-y += clk.o cpu.o cs.o gpio.o irq.o nvram.o prom.o reset.o \
|
||||
setup.o timer.o dev-dsp.o dev-enet.o dev-flash.o \
|
||||
dev-pcmcia.o dev-rng.o dev-spi.o dev-hsspi.o dev-uart.o \
|
||||
- dev-wdt.o dev-usb-ohci.o dev-usb-usbd.o usb-common.o
|
||||
+ dev-wdt.o dev-usb-ehci.o dev-usb-ohci.o dev-usb-usbd.o \
|
||||
+ usb-common.o
|
||||
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
|
||||
|
||||
obj-y += boards/
|
||||
--- /dev/null
|
||||
+++ b/arch/mips/bcm63xx/dev-usb-ehci.c
|
||||
@@ -0,0 +1,92 @@
|
||||
+/*
|
||||
+ * This file is subject to the terms and conditions of the GNU General Public
|
||||
+ * License. See the file "COPYING" in the main directory of this archive
|
||||
+ * for more details.
|
||||
+ *
|
||||
+ * Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
|
||||
+ * Copyright (C) 2013 Florian Fainelli <florian@openwrt.org>
|
||||
+ */
|
||||
+
|
||||
+#include <linux/init.h>
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+#include <linux/clk.h>
|
||||
+#include <linux/delay.h>
|
||||
+#include <linux/usb/ehci_pdriver.h>
|
||||
+#include <linux/dma-mapping.h>
|
||||
+
|
||||
+#include <bcm63xx_cpu.h>
|
||||
+#include <bcm63xx_regs.h>
|
||||
+#include <bcm63xx_io.h>
|
||||
+#include <bcm63xx_usb_priv.h>
|
||||
+#include <bcm63xx_dev_usb_ehci.h>
|
||||
+
|
||||
+static struct resource ehci_resources[] = {
|
||||
+ {
|
||||
+ .start = -1, /* filled at runtime */
|
||||
+ .end = -1, /* filled at runtime */
|
||||
+ .flags = IORESOURCE_MEM,
|
||||
+ },
|
||||
+ {
|
||||
+ .start = -1, /* filled at runtime */
|
||||
+ .flags = IORESOURCE_IRQ,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static u64 ehci_dmamask = DMA_BIT_MASK(32);
|
||||
+
|
||||
+static struct clk *usb_host_clock;
|
||||
+
|
||||
+static int bcm63xx_ehci_power_on(struct platform_device *pdev)
|
||||
+{
|
||||
+ usb_host_clock = clk_get(&pdev->dev, "usbh");
|
||||
+ if (IS_ERR_OR_NULL(usb_host_clock))
|
||||
+ return -ENODEV;
|
||||
+
|
||||
+ clk_prepare_enable(usb_host_clock);
|
||||
+
|
||||
+ bcm63xx_usb_priv_ehci_cfg_set();
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void bcm63xx_ehci_power_off(struct platform_device *pdev)
|
||||
+{
|
||||
+ if (!IS_ERR_OR_NULL(usb_host_clock)) {
|
||||
+ clk_disable_unprepare(usb_host_clock);
|
||||
+ clk_put(usb_host_clock);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static struct usb_ehci_pdata bcm63xx_ehci_pdata = {
|
||||
+ .big_endian_desc = 1,
|
||||
+ .big_endian_mmio = 1,
|
||||
+ .power_on = bcm63xx_ehci_power_on,
|
||||
+ .power_off = bcm63xx_ehci_power_off,
|
||||
+ .power_suspend = bcm63xx_ehci_power_off,
|
||||
+};
|
||||
+
|
||||
+static struct platform_device bcm63xx_ehci_device = {
|
||||
+ .name = "ehci-platform",
|
||||
+ .id = -1,
|
||||
+ .num_resources = ARRAY_SIZE(ehci_resources),
|
||||
+ .resource = ehci_resources,
|
||||
+ .dev = {
|
||||
+ .platform_data = &bcm63xx_ehci_pdata,
|
||||
+ .dma_mask = &ehci_dmamask,
|
||||
+ .coherent_dma_mask = DMA_BIT_MASK(32),
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+int __init bcm63xx_ehci_register(void)
|
||||
+{
|
||||
+ if (!BCMCPU_IS_6328() && !BCMCPU_IS_6358() && !BCMCPU_IS_6362() && !BCMCPU_IS_6368())
|
||||
+ return 0;
|
||||
+
|
||||
+ ehci_resources[0].start = bcm63xx_regset_address(RSET_EHCI0);
|
||||
+ ehci_resources[0].end = ehci_resources[0].start;
|
||||
+ ehci_resources[0].end += RSET_EHCI_SIZE - 1;
|
||||
+ ehci_resources[1].start = bcm63xx_get_irq_number(IRQ_EHCI0);
|
||||
+
|
||||
+ return platform_device_register(&bcm63xx_ehci_device);
|
||||
+}
|
||||
--- /dev/null
|
||||
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_usb_ehci.h
|
||||
@@ -0,0 +1,6 @@
|
||||
+#ifndef BCM63XX_DEV_USB_EHCI_H_
|
||||
+#define BCM63XX_DEV_USB_EHCI_H_
|
||||
+
|
||||
+int bcm63xx_ehci_register(void);
|
||||
+
|
||||
+#endif /* BCM63XX_DEV_USB_EHCI_H_ */
|
@ -1,36 +0,0 @@
|
||||
From 709ef2034f5ba06da35f89856ad7baf2b7a41287 Mon Sep 17 00:00:00 2001
|
||||
From: Florian Fainelli <florian@openwrt.org>
|
||||
Date: Mon, 28 Jan 2013 20:06:28 +0100
|
||||
Subject: [PATCH 10/11] MIPS: BCM63XX: register EHCI controller if board
|
||||
enables it
|
||||
|
||||
BCM63XX-based board can control the registration of the EHCI controller
|
||||
by setting their has_ehci0 flag to 1. Handle this in the generic
|
||||
code dealing with board registration and call the actual helper to register
|
||||
the EHCI controller.
|
||||
|
||||
Signed-off-by: Florian Fainelli <florian@openwrt.org>
|
||||
---
|
||||
arch/mips/bcm63xx/boards/board_bcm963xx.c | 4 ++++
|
||||
1 file changed, 4 insertions(+)
|
||||
|
||||
--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
|
||||
+++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
|
||||
@@ -28,6 +28,7 @@
|
||||
#include <bcm63xx_dev_hsspi.h>
|
||||
#include <bcm63xx_dev_pcmcia.h>
|
||||
#include <bcm63xx_dev_spi.h>
|
||||
+#include <bcm63xx_dev_usb_ehci.h>
|
||||
#include <bcm63xx_dev_usb_ohci.h>
|
||||
#include <bcm63xx_dev_usb_usbd.h>
|
||||
#include <board_bcm963xx.h>
|
||||
@@ -899,6 +900,9 @@ int __init board_register_devices(void)
|
||||
if (board.has_usbd)
|
||||
bcm63xx_usbd_register(&board.usbd);
|
||||
|
||||
+ if (board.has_ehci0)
|
||||
+ bcm63xx_ehci_register();
|
||||
+
|
||||
if (board.has_ohci0)
|
||||
bcm63xx_ohci_register();
|
||||
|
@ -1,24 +0,0 @@
|
||||
From 111bbd770441ab34f9da5bb1d85767a9b75227b4 Mon Sep 17 00:00:00 2001
|
||||
From: Florian Fainelli <florian@openwrt.org>
|
||||
Date: Mon, 28 Jan 2013 20:06:30 +0100
|
||||
Subject: [PATCH 12/12] MIPS: BCM63XX: EHCI controller does not support
|
||||
overcurrent
|
||||
|
||||
This patch sets the ignore_oc flag for the BCM63XX EHCI controller as it
|
||||
does not support proper overcurrent reporting.
|
||||
|
||||
Signed-off-by: Florian Fainelli <florian@openwrt.org>
|
||||
---
|
||||
arch/mips/bcm63xx/dev-usb-ehci.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
--- a/arch/mips/bcm63xx/dev-usb-ehci.c
|
||||
+++ b/arch/mips/bcm63xx/dev-usb-ehci.c
|
||||
@@ -61,6 +61,7 @@ static void bcm63xx_ehci_power_off(struc
|
||||
static struct usb_ehci_pdata bcm63xx_ehci_pdata = {
|
||||
.big_endian_desc = 1,
|
||||
.big_endian_mmio = 1,
|
||||
+ .ignore_oc = 1,
|
||||
.power_on = bcm63xx_ehci_power_on,
|
||||
.power_off = bcm63xx_ehci_power_off,
|
||||
.power_suspend = bcm63xx_ehci_power_off,
|
@ -1,48 +0,0 @@
|
||||
From patchwork Tue Jul 18 10:17:27 2017
|
||||
Content-Type: text/plain; charset="utf-8"
|
||||
MIME-Version: 1.0
|
||||
Content-Transfer-Encoding: 7bit
|
||||
Subject: [6/9] MIPS: BCM63XX: allow NULL clock for clk_get_rate
|
||||
X-Patchwork-Submitter: Jonas Gorski <jonas.gorski@gmail.com>
|
||||
X-Patchwork-Id: 16776
|
||||
Message-Id: <20170718101730.2541-7-jonas.gorski@gmail.com>
|
||||
To: unlisted-recipients:; (no To-header on input)
|
||||
Cc: Ralf Baechle <ralf@linux-mips.org>,
|
||||
Florian Fainelli <f.fainelli@gmail.com>,
|
||||
bcm-kernel-feedback-list@broadcom.com,
|
||||
James Hogan <james.hogan@imgtec.com>,
|
||||
linux-mips@linux-mips.org, linux-kernel@vger.kernel.org
|
||||
Date: Tue, 18 Jul 2017 12:17:27 +0200
|
||||
From: Jonas Gorski <jonas.gorski@gmail.com>
|
||||
List-Id: linux-mips <linux-mips.eddie.linux-mips.org>
|
||||
|
||||
Make the behaviour of clk_get_rate consistent with common clk's
|
||||
clk_get_rate by accepting NULL clocks as parameter. Some device
|
||||
drivers rely on this, and will cause an OOPS otherwise.
|
||||
|
||||
Fixes: e7300d04bd08 ("MIPS: BCM63xx: Add support for the Broadcom BCM63xx family of SOCs.")
|
||||
Cc: Ralf Baechle <ralf@linux-mips.org>
|
||||
Cc: Florian Fainelli <f.fainelli@gmail.com>
|
||||
Cc: bcm-kernel-feedback-list@broadcom.com
|
||||
Cc: James Hogan <james.hogan@imgtec.com>
|
||||
Cc: linux-mips@linux-mips.org
|
||||
Cc: linux-kernel@vger.kernel.org
|
||||
Reported-by: Mathias Kresin <dev@kresin.me>
|
||||
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
|
||||
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
|
||||
---
|
||||
arch/mips/bcm63xx/clk.c | 3 +++
|
||||
1 file changed, 3 insertions(+)
|
||||
|
||||
--- a/arch/mips/bcm63xx/clk.c
|
||||
+++ b/arch/mips/bcm63xx/clk.c
|
||||
@@ -389,6 +389,9 @@ EXPORT_SYMBOL(clk_disable);
|
||||
|
||||
unsigned long clk_get_rate(struct clk *clk)
|
||||
{
|
||||
+ if (!clk)
|
||||
+ return 0;
|
||||
+
|
||||
return clk->rate;
|
||||
}
|
||||
|
@ -1,13 +0,0 @@
|
||||
--- a/drivers/mtd/mtdpart.c
|
||||
+++ b/drivers/mtd/mtdpart.c
|
||||
@@ -978,8 +978,8 @@ int parse_mtd_partitions(struct mtd_info
|
||||
int ret, err = 0;
|
||||
const char *const *types_of = NULL;
|
||||
|
||||
- if (data && data->of_node) {
|
||||
- types_of = of_get_probes(data->of_node);
|
||||
+ if (mtd_get_of_node(master)) {
|
||||
+ types_of = of_get_probes(mtd_get_of_node(master));
|
||||
if (types_of != NULL)
|
||||
types = types_of;
|
||||
}
|
@ -1,226 +0,0 @@
|
||||
From ab2f33e35e35905a76204138143875251f3e1088 Mon Sep 17 00:00:00 2001
|
||||
From: Jonas Gorski <jonas.gorski@gmail.com>
|
||||
Date: Fri, 24 Jun 2016 22:07:42 +0200
|
||||
Subject: [PATCH 01/13] pinctrl: add bcm63xx base code
|
||||
|
||||
Setup directory and add a helper for bcm63xx pinctrl support.
|
||||
|
||||
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
|
||||
---
|
||||
drivers/pinctrl/Kconfig | 1 +
|
||||
drivers/pinctrl/Makefile | 1 +
|
||||
drivers/pinctrl/bcm63xx/Kconfig | 3 +
|
||||
drivers/pinctrl/bcm63xx/Makefile | 1 +
|
||||
drivers/pinctrl/bcm63xx/pinctrl-bcm63xx.c | 142 ++++++++++++++++++++++++++++++
|
||||
drivers/pinctrl/bcm63xx/pinctrl-bcm63xx.h | 14 +++
|
||||
7 files changed, 163 insertions(+)
|
||||
create mode 100644 drivers/pinctrl/bcm63xx/Kconfig
|
||||
create mode 100644 drivers/pinctrl/bcm63xx/Makefile
|
||||
create mode 100644 drivers/pinctrl/bcm63xx/pinctrl-bcm63xx.c
|
||||
create mode 100644 drivers/pinctrl/bcm63xx/pinctrl-bcm63xx.h
|
||||
|
||||
--- a/drivers/pinctrl/Kconfig
|
||||
+++ b/drivers/pinctrl/Kconfig
|
||||
@@ -248,6 +248,7 @@ config PINCTRL_ZYNQ
|
||||
This selectes the pinctrl driver for Xilinx Zynq.
|
||||
|
||||
source "drivers/pinctrl/bcm/Kconfig"
|
||||
+source "drivers/pinctrl/bcm63xx/Kconfig"
|
||||
source "drivers/pinctrl/berlin/Kconfig"
|
||||
source "drivers/pinctrl/freescale/Kconfig"
|
||||
source "drivers/pinctrl/intel/Kconfig"
|
||||
--- a/drivers/pinctrl/Makefile
|
||||
+++ b/drivers/pinctrl/Makefile
|
||||
@@ -41,6 +41,7 @@ obj-$(CONFIG_PINCTRL_ST) += pinctrl-st.
|
||||
obj-$(CONFIG_PINCTRL_ZYNQ) += pinctrl-zynq.o
|
||||
|
||||
obj-$(CONFIG_ARCH_BCM) += bcm/
|
||||
+obj-y += bcm63xx/
|
||||
obj-$(CONFIG_ARCH_BERLIN) += berlin/
|
||||
obj-y += freescale/
|
||||
obj-$(CONFIG_X86) += intel/
|
||||
--- /dev/null
|
||||
+++ b/drivers/pinctrl/bcm63xx/Kconfig
|
||||
@@ -0,0 +1,3 @@
|
||||
+config PINCTRL_BCM63XX
|
||||
+ bool
|
||||
+ select GPIO_GENERIC
|
||||
--- /dev/null
|
||||
+++ b/drivers/pinctrl/bcm63xx/Makefile
|
||||
@@ -0,0 +1 @@
|
||||
+obj-$(CONFIG_PINCTRL_BCM63XX) += pinctrl-bcm63xx.o
|
||||
--- /dev/null
|
||||
+++ b/drivers/pinctrl/bcm63xx/pinctrl-bcm63xx.c
|
||||
@@ -0,0 +1,155 @@
|
||||
+/*
|
||||
+ * This file is subject to the terms and conditions of the GNU General Public
|
||||
+ * License. See the file "COPYING" in the main directory of this archive
|
||||
+ * for more details.
|
||||
+ *
|
||||
+ * Copyright (C) 2016 Jonas Gorski <jonas.gorski@gmail.com>
|
||||
+ */
|
||||
+
|
||||
+#include <linux/bitops.h>
|
||||
+#include <linux/device.h>
|
||||
+#include <linux/gpio/driver.h>
|
||||
+#include <linux/of_irq.h>
|
||||
+
|
||||
+#include "pinctrl-bcm63xx.h"
|
||||
+#include "../core.h"
|
||||
+
|
||||
+#define BANK_SIZE sizeof(u32)
|
||||
+#define PINS_PER_BANK (BANK_SIZE * BITS_PER_BYTE)
|
||||
+
|
||||
+#ifdef CONFIG_OF
|
||||
+static int bcm63xx_gpio_of_xlate(struct gpio_chip *gc,
|
||||
+ const struct of_phandle_args *gpiospec,
|
||||
+ u32 *flags)
|
||||
+{
|
||||
+ struct gpio_chip *base = gpiochip_get_data(gc);
|
||||
+ int pin = gpiospec->args[0];
|
||||
+
|
||||
+ if (gc != &base[pin / PINS_PER_BANK])
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ pin = pin % PINS_PER_BANK;
|
||||
+
|
||||
+ if (pin >= gc->ngpio)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ if (flags)
|
||||
+ *flags = gpiospec->args[1];
|
||||
+
|
||||
+ return pin;
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
+static int bcm63xx_gpio_to_irq(struct gpio_chip *chip, unsigned gpio)
|
||||
+{
|
||||
+ struct gpio_chip *base = gpiochip_get_data(chip);
|
||||
+ char irq_name[7]; /* "gpioXX" */
|
||||
+
|
||||
+ /* FIXME: this is ugly */
|
||||
+ sprintf(irq_name, "gpio%d", gpio + PINS_PER_BANK * (chip - base));
|
||||
+ return of_irq_get_byname(chip->of_node, irq_name);
|
||||
+}
|
||||
+
|
||||
+static int bcm63xx_setup_gpio(struct device *dev, struct gpio_chip *gc,
|
||||
+ void __iomem *dirout, void __iomem *data,
|
||||
+ size_t sz, int ngpio)
|
||||
+
|
||||
+{
|
||||
+ int banks, chips, i, ret = -EINVAL;
|
||||
+
|
||||
+ chips = DIV_ROUND_UP(ngpio, PINS_PER_BANK);
|
||||
+ banks = sz / BANK_SIZE;
|
||||
+
|
||||
+ for (i = 0; i < chips; i++) {
|
||||
+ int offset, pins;
|
||||
+ int reg_offset;
|
||||
+ char *label;
|
||||
+
|
||||
+ label = devm_kasprintf(dev, GFP_KERNEL, "bcm63xx-gpio.%i", i);
|
||||
+ if (!label)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ offset = i * PINS_PER_BANK;
|
||||
+ pins = min_t(int, ngpio - offset, PINS_PER_BANK);
|
||||
+
|
||||
+ /* the registers are treated like a huge big endian register */
|
||||
+ reg_offset = (banks - i - 1) * BANK_SIZE;
|
||||
+
|
||||
+ ret = bgpio_init(&gc[i], dev, BANK_SIZE, data + reg_offset,
|
||||
+ NULL, NULL, dirout + reg_offset, NULL,
|
||||
+ BGPIOF_BIG_ENDIAN_BYTE_ORDER);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ gc[i].request = gpiochip_generic_request;
|
||||
+ gc[i].free = gpiochip_generic_free;
|
||||
+
|
||||
+ if (of_get_property(dev->of_node, "interrupt-names", NULL))
|
||||
+ gc[i].to_irq = bcm63xx_gpio_to_irq;
|
||||
+
|
||||
+#ifdef CONFIG_OF
|
||||
+ gc[i].of_gpio_n_cells = 2;
|
||||
+ gc[i].of_xlate = bcm63xx_gpio_of_xlate;
|
||||
+#endif
|
||||
+
|
||||
+ gc[i].label = label;
|
||||
+ gc[i].ngpio = pins;
|
||||
+
|
||||
+ devm_gpiochip_add_data(dev, &gc[i], gc);
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void bcm63xx_setup_pinranges(struct gpio_chip *gc, const char *name,
|
||||
+ int ngpio)
|
||||
+{
|
||||
+ int i, chips = DIV_ROUND_UP(ngpio, PINS_PER_BANK);
|
||||
+
|
||||
+ for (i = 0; i < chips; i++) {
|
||||
+ int offset, pins;
|
||||
+
|
||||
+ offset = i * PINS_PER_BANK;
|
||||
+ pins = min_t(int, ngpio - offset, PINS_PER_BANK);
|
||||
+
|
||||
+ gpiochip_add_pin_range(&gc[i], name, 0, offset, pins);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+struct pinctrl_dev *bcm63xx_pinctrl_register(struct platform_device *pdev,
|
||||
+ struct pinctrl_desc *desc,
|
||||
+ void *priv, struct gpio_chip *gc,
|
||||
+ int ngpio)
|
||||
+{
|
||||
+ struct pinctrl_dev *pctldev;
|
||||
+ struct resource *res;
|
||||
+ void __iomem *dirout, *data;
|
||||
+ size_t sz;
|
||||
+ int ret;
|
||||
+
|
||||
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dirout");
|
||||
+ dirout = devm_ioremap_resource(&pdev->dev, res);
|
||||
+ if (IS_ERR(dirout))
|
||||
+ return ERR_CAST(dirout);
|
||||
+
|
||||
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dat");
|
||||
+ data = devm_ioremap_resource(&pdev->dev, res);
|
||||
+ if (IS_ERR(data))
|
||||
+ return ERR_CAST(data);
|
||||
+
|
||||
+ sz = resource_size(res);
|
||||
+
|
||||
+ ret = bcm63xx_setup_gpio(&pdev->dev, gc, dirout, data, sz, ngpio);
|
||||
+ if (ret)
|
||||
+ return ERR_PTR(ret);
|
||||
+
|
||||
+ pctldev = devm_pinctrl_register(&pdev->dev, desc, priv);
|
||||
+ if (IS_ERR(pctldev))
|
||||
+ return pctldev;
|
||||
+
|
||||
+ bcm63xx_setup_pinranges(gc, pinctrl_dev_get_devname(pctldev), ngpio);
|
||||
+
|
||||
+ dev_info(&pdev->dev, "registered at mmio %p\n", dirout);
|
||||
+
|
||||
+ return pctldev;
|
||||
+}
|
||||
--- /dev/null
|
||||
+++ b/drivers/pinctrl/bcm63xx/pinctrl-bcm63xx.h
|
||||
@@ -0,0 +1,14 @@
|
||||
+#ifndef __PINCTRL_BCM63XX
|
||||
+#define __PINCTRL_BCM63XX
|
||||
+
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/gpio.h>
|
||||
+#include <linux/pinctrl/pinctrl.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+
|
||||
+struct pinctrl_dev *bcm63xx_pinctrl_register(struct platform_device *pdev,
|
||||
+ struct pinctrl_desc *desc,
|
||||
+ void *priv, struct gpio_chip *gc,
|
||||
+ int ngpio);
|
||||
+
|
||||
+#endif
|
@ -1,78 +0,0 @@
|
||||
From 4bdd40849632608d5cb7d3a64380cd76e7eea07b Mon Sep 17 00:00:00 2001
|
||||
From: Jonas Gorski <jonas.gorski@gmail.com>
|
||||
Date: Wed, 27 Jul 2016 11:33:56 +0200
|
||||
Subject: [PATCH 02/16] Documentation: add BCM6328 pincontroller binding
|
||||
documentation
|
||||
|
||||
Add binding documentation for the pincontrol core found in BCM6328 SoCs.
|
||||
|
||||
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
|
||||
---
|
||||
.../bindings/pinctrl/brcm,bcm6328-pinctrl.txt | 61 ++++++++++++++++++++++
|
||||
1 file changed, 61 insertions(+)
|
||||
create mode 100644 Documentation/devicetree/bindings/pinctrl/brcm,bcm6328-pinctrl.txt
|
||||
|
||||
--- /dev/null
|
||||
+++ b/Documentation/devicetree/bindings/pinctrl/brcm,bcm6328-pinctrl.txt
|
||||
@@ -0,0 +1,61 @@
|
||||
+* Broadcom BCM6328 pin controller
|
||||
+
|
||||
+Required properties:
|
||||
+- compatible: Must be "brcm,bcm6328-pinctrl".
|
||||
+- reg: Register specifies of dirout, dat, mode, mux registers.
|
||||
+- reg-names: Must be "dirout", "dat", "mode", "mux".
|
||||
+- gpio-controller: Identifies this node as a GPIO controller.
|
||||
+- #gpio-cells: Must be <2>
|
||||
+
|
||||
+Example:
|
||||
+
|
||||
+pinctrl: pin-controller@10000080 {
|
||||
+ compatible = "brcm,bcm6328-pinctrl";
|
||||
+ reg = <0x10000080 0x8>,
|
||||
+ <0x10000088 0x8>,
|
||||
+ <0x10000098 0x4>,
|
||||
+ <0x1000009c 0xc>;
|
||||
+ reg-names = "dirout", "dat", "mode", "mux";
|
||||
+
|
||||
+ gpio-controller;
|
||||
+ #gpio-cells = <2>;
|
||||
+};
|
||||
+
|
||||
+Available pins/groups and functions:
|
||||
+
|
||||
+name pins functions
|
||||
+-----------------------------------------------------------
|
||||
+gpio0 0 led
|
||||
+gpio1 1 led
|
||||
+gpio2 2 led
|
||||
+gpio3 3 led
|
||||
+gpio4 4 led
|
||||
+gpio5 5 led
|
||||
+gpio6 6 led, serial_led_data
|
||||
+gpio7 7 led, serial_led_clk
|
||||
+gpio8 8 led
|
||||
+gpio9 9 led
|
||||
+gpio10 10 led
|
||||
+gpio11 11 led
|
||||
+gpio12 12 led
|
||||
+gpio13 13 led
|
||||
+gpio14 14 led
|
||||
+gpio15 15 led
|
||||
+gpio16 16 led, pcie_clkreq
|
||||
+gpio17 17 led
|
||||
+gpio18 18 led
|
||||
+gpio19 19 led
|
||||
+gpio20 20 led
|
||||
+gpio21 21 led
|
||||
+gpio22 22 led
|
||||
+gpio23 23 led
|
||||
+gpio24 24 -
|
||||
+gpio25 25 ephy0_act_led
|
||||
+gpio26 26 ephy1_act_led
|
||||
+gpio27 27 ephy2_act_led
|
||||
+gpio28 28 ephy3_act_led
|
||||
+gpio29 29 -
|
||||
+gpio30 30 -
|
||||
+gpio31 31 -
|
||||
+hsspi_cs1 - hsspi_cs1
|
||||
+usb_port1 - usb_host_port, usb_device_port
|
@ -1,495 +0,0 @@
|
||||
From 393e9753f6492c1fdf55891ddee60d955ae8b119 Mon Sep 17 00:00:00 2001
|
||||
From: Jonas Gorski <jonas.gorski@gmail.com>
|
||||
Date: Fri, 24 Jun 2016 22:12:50 +0200
|
||||
Subject: [PATCH 03/16] pinctrl: add a pincontrol driver for BCM6328
|
||||
|
||||
Add a pincontrol driver for BCM6328. BCM628 supports muxing 32 pins as
|
||||
GPIOs, as LEDs for the integrated LED controller, or various other
|
||||
functions. Its pincontrol mux registers also control other aspects, like
|
||||
switching the second USB port between host and device mode.
|
||||
|
||||
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
|
||||
---
|
||||
drivers/pinctrl/bcm63xx/Kconfig | 7 +
|
||||
drivers/pinctrl/bcm63xx/Makefile | 1 +
|
||||
drivers/pinctrl/bcm63xx/pinctrl-bcm6328.c | 456 ++++++++++++++++++++++++++++++
|
||||
3 files changed, 464 insertions(+)
|
||||
create mode 100644 drivers/pinctrl/bcm63xx/pinctrl-bcm6328.c
|
||||
|
||||
--- a/drivers/pinctrl/bcm63xx/Kconfig
|
||||
+++ b/drivers/pinctrl/bcm63xx/Kconfig
|
||||
@@ -1,3 +1,10 @@
|
||||
config PINCTRL_BCM63XX
|
||||
bool
|
||||
select GPIO_GENERIC
|
||||
+
|
||||
+config PINCTRL_BCM6328
|
||||
+ bool "BCM6328 pincontrol driver" if COMPILE_TEST
|
||||
+ select PINMUX
|
||||
+ select PINCONF
|
||||
+ select PINCTRL_BCM63XX
|
||||
+ select GENERIC_PINCONF
|
||||
--- a/drivers/pinctrl/bcm63xx/Makefile
|
||||
+++ b/drivers/pinctrl/bcm63xx/Makefile
|
||||
@@ -1 +1,2 @@
|
||||
obj-$(CONFIG_PINCTRL_BCM63XX) += pinctrl-bcm63xx.o
|
||||
+obj-$(CONFIG_PINCTRL_BCM6328) += pinctrl-bcm6328.o
|
||||
--- /dev/null
|
||||
+++ b/drivers/pinctrl/bcm63xx/pinctrl-bcm6328.c
|
||||
@@ -0,0 +1,456 @@
|
||||
+/*
|
||||
+ * This file is subject to the terms and conditions of the GNU General Public
|
||||
+ * License. See the file "COPYING" in the main directory of this archive
|
||||
+ * for more details.
|
||||
+ *
|
||||
+ * Copyright (C) 2016 Jonas Gorski <jonas.gorski@gmail.com>
|
||||
+ */
|
||||
+
|
||||
+#include <linux/bitops.h>
|
||||
+#include <linux/gpio.h>
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/slab.h>
|
||||
+#include <linux/spinlock.h>
|
||||
+#include <linux/of.h>
|
||||
+#include <linux/of_gpio.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+
|
||||
+#include <linux/pinctrl/machine.h>
|
||||
+#include <linux/pinctrl/pinconf.h>
|
||||
+#include <linux/pinctrl/pinconf-generic.h>
|
||||
+#include <linux/pinctrl/pinmux.h>
|
||||
+
|
||||
+#include "../core.h"
|
||||
+#include "../pinctrl-utils.h"
|
||||
+
|
||||
+#include "pinctrl-bcm63xx.h"
|
||||
+
|
||||
+#define BCM6328_MUX_LO_REG 0x4
|
||||
+#define BCM6328_MUX_HI_REG 0x0
|
||||
+#define BCM6328_MUX_OTHER_REG 0x8
|
||||
+
|
||||
+#define BCM6328_NGPIO 32
|
||||
+
|
||||
+struct bcm6328_pingroup {
|
||||
+ const char *name;
|
||||
+ const unsigned * const pins;
|
||||
+ const unsigned num_pins;
|
||||
+};
|
||||
+
|
||||
+struct bcm6328_function {
|
||||
+ const char *name;
|
||||
+ const char * const *groups;
|
||||
+ const unsigned num_groups;
|
||||
+
|
||||
+ unsigned mode_val:1;
|
||||
+ unsigned mux_val:2;
|
||||
+};
|
||||
+
|
||||
+struct bcm6328_pinctrl {
|
||||
+ struct pinctrl_dev *pctldev;
|
||||
+ struct pinctrl_desc desc;
|
||||
+
|
||||
+ void __iomem *mode;
|
||||
+ void __iomem *mux[3];
|
||||
+
|
||||
+ /* register access lock */
|
||||
+ spinlock_t lock;
|
||||
+
|
||||
+ struct gpio_chip gpio;
|
||||
+};
|
||||
+
|
||||
+static const struct pinctrl_pin_desc bcm6328_pins[] = {
|
||||
+ PINCTRL_PIN(0, "gpio0"),
|
||||
+ PINCTRL_PIN(1, "gpio1"),
|
||||
+ PINCTRL_PIN(2, "gpio2"),
|
||||
+ PINCTRL_PIN(3, "gpio3"),
|
||||
+ PINCTRL_PIN(4, "gpio4"),
|
||||
+ PINCTRL_PIN(5, "gpio5"),
|
||||
+ PINCTRL_PIN(6, "gpio6"),
|
||||
+ PINCTRL_PIN(7, "gpio7"),
|
||||
+ PINCTRL_PIN(8, "gpio8"),
|
||||
+ PINCTRL_PIN(9, "gpio9"),
|
||||
+ PINCTRL_PIN(10, "gpio10"),
|
||||
+ PINCTRL_PIN(11, "gpio11"),
|
||||
+ PINCTRL_PIN(12, "gpio12"),
|
||||
+ PINCTRL_PIN(13, "gpio13"),
|
||||
+ PINCTRL_PIN(14, "gpio14"),
|
||||
+ PINCTRL_PIN(15, "gpio15"),
|
||||
+ PINCTRL_PIN(16, "gpio16"),
|
||||
+ PINCTRL_PIN(17, "gpio17"),
|
||||
+ PINCTRL_PIN(18, "gpio18"),
|
||||
+ PINCTRL_PIN(19, "gpio19"),
|
||||
+ PINCTRL_PIN(20, "gpio20"),
|
||||
+ PINCTRL_PIN(21, "gpio21"),
|
||||
+ PINCTRL_PIN(22, "gpio22"),
|
||||
+ PINCTRL_PIN(23, "gpio23"),
|
||||
+ PINCTRL_PIN(24, "gpio24"),
|
||||
+ PINCTRL_PIN(25, "gpio25"),
|
||||
+ PINCTRL_PIN(26, "gpio26"),
|
||||
+ PINCTRL_PIN(27, "gpio27"),
|
||||
+ PINCTRL_PIN(28, "gpio28"),
|
||||
+ PINCTRL_PIN(29, "gpio29"),
|
||||
+ PINCTRL_PIN(30, "gpio30"),
|
||||
+ PINCTRL_PIN(31, "gpio31"),
|
||||
+
|
||||
+ /*
|
||||
+ * No idea where they really are; so let's put them according
|
||||
+ * to their mux offsets.
|
||||
+ */
|
||||
+ PINCTRL_PIN(36, "hsspi_cs1"),
|
||||
+ PINCTRL_PIN(38, "usb_p2"),
|
||||
+};
|
||||
+
|
||||
+static unsigned gpio0_pins[] = { 0 };
|
||||
+static unsigned gpio1_pins[] = { 1 };
|
||||
+static unsigned gpio2_pins[] = { 2 };
|
||||
+static unsigned gpio3_pins[] = { 3 };
|
||||
+static unsigned gpio4_pins[] = { 4 };
|
||||
+static unsigned gpio5_pins[] = { 5 };
|
||||
+static unsigned gpio6_pins[] = { 6 };
|
||||
+static unsigned gpio7_pins[] = { 7 };
|
||||
+static unsigned gpio8_pins[] = { 8 };
|
||||
+static unsigned gpio9_pins[] = { 9 };
|
||||
+static unsigned gpio10_pins[] = { 10 };
|
||||
+static unsigned gpio11_pins[] = { 11 };
|
||||
+static unsigned gpio12_pins[] = { 12 };
|
||||
+static unsigned gpio13_pins[] = { 13 };
|
||||
+static unsigned gpio14_pins[] = { 14 };
|
||||
+static unsigned gpio15_pins[] = { 15 };
|
||||
+static unsigned gpio16_pins[] = { 16 };
|
||||
+static unsigned gpio17_pins[] = { 17 };
|
||||
+static unsigned gpio18_pins[] = { 18 };
|
||||
+static unsigned gpio19_pins[] = { 19 };
|
||||
+static unsigned gpio20_pins[] = { 20 };
|
||||
+static unsigned gpio21_pins[] = { 21 };
|
||||
+static unsigned gpio22_pins[] = { 22 };
|
||||
+static unsigned gpio23_pins[] = { 23 };
|
||||
+static unsigned gpio24_pins[] = { 24 };
|
||||
+static unsigned gpio25_pins[] = { 25 };
|
||||
+static unsigned gpio26_pins[] = { 26 };
|
||||
+static unsigned gpio27_pins[] = { 27 };
|
||||
+static unsigned gpio28_pins[] = { 28 };
|
||||
+static unsigned gpio29_pins[] = { 29 };
|
||||
+static unsigned gpio30_pins[] = { 30 };
|
||||
+static unsigned gpio31_pins[] = { 31 };
|
||||
+
|
||||
+static unsigned hsspi_cs1_pins[] = { 36 };
|
||||
+static unsigned usb_port1_pins[] = { 38 };
|
||||
+
|
||||
+#define BCM6328_GROUP(n) \
|
||||
+ { \
|
||||
+ .name = #n, \
|
||||
+ .pins = n##_pins, \
|
||||
+ .num_pins = ARRAY_SIZE(n##_pins), \
|
||||
+ }
|
||||
+
|
||||
+static struct bcm6328_pingroup bcm6328_groups[] = {
|
||||
+ BCM6328_GROUP(gpio0),
|
||||
+ BCM6328_GROUP(gpio1),
|
||||
+ BCM6328_GROUP(gpio2),
|
||||
+ BCM6328_GROUP(gpio3),
|
||||
+ BCM6328_GROUP(gpio4),
|
||||
+ BCM6328_GROUP(gpio5),
|
||||
+ BCM6328_GROUP(gpio6),
|
||||
+ BCM6328_GROUP(gpio7),
|
||||
+ BCM6328_GROUP(gpio8),
|
||||
+ BCM6328_GROUP(gpio9),
|
||||
+ BCM6328_GROUP(gpio10),
|
||||
+ BCM6328_GROUP(gpio11),
|
||||
+ BCM6328_GROUP(gpio12),
|
||||
+ BCM6328_GROUP(gpio13),
|
||||
+ BCM6328_GROUP(gpio14),
|
||||
+ BCM6328_GROUP(gpio15),
|
||||
+ BCM6328_GROUP(gpio16),
|
||||
+ BCM6328_GROUP(gpio17),
|
||||
+ BCM6328_GROUP(gpio18),
|
||||
+ BCM6328_GROUP(gpio19),
|
||||
+ BCM6328_GROUP(gpio20),
|
||||
+ BCM6328_GROUP(gpio21),
|
||||
+ BCM6328_GROUP(gpio22),
|
||||
+ BCM6328_GROUP(gpio23),
|
||||
+ BCM6328_GROUP(gpio24),
|
||||
+ BCM6328_GROUP(gpio25),
|
||||
+ BCM6328_GROUP(gpio26),
|
||||
+ BCM6328_GROUP(gpio27),
|
||||
+ BCM6328_GROUP(gpio28),
|
||||
+ BCM6328_GROUP(gpio29),
|
||||
+ BCM6328_GROUP(gpio30),
|
||||
+ BCM6328_GROUP(gpio31),
|
||||
+
|
||||
+ BCM6328_GROUP(hsspi_cs1),
|
||||
+ BCM6328_GROUP(usb_port1),
|
||||
+};
|
||||
+
|
||||
+/* GPIO_MODE */
|
||||
+static const char * const led_groups[] = {
|
||||
+ "gpio0",
|
||||
+ "gpio1",
|
||||
+ "gpio2",
|
||||
+ "gpio3",
|
||||
+ "gpio4",
|
||||
+ "gpio5",
|
||||
+ "gpio6",
|
||||
+ "gpio7",
|
||||
+ "gpio8",
|
||||
+ "gpio9",
|
||||
+ "gpio10",
|
||||
+ "gpio11",
|
||||
+ "gpio12",
|
||||
+ "gpio13",
|
||||
+ "gpio14",
|
||||
+ "gpio15",
|
||||
+ "gpio16",
|
||||
+ "gpio17",
|
||||
+ "gpio18",
|
||||
+ "gpio19",
|
||||
+ "gpio20",
|
||||
+ "gpio21",
|
||||
+ "gpio22",
|
||||
+ "gpio23",
|
||||
+};
|
||||
+
|
||||
+/* PINMUX_SEL */
|
||||
+static const char * const serial_led_data_groups[] = {
|
||||
+ "gpio6",
|
||||
+};
|
||||
+
|
||||
+static const char * const serial_led_clk_groups[] = {
|
||||
+ "gpio7",
|
||||
+};
|
||||
+
|
||||
+static const char * const inet_act_led_groups[] = {
|
||||
+ "gpio11",
|
||||
+};
|
||||
+
|
||||
+static const char * const pcie_clkreq_groups[] = {
|
||||
+ "gpio16",
|
||||
+};
|
||||
+
|
||||
+static const char * const ephy0_act_led_groups[] = {
|
||||
+ "gpio25",
|
||||
+};
|
||||
+
|
||||
+static const char * const ephy1_act_led_groups[] = {
|
||||
+ "gpio26",
|
||||
+};
|
||||
+
|
||||
+static const char * const ephy2_act_led_groups[] = {
|
||||
+ "gpio27",
|
||||
+};
|
||||
+
|
||||
+static const char * const ephy3_act_led_groups[] = {
|
||||
+ "gpio28",
|
||||
+};
|
||||
+
|
||||
+static const char * const hsspi_cs1_groups[] = {
|
||||
+ "hsspi_cs1"
|
||||
+};
|
||||
+
|
||||
+static const char * const usb_host_port_groups[] = {
|
||||
+ "usb_port1",
|
||||
+};
|
||||
+
|
||||
+static const char * const usb_device_port_groups[] = {
|
||||
+ "usb_port1",
|
||||
+};
|
||||
+
|
||||
+#define BCM6328_MODE_FUN(n) \
|
||||
+ { \
|
||||
+ .name = #n, \
|
||||
+ .groups = n##_groups, \
|
||||
+ .num_groups = ARRAY_SIZE(n##_groups), \
|
||||
+ .mode_val = 1, \
|
||||
+ }
|
||||
+
|
||||
+#define BCM6328_MUX_FUN(n, mux) \
|
||||
+ { \
|
||||
+ .name = #n, \
|
||||
+ .groups = n##_groups, \
|
||||
+ .num_groups = ARRAY_SIZE(n##_groups), \
|
||||
+ .mux_val = mux, \
|
||||
+ }
|
||||
+
|
||||
+static const struct bcm6328_function bcm6328_funcs[] = {
|
||||
+ BCM6328_MODE_FUN(led),
|
||||
+ BCM6328_MUX_FUN(serial_led_data, 2),
|
||||
+ BCM6328_MUX_FUN(serial_led_clk, 2),
|
||||
+ BCM6328_MUX_FUN(inet_act_led, 1),
|
||||
+ BCM6328_MUX_FUN(pcie_clkreq, 2),
|
||||
+ BCM6328_MUX_FUN(ephy0_act_led, 1),
|
||||
+ BCM6328_MUX_FUN(ephy1_act_led, 1),
|
||||
+ BCM6328_MUX_FUN(ephy2_act_led, 1),
|
||||
+ BCM6328_MUX_FUN(ephy3_act_led, 1),
|
||||
+ BCM6328_MUX_FUN(hsspi_cs1, 2),
|
||||
+ BCM6328_MUX_FUN(usb_host_port, 1),
|
||||
+ BCM6328_MUX_FUN(usb_device_port, 2),
|
||||
+};
|
||||
+
|
||||
+static int bcm6328_pinctrl_get_group_count(struct pinctrl_dev *pctldev)
|
||||
+{
|
||||
+ return ARRAY_SIZE(bcm6328_groups);
|
||||
+}
|
||||
+
|
||||
+static const char *bcm6328_pinctrl_get_group_name(struct pinctrl_dev *pctldev,
|
||||
+ unsigned group)
|
||||
+{
|
||||
+ return bcm6328_groups[group].name;
|
||||
+}
|
||||
+
|
||||
+static int bcm6328_pinctrl_get_group_pins(struct pinctrl_dev *pctldev,
|
||||
+ unsigned group, const unsigned **pins,
|
||||
+ unsigned *num_pins)
|
||||
+{
|
||||
+ *pins = bcm6328_groups[group].pins;
|
||||
+ *num_pins = bcm6328_groups[group].num_pins;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int bcm6328_pinctrl_get_func_count(struct pinctrl_dev *pctldev)
|
||||
+{
|
||||
+ return ARRAY_SIZE(bcm6328_funcs);
|
||||
+}
|
||||
+
|
||||
+static const char *bcm6328_pinctrl_get_func_name(struct pinctrl_dev *pctldev,
|
||||
+ unsigned selector)
|
||||
+{
|
||||
+ return bcm6328_funcs[selector].name;
|
||||
+}
|
||||
+
|
||||
+static int bcm6328_pinctrl_get_groups(struct pinctrl_dev *pctldev,
|
||||
+ unsigned selector,
|
||||
+ const char * const **groups,
|
||||
+ unsigned * const num_groups)
|
||||
+{
|
||||
+ *groups = bcm6328_funcs[selector].groups;
|
||||
+ *num_groups = bcm6328_funcs[selector].num_groups;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void bcm6328_rmw_mux(struct bcm6328_pinctrl *pctl, unsigned pin,
|
||||
+ u32 mode, u32 mux)
|
||||
+{
|
||||
+ unsigned long flags;
|
||||
+ u32 reg;
|
||||
+
|
||||
+ spin_lock_irqsave(&pctl->lock, flags);
|
||||
+ if (pin < 32) {
|
||||
+ reg = __raw_readl(pctl->mode);
|
||||
+ reg &= ~BIT(pin);
|
||||
+ if (mode)
|
||||
+ reg |= BIT(pin);
|
||||
+ __raw_writel(reg, pctl->mode);
|
||||
+ }
|
||||
+
|
||||
+ reg = __raw_readl(pctl->mux[pin / 16]);
|
||||
+ reg &= ~(3UL << ((pin % 16) * 2));
|
||||
+ reg |= mux << ((pin % 16) * 2);
|
||||
+ __raw_writel(reg, pctl->mux[pin / 16]);
|
||||
+
|
||||
+ spin_unlock_irqrestore(&pctl->lock, flags);
|
||||
+}
|
||||
+
|
||||
+static int bcm6328_pinctrl_set_mux(struct pinctrl_dev *pctldev,
|
||||
+ unsigned selector, unsigned group)
|
||||
+{
|
||||
+ struct bcm6328_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
|
||||
+ const struct bcm6328_pingroup *grp = &bcm6328_groups[group];
|
||||
+ const struct bcm6328_function *f = &bcm6328_funcs[selector];
|
||||
+
|
||||
+ bcm6328_rmw_mux(pctl, grp->pins[0], f->mode_val, f->mux_val);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int bcm6328_gpio_request_enable(struct pinctrl_dev *pctldev,
|
||||
+ struct pinctrl_gpio_range *range,
|
||||
+ unsigned offset)
|
||||
+{
|
||||
+ struct bcm6328_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
|
||||
+
|
||||
+ /* disable all functions using this pin */
|
||||
+ bcm6328_rmw_mux(pctl, offset, 0, 0);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static struct pinctrl_ops bcm6328_pctl_ops = {
|
||||
+ .get_groups_count = bcm6328_pinctrl_get_group_count,
|
||||
+ .get_group_name = bcm6328_pinctrl_get_group_name,
|
||||
+ .get_group_pins = bcm6328_pinctrl_get_group_pins,
|
||||
+#ifdef CONFIG_OF
|
||||
+ .dt_node_to_map = pinconf_generic_dt_node_to_map_pin,
|
||||
+ .dt_free_map = pinctrl_utils_free_map,
|
||||
+#endif
|
||||
+};
|
||||
+
|
||||
+static struct pinmux_ops bcm6328_pmx_ops = {
|
||||
+ .get_functions_count = bcm6328_pinctrl_get_func_count,
|
||||
+ .get_function_name = bcm6328_pinctrl_get_func_name,
|
||||
+ .get_function_groups = bcm6328_pinctrl_get_groups,
|
||||
+ .set_mux = bcm6328_pinctrl_set_mux,
|
||||
+ .gpio_request_enable = bcm6328_gpio_request_enable,
|
||||
+ .strict = true,
|
||||
+};
|
||||
+
|
||||
+static int bcm6328_pinctrl_probe(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct bcm6328_pinctrl *pctl;
|
||||
+ struct resource *res;
|
||||
+ void __iomem *mode, *mux;
|
||||
+
|
||||
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mode");
|
||||
+ mode = devm_ioremap_resource(&pdev->dev, res);
|
||||
+ if (IS_ERR(mode))
|
||||
+ return PTR_ERR(mode);
|
||||
+
|
||||
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mux");
|
||||
+ mux = devm_ioremap_resource(&pdev->dev, res);
|
||||
+ if (IS_ERR(mux))
|
||||
+ return PTR_ERR(mux);
|
||||
+
|
||||
+ pctl = devm_kzalloc(&pdev->dev, sizeof(*pctl), GFP_KERNEL);
|
||||
+ if (!pctl)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ spin_lock_init(&pctl->lock);
|
||||
+
|
||||
+ pctl->mode = mode;
|
||||
+ pctl->mux[0] = mux + BCM6328_MUX_LO_REG;
|
||||
+ pctl->mux[1] = mux + BCM6328_MUX_HI_REG;
|
||||
+ pctl->mux[2] = mux + BCM6328_MUX_OTHER_REG;
|
||||
+
|
||||
+ pctl->desc.name = dev_name(&pdev->dev);
|
||||
+ pctl->desc.owner = THIS_MODULE;
|
||||
+ pctl->desc.pctlops = &bcm6328_pctl_ops;
|
||||
+ pctl->desc.pmxops = &bcm6328_pmx_ops;
|
||||
+
|
||||
+ pctl->desc.npins = ARRAY_SIZE(bcm6328_pins);
|
||||
+ pctl->desc.pins = bcm6328_pins;
|
||||
+
|
||||
+ platform_set_drvdata(pdev, pctl);
|
||||
+
|
||||
+ pctl->pctldev = bcm63xx_pinctrl_register(pdev, &pctl->desc, pctl,
|
||||
+ &pctl->gpio, BCM6328_NGPIO);
|
||||
+ if (IS_ERR(pctl->pctldev))
|
||||
+ return PTR_ERR(pctl->pctldev);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static const struct of_device_id bcm6328_pinctrl_match[] = {
|
||||
+ { .compatible = "brcm,bcm6328-pinctrl", },
|
||||
+ { },
|
||||
+};
|
||||
+
|
||||
+static struct platform_driver bcm6328_pinctrl_driver = {
|
||||
+ .probe = bcm6328_pinctrl_probe,
|
||||
+ .driver = {
|
||||
+ .name = "bcm6328-pinctrl",
|
||||
+ .of_match_table = bcm6328_pinctrl_match,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+builtin_platform_driver(bcm6328_pinctrl_driver);
|
@ -1,49 +0,0 @@
|
||||
From 962c46bf7f43df730e2d3698930e77958cc6b191 Mon Sep 17 00:00:00 2001
|
||||
From: Jonas Gorski <jonas.gorski@gmail.com>
|
||||
Date: Wed, 27 Jul 2016 11:35:45 +0200
|
||||
Subject: [PATCH 04/16] Documentation: add BCM6348 pincontroller binding
|
||||
documentation
|
||||
|
||||
Add binding documentation for the pincontrol core found in BCM6348 SoCs.
|
||||
|
||||
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
|
||||
---
|
||||
.../bindings/pinctrl/brcm,bcm6348-pinctrl.txt | 32 ++++++++++++++++++++++
|
||||
1 file changed, 32 insertions(+)
|
||||
create mode 100644 Documentation/devicetree/bindings/pinctrl/brcm,bcm6348-pinctrl.txt
|
||||
|
||||
--- /dev/null
|
||||
+++ b/Documentation/devicetree/bindings/pinctrl/brcm,bcm6348-pinctrl.txt
|
||||
@@ -0,0 +1,32 @@
|
||||
+* Broadcom BCM6348 pin controller
|
||||
+
|
||||
+Required properties:
|
||||
+- compatible: Must be "brcm,bcm6348-pinctrl".
|
||||
+- reg: register Specifiers of dirout, dat, mode registers.
|
||||
+- reg-names: Must be "dirout", "dat", "mode".
|
||||
+- gpio-controller: Identifies this node as a GPIO controller.
|
||||
+- #gpio-cells: Must be <2>.
|
||||
+
|
||||
+Example:
|
||||
+
|
||||
+pinctrl: pin-controller@fffe0080 {
|
||||
+ compatible = "brcm,bcm6348-pinctrl";
|
||||
+ reg = <0xfffe0080 0x8>,
|
||||
+ <0xfffe0088 0x8>,
|
||||
+ <0xfffe0098 0x4>;
|
||||
+ reg-names = "dirout", "dat", "mode";
|
||||
+
|
||||
+ gpio-controller;
|
||||
+ #gpio-cells = <2>;
|
||||
+};
|
||||
+
|
||||
+Available pins/groups and functions:
|
||||
+
|
||||
+name pins functions
|
||||
+-----------------------------------------------------------
|
||||
+group0 32-36 ext_mii, utopia, diag
|
||||
+group1 22-31 ext_ephy, mii_snoop, mii_pccard,
|
||||
+ spi_master_uart, utopia, diag
|
||||
+group2 16-21 pci, diag
|
||||
+group3 8-15 ext_mii, utopia
|
||||
+group4 0-7 ext_ephy, mii_snoop, legacy_led, diag
|
@ -1,432 +0,0 @@
|
||||
From 45444cb631555e2dc16b95d779b10aa075c7482e Mon Sep 17 00:00:00 2001
|
||||
From: Jonas Gorski <jonas.gorski@gmail.com>
|
||||
Date: Fri, 24 Jun 2016 22:14:13 +0200
|
||||
Subject: [PATCH 05/16] pinctrl: add a pincontrol driver for BCM6348
|
||||
|
||||
Add a pincotrol driver for BCM6348. BCM6348 allow muxing five groups of
|
||||
up to ten gpios into fourteen potential functions. It does not allow
|
||||
muxing individual pins. Some functions require more than one group to be
|
||||
muxed to the same function.
|
||||
|
||||
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
|
||||
---
|
||||
drivers/pinctrl/bcm63xx/Kconfig | 7 +
|
||||
drivers/pinctrl/bcm63xx/Makefile | 1 +
|
||||
drivers/pinctrl/bcm63xx/pinctrl-bcm6348.c | 392 ++++++++++++++++++++++++++++++
|
||||
3 files changed, 400 insertions(+)
|
||||
create mode 100644 drivers/pinctrl/bcm63xx/pinctrl-bcm6348.c
|
||||
|
||||
--- a/drivers/pinctrl/bcm63xx/Kconfig
|
||||
+++ b/drivers/pinctrl/bcm63xx/Kconfig
|
||||
@@ -8,3 +8,10 @@ config PINCTRL_BCM6328
|
||||
select PINCONF
|
||||
select PINCTRL_BCM63XX
|
||||
select GENERIC_PINCONF
|
||||
+
|
||||
+config PINCTRL_BCM6348
|
||||
+ bool "BCM6348 pincontrol driver" if COMPILE_TEST
|
||||
+ select PINMUX
|
||||
+ select PINCONF
|
||||
+ select PINCTRL_BCM63XX
|
||||
+ select GENERIC_PINCONF
|
||||
--- a/drivers/pinctrl/bcm63xx/Makefile
|
||||
+++ b/drivers/pinctrl/bcm63xx/Makefile
|
||||
@@ -1,2 +1,3 @@
|
||||
obj-$(CONFIG_PINCTRL_BCM63XX) += pinctrl-bcm63xx.o
|
||||
obj-$(CONFIG_PINCTRL_BCM6328) += pinctrl-bcm6328.o
|
||||
+obj-$(CONFIG_PINCTRL_BCM6348) += pinctrl-bcm6348.o
|
||||
--- /dev/null
|
||||
+++ b/drivers/pinctrl/bcm63xx/pinctrl-bcm6348.c
|
||||
@@ -0,0 +1,392 @@
|
||||
+/*
|
||||
+ * This file is subject to the terms and conditions of the GNU General Public
|
||||
+ * License. See the file "COPYING" in the main directory of this archive
|
||||
+ * for more details.
|
||||
+ *
|
||||
+ * Copyright (C) 2016 Jonas Gorski <jonas.gorski@gmail.com>
|
||||
+ */
|
||||
+
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/spinlock.h>
|
||||
+#include <linux/bitops.h>
|
||||
+#include <linux/gpio.h>
|
||||
+#include <linux/of.h>
|
||||
+#include <linux/of_gpio.h>
|
||||
+#include <linux/slab.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+
|
||||
+#include <linux/pinctrl/machine.h>
|
||||
+#include <linux/pinctrl/pinconf.h>
|
||||
+#include <linux/pinctrl/pinconf-generic.h>
|
||||
+#include <linux/pinctrl/pinmux.h>
|
||||
+
|
||||
+#include "../core.h"
|
||||
+#include "../pinctrl-utils.h"
|
||||
+
|
||||
+#include "pinctrl-bcm63xx.h"
|
||||
+
|
||||
+#define BCM6348_NGPIO 37
|
||||
+
|
||||
+#define MAX_GROUP 4
|
||||
+#define PINS_PER_GROUP 8
|
||||
+#define PIN_TO_GROUP(pin) (MAX_GROUP - ((pin) / PINS_PER_GROUP))
|
||||
+#define GROUP_SHIFT(pin) (PIN_TO_GROUP(pin) * 4)
|
||||
+#define GROUP_MASK(pin) (0xf << GROUP_SHIFT(pin))
|
||||
+
|
||||
+struct bcm6348_pingroup {
|
||||
+ const char *name;
|
||||
+ const unsigned * const pins;
|
||||
+ const unsigned num_pins;
|
||||
+};
|
||||
+
|
||||
+struct bcm6348_function {
|
||||
+ const char *name;
|
||||
+ const char * const *groups;
|
||||
+ const unsigned num_groups;
|
||||
+ unsigned int value;
|
||||
+};
|
||||
+
|
||||
+struct bcm6348_pinctrl {
|
||||
+ struct pinctrl_dev *pctldev;
|
||||
+ struct pinctrl_desc desc;
|
||||
+
|
||||
+ void __iomem *mode;
|
||||
+
|
||||
+ /* register access lock */
|
||||
+ spinlock_t lock;
|
||||
+
|
||||
+ struct gpio_chip gpio[2];
|
||||
+};
|
||||
+
|
||||
+#define BCM6348_PIN(a, b, group) \
|
||||
+ { \
|
||||
+ .number = a, \
|
||||
+ .name = b, \
|
||||
+ .drv_data = (void *)(group), \
|
||||
+ }
|
||||
+
|
||||
+static const struct pinctrl_pin_desc bcm6348_pins[] = {
|
||||
+ BCM6348_PIN(0, "gpio0", 4),
|
||||
+ BCM6348_PIN(1, "gpio1", 4),
|
||||
+ BCM6348_PIN(2, "gpio2", 4),
|
||||
+ BCM6348_PIN(3, "gpio3", 4),
|
||||
+ BCM6348_PIN(4, "gpio4", 4),
|
||||
+ BCM6348_PIN(5, "gpio5", 4),
|
||||
+ BCM6348_PIN(6, "gpio6", 4),
|
||||
+ BCM6348_PIN(7, "gpio7", 4),
|
||||
+ BCM6348_PIN(8, "gpio8", 3),
|
||||
+ BCM6348_PIN(9, "gpio9", 3),
|
||||
+ BCM6348_PIN(10, "gpio10", 3),
|
||||
+ BCM6348_PIN(11, "gpio11", 3),
|
||||
+ BCM6348_PIN(12, "gpio12", 3),
|
||||
+ BCM6348_PIN(13, "gpio13", 3),
|
||||
+ BCM6348_PIN(14, "gpio14", 3),
|
||||
+ BCM6348_PIN(15, "gpio15", 3),
|
||||
+ BCM6348_PIN(16, "gpio16", 2),
|
||||
+ BCM6348_PIN(17, "gpio17", 2),
|
||||
+ BCM6348_PIN(18, "gpio18", 2),
|
||||
+ BCM6348_PIN(19, "gpio19", 2),
|
||||
+ BCM6348_PIN(20, "gpio20", 2),
|
||||
+ BCM6348_PIN(21, "gpio21", 2),
|
||||
+ BCM6348_PIN(22, "gpio22", 1),
|
||||
+ BCM6348_PIN(23, "gpio23", 1),
|
||||
+ BCM6348_PIN(24, "gpio24", 1),
|
||||
+ BCM6348_PIN(25, "gpio25", 1),
|
||||
+ BCM6348_PIN(26, "gpio26", 1),
|
||||
+ BCM6348_PIN(27, "gpio27", 1),
|
||||
+ BCM6348_PIN(28, "gpio28", 1),
|
||||
+ BCM6348_PIN(29, "gpio29", 1),
|
||||
+ BCM6348_PIN(30, "gpio30", 1),
|
||||
+ BCM6348_PIN(31, "gpio31", 1),
|
||||
+ BCM6348_PIN(32, "gpio32", 0),
|
||||
+ BCM6348_PIN(33, "gpio33", 0),
|
||||
+ BCM6348_PIN(34, "gpio34", 0),
|
||||
+ BCM6348_PIN(35, "gpio35", 0),
|
||||
+ BCM6348_PIN(36, "gpio36", 0),
|
||||
+};
|
||||
+
|
||||
+enum bcm6348_muxes {
|
||||
+ BCM6348_MUX_GPIO = 0,
|
||||
+ BCM6348_MUX_EXT_EPHY,
|
||||
+ BCM6348_MUX_MII_SNOOP,
|
||||
+ BCM6348_MUX_LEGACY_LED,
|
||||
+ BCM6348_MUX_MII_PCCARD,
|
||||
+ BCM6348_MUX_PCI,
|
||||
+ BCM6348_MUX_SPI_MASTER_UART,
|
||||
+ BCM6348_MUX_EXT_MII,
|
||||
+ BCM6348_MUX_UTOPIA,
|
||||
+ BCM6348_MUX_DIAG,
|
||||
+};
|
||||
+
|
||||
+static unsigned group0_pins[] = {
|
||||
+ 32, 33, 34, 35, 36,
|
||||
+};
|
||||
+
|
||||
+static unsigned group1_pins[] = {
|
||||
+ 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
|
||||
+};
|
||||
+
|
||||
+static unsigned group2_pins[] = {
|
||||
+ 16, 17, 18, 19, 20, 21,
|
||||
+};
|
||||
+
|
||||
+static unsigned group3_pins[] = {
|
||||
+ 8, 9, 10, 11, 12, 13, 14, 15,
|
||||
+};
|
||||
+
|
||||
+static unsigned group4_pins[] = {
|
||||
+ 0, 1, 2, 3, 4, 5, 6, 7,
|
||||
+};
|
||||
+
|
||||
+#define BCM6348_GROUP(n) \
|
||||
+ { \
|
||||
+ .name = #n, \
|
||||
+ .pins = n##_pins, \
|
||||
+ .num_pins = ARRAY_SIZE(n##_pins), \
|
||||
+ } \
|
||||
+
|
||||
+static struct bcm6348_pingroup bcm6348_groups[] = {
|
||||
+ BCM6348_GROUP(group0),
|
||||
+ BCM6348_GROUP(group1),
|
||||
+ BCM6348_GROUP(group2),
|
||||
+ BCM6348_GROUP(group3),
|
||||
+ BCM6348_GROUP(group4),
|
||||
+};
|
||||
+
|
||||
+static const char * const ext_mii_groups[] = {
|
||||
+ "group0",
|
||||
+ "group3",
|
||||
+};
|
||||
+
|
||||
+static const char * const ext_ephy_groups[] = {
|
||||
+ "group1",
|
||||
+ "group4"
|
||||
+};
|
||||
+
|
||||
+static const char * const mii_snoop_groups[] = {
|
||||
+ "group1",
|
||||
+ "group4",
|
||||
+};
|
||||
+
|
||||
+static const char * const legacy_led_groups[] = {
|
||||
+ "group4",
|
||||
+};
|
||||
+
|
||||
+static const char * const mii_pccard_groups[] = {
|
||||
+ "group1",
|
||||
+};
|
||||
+
|
||||
+static const char * const pci_groups[] = {
|
||||
+ "group2",
|
||||
+};
|
||||
+
|
||||
+static const char * const spi_master_uart_groups[] = {
|
||||
+ "group1",
|
||||
+};
|
||||
+
|
||||
+static const char * const utopia_groups[] = {
|
||||
+ "group0",
|
||||
+ "group1",
|
||||
+ "group3",
|
||||
+};
|
||||
+
|
||||
+static const char * const diag_groups[] = {
|
||||
+ "group0",
|
||||
+ "group1",
|
||||
+ "group2",
|
||||
+ "group4",
|
||||
+};
|
||||
+
|
||||
+#define BCM6348_FUN(n, f) \
|
||||
+ { \
|
||||
+ .name = #n, \
|
||||
+ .groups = n##_groups, \
|
||||
+ .num_groups = ARRAY_SIZE(n##_groups), \
|
||||
+ .value = BCM6348_MUX_##f, \
|
||||
+ }
|
||||
+
|
||||
+static const struct bcm6348_function bcm6348_funcs[] = {
|
||||
+ BCM6348_FUN(ext_mii, EXT_MII),
|
||||
+ BCM6348_FUN(ext_ephy, EXT_EPHY),
|
||||
+ BCM6348_FUN(mii_snoop, MII_SNOOP),
|
||||
+ BCM6348_FUN(legacy_led, LEGACY_LED),
|
||||
+ BCM6348_FUN(mii_pccard, MII_PCCARD),
|
||||
+ BCM6348_FUN(pci, PCI),
|
||||
+ BCM6348_FUN(spi_master_uart, SPI_MASTER_UART),
|
||||
+ BCM6348_FUN(utopia, UTOPIA),
|
||||
+ BCM6348_FUN(diag, DIAG),
|
||||
+};
|
||||
+
|
||||
+static int bcm6348_pinctrl_get_group_count(struct pinctrl_dev *pctldev)
|
||||
+{
|
||||
+ return ARRAY_SIZE(bcm6348_groups);
|
||||
+}
|
||||
+
|
||||
+static const char *bcm6348_pinctrl_get_group_name(struct pinctrl_dev *pctldev,
|
||||
+ unsigned group)
|
||||
+{
|
||||
+ return bcm6348_groups[group].name;
|
||||
+}
|
||||
+
|
||||
+static int bcm6348_pinctrl_get_group_pins(struct pinctrl_dev *pctldev,
|
||||
+ unsigned group, const unsigned **pins,
|
||||
+ unsigned *num_pins)
|
||||
+{
|
||||
+ *pins = bcm6348_groups[group].pins;
|
||||
+ *num_pins = bcm6348_groups[group].num_pins;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int bcm6348_pinctrl_get_func_count(struct pinctrl_dev *pctldev)
|
||||
+{
|
||||
+ return ARRAY_SIZE(bcm6348_funcs);
|
||||
+}
|
||||
+
|
||||
+static const char *bcm6348_pinctrl_get_func_name(struct pinctrl_dev *pctldev,
|
||||
+ unsigned selector)
|
||||
+{
|
||||
+ return bcm6348_funcs[selector].name;
|
||||
+}
|
||||
+
|
||||
+static int bcm6348_pinctrl_get_groups(struct pinctrl_dev *pctldev,
|
||||
+ unsigned selector,
|
||||
+ const char * const **groups,
|
||||
+ unsigned * const num_groups)
|
||||
+{
|
||||
+ *groups = bcm6348_funcs[selector].groups;
|
||||
+ *num_groups = bcm6348_funcs[selector].num_groups;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void bcm6348_rmw_mux(struct bcm6348_pinctrl *pctl, u32 mask, u32 val)
|
||||
+{
|
||||
+ unsigned long flags;
|
||||
+ u32 reg;
|
||||
+
|
||||
+ spin_lock_irqsave(&pctl->lock, flags);
|
||||
+
|
||||
+ reg = __raw_readl(pctl->mode);
|
||||
+ reg &= ~mask;
|
||||
+ reg |= val & mask;
|
||||
+ __raw_writel(reg, pctl->mode);
|
||||
+
|
||||
+ spin_unlock_irqrestore(&pctl->lock, flags);
|
||||
+}
|
||||
+
|
||||
+static int bcm6348_pinctrl_set_mux(struct pinctrl_dev *pctldev,
|
||||
+ unsigned selector, unsigned group)
|
||||
+{
|
||||
+ struct bcm6348_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
|
||||
+ const struct bcm6348_pingroup *grp = &bcm6348_groups[group];
|
||||
+ const struct bcm6348_function *f = &bcm6348_funcs[selector];
|
||||
+ u32 group_num, mask, val;
|
||||
+
|
||||
+ /*
|
||||
+ * pins n..(n+7) share the same group, so we only need to look at
|
||||
+ * the first pin.
|
||||
+ */
|
||||
+ group_num = (unsigned long)bcm6348_pins[grp->pins[0]].drv_data;
|
||||
+ mask = GROUP_MASK(group_num);
|
||||
+ val = f->value << GROUP_SHIFT(group_num);
|
||||
+
|
||||
+ bcm6348_rmw_mux(pctl, mask, val);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int bcm6348_gpio_request_enable(struct pinctrl_dev *pctldev,
|
||||
+ struct pinctrl_gpio_range *range,
|
||||
+ unsigned offset)
|
||||
+{
|
||||
+ struct bcm6348_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
|
||||
+ struct pin_desc *desc;
|
||||
+ u32 mask;
|
||||
+
|
||||
+ /* don't reconfigure if already muxed */
|
||||
+ desc = pin_desc_get(pctldev, offset);
|
||||
+ if (desc->mux_usecount)
|
||||
+ return 0;
|
||||
+
|
||||
+ mask = GROUP_MASK(offset);
|
||||
+
|
||||
+ /* disable all functions using this pin */
|
||||
+ bcm6348_rmw_mux(pctl, mask, 0);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static struct pinctrl_ops bcm6348_pctl_ops = {
|
||||
+ .get_groups_count = bcm6348_pinctrl_get_group_count,
|
||||
+ .get_group_name = bcm6348_pinctrl_get_group_name,
|
||||
+ .get_group_pins = bcm6348_pinctrl_get_group_pins,
|
||||
+#ifdef CONFIG_OF
|
||||
+ .dt_node_to_map = pinconf_generic_dt_node_to_map_pin,
|
||||
+ .dt_free_map = pinctrl_utils_free_map,
|
||||
+#endif
|
||||
+};
|
||||
+
|
||||
+static struct pinmux_ops bcm6348_pmx_ops = {
|
||||
+ .get_functions_count = bcm6348_pinctrl_get_func_count,
|
||||
+ .get_function_name = bcm6348_pinctrl_get_func_name,
|
||||
+ .get_function_groups = bcm6348_pinctrl_get_groups,
|
||||
+ .set_mux = bcm6348_pinctrl_set_mux,
|
||||
+ .gpio_request_enable = bcm6348_gpio_request_enable,
|
||||
+ .strict = true,
|
||||
+};
|
||||
+
|
||||
+static int bcm6348_pinctrl_probe(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct bcm6348_pinctrl *pctl;
|
||||
+ struct resource *res;
|
||||
+ void __iomem *mode;
|
||||
+
|
||||
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mode");
|
||||
+ mode = devm_ioremap_resource(&pdev->dev, res);
|
||||
+ if (IS_ERR(mode))
|
||||
+ return PTR_ERR(mode);
|
||||
+
|
||||
+ pctl = devm_kzalloc(&pdev->dev, sizeof(*pctl), GFP_KERNEL);
|
||||
+ if (!pctl)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ spin_lock_init(&pctl->lock);
|
||||
+
|
||||
+ pctl->mode = mode;
|
||||
+
|
||||
+ /* disable all muxes by default */
|
||||
+ __raw_writel(0, pctl->mode);
|
||||
+
|
||||
+ pctl->desc.name = dev_name(&pdev->dev);
|
||||
+ pctl->desc.owner = THIS_MODULE;
|
||||
+ pctl->desc.pctlops = &bcm6348_pctl_ops;
|
||||
+ pctl->desc.pmxops = &bcm6348_pmx_ops;
|
||||
+
|
||||
+ pctl->desc.npins = ARRAY_SIZE(bcm6348_pins);
|
||||
+ pctl->desc.pins = bcm6348_pins;
|
||||
+
|
||||
+ platform_set_drvdata(pdev, pctl);
|
||||
+
|
||||
+ pctl->pctldev = bcm63xx_pinctrl_register(pdev, &pctl->desc, pctl,
|
||||
+ pctl->gpio, BCM6348_NGPIO);
|
||||
+ if (IS_ERR(pctl->pctldev))
|
||||
+ return PTR_ERR(pctl->pctldev);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static const struct of_device_id bcm6348_pinctrl_match[] = {
|
||||
+ { .compatible = "brcm,bcm6348-pinctrl", },
|
||||
+ { },
|
||||
+};
|
||||
+
|
||||
+static struct platform_driver bcm6348_pinctrl_driver = {
|
||||
+ .probe = bcm6348_pinctrl_probe,
|
||||
+ .driver = {
|
||||
+ .name = "bcm6348-pinctrl",
|
||||
+ .of_match_table = bcm6348_pinctrl_match,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+builtin_platform_driver(bcm6348_pinctrl_driver);
|
@ -1,61 +0,0 @@
|
||||
From c7c8fa7f5b5ee9bea751fa7bdae8ff4acde8f26e Mon Sep 17 00:00:00 2001
|
||||
From: Jonas Gorski <jonas.gorski@gmail.com>
|
||||
Date: Wed, 27 Jul 2016 11:36:00 +0200
|
||||
Subject: [PATCH 06/16] Documentation: add BCM6358 pincontroller binding
|
||||
documentation
|
||||
|
||||
Add binding documentation for the pincontrol core found in BCM6358 SoCs.
|
||||
|
||||
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
|
||||
---
|
||||
.../bindings/pinctrl/brcm,bcm6358-pinctrl.txt | 44 ++++++++++++++++++++++
|
||||
1 file changed, 44 insertions(+)
|
||||
create mode 100644 Documentation/devicetree/bindings/pinctrl/brcm,bcm6358-pinctrl.txt
|
||||
|
||||
--- /dev/null
|
||||
+++ b/Documentation/devicetree/bindings/pinctrl/brcm,bcm6358-pinctrl.txt
|
||||
@@ -0,0 +1,44 @@
|
||||
+* Broadcom BCM6358 pin controller
|
||||
+
|
||||
+Required properties:
|
||||
+- compatible: Must be "brcm,bcm6358-pinctrl".
|
||||
+- reg: Register specifiers of dirout, dat registers.
|
||||
+- reg-names: Must be "dirout", "dat".
|
||||
+- brcm,gpiomode: Phandle to the shared gpiomode register.
|
||||
+- gpio-controller: Identifies this node as a gpio-controller.
|
||||
+- #gpio-cells: Must be <2>.
|
||||
+
|
||||
+Example:
|
||||
+
|
||||
+pinctrl: pin-controller@fffe0080 {
|
||||
+ compatible = "brcm,bcm6358-pinctrl";
|
||||
+ reg = <0xfffe0080 0x8>,
|
||||
+ <0xfffe0088 0x8>,
|
||||
+ <0xfffe0098 0x4>;
|
||||
+ reg-names = "dirout", "dat";
|
||||
+ brcm,gpiomode = <&gpiomode>;
|
||||
+
|
||||
+ gpio-controller;
|
||||
+ #gpio-cells = <2>;
|
||||
+};
|
||||
+
|
||||
+gpiomode: syscon@fffe0098 {
|
||||
+ compatible = "brcm,bcm6358-gpiomode", "syscon";
|
||||
+ reg = <0xfffe0098 0x4>;
|
||||
+ native-endian;
|
||||
+};
|
||||
+
|
||||
+Available pins/groups and functions:
|
||||
+
|
||||
+name pins functions
|
||||
+-----------------------------------------------------------
|
||||
+ebi_cs_grp 30-31 ebi_cs
|
||||
+uart1_grp 28-31 uart1
|
||||
+spi_cs_grp 32-33 spi_cs
|
||||
+async_modem_grp 12-15 async_modem
|
||||
+legacy_led_grp 9-15 legacy_led
|
||||
+serial_led_grp 6-7 serial_led
|
||||
+led_grp 0-3 led
|
||||
+utopia_grp 12-15, 22-31 utopia
|
||||
+pwm_syn_clk_grp 8 pwm_syn_clk
|
||||
+sys_irq_grp 5 sys_irq
|
@ -1,436 +0,0 @@
|
||||
From fb00ef462f3f8b70ea8902151cc72810fe90b999 Mon Sep 17 00:00:00 2001
|
||||
From: Jonas Gorski <jonas.gorski@gmail.com>
|
||||
Date: Fri, 24 Jun 2016 22:16:01 +0200
|
||||
Subject: [PATCH 07/16] pinctrl: add a pincontrol driver for BCM6358
|
||||
|
||||
Add a pincotrol driver for BCM6358. BCM6358 allow overlaying different
|
||||
functions onto the GPIO pins. It does not support configuring individual
|
||||
pins but only whole groups. These groups may overlap, and still require
|
||||
the directions to be set correctly in the GPIO register. In addition the
|
||||
functions register controls other, not directly mux related functions.
|
||||
|
||||
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
|
||||
---
|
||||
drivers/pinctrl/bcm63xx/Kconfig | 8 +
|
||||
drivers/pinctrl/bcm63xx/Makefile | 1 +
|
||||
drivers/pinctrl/bcm63xx/pinctrl-bcm6358.c | 393 ++++++++++++++++++++++++++++++
|
||||
3 files changed, 402 insertions(+)
|
||||
create mode 100644 drivers/pinctrl/bcm63xx/pinctrl-bcm6358.c
|
||||
|
||||
--- a/drivers/pinctrl/bcm63xx/Kconfig
|
||||
+++ b/drivers/pinctrl/bcm63xx/Kconfig
|
||||
@@ -15,3 +15,11 @@ config PINCTRL_BCM6348
|
||||
select PINCONF
|
||||
select PINCTRL_BCM63XX
|
||||
select GENERIC_PINCONF
|
||||
+
|
||||
+config PINCTRL_BCM6358
|
||||
+ bool "BCM6358 pincontrol driver" if COMPILE_TEST
|
||||
+ select PINMUX
|
||||
+ select PINCONF
|
||||
+ select PINCTRL_BCM63XX
|
||||
+ select GENERIC_PINCONF
|
||||
+ select MFD_SYSCON
|
||||
--- a/drivers/pinctrl/bcm63xx/Makefile
|
||||
+++ b/drivers/pinctrl/bcm63xx/Makefile
|
||||
@@ -1,3 +1,4 @@
|
||||
obj-$(CONFIG_PINCTRL_BCM63XX) += pinctrl-bcm63xx.o
|
||||
obj-$(CONFIG_PINCTRL_BCM6328) += pinctrl-bcm6328.o
|
||||
obj-$(CONFIG_PINCTRL_BCM6348) += pinctrl-bcm6348.o
|
||||
+obj-$(CONFIG_PINCTRL_BCM6358) += pinctrl-bcm6358.o
|
||||
--- /dev/null
|
||||
+++ b/drivers/pinctrl/bcm63xx/pinctrl-bcm6358.c
|
||||
@@ -0,0 +1,393 @@
|
||||
+/*
|
||||
+ * This file is subject to the terms and conditions of the GNU General Public
|
||||
+ * License. See the file "COPYING" in the main directory of this archive
|
||||
+ * for more details.
|
||||
+ *
|
||||
+ * Copyright (C) 2016 Jonas Gorski <jonas.gorski@gmail.com>
|
||||
+ */
|
||||
+
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/bitops.h>
|
||||
+#include <linux/gpio.h>
|
||||
+#include <linux/gpio/driver.h>
|
||||
+#include <linux/mfd/syscon.h>
|
||||
+#include <linux/of.h>
|
||||
+#include <linux/of_gpio.h>
|
||||
+#include <linux/of_address.h>
|
||||
+#include <linux/slab.h>
|
||||
+#include <linux/regmap.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+
|
||||
+#include <linux/pinctrl/pinconf.h>
|
||||
+#include <linux/pinctrl/pinconf-generic.h>
|
||||
+#include <linux/pinctrl/pinmux.h>
|
||||
+#include <linux/pinctrl/machine.h>
|
||||
+
|
||||
+#include "../core.h"
|
||||
+#include "../pinctrl-utils.h"
|
||||
+
|
||||
+#include "pinctrl-bcm63xx.h"
|
||||
+
|
||||
+/* GPIO_MODE register */
|
||||
+#define BCM6358_MODE_MUX_NONE 0
|
||||
+
|
||||
+/* overlays on gpio pins */
|
||||
+#define BCM6358_MODE_MUX_EBI_CS BIT(5)
|
||||
+#define BCM6358_MODE_MUX_UART1 BIT(6)
|
||||
+#define BCM6358_MODE_MUX_SPI_CS BIT(7)
|
||||
+#define BCM6358_MODE_MUX_ASYNC_MODEM BIT(8)
|
||||
+#define BCM6358_MODE_MUX_LEGACY_LED BIT(9)
|
||||
+#define BCM6358_MODE_MUX_SERIAL_LED BIT(10)
|
||||
+#define BCM6358_MODE_MUX_LED BIT(11)
|
||||
+#define BCM6358_MODE_MUX_UTOPIA BIT(12)
|
||||
+#define BCM6358_MODE_MUX_CLKRST BIT(13)
|
||||
+#define BCM6358_MODE_MUX_PWM_SYN_CLK BIT(14)
|
||||
+#define BCM6358_MODE_MUX_SYS_IRQ BIT(15)
|
||||
+
|
||||
+#define BCM6358_NGPIO 40
|
||||
+
|
||||
+struct bcm6358_pingroup {
|
||||
+ const char *name;
|
||||
+ const unsigned * const pins;
|
||||
+ const unsigned num_pins;
|
||||
+
|
||||
+ const u16 mode_val;
|
||||
+
|
||||
+ /* non-GPIO function muxes require the gpio direction to be set */
|
||||
+ const u16 direction;
|
||||
+};
|
||||
+
|
||||
+struct bcm6358_function {
|
||||
+ const char *name;
|
||||
+ const char * const *groups;
|
||||
+ const unsigned num_groups;
|
||||
+};
|
||||
+
|
||||
+struct bcm6358_pinctrl {
|
||||
+ struct device *dev;
|
||||
+ struct pinctrl_dev *pctldev;
|
||||
+ struct pinctrl_desc desc;
|
||||
+
|
||||
+ struct regmap_field *overlays;
|
||||
+
|
||||
+ struct gpio_chip gpio[2];
|
||||
+};
|
||||
+
|
||||
+#define BCM6358_GPIO_PIN(a, b, bit1, bit2, bit3) \
|
||||
+ { \
|
||||
+ .number = a, \
|
||||
+ .name = b, \
|
||||
+ .drv_data = (void *)(BCM6358_MODE_MUX_##bit1 | \
|
||||
+ BCM6358_MODE_MUX_##bit2 | \
|
||||
+ BCM6358_MODE_MUX_##bit3), \
|
||||
+ }
|
||||
+
|
||||
+static const struct pinctrl_pin_desc bcm6358_pins[] = {
|
||||
+ BCM6358_GPIO_PIN(0, "gpio0", LED, NONE, NONE),
|
||||
+ BCM6358_GPIO_PIN(1, "gpio1", LED, NONE, NONE),
|
||||
+ BCM6358_GPIO_PIN(2, "gpio2", LED, NONE, NONE),
|
||||
+ BCM6358_GPIO_PIN(3, "gpio3", LED, NONE, NONE),
|
||||
+ PINCTRL_PIN(4, "gpio4"),
|
||||
+ BCM6358_GPIO_PIN(5, "gpio5", SYS_IRQ, NONE, NONE),
|
||||
+ BCM6358_GPIO_PIN(6, "gpio6", SERIAL_LED, NONE, NONE),
|
||||
+ BCM6358_GPIO_PIN(7, "gpio7", SERIAL_LED, NONE, NONE),
|
||||
+ BCM6358_GPIO_PIN(8, "gpio8", PWM_SYN_CLK, NONE, NONE),
|
||||
+ BCM6358_GPIO_PIN(9, "gpio09", LEGACY_LED, NONE, NONE),
|
||||
+ BCM6358_GPIO_PIN(10, "gpio10", LEGACY_LED, NONE, NONE),
|
||||
+ BCM6358_GPIO_PIN(11, "gpio11", LEGACY_LED, NONE, NONE),
|
||||
+ BCM6358_GPIO_PIN(12, "gpio12", LEGACY_LED, ASYNC_MODEM, UTOPIA),
|
||||
+ BCM6358_GPIO_PIN(13, "gpio13", LEGACY_LED, ASYNC_MODEM, UTOPIA),
|
||||
+ BCM6358_GPIO_PIN(14, "gpio14", LEGACY_LED, ASYNC_MODEM, UTOPIA),
|
||||
+ BCM6358_GPIO_PIN(15, "gpio15", LEGACY_LED, ASYNC_MODEM, UTOPIA),
|
||||
+ PINCTRL_PIN(16, "gpio16"),
|
||||
+ PINCTRL_PIN(17, "gpio17"),
|
||||
+ PINCTRL_PIN(18, "gpio18"),
|
||||
+ PINCTRL_PIN(19, "gpio19"),
|
||||
+ PINCTRL_PIN(20, "gpio20"),
|
||||
+ PINCTRL_PIN(21, "gpio21"),
|
||||
+ BCM6358_GPIO_PIN(22, "gpio22", UTOPIA, NONE, NONE),
|
||||
+ BCM6358_GPIO_PIN(23, "gpio23", UTOPIA, NONE, NONE),
|
||||
+ BCM6358_GPIO_PIN(24, "gpio24", UTOPIA, NONE, NONE),
|
||||
+ BCM6358_GPIO_PIN(25, "gpio25", UTOPIA, NONE, NONE),
|
||||
+ BCM6358_GPIO_PIN(26, "gpio26", UTOPIA, NONE, NONE),
|
||||
+ BCM6358_GPIO_PIN(27, "gpio27", UTOPIA, NONE, NONE),
|
||||
+ BCM6358_GPIO_PIN(28, "gpio28", UTOPIA, UART1, NONE),
|
||||
+ BCM6358_GPIO_PIN(29, "gpio29", UTOPIA, UART1, NONE),
|
||||
+ BCM6358_GPIO_PIN(30, "gpio30", UTOPIA, UART1, EBI_CS),
|
||||
+ BCM6358_GPIO_PIN(31, "gpio31", UTOPIA, UART1, EBI_CS),
|
||||
+ BCM6358_GPIO_PIN(32, "gpio32", SPI_CS, NONE, NONE),
|
||||
+ BCM6358_GPIO_PIN(33, "gpio33", SPI_CS, NONE, NONE),
|
||||
+ PINCTRL_PIN(34, "gpio34"),
|
||||
+ PINCTRL_PIN(35, "gpio35"),
|
||||
+ PINCTRL_PIN(36, "gpio36"),
|
||||
+ PINCTRL_PIN(37, "gpio37"),
|
||||
+ PINCTRL_PIN(38, "gpio38"),
|
||||
+ PINCTRL_PIN(39, "gpio39"),
|
||||
+};
|
||||
+
|
||||
+static unsigned ebi_cs_grp_pins[] = { 30, 31 };
|
||||
+
|
||||
+static unsigned uart1_grp_pins[] = { 28, 29, 30, 31 };
|
||||
+
|
||||
+static unsigned spi_cs_grp_pins[] = { 32, 33 };
|
||||
+
|
||||
+static unsigned async_modem_grp_pins[] = { 12, 13, 14, 15 };
|
||||
+
|
||||
+static unsigned serial_led_grp_pins[] = { 6, 7 };
|
||||
+
|
||||
+static unsigned legacy_led_grp_pins[] = { 9, 10, 11, 12, 13, 14, 15 };
|
||||
+
|
||||
+static unsigned led_grp_pins[] = { 0, 1, 2, 3 };
|
||||
+
|
||||
+static unsigned utopia_grp_pins[] = {
|
||||
+ 12, 13, 14, 15, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
|
||||
+};
|
||||
+
|
||||
+static unsigned pwm_syn_clk_grp_pins[] = { 8 };
|
||||
+
|
||||
+static unsigned sys_irq_grp_pins[] = { 5 };
|
||||
+
|
||||
+#define BCM6358_GPIO_MUX_GROUP(n, bit, dir) \
|
||||
+ { \
|
||||
+ .name = #n, \
|
||||
+ .pins = n##_pins, \
|
||||
+ .num_pins = ARRAY_SIZE(n##_pins), \
|
||||
+ .mode_val = BCM6358_MODE_MUX_##bit, \
|
||||
+ .direction = dir, \
|
||||
+ }
|
||||
+
|
||||
+static const struct bcm6358_pingroup bcm6358_groups[] = {
|
||||
+ BCM6358_GPIO_MUX_GROUP(ebi_cs_grp, EBI_CS, 0x3),
|
||||
+ BCM6358_GPIO_MUX_GROUP(uart1_grp, UART1, 0x2),
|
||||
+ BCM6358_GPIO_MUX_GROUP(spi_cs_grp, SPI_CS, 0x6),
|
||||
+ BCM6358_GPIO_MUX_GROUP(async_modem_grp, ASYNC_MODEM, 0x6),
|
||||
+ BCM6358_GPIO_MUX_GROUP(legacy_led_grp, LEGACY_LED, 0x7f),
|
||||
+ BCM6358_GPIO_MUX_GROUP(serial_led_grp, SERIAL_LED, 0x3),
|
||||
+ BCM6358_GPIO_MUX_GROUP(led_grp, LED, 0xf),
|
||||
+ BCM6358_GPIO_MUX_GROUP(utopia_grp, UTOPIA, 0x000f),
|
||||
+ BCM6358_GPIO_MUX_GROUP(pwm_syn_clk_grp, PWM_SYN_CLK, 0x1),
|
||||
+ BCM6358_GPIO_MUX_GROUP(sys_irq_grp, SYS_IRQ, 0x1),
|
||||
+};
|
||||
+
|
||||
+static const char * const ebi_cs_groups[] = {
|
||||
+ "ebi_cs_grp"
|
||||
+};
|
||||
+
|
||||
+static const char * const uart1_groups[] = {
|
||||
+ "uart1_grp"
|
||||
+};
|
||||
+
|
||||
+static const char * const spi_cs_2_3_groups[] = {
|
||||
+ "spi_cs_2_3_grp"
|
||||
+};
|
||||
+
|
||||
+static const char * const async_modem_groups[] = {
|
||||
+ "async_modem_grp"
|
||||
+};
|
||||
+
|
||||
+static const char * const legacy_led_groups[] = {
|
||||
+ "legacy_led_grp",
|
||||
+};
|
||||
+
|
||||
+static const char * const serial_led_groups[] = {
|
||||
+ "serial_led_grp",
|
||||
+};
|
||||
+
|
||||
+static const char * const led_groups[] = {
|
||||
+ "led_grp",
|
||||
+};
|
||||
+
|
||||
+static const char * const clkrst_groups[] = {
|
||||
+ "clkrst_grp",
|
||||
+};
|
||||
+
|
||||
+static const char * const pwm_syn_clk_groups[] = {
|
||||
+ "pwm_syn_clk_grp",
|
||||
+};
|
||||
+
|
||||
+static const char * const sys_irq_groups[] = {
|
||||
+ "sys_irq_grp",
|
||||
+};
|
||||
+
|
||||
+#define BCM6358_FUN(n) \
|
||||
+ { \
|
||||
+ .name = #n, \
|
||||
+ .groups = n##_groups, \
|
||||
+ .num_groups = ARRAY_SIZE(n##_groups), \
|
||||
+ }
|
||||
+
|
||||
+static const struct bcm6358_function bcm6358_funcs[] = {
|
||||
+ BCM6358_FUN(ebi_cs),
|
||||
+ BCM6358_FUN(uart1),
|
||||
+ BCM6358_FUN(spi_cs_2_3),
|
||||
+ BCM6358_FUN(async_modem),
|
||||
+ BCM6358_FUN(legacy_led),
|
||||
+ BCM6358_FUN(serial_led),
|
||||
+ BCM6358_FUN(led),
|
||||
+ BCM6358_FUN(clkrst),
|
||||
+ BCM6358_FUN(pwm_syn_clk),
|
||||
+ BCM6358_FUN(sys_irq),
|
||||
+};
|
||||
+
|
||||
+static int bcm6358_pinctrl_get_group_count(struct pinctrl_dev *pctldev)
|
||||
+{
|
||||
+ return ARRAY_SIZE(bcm6358_groups);
|
||||
+}
|
||||
+
|
||||
+static const char *bcm6358_pinctrl_get_group_name(struct pinctrl_dev *pctldev,
|
||||
+ unsigned group)
|
||||
+{
|
||||
+ return bcm6358_groups[group].name;
|
||||
+}
|
||||
+
|
||||
+static int bcm6358_pinctrl_get_group_pins(struct pinctrl_dev *pctldev,
|
||||
+ unsigned group, const unsigned **pins,
|
||||
+ unsigned *num_pins)
|
||||
+{
|
||||
+ *pins = bcm6358_groups[group].pins;
|
||||
+ *num_pins = bcm6358_groups[group].num_pins;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int bcm6358_pinctrl_get_func_count(struct pinctrl_dev *pctldev)
|
||||
+{
|
||||
+ return ARRAY_SIZE(bcm6358_funcs);
|
||||
+}
|
||||
+
|
||||
+static const char *bcm6358_pinctrl_get_func_name(struct pinctrl_dev *pctldev,
|
||||
+ unsigned selector)
|
||||
+{
|
||||
+ return bcm6358_funcs[selector].name;
|
||||
+}
|
||||
+
|
||||
+static int bcm6358_pinctrl_get_groups(struct pinctrl_dev *pctldev,
|
||||
+ unsigned selector,
|
||||
+ const char * const **groups,
|
||||
+ unsigned * const num_groups)
|
||||
+{
|
||||
+ *groups = bcm6358_funcs[selector].groups;
|
||||
+ *num_groups = bcm6358_funcs[selector].num_groups;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int bcm6358_pinctrl_set_mux(struct pinctrl_dev *pctldev,
|
||||
+ unsigned selector, unsigned group)
|
||||
+{
|
||||
+ struct bcm6358_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
|
||||
+ const struct bcm6358_pingroup *grp = &bcm6358_groups[group];
|
||||
+ u32 val = grp->mode_val;
|
||||
+ u32 mask = val;
|
||||
+ unsigned pin;
|
||||
+
|
||||
+ for (pin = 0; pin < grp->num_pins; pin++)
|
||||
+ mask |= (unsigned long)bcm6358_pins[pin].drv_data;
|
||||
+
|
||||
+ regmap_field_update_bits(pctl->overlays, mask, val);
|
||||
+
|
||||
+ for (pin = 0; pin < grp->num_pins; pin++) {
|
||||
+ int hw_gpio = bcm6358_pins[pin].number;
|
||||
+ struct gpio_chip *gc = &pctl->gpio[hw_gpio / 32];
|
||||
+
|
||||
+ if (grp->direction & BIT(pin))
|
||||
+ gc->direction_output(gc, hw_gpio % 32, 0);
|
||||
+ else
|
||||
+ gc->direction_input(gc, hw_gpio % 32);
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int bcm6358_gpio_request_enable(struct pinctrl_dev *pctldev,
|
||||
+ struct pinctrl_gpio_range *range,
|
||||
+ unsigned offset)
|
||||
+{
|
||||
+ struct bcm6358_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
|
||||
+ u32 mask;
|
||||
+
|
||||
+ mask = (unsigned long)bcm6358_pins[offset].drv_data;
|
||||
+ if (!mask)
|
||||
+ return 0;
|
||||
+
|
||||
+ /* disable all functions using this pin */
|
||||
+ return regmap_field_update_bits(pctl->overlays, mask, 0);
|
||||
+}
|
||||
+
|
||||
+static struct pinctrl_ops bcm6358_pctl_ops = {
|
||||
+ .get_groups_count = bcm6358_pinctrl_get_group_count,
|
||||
+ .get_group_name = bcm6358_pinctrl_get_group_name,
|
||||
+ .get_group_pins = bcm6358_pinctrl_get_group_pins,
|
||||
+#ifdef CONFIG_OF
|
||||
+ .dt_node_to_map = pinconf_generic_dt_node_to_map_pin,
|
||||
+ .dt_free_map = pinctrl_utils_free_map,
|
||||
+#endif
|
||||
+};
|
||||
+
|
||||
+static struct pinmux_ops bcm6358_pmx_ops = {
|
||||
+ .get_functions_count = bcm6358_pinctrl_get_func_count,
|
||||
+ .get_function_name = bcm6358_pinctrl_get_func_name,
|
||||
+ .get_function_groups = bcm6358_pinctrl_get_groups,
|
||||
+ .set_mux = bcm6358_pinctrl_set_mux,
|
||||
+ .gpio_request_enable = bcm6358_gpio_request_enable,
|
||||
+ .strict = true,
|
||||
+};
|
||||
+
|
||||
+static int bcm6358_pinctrl_probe(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct bcm6358_pinctrl *pctl;
|
||||
+ struct regmap *mode;
|
||||
+ struct reg_field overlays = REG_FIELD(0, 0, 15);
|
||||
+
|
||||
+ if (pdev->dev.of_node)
|
||||
+ mode = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
|
||||
+ "brcm,gpiomode");
|
||||
+ else
|
||||
+ mode = syscon_regmap_lookup_by_pdevname("syscon.fffe0098");
|
||||
+
|
||||
+ if (IS_ERR(mode))
|
||||
+ return PTR_ERR(mode);
|
||||
+
|
||||
+ pctl = devm_kzalloc(&pdev->dev, sizeof(*pctl), GFP_KERNEL);
|
||||
+ if (!pctl)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ pctl->overlays = devm_regmap_field_alloc(&pdev->dev, mode, overlays);
|
||||
+ if (IS_ERR(pctl->overlays))
|
||||
+ return PTR_ERR(pctl->overlays);
|
||||
+
|
||||
+ /* disable all muxes by default */
|
||||
+ regmap_field_write(pctl->overlays, 0);
|
||||
+
|
||||
+ pctl->desc.name = dev_name(&pdev->dev);
|
||||
+ pctl->desc.owner = THIS_MODULE;
|
||||
+ pctl->desc.pctlops = &bcm6358_pctl_ops;
|
||||
+ pctl->desc.pmxops = &bcm6358_pmx_ops;
|
||||
+
|
||||
+ pctl->desc.npins = ARRAY_SIZE(bcm6358_pins);
|
||||
+ pctl->desc.pins = bcm6358_pins;
|
||||
+
|
||||
+ platform_set_drvdata(pdev, pctl);
|
||||
+
|
||||
+ pctl->pctldev = bcm63xx_pinctrl_register(pdev, &pctl->desc, pctl,
|
||||
+ pctl->gpio, BCM6358_NGPIO);
|
||||
+ if (IS_ERR(pctl->pctldev))
|
||||
+ return PTR_ERR(pctl->pctldev);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static const struct of_device_id bcm6358_pinctrl_match[] = {
|
||||
+ { .compatible = "brcm,bcm6358-pinctrl", },
|
||||
+ { },
|
||||
+};
|
||||
+
|
||||
+static struct platform_driver bcm6358_pinctrl_driver = {
|
||||
+ .probe = bcm6358_pinctrl_probe,
|
||||
+ .driver = {
|
||||
+ .name = "bcm6358-pinctrl",
|
||||
+ .of_match_table = bcm6358_pinctrl_match,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+builtin_platform_driver(bcm6358_pinctrl_driver);
|
@ -1,96 +0,0 @@
|
||||
From ba03ea8ada2ca71c9095d96a1e4085c2c5cf0e69 Mon Sep 17 00:00:00 2001
|
||||
From: Jonas Gorski <jonas.gorski@gmail.com>
|
||||
Date: Wed, 27 Jul 2016 11:36:18 +0200
|
||||
Subject: [PATCH 08/16] Documentation: add BCM6362 pincontroller binding
|
||||
documentation
|
||||
|
||||
Add binding documentation for the pincontrol core found in BCM6362 SoCs.
|
||||
|
||||
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
|
||||
---
|
||||
.../bindings/pinctrl/brcm,bcm6362-pinctrl.txt | 79 ++++++++++++++++++++++
|
||||
1 file changed, 79 insertions(+)
|
||||
create mode 100644 Documentation/devicetree/bindings/pinctrl/brcm,bcm6362-pinctrl.txt
|
||||
|
||||
--- /dev/null
|
||||
+++ b/Documentation/devicetree/bindings/pinctrl/brcm,bcm6362-pinctrl.txt
|
||||
@@ -0,0 +1,79 @@
|
||||
+* Broadcom BCM6362 pin controller
|
||||
+
|
||||
+Required properties:
|
||||
+- compatible: Must be "brcm,bcm6362-pinctrl"
|
||||
+- reg: Register specifiers of dirout, dat, led, mode, ctrl, basemode registers.
|
||||
+- reg-names: Must be "dirout", "dat", "led", "mode", "ctrl", "basemode".
|
||||
+- gpio-controller: Identifies this node as a GPIO controller.
|
||||
+- #gpio-cells: Must be <2>.
|
||||
+
|
||||
+Example:
|
||||
+
|
||||
+pinctrl: pin-controller@10000080 {
|
||||
+ compatible = "brcm,bcm6362-pinctrl";
|
||||
+ reg = <0x10000080 0x8>,
|
||||
+ <0x10000088 0x8>,
|
||||
+ <0x10000090 0x4>,
|
||||
+ <0x10000098 0x4>,
|
||||
+ <0x1000009c 0x4>,
|
||||
+ <0x100000b8 0x4>;
|
||||
+ reg-names = "dirout", "dat", "led",
|
||||
+ "mode", "ctrl", "basemode";
|
||||
+
|
||||
+ gpio-controller;
|
||||
+ #gpio-cells = <2>;
|
||||
+};
|
||||
+
|
||||
+Available pins/groups and functions:
|
||||
+
|
||||
+name pins functions
|
||||
+-----------------------------------------------------------
|
||||
+gpio0 0 led, usb_device_led
|
||||
+gpio1 1 led, sys_irq
|
||||
+gpio2 2 led, serial_led_clk
|
||||
+gpio3 3 led, serial_led_data
|
||||
+gpio4 4 led, robosw_led_data
|
||||
+gpio5 5 led, robosw_led_clk
|
||||
+gpio6 6 led, robosw_led0
|
||||
+gpio7 7 led, robosw_led1
|
||||
+gpio8 8 led, inet_led
|
||||
+gpio9 9 led, spi_cs2
|
||||
+gpio10 10 led, spi_cs3
|
||||
+gpio11 11 led, ntr_pulse
|
||||
+gpio12 12 led, uart1_scts
|
||||
+gpio13 13 led, uart1_srts
|
||||
+gpio14 14 led, uart1_sdin
|
||||
+gpio15 15 led, uart1_sdout
|
||||
+gpio16 16 led, adsl_spi_miso
|
||||
+gpio17 17 led, adsl_spi_mosi
|
||||
+gpio18 18 led, adsl_spi_clk
|
||||
+gpio19 19 led, adsl_spi_cs
|
||||
+gpio20 20 led, ephy0_led
|
||||
+gpio21 21 led, ephy1_led
|
||||
+gpio22 22 led, ephy2_led
|
||||
+gpio23 23 led, ephy3_led
|
||||
+gpio24 24 ext_irq0
|
||||
+gpio25 25 ext_irq1
|
||||
+gpio26 26 ext_irq2
|
||||
+gpio27 27 ext_irq3
|
||||
+gpio28 28 -
|
||||
+gpio29 29 -
|
||||
+gpio30 30 -
|
||||
+gpio31 31 -
|
||||
+gpio32 32 wifi
|
||||
+gpio33 33 wifi
|
||||
+gpio34 34 wifi
|
||||
+gpio35 35 wifi
|
||||
+gpio36 36 wifi
|
||||
+gpio37 37 wifi
|
||||
+gpio38 38 wifi
|
||||
+gpio39 39 wifi
|
||||
+gpio40 40 wifi
|
||||
+gpio41 41 wifi
|
||||
+gpio42 42 wifi
|
||||
+gpio43 43 wifi
|
||||
+gpio44 44 wifi
|
||||
+gpio45 45 wifi
|
||||
+gpio46 46 wifi
|
||||
+gpio47 47 wifi
|
||||
+nand_grp 8, 12-23, 27 nand
|
@ -1,733 +0,0 @@
|
||||
From eea6b96701d734095e2f823f3a82d9b063f553ae Mon Sep 17 00:00:00 2001
|
||||
From: Jonas Gorski <jonas.gorski@gmail.com>
|
||||
Date: Fri, 24 Jun 2016 22:17:20 +0200
|
||||
Subject: [PATCH 09/16] pinctrl: add a pincontrol driver for BCM6362
|
||||
|
||||
Add a pincotrol driver for BCM6362. BCM6362 allows muxing individual
|
||||
GPIO pins to the LED controller, to be available by the integrated
|
||||
wifi, or other functions. It also supports overlay groups, of which
|
||||
only NAND is documented.
|
||||
|
||||
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
|
||||
---
|
||||
drivers/pinctrl/bcm63xx/Kconfig | 7 +
|
||||
drivers/pinctrl/bcm63xx/Makefile | 1 +
|
||||
drivers/pinctrl/bcm63xx/pinctrl-bcm6362.c | 692 ++++++++++++++++++++++++++++++
|
||||
3 files changed, 700 insertions(+)
|
||||
create mode 100644 drivers/pinctrl/bcm63xx/pinctrl-bcm6362.c
|
||||
|
||||
--- a/drivers/pinctrl/bcm63xx/Kconfig
|
||||
+++ b/drivers/pinctrl/bcm63xx/Kconfig
|
||||
@@ -23,3 +23,10 @@ config PINCTRL_BCM6358
|
||||
select PINCTRL_BCM63XX
|
||||
select GENERIC_PINCONF
|
||||
select MFD_SYSCON
|
||||
+
|
||||
+config PINCTRL_BCM6362
|
||||
+ bool "BCM6362 pincontrol driver" if COMPILE_TEST
|
||||
+ select PINMUX
|
||||
+ select PINCONF
|
||||
+ select PINCTRL_BCM63XX
|
||||
+ select GENERIC_PINCONF
|
||||
--- a/drivers/pinctrl/bcm63xx/Makefile
|
||||
+++ b/drivers/pinctrl/bcm63xx/Makefile
|
||||
@@ -2,3 +2,4 @@ obj-$(CONFIG_PINCTRL_BCM63XX) += pinctrl
|
||||
obj-$(CONFIG_PINCTRL_BCM6328) += pinctrl-bcm6328.o
|
||||
obj-$(CONFIG_PINCTRL_BCM6348) += pinctrl-bcm6348.o
|
||||
obj-$(CONFIG_PINCTRL_BCM6358) += pinctrl-bcm6358.o
|
||||
+obj-$(CONFIG_PINCTRL_BCM6362) += pinctrl-bcm6362.o
|
||||
--- /dev/null
|
||||
+++ b/drivers/pinctrl/bcm63xx/pinctrl-bcm6362.c
|
||||
@@ -0,0 +1,692 @@
|
||||
+/*
|
||||
+ * This file is subject to the terms and conditions of the GNU General Public
|
||||
+ * License. See the file "COPYING" in the main directory of this archive
|
||||
+ * for more details.
|
||||
+ *
|
||||
+ * Copyright (C) 2016 Jonas Gorski <jonas.gorski@gmail.com>
|
||||
+ */
|
||||
+
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/spinlock.h>
|
||||
+#include <linux/bitops.h>
|
||||
+#include <linux/gpio.h>
|
||||
+#include <linux/of.h>
|
||||
+#include <linux/of_gpio.h>
|
||||
+#include <linux/slab.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+
|
||||
+#include <linux/pinctrl/pinconf.h>
|
||||
+#include <linux/pinctrl/pinconf-generic.h>
|
||||
+#include <linux/pinctrl/pinmux.h>
|
||||
+#include <linux/pinctrl/machine.h>
|
||||
+
|
||||
+#include "../core.h"
|
||||
+#include "../pinctrl-utils.h"
|
||||
+
|
||||
+#include "pinctrl-bcm63xx.h"
|
||||
+
|
||||
+#define BCM6362_NGPIO 48
|
||||
+
|
||||
+/* GPIO_BASEMODE register */
|
||||
+#define BASEMODE_NAND BIT(2)
|
||||
+
|
||||
+enum bcm6362_pinctrl_reg {
|
||||
+ BCM6362_LEDCTRL,
|
||||
+ BCM6362_MODE,
|
||||
+ BCM6362_CTRL,
|
||||
+ BCM6362_BASEMODE,
|
||||
+};
|
||||
+
|
||||
+struct bcm6362_pingroup {
|
||||
+ const char *name;
|
||||
+ const unsigned * const pins;
|
||||
+ const unsigned num_pins;
|
||||
+};
|
||||
+
|
||||
+struct bcm6362_function {
|
||||
+ const char *name;
|
||||
+ const char * const *groups;
|
||||
+ const unsigned num_groups;
|
||||
+
|
||||
+ enum bcm6362_pinctrl_reg reg;
|
||||
+ u32 basemode_mask;
|
||||
+};
|
||||
+
|
||||
+struct bcm6362_pinctrl {
|
||||
+ struct pinctrl_dev *pctldev;
|
||||
+ struct pinctrl_desc desc;
|
||||
+
|
||||
+ void __iomem *led;
|
||||
+ void __iomem *mode;
|
||||
+ void __iomem *ctrl;
|
||||
+ void __iomem *basemode;
|
||||
+
|
||||
+ /* register access lock */
|
||||
+ spinlock_t lock;
|
||||
+
|
||||
+ struct gpio_chip gpio[2];
|
||||
+};
|
||||
+
|
||||
+#define BCM6362_PIN(a, b, mask) \
|
||||
+ { \
|
||||
+ .number = a, \
|
||||
+ .name = b, \
|
||||
+ .drv_data = (void *)(mask), \
|
||||
+ }
|
||||
+
|
||||
+static const struct pinctrl_pin_desc bcm6362_pins[] = {
|
||||
+ PINCTRL_PIN(0, "gpio0"),
|
||||
+ PINCTRL_PIN(1, "gpio1"),
|
||||
+ PINCTRL_PIN(2, "gpio2"),
|
||||
+ PINCTRL_PIN(3, "gpio3"),
|
||||
+ PINCTRL_PIN(4, "gpio4"),
|
||||
+ PINCTRL_PIN(5, "gpio5"),
|
||||
+ PINCTRL_PIN(6, "gpio6"),
|
||||
+ PINCTRL_PIN(7, "gpio7"),
|
||||
+ BCM6362_PIN(8, "gpio8", BASEMODE_NAND),
|
||||
+ PINCTRL_PIN(9, "gpio9"),
|
||||
+ PINCTRL_PIN(10, "gpio10"),
|
||||
+ PINCTRL_PIN(11, "gpio11"),
|
||||
+ BCM6362_PIN(12, "gpio12", BASEMODE_NAND),
|
||||
+ BCM6362_PIN(13, "gpio13", BASEMODE_NAND),
|
||||
+ BCM6362_PIN(14, "gpio14", BASEMODE_NAND),
|
||||
+ BCM6362_PIN(15, "gpio15", BASEMODE_NAND),
|
||||
+ BCM6362_PIN(16, "gpio16", BASEMODE_NAND),
|
||||
+ BCM6362_PIN(17, "gpio17", BASEMODE_NAND),
|
||||
+ BCM6362_PIN(18, "gpio18", BASEMODE_NAND),
|
||||
+ BCM6362_PIN(19, "gpio19", BASEMODE_NAND),
|
||||
+ BCM6362_PIN(20, "gpio20", BASEMODE_NAND),
|
||||
+ BCM6362_PIN(21, "gpio21", BASEMODE_NAND),
|
||||
+ BCM6362_PIN(22, "gpio22", BASEMODE_NAND),
|
||||
+ BCM6362_PIN(23, "gpio23", BASEMODE_NAND),
|
||||
+ PINCTRL_PIN(24, "gpio24"),
|
||||
+ PINCTRL_PIN(25, "gpio25"),
|
||||
+ PINCTRL_PIN(26, "gpio26"),
|
||||
+ BCM6362_PIN(27, "gpio27", BASEMODE_NAND),
|
||||
+ PINCTRL_PIN(28, "gpio28"),
|
||||
+ PINCTRL_PIN(29, "gpio29"),
|
||||
+ PINCTRL_PIN(30, "gpio30"),
|
||||
+ PINCTRL_PIN(31, "gpio31"),
|
||||
+ PINCTRL_PIN(32, "gpio32"),
|
||||
+ PINCTRL_PIN(33, "gpio33"),
|
||||
+ PINCTRL_PIN(34, "gpio34"),
|
||||
+ PINCTRL_PIN(35, "gpio35"),
|
||||
+ PINCTRL_PIN(36, "gpio36"),
|
||||
+ PINCTRL_PIN(37, "gpio37"),
|
||||
+ PINCTRL_PIN(38, "gpio38"),
|
||||
+ PINCTRL_PIN(39, "gpio39"),
|
||||
+ PINCTRL_PIN(40, "gpio40"),
|
||||
+ PINCTRL_PIN(41, "gpio41"),
|
||||
+ PINCTRL_PIN(42, "gpio42"),
|
||||
+ PINCTRL_PIN(43, "gpio43"),
|
||||
+ PINCTRL_PIN(44, "gpio44"),
|
||||
+ PINCTRL_PIN(45, "gpio45"),
|
||||
+ PINCTRL_PIN(46, "gpio46"),
|
||||
+ PINCTRL_PIN(47, "gpio47"),
|
||||
+};
|
||||
+
|
||||
+static unsigned gpio0_pins[] = { 0 };
|
||||
+static unsigned gpio1_pins[] = { 1 };
|
||||
+static unsigned gpio2_pins[] = { 2 };
|
||||
+static unsigned gpio3_pins[] = { 3 };
|
||||
+static unsigned gpio4_pins[] = { 4 };
|
||||
+static unsigned gpio5_pins[] = { 5 };
|
||||
+static unsigned gpio6_pins[] = { 6 };
|
||||
+static unsigned gpio7_pins[] = { 7 };
|
||||
+static unsigned gpio8_pins[] = { 8 };
|
||||
+static unsigned gpio9_pins[] = { 9 };
|
||||
+static unsigned gpio10_pins[] = { 10 };
|
||||
+static unsigned gpio11_pins[] = { 11 };
|
||||
+static unsigned gpio12_pins[] = { 12 };
|
||||
+static unsigned gpio13_pins[] = { 13 };
|
||||
+static unsigned gpio14_pins[] = { 14 };
|
||||
+static unsigned gpio15_pins[] = { 15 };
|
||||
+static unsigned gpio16_pins[] = { 16 };
|
||||
+static unsigned gpio17_pins[] = { 17 };
|
||||
+static unsigned gpio18_pins[] = { 18 };
|
||||
+static unsigned gpio19_pins[] = { 19 };
|
||||
+static unsigned gpio20_pins[] = { 20 };
|
||||
+static unsigned gpio21_pins[] = { 21 };
|
||||
+static unsigned gpio22_pins[] = { 22 };
|
||||
+static unsigned gpio23_pins[] = { 23 };
|
||||
+static unsigned gpio24_pins[] = { 24 };
|
||||
+static unsigned gpio25_pins[] = { 25 };
|
||||
+static unsigned gpio26_pins[] = { 26 };
|
||||
+static unsigned gpio27_pins[] = { 27 };
|
||||
+static unsigned gpio28_pins[] = { 28 };
|
||||
+static unsigned gpio29_pins[] = { 29 };
|
||||
+static unsigned gpio30_pins[] = { 30 };
|
||||
+static unsigned gpio31_pins[] = { 31 };
|
||||
+static unsigned gpio32_pins[] = { 32 };
|
||||
+static unsigned gpio33_pins[] = { 33 };
|
||||
+static unsigned gpio34_pins[] = { 34 };
|
||||
+static unsigned gpio35_pins[] = { 35 };
|
||||
+static unsigned gpio36_pins[] = { 36 };
|
||||
+static unsigned gpio37_pins[] = { 37 };
|
||||
+static unsigned gpio38_pins[] = { 38 };
|
||||
+static unsigned gpio39_pins[] = { 39 };
|
||||
+static unsigned gpio40_pins[] = { 40 };
|
||||
+static unsigned gpio41_pins[] = { 41 };
|
||||
+static unsigned gpio42_pins[] = { 42 };
|
||||
+static unsigned gpio43_pins[] = { 43 };
|
||||
+static unsigned gpio44_pins[] = { 44 };
|
||||
+static unsigned gpio45_pins[] = { 45 };
|
||||
+static unsigned gpio46_pins[] = { 46 };
|
||||
+static unsigned gpio47_pins[] = { 47 };
|
||||
+
|
||||
+static unsigned nand_grp_pins[] = {
|
||||
+ 8, 12, 13, 14, 15, 16, 17,
|
||||
+ 18, 19, 20, 21, 22, 23, 27,
|
||||
+};
|
||||
+
|
||||
+#define BCM6362_GROUP(n) \
|
||||
+ { \
|
||||
+ .name = #n, \
|
||||
+ .pins = n##_pins, \
|
||||
+ .num_pins = ARRAY_SIZE(n##_pins), \
|
||||
+ }
|
||||
+
|
||||
+static struct bcm6362_pingroup bcm6362_groups[] = {
|
||||
+ BCM6362_GROUP(gpio0),
|
||||
+ BCM6362_GROUP(gpio1),
|
||||
+ BCM6362_GROUP(gpio2),
|
||||
+ BCM6362_GROUP(gpio3),
|
||||
+ BCM6362_GROUP(gpio4),
|
||||
+ BCM6362_GROUP(gpio5),
|
||||
+ BCM6362_GROUP(gpio6),
|
||||
+ BCM6362_GROUP(gpio7),
|
||||
+ BCM6362_GROUP(gpio8),
|
||||
+ BCM6362_GROUP(gpio9),
|
||||
+ BCM6362_GROUP(gpio10),
|
||||
+ BCM6362_GROUP(gpio11),
|
||||
+ BCM6362_GROUP(gpio12),
|
||||
+ BCM6362_GROUP(gpio13),
|
||||
+ BCM6362_GROUP(gpio14),
|
||||
+ BCM6362_GROUP(gpio15),
|
||||
+ BCM6362_GROUP(gpio16),
|
||||
+ BCM6362_GROUP(gpio17),
|
||||
+ BCM6362_GROUP(gpio18),
|
||||
+ BCM6362_GROUP(gpio19),
|
||||
+ BCM6362_GROUP(gpio20),
|
||||
+ BCM6362_GROUP(gpio21),
|
||||
+ BCM6362_GROUP(gpio22),
|
||||
+ BCM6362_GROUP(gpio23),
|
||||
+ BCM6362_GROUP(gpio24),
|
||||
+ BCM6362_GROUP(gpio25),
|
||||
+ BCM6362_GROUP(gpio26),
|
||||
+ BCM6362_GROUP(gpio27),
|
||||
+ BCM6362_GROUP(gpio28),
|
||||
+ BCM6362_GROUP(gpio29),
|
||||
+ BCM6362_GROUP(gpio30),
|
||||
+ BCM6362_GROUP(gpio31),
|
||||
+ BCM6362_GROUP(gpio32),
|
||||
+ BCM6362_GROUP(gpio33),
|
||||
+ BCM6362_GROUP(gpio34),
|
||||
+ BCM6362_GROUP(gpio35),
|
||||
+ BCM6362_GROUP(gpio36),
|
||||
+ BCM6362_GROUP(gpio37),
|
||||
+ BCM6362_GROUP(gpio38),
|
||||
+ BCM6362_GROUP(gpio39),
|
||||
+ BCM6362_GROUP(gpio40),
|
||||
+ BCM6362_GROUP(gpio41),
|
||||
+ BCM6362_GROUP(gpio42),
|
||||
+ BCM6362_GROUP(gpio43),
|
||||
+ BCM6362_GROUP(gpio44),
|
||||
+ BCM6362_GROUP(gpio45),
|
||||
+ BCM6362_GROUP(gpio46),
|
||||
+ BCM6362_GROUP(gpio47),
|
||||
+ BCM6362_GROUP(nand_grp),
|
||||
+};
|
||||
+
|
||||
+static const char * const led_groups[] = {
|
||||
+ "gpio0",
|
||||
+ "gpio1",
|
||||
+ "gpio2",
|
||||
+ "gpio3",
|
||||
+ "gpio4",
|
||||
+ "gpio5",
|
||||
+ "gpio6",
|
||||
+ "gpio7",
|
||||
+ "gpio8",
|
||||
+ "gpio9",
|
||||
+ "gpio10",
|
||||
+ "gpio11",
|
||||
+ "gpio12",
|
||||
+ "gpio13",
|
||||
+ "gpio14",
|
||||
+ "gpio15",
|
||||
+ "gpio16",
|
||||
+ "gpio17",
|
||||
+ "gpio18",
|
||||
+ "gpio19",
|
||||
+ "gpio20",
|
||||
+ "gpio21",
|
||||
+ "gpio22",
|
||||
+ "gpio23",
|
||||
+};
|
||||
+
|
||||
+static const char * const usb_device_led_groups[] = {
|
||||
+ "gpio0",
|
||||
+};
|
||||
+
|
||||
+static const char * const sys_irq_groups[] = {
|
||||
+ "gpio1",
|
||||
+};
|
||||
+
|
||||
+static const char * const serial_led_clk_groups[] = {
|
||||
+ "gpio2",
|
||||
+};
|
||||
+
|
||||
+static const char * const serial_led_data_groups[] = {
|
||||
+ "gpio3",
|
||||
+};
|
||||
+
|
||||
+static const char * const robosw_led_data_groups[] = {
|
||||
+ "gpio4",
|
||||
+};
|
||||
+
|
||||
+static const char * const robosw_led_clk_groups[] = {
|
||||
+ "gpio5",
|
||||
+};
|
||||
+
|
||||
+static const char * const robosw_led0_groups[] = {
|
||||
+ "gpio6",
|
||||
+};
|
||||
+
|
||||
+static const char * const robosw_led1_groups[] = {
|
||||
+ "gpio7",
|
||||
+};
|
||||
+
|
||||
+static const char * const inet_led_groups[] = {
|
||||
+ "gpio8",
|
||||
+};
|
||||
+
|
||||
+static const char * const spi_cs2_groups[] = {
|
||||
+ "gpio9",
|
||||
+};
|
||||
+
|
||||
+static const char * const spi_cs3_groups[] = {
|
||||
+ "gpio10",
|
||||
+};
|
||||
+
|
||||
+static const char * const ntr_pulse_groups[] = {
|
||||
+ "gpio11",
|
||||
+};
|
||||
+
|
||||
+static const char * const uart1_scts_groups[] = {
|
||||
+ "gpio12",
|
||||
+};
|
||||
+
|
||||
+static const char * const uart1_srts_groups[] = {
|
||||
+ "gpio13",
|
||||
+};
|
||||
+
|
||||
+static const char * const uart1_sdin_groups[] = {
|
||||
+ "gpio14",
|
||||
+};
|
||||
+
|
||||
+static const char * const uart1_sdout_groups[] = {
|
||||
+ "gpio15",
|
||||
+};
|
||||
+
|
||||
+static const char * const adsl_spi_miso_groups[] = {
|
||||
+ "gpio16",
|
||||
+};
|
||||
+
|
||||
+static const char * const adsl_spi_mosi_groups[] = {
|
||||
+ "gpio17",
|
||||
+};
|
||||
+
|
||||
+static const char * const adsl_spi_clk_groups[] = {
|
||||
+ "gpio18",
|
||||
+};
|
||||
+
|
||||
+static const char * const adsl_spi_cs_groups[] = {
|
||||
+ "gpio19",
|
||||
+};
|
||||
+
|
||||
+static const char * const ephy0_led_groups[] = {
|
||||
+ "gpio20",
|
||||
+};
|
||||
+
|
||||
+static const char * const ephy1_led_groups[] = {
|
||||
+ "gpio21",
|
||||
+};
|
||||
+
|
||||
+static const char * const ephy2_led_groups[] = {
|
||||
+ "gpio22",
|
||||
+};
|
||||
+
|
||||
+static const char * const ephy3_led_groups[] = {
|
||||
+ "gpio23",
|
||||
+};
|
||||
+
|
||||
+static const char * const ext_irq0_groups[] = {
|
||||
+ "gpio24",
|
||||
+};
|
||||
+
|
||||
+static const char * const ext_irq1_groups[] = {
|
||||
+ "gpio25",
|
||||
+};
|
||||
+
|
||||
+static const char * const ext_irq2_groups[] = {
|
||||
+ "gpio26",
|
||||
+};
|
||||
+
|
||||
+static const char * const ext_irq3_groups[] = {
|
||||
+ "gpio27",
|
||||
+};
|
||||
+
|
||||
+static const char * const wifi_groups[] = {
|
||||
+ "gpio32",
|
||||
+ "gpio33",
|
||||
+ "gpio34",
|
||||
+ "gpio35",
|
||||
+ "gpio36",
|
||||
+ "gpio37",
|
||||
+ "gpio38",
|
||||
+ "gpio39",
|
||||
+ "gpio40",
|
||||
+ "gpio41",
|
||||
+ "gpio42",
|
||||
+ "gpio43",
|
||||
+ "gpio44",
|
||||
+ "gpio45",
|
||||
+ "gpio46",
|
||||
+ "gpio47",
|
||||
+};
|
||||
+
|
||||
+static const char * const nand_groups[] = {
|
||||
+ "nand_grp",
|
||||
+};
|
||||
+
|
||||
+#define BCM6362_LED_FUN(n) \
|
||||
+ { \
|
||||
+ .name = #n, \
|
||||
+ .groups = n##_groups, \
|
||||
+ .num_groups = ARRAY_SIZE(n##_groups), \
|
||||
+ .reg = BCM6362_LEDCTRL, \
|
||||
+ }
|
||||
+
|
||||
+#define BCM6362_MODE_FUN(n) \
|
||||
+ { \
|
||||
+ .name = #n, \
|
||||
+ .groups = n##_groups, \
|
||||
+ .num_groups = ARRAY_SIZE(n##_groups), \
|
||||
+ .reg = BCM6362_MODE, \
|
||||
+ }
|
||||
+
|
||||
+#define BCM6362_CTRL_FUN(n) \
|
||||
+ { \
|
||||
+ .name = #n, \
|
||||
+ .groups = n##_groups, \
|
||||
+ .num_groups = ARRAY_SIZE(n##_groups), \
|
||||
+ .reg = BCM6362_CTRL, \
|
||||
+ }
|
||||
+
|
||||
+#define BCM6362_BASEMODE_FUN(n, mask) \
|
||||
+ { \
|
||||
+ .name = #n, \
|
||||
+ .groups = n##_groups, \
|
||||
+ .num_groups = ARRAY_SIZE(n##_groups), \
|
||||
+ .reg = BCM6362_BASEMODE, \
|
||||
+ .basemode_mask = (mask), \
|
||||
+ }
|
||||
+
|
||||
+static const struct bcm6362_function bcm6362_funcs[] = {
|
||||
+ BCM6362_LED_FUN(led),
|
||||
+ BCM6362_MODE_FUN(usb_device_led),
|
||||
+ BCM6362_MODE_FUN(sys_irq),
|
||||
+ BCM6362_MODE_FUN(serial_led_clk),
|
||||
+ BCM6362_MODE_FUN(serial_led_data),
|
||||
+ BCM6362_MODE_FUN(robosw_led_data),
|
||||
+ BCM6362_MODE_FUN(robosw_led_clk),
|
||||
+ BCM6362_MODE_FUN(robosw_led0),
|
||||
+ BCM6362_MODE_FUN(robosw_led1),
|
||||
+ BCM6362_MODE_FUN(inet_led),
|
||||
+ BCM6362_MODE_FUN(spi_cs2),
|
||||
+ BCM6362_MODE_FUN(spi_cs3),
|
||||
+ BCM6362_MODE_FUN(ntr_pulse),
|
||||
+ BCM6362_MODE_FUN(uart1_scts),
|
||||
+ BCM6362_MODE_FUN(uart1_srts),
|
||||
+ BCM6362_MODE_FUN(uart1_sdin),
|
||||
+ BCM6362_MODE_FUN(uart1_sdout),
|
||||
+ BCM6362_MODE_FUN(adsl_spi_miso),
|
||||
+ BCM6362_MODE_FUN(adsl_spi_mosi),
|
||||
+ BCM6362_MODE_FUN(adsl_spi_clk),
|
||||
+ BCM6362_MODE_FUN(adsl_spi_cs),
|
||||
+ BCM6362_MODE_FUN(ephy0_led),
|
||||
+ BCM6362_MODE_FUN(ephy1_led),
|
||||
+ BCM6362_MODE_FUN(ephy2_led),
|
||||
+ BCM6362_MODE_FUN(ephy3_led),
|
||||
+ BCM6362_MODE_FUN(ext_irq0),
|
||||
+ BCM6362_MODE_FUN(ext_irq1),
|
||||
+ BCM6362_MODE_FUN(ext_irq2),
|
||||
+ BCM6362_MODE_FUN(ext_irq3),
|
||||
+ BCM6362_CTRL_FUN(wifi),
|
||||
+ BCM6362_BASEMODE_FUN(nand, BASEMODE_NAND),
|
||||
+};
|
||||
+
|
||||
+static int bcm6362_pinctrl_get_group_count(struct pinctrl_dev *pctldev)
|
||||
+{
|
||||
+ return ARRAY_SIZE(bcm6362_groups);
|
||||
+}
|
||||
+
|
||||
+static const char *bcm6362_pinctrl_get_group_name(struct pinctrl_dev *pctldev,
|
||||
+ unsigned group)
|
||||
+{
|
||||
+ return bcm6362_groups[group].name;
|
||||
+}
|
||||
+
|
||||
+static int bcm6362_pinctrl_get_group_pins(struct pinctrl_dev *pctldev,
|
||||
+ unsigned group, const unsigned **pins,
|
||||
+ unsigned *num_pins)
|
||||
+{
|
||||
+ *pins = bcm6362_groups[group].pins;
|
||||
+ *num_pins = bcm6362_groups[group].num_pins;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int bcm6362_pinctrl_get_func_count(struct pinctrl_dev *pctldev)
|
||||
+{
|
||||
+ return ARRAY_SIZE(bcm6362_funcs);
|
||||
+}
|
||||
+
|
||||
+static const char *bcm6362_pinctrl_get_func_name(struct pinctrl_dev *pctldev,
|
||||
+ unsigned selector)
|
||||
+{
|
||||
+ return bcm6362_funcs[selector].name;
|
||||
+}
|
||||
+
|
||||
+static int bcm6362_pinctrl_get_groups(struct pinctrl_dev *pctldev,
|
||||
+ unsigned selector,
|
||||
+ const char * const **groups,
|
||||
+ unsigned * const num_groups)
|
||||
+{
|
||||
+ *groups = bcm6362_funcs[selector].groups;
|
||||
+ *num_groups = bcm6362_funcs[selector].num_groups;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void bcm6362_rmw_mux(struct bcm6362_pinctrl *pctl, void __iomem *reg,
|
||||
+ u32 mask, u32 val)
|
||||
+{
|
||||
+ unsigned long flags;
|
||||
+ u32 tmp;
|
||||
+
|
||||
+ spin_lock_irqsave(&pctl->lock, flags);
|
||||
+ tmp = __raw_readl(reg);
|
||||
+ tmp &= ~mask;
|
||||
+ tmp |= val & mask;
|
||||
+ __raw_writel(tmp, reg);
|
||||
+
|
||||
+ spin_unlock_irqrestore(&pctl->lock, flags);
|
||||
+}
|
||||
+
|
||||
+static void bcm6362_set_gpio(struct bcm6362_pinctrl *pctl, unsigned pin)
|
||||
+{
|
||||
+ const struct pinctrl_pin_desc *desc = &bcm6362_pins[pin];
|
||||
+ u32 mask = BIT(pin % 32);
|
||||
+
|
||||
+ if (desc->drv_data)
|
||||
+ bcm6362_rmw_mux(pctl, pctl->basemode, (u32)desc->drv_data, 0);
|
||||
+
|
||||
+ if (pin < 32) {
|
||||
+ /* base mode 0 => gpio 1 => mux function */
|
||||
+ bcm6362_rmw_mux(pctl, pctl->mode, mask, 0);
|
||||
+
|
||||
+ /* pins 0-23 might be muxed to led */
|
||||
+ if (pin < 24)
|
||||
+ bcm6362_rmw_mux(pctl, pctl->led, mask, 0);
|
||||
+ } else {
|
||||
+ /* ctrl reg 0 => wifi function 1 => gpio */
|
||||
+ bcm6362_rmw_mux(pctl, pctl->ctrl, mask, mask);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static int bcm6362_pinctrl_set_mux(struct pinctrl_dev *pctldev,
|
||||
+ unsigned selector, unsigned group)
|
||||
+{
|
||||
+ struct bcm6362_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
|
||||
+ const struct bcm6362_pingroup *grp = &bcm6362_groups[group];
|
||||
+ const struct bcm6362_function *f = &bcm6362_funcs[selector];
|
||||
+ unsigned i;
|
||||
+ void __iomem *reg;
|
||||
+ u32 val, mask;
|
||||
+
|
||||
+ for (i = 0; i < grp->num_pins; i++)
|
||||
+ bcm6362_set_gpio(pctl, grp->pins[i]);
|
||||
+
|
||||
+ switch (f->reg) {
|
||||
+ case BCM6362_LEDCTRL:
|
||||
+ reg = pctl->led;
|
||||
+ mask = BIT(grp->pins[0]);
|
||||
+ val = BIT(grp->pins[0]);
|
||||
+ break;
|
||||
+ case BCM6362_MODE:
|
||||
+ reg = pctl->ctrl;
|
||||
+ mask = BIT(grp->pins[0]);
|
||||
+ val = BIT(grp->pins[0]);
|
||||
+ break;
|
||||
+ case BCM6362_CTRL:
|
||||
+ reg = pctl->ctrl;
|
||||
+ mask = BIT(grp->pins[0]);
|
||||
+ val = 0;
|
||||
+ break;
|
||||
+ case BCM6362_BASEMODE:
|
||||
+ reg = pctl->basemode;
|
||||
+ mask = f->basemode_mask;
|
||||
+ val = f->basemode_mask;
|
||||
+ break;
|
||||
+ default:
|
||||
+ WARN_ON(1);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ bcm6362_rmw_mux(pctl, reg, mask, val);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int bcm6362_gpio_request_enable(struct pinctrl_dev *pctldev,
|
||||
+ struct pinctrl_gpio_range *range,
|
||||
+ unsigned offset)
|
||||
+{
|
||||
+ struct bcm6362_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
|
||||
+
|
||||
+ /* disable all functions using this pin */
|
||||
+ bcm6362_set_gpio(pctl, offset);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static struct pinctrl_ops bcm6362_pctl_ops = {
|
||||
+ .get_groups_count = bcm6362_pinctrl_get_group_count,
|
||||
+ .get_group_name = bcm6362_pinctrl_get_group_name,
|
||||
+ .get_group_pins = bcm6362_pinctrl_get_group_pins,
|
||||
+#ifdef CONFIG_OF
|
||||
+ .dt_node_to_map = pinconf_generic_dt_node_to_map_pin,
|
||||
+ .dt_free_map = pinctrl_utils_free_map,
|
||||
+#endif
|
||||
+};
|
||||
+
|
||||
+static struct pinmux_ops bcm6362_pmx_ops = {
|
||||
+ .get_functions_count = bcm6362_pinctrl_get_func_count,
|
||||
+ .get_function_name = bcm6362_pinctrl_get_func_name,
|
||||
+ .get_function_groups = bcm6362_pinctrl_get_groups,
|
||||
+ .set_mux = bcm6362_pinctrl_set_mux,
|
||||
+ .gpio_request_enable = bcm6362_gpio_request_enable,
|
||||
+ .strict = true,
|
||||
+};
|
||||
+
|
||||
+static int bcm6362_pinctrl_probe(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct bcm6362_pinctrl *pctl;
|
||||
+ struct resource *res;
|
||||
+ void __iomem *led, *mode, *ctrl, *basemode;
|
||||
+
|
||||
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "led");
|
||||
+ led = devm_ioremap_resource(&pdev->dev, res);
|
||||
+ if (IS_ERR(led))
|
||||
+ return PTR_ERR(led);
|
||||
+
|
||||
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mode");
|
||||
+ mode = devm_ioremap_resource(&pdev->dev, res);
|
||||
+ if (IS_ERR(mode))
|
||||
+ return PTR_ERR(mode);
|
||||
+
|
||||
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ctrl");
|
||||
+ ctrl = devm_ioremap_resource(&pdev->dev, res);
|
||||
+ if (IS_ERR(ctrl))
|
||||
+ return PTR_ERR(ctrl);
|
||||
+
|
||||
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "basemode");
|
||||
+ basemode = devm_ioremap_resource(&pdev->dev, res);
|
||||
+ if (IS_ERR(basemode))
|
||||
+ return PTR_ERR(basemode);
|
||||
+
|
||||
+ pctl = devm_kzalloc(&pdev->dev, sizeof(*pctl), GFP_KERNEL);
|
||||
+ if (!pctl)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ spin_lock_init(&pctl->lock);
|
||||
+
|
||||
+ pctl->led = led;
|
||||
+ pctl->mode = mode;
|
||||
+ pctl->ctrl = ctrl;
|
||||
+ pctl->basemode = basemode;
|
||||
+
|
||||
+ pctl->desc.name = dev_name(&pdev->dev);
|
||||
+ pctl->desc.owner = THIS_MODULE;
|
||||
+ pctl->desc.pctlops = &bcm6362_pctl_ops;
|
||||
+ pctl->desc.pmxops = &bcm6362_pmx_ops;
|
||||
+
|
||||
+ pctl->desc.npins = ARRAY_SIZE(bcm6362_pins);
|
||||
+ pctl->desc.pins = bcm6362_pins;
|
||||
+
|
||||
+ platform_set_drvdata(pdev, pctl);
|
||||
+
|
||||
+ pctl->pctldev = bcm63xx_pinctrl_register(pdev, &pctl->desc, pctl,
|
||||
+ pctl->gpio, BCM6362_NGPIO);
|
||||
+ if (IS_ERR(pctl->pctldev))
|
||||
+ return PTR_ERR(pctl->pctldev);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static const struct of_device_id bcm6362_pinctrl_match[] = {
|
||||
+ { .compatible = "brcm,bcm6362-pinctrl", },
|
||||
+ { },
|
||||
+};
|
||||
+
|
||||
+static struct platform_driver bcm6362_pinctrl_driver = {
|
||||
+ .probe = bcm6362_pinctrl_probe,
|
||||
+ .driver = {
|
||||
+ .name = "bcm6362-pinctrl",
|
||||
+ .of_match_table = bcm6362_pinctrl_match,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+builtin_platform_driver(bcm6362_pinctrl_driver);
|
@ -1,84 +0,0 @@
|
||||
From 30594cf9bfff176a9e4b14c50dcd8b9d0cc3edec Mon Sep 17 00:00:00 2001
|
||||
From: Jonas Gorski <jonas.gorski@gmail.com>
|
||||
Date: Wed, 27 Jul 2016 11:36:51 +0200
|
||||
Subject: [PATCH 10/16] Documentation: add BCM6368 pincontroller binding
|
||||
documentation
|
||||
|
||||
Add binding documentation for the pincontrol core found in BCM6368 SoCs.
|
||||
|
||||
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
|
||||
---
|
||||
.../bindings/pinctrl/brcm,bcm6368-pinctrl.txt | 67 ++++++++++++++++++++++
|
||||
1 file changed, 67 insertions(+)
|
||||
create mode 100644 Documentation/devicetree/bindings/pinctrl/brcm,bcm6368-pinctrl.txt
|
||||
|
||||
--- /dev/null
|
||||
+++ b/Documentation/devicetree/bindings/pinctrl/brcm,bcm6368-pinctrl.txt
|
||||
@@ -0,0 +1,67 @@
|
||||
+* Broadcom BCM6368 pin controller
|
||||
+
|
||||
+Required properties:
|
||||
+- compatible: Must be "brcm,bcm6368-pinctrl".
|
||||
+- reg: Register specifiers of dirout, dat, mode registers.
|
||||
+- reg-names: Must be "dirout", "dat", "mode".
|
||||
+- brcm,gpiobasemode: Phandle to the gpio basemode register.
|
||||
+- gpio-controller: Identifies this node as a GPIO controller.
|
||||
+- #gpio-cells: Must be <2>.
|
||||
+
|
||||
+Example:
|
||||
+
|
||||
+pinctrl: pin-controller@10000080 {
|
||||
+ compatible = "brcm,bcm6368-pinctrl";
|
||||
+ reg = <0x10000080 0x08>,
|
||||
+ <0x10000088 0x08>,
|
||||
+ <0x10000098 0x04>;
|
||||
+ reg-names = "dirout", "dat", "mode";
|
||||
+ brcm,gpiobasemode = <&gpiobasemode>;
|
||||
+
|
||||
+ gpio-controller;
|
||||
+ #gpio-cells = <2>;
|
||||
+};
|
||||
+
|
||||
+gpiobasemode: syscon@100000b8 {
|
||||
+ compatible = "brcm,bcm6368-gpiobasemode", "syscon";
|
||||
+ reg = <0x100000b8 4>;
|
||||
+ native-endian;
|
||||
+};
|
||||
+
|
||||
+Available pins/groups and functions:
|
||||
+
|
||||
+name pins functions
|
||||
+-----------------------------------------------------------
|
||||
+gpio0 0 analog_afe0
|
||||
+gpio1 1 analog_afe1
|
||||
+gpio2 2 sys_irq
|
||||
+gpio3 3 serial_led_data
|
||||
+gpio4 4 serial_led_clk
|
||||
+gpio5 5 inet_led
|
||||
+gpio6 6 ephy0_led
|
||||
+gpio7 7 ephy1_led
|
||||
+gpio8 8 ephy2_led
|
||||
+gpio9 9 ephy3_led
|
||||
+gpio10 10 robosw_led_data
|
||||
+gpio11 11 robosw_led_clk
|
||||
+gpio12 12 robosw_led0
|
||||
+gpio13 13 robosw_led1
|
||||
+gpio14 14 usb_device_led
|
||||
+gpio15 15 -
|
||||
+gpio16 16 pci_req1
|
||||
+gpio17 17 pci_gnt1
|
||||
+gpio18 18 pci_intb
|
||||
+gpio19 19 pci_req0
|
||||
+gpio20 20 pci_gnt0
|
||||
+gpio21 21 -
|
||||
+gpio22 22 pcmcia_cd1
|
||||
+gpio23 23 pcmcia_cd2
|
||||
+gpio24 24 pcmcia_vs1
|
||||
+gpio25 25 pcmcia_vs2
|
||||
+gpio26 26 ebi_cs2
|
||||
+gpio27 27 ebi_cs3
|
||||
+gpio28 28 spi_cs2
|
||||
+gpio29 29 spi_cs3
|
||||
+gpio30 30 spi_cs4
|
||||
+gpio31 31 spi_cs5
|
||||
+uart1_grp 30-33 uart1
|
@ -1,620 +0,0 @@
|
||||
From 90be3cb4f1a45b8be4a4ec264cd66c2f8e893fcb Mon Sep 17 00:00:00 2001
|
||||
From: Jonas Gorski <jonas.gorski@gmail.com>
|
||||
Date: Fri, 24 Jun 2016 22:18:25 +0200
|
||||
Subject: [PATCH 11/16] pinctrl: add a pincontrol driver for BCM6368
|
||||
|
||||
Add a pincontrol driver for BCM6368. BCM6368 allows muxing the first 32
|
||||
GPIOs onto alternative functions. Not all are documented.
|
||||
|
||||
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
|
||||
---
|
||||
drivers/pinctrl/bcm63xx/Kconfig | 15 +
|
||||
drivers/pinctrl/bcm63xx/Makefile | 1 +
|
||||
drivers/pinctrl/bcm63xx/pinctrl-bcm6368.c | 573 ++++++++++++++++++++++++++++++
|
||||
3 files changed, 589 insertions(+)
|
||||
create mode 100644 drivers/pinctrl/bcm63xx/pinctrl-bcm6368.c
|
||||
|
||||
--- a/drivers/pinctrl/bcm63xx/Kconfig
|
||||
+++ b/drivers/pinctrl/bcm63xx/Kconfig
|
||||
@@ -30,3 +30,18 @@ config PINCTRL_BCM6362
|
||||
select PINCONF
|
||||
select PINCTRL_BCM63XX
|
||||
select GENERIC_PINCONF
|
||||
+
|
||||
+config PINCTRL_BCM6368
|
||||
+ bool "BCM6368 pincontrol driver" if COMPILE_TEST
|
||||
+ select PINMUX
|
||||
+ select PINCONF
|
||||
+ select PINCTRL_BCM63XX
|
||||
+ select GENERIC_PINCONF
|
||||
+ select MFD_SYSCON
|
||||
+
|
||||
+config PINCTRL_BCM63268
|
||||
+ bool "BCM63268 pincontrol driver" if COMPILE_TEST
|
||||
+ select PINMUX
|
||||
+ select PINCONF
|
||||
+ select PINCTRL_BCM63XX
|
||||
+ select GENERIC_PINCONF
|
||||
--- a/drivers/pinctrl/bcm63xx/Makefile
|
||||
+++ b/drivers/pinctrl/bcm63xx/Makefile
|
||||
@@ -3,3 +3,4 @@ obj-$(CONFIG_PINCTRL_BCM6328) += pinctrl
|
||||
obj-$(CONFIG_PINCTRL_BCM6348) += pinctrl-bcm6348.o
|
||||
obj-$(CONFIG_PINCTRL_BCM6358) += pinctrl-bcm6358.o
|
||||
obj-$(CONFIG_PINCTRL_BCM6362) += pinctrl-bcm6362.o
|
||||
+obj-$(CONFIG_PINCTRL_BCM6368) += pinctrl-bcm6368.o
|
||||
--- /dev/null
|
||||
+++ b/drivers/pinctrl/bcm63xx/pinctrl-bcm6368.c
|
||||
@@ -0,0 +1,573 @@
|
||||
+/*
|
||||
+ * This file is subject to the terms and conditions of the GNU General Public
|
||||
+ * License. See the file "COPYING" in the main directory of this archive
|
||||
+ * for more details.
|
||||
+ *
|
||||
+ * Copyright (C) 2016 Jonas Gorski <jonas.gorski@gmail.com>
|
||||
+ */
|
||||
+
|
||||
+#include <linux/bitops.h>
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/gpio.h>
|
||||
+#include <linux/mfd/syscon.h>
|
||||
+#include <linux/of.h>
|
||||
+#include <linux/of_address.h>
|
||||
+#include <linux/of_gpio.h>
|
||||
+#include <linux/pinctrl/pinconf.h>
|
||||
+#include <linux/pinctrl/pinconf-generic.h>
|
||||
+#include <linux/pinctrl/pinmux.h>
|
||||
+#include <linux/pinctrl/machine.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+#include <linux/regmap.h>
|
||||
+#include <linux/slab.h>
|
||||
+#include <linux/spinlock.h>
|
||||
+
|
||||
+#include "../core.h"
|
||||
+#include "../pinctrl-utils.h"
|
||||
+
|
||||
+#include "pinctrl-bcm63xx.h"
|
||||
+
|
||||
+#define BCM6368_NGPIO 38
|
||||
+
|
||||
+#define BCM6368_BASEMODE_MASK 0x7
|
||||
+#define BCM6368_BASEMODE_GPIO 0x0
|
||||
+#define BCM6368_BASEMODE_UART1 0x1
|
||||
+
|
||||
+struct bcm6368_pingroup {
|
||||
+ const char *name;
|
||||
+ const unsigned * const pins;
|
||||
+ const unsigned num_pins;
|
||||
+};
|
||||
+
|
||||
+struct bcm6368_function {
|
||||
+ const char *name;
|
||||
+ const char * const *groups;
|
||||
+ const unsigned num_groups;
|
||||
+
|
||||
+ unsigned dir_out:16;
|
||||
+ unsigned basemode:3;
|
||||
+};
|
||||
+
|
||||
+struct bcm6368_pinctrl {
|
||||
+ struct pinctrl_dev *pctldev;
|
||||
+ struct pinctrl_desc desc;
|
||||
+
|
||||
+ void __iomem *mode;
|
||||
+ struct regmap_field *overlay;
|
||||
+
|
||||
+ /* register access lock */
|
||||
+ spinlock_t lock;
|
||||
+
|
||||
+ struct gpio_chip gpio[2];
|
||||
+};
|
||||
+
|
||||
+#define BCM6368_BASEMODE_PIN(a, b) \
|
||||
+ { \
|
||||
+ .number = a, \
|
||||
+ .name = b, \
|
||||
+ .drv_data = (void *)true \
|
||||
+ }
|
||||
+
|
||||
+static const struct pinctrl_pin_desc bcm6368_pins[] = {
|
||||
+ PINCTRL_PIN(0, "gpio0"),
|
||||
+ PINCTRL_PIN(1, "gpio1"),
|
||||
+ PINCTRL_PIN(2, "gpio2"),
|
||||
+ PINCTRL_PIN(3, "gpio3"),
|
||||
+ PINCTRL_PIN(4, "gpio4"),
|
||||
+ PINCTRL_PIN(5, "gpio5"),
|
||||
+ PINCTRL_PIN(6, "gpio6"),
|
||||
+ PINCTRL_PIN(7, "gpio7"),
|
||||
+ PINCTRL_PIN(8, "gpio8"),
|
||||
+ PINCTRL_PIN(9, "gpio9"),
|
||||
+ PINCTRL_PIN(10, "gpio10"),
|
||||
+ PINCTRL_PIN(11, "gpio11"),
|
||||
+ PINCTRL_PIN(12, "gpio12"),
|
||||
+ PINCTRL_PIN(13, "gpio13"),
|
||||
+ PINCTRL_PIN(14, "gpio14"),
|
||||
+ PINCTRL_PIN(15, "gpio15"),
|
||||
+ PINCTRL_PIN(16, "gpio16"),
|
||||
+ PINCTRL_PIN(17, "gpio17"),
|
||||
+ PINCTRL_PIN(18, "gpio18"),
|
||||
+ PINCTRL_PIN(19, "gpio19"),
|
||||
+ PINCTRL_PIN(20, "gpio20"),
|
||||
+ PINCTRL_PIN(21, "gpio21"),
|
||||
+ PINCTRL_PIN(22, "gpio22"),
|
||||
+ PINCTRL_PIN(23, "gpio23"),
|
||||
+ PINCTRL_PIN(24, "gpio24"),
|
||||
+ PINCTRL_PIN(25, "gpio25"),
|
||||
+ PINCTRL_PIN(26, "gpio26"),
|
||||
+ PINCTRL_PIN(27, "gpio27"),
|
||||
+ PINCTRL_PIN(28, "gpio28"),
|
||||
+ PINCTRL_PIN(29, "gpio29"),
|
||||
+ BCM6368_BASEMODE_PIN(30, "gpio30"),
|
||||
+ BCM6368_BASEMODE_PIN(31, "gpio31"),
|
||||
+ BCM6368_BASEMODE_PIN(32, "gpio32"),
|
||||
+ BCM6368_BASEMODE_PIN(33, "gpio33"),
|
||||
+ PINCTRL_PIN(34, "gpio34"),
|
||||
+ PINCTRL_PIN(35, "gpio35"),
|
||||
+ PINCTRL_PIN(36, "gpio36"),
|
||||
+ PINCTRL_PIN(37, "gpio37"),
|
||||
+};
|
||||
+
|
||||
+static unsigned gpio0_pins[] = { 0 };
|
||||
+static unsigned gpio1_pins[] = { 1 };
|
||||
+static unsigned gpio2_pins[] = { 2 };
|
||||
+static unsigned gpio3_pins[] = { 3 };
|
||||
+static unsigned gpio4_pins[] = { 4 };
|
||||
+static unsigned gpio5_pins[] = { 5 };
|
||||
+static unsigned gpio6_pins[] = { 6 };
|
||||
+static unsigned gpio7_pins[] = { 7 };
|
||||
+static unsigned gpio8_pins[] = { 8 };
|
||||
+static unsigned gpio9_pins[] = { 9 };
|
||||
+static unsigned gpio10_pins[] = { 10 };
|
||||
+static unsigned gpio11_pins[] = { 11 };
|
||||
+static unsigned gpio12_pins[] = { 12 };
|
||||
+static unsigned gpio13_pins[] = { 13 };
|
||||
+static unsigned gpio14_pins[] = { 14 };
|
||||
+static unsigned gpio15_pins[] = { 15 };
|
||||
+static unsigned gpio16_pins[] = { 16 };
|
||||
+static unsigned gpio17_pins[] = { 17 };
|
||||
+static unsigned gpio18_pins[] = { 18 };
|
||||
+static unsigned gpio19_pins[] = { 19 };
|
||||
+static unsigned gpio20_pins[] = { 20 };
|
||||
+static unsigned gpio21_pins[] = { 21 };
|
||||
+static unsigned gpio22_pins[] = { 22 };
|
||||
+static unsigned gpio23_pins[] = { 23 };
|
||||
+static unsigned gpio24_pins[] = { 24 };
|
||||
+static unsigned gpio25_pins[] = { 25 };
|
||||
+static unsigned gpio26_pins[] = { 26 };
|
||||
+static unsigned gpio27_pins[] = { 27 };
|
||||
+static unsigned gpio28_pins[] = { 28 };
|
||||
+static unsigned gpio29_pins[] = { 29 };
|
||||
+static unsigned gpio30_pins[] = { 30 };
|
||||
+static unsigned gpio31_pins[] = { 31 };
|
||||
+static unsigned uart1_grp_pins[] = { 30, 31, 32, 33 };
|
||||
+
|
||||
+#define BCM6368_GROUP(n) \
|
||||
+ { \
|
||||
+ .name = #n, \
|
||||
+ .pins = n##_pins, \
|
||||
+ .num_pins = ARRAY_SIZE(n##_pins), \
|
||||
+ }
|
||||
+
|
||||
+static struct bcm6368_pingroup bcm6368_groups[] = {
|
||||
+ BCM6368_GROUP(gpio0),
|
||||
+ BCM6368_GROUP(gpio1),
|
||||
+ BCM6368_GROUP(gpio2),
|
||||
+ BCM6368_GROUP(gpio3),
|
||||
+ BCM6368_GROUP(gpio4),
|
||||
+ BCM6368_GROUP(gpio5),
|
||||
+ BCM6368_GROUP(gpio6),
|
||||
+ BCM6368_GROUP(gpio7),
|
||||
+ BCM6368_GROUP(gpio8),
|
||||
+ BCM6368_GROUP(gpio9),
|
||||
+ BCM6368_GROUP(gpio10),
|
||||
+ BCM6368_GROUP(gpio11),
|
||||
+ BCM6368_GROUP(gpio12),
|
||||
+ BCM6368_GROUP(gpio13),
|
||||
+ BCM6368_GROUP(gpio14),
|
||||
+ BCM6368_GROUP(gpio15),
|
||||
+ BCM6368_GROUP(gpio16),
|
||||
+ BCM6368_GROUP(gpio17),
|
||||
+ BCM6368_GROUP(gpio18),
|
||||
+ BCM6368_GROUP(gpio19),
|
||||
+ BCM6368_GROUP(gpio20),
|
||||
+ BCM6368_GROUP(gpio21),
|
||||
+ BCM6368_GROUP(gpio22),
|
||||
+ BCM6368_GROUP(gpio23),
|
||||
+ BCM6368_GROUP(gpio24),
|
||||
+ BCM6368_GROUP(gpio25),
|
||||
+ BCM6368_GROUP(gpio26),
|
||||
+ BCM6368_GROUP(gpio27),
|
||||
+ BCM6368_GROUP(gpio28),
|
||||
+ BCM6368_GROUP(gpio29),
|
||||
+ BCM6368_GROUP(gpio30),
|
||||
+ BCM6368_GROUP(gpio31),
|
||||
+ BCM6368_GROUP(uart1_grp),
|
||||
+};
|
||||
+
|
||||
+static const char * const analog_afe_0_groups[] = {
|
||||
+ "gpio0",
|
||||
+};
|
||||
+
|
||||
+static const char * const analog_afe_1_groups[] = {
|
||||
+ "gpio1",
|
||||
+};
|
||||
+
|
||||
+static const char * const sys_irq_groups[] = {
|
||||
+ "gpio2",
|
||||
+};
|
||||
+
|
||||
+static const char * const serial_led_data_groups[] = {
|
||||
+ "gpio3",
|
||||
+};
|
||||
+
|
||||
+static const char * const serial_led_clk_groups[] = {
|
||||
+ "gpio4",
|
||||
+};
|
||||
+
|
||||
+static const char * const inet_led_groups[] = {
|
||||
+ "gpio5",
|
||||
+};
|
||||
+
|
||||
+static const char * const ephy0_led_groups[] = {
|
||||
+ "gpio6",
|
||||
+};
|
||||
+
|
||||
+static const char * const ephy1_led_groups[] = {
|
||||
+ "gpio7",
|
||||
+};
|
||||
+
|
||||
+static const char * const ephy2_led_groups[] = {
|
||||
+ "gpio8",
|
||||
+};
|
||||
+
|
||||
+static const char * const ephy3_led_groups[] = {
|
||||
+ "gpio9",
|
||||
+};
|
||||
+
|
||||
+static const char * const robosw_led_data_groups[] = {
|
||||
+ "gpio10",
|
||||
+};
|
||||
+
|
||||
+static const char * const robosw_led_clk_groups[] = {
|
||||
+ "gpio11",
|
||||
+};
|
||||
+
|
||||
+static const char * const robosw_led0_groups[] = {
|
||||
+ "gpio12",
|
||||
+};
|
||||
+
|
||||
+static const char * const robosw_led1_groups[] = {
|
||||
+ "gpio13",
|
||||
+};
|
||||
+
|
||||
+static const char * const usb_device_led_groups[] = {
|
||||
+ "gpio14",
|
||||
+};
|
||||
+
|
||||
+static const char * const pci_req1_groups[] = {
|
||||
+ "gpio16",
|
||||
+};
|
||||
+
|
||||
+static const char * const pci_gnt1_groups[] = {
|
||||
+ "gpio17",
|
||||
+};
|
||||
+
|
||||
+static const char * const pci_intb_groups[] = {
|
||||
+ "gpio18",
|
||||
+};
|
||||
+
|
||||
+static const char * const pci_req0_groups[] = {
|
||||
+ "gpio19",
|
||||
+};
|
||||
+
|
||||
+static const char * const pci_gnt0_groups[] = {
|
||||
+ "gpio20",
|
||||
+};
|
||||
+
|
||||
+static const char * const pcmcia_cd1_groups[] = {
|
||||
+ "gpio22",
|
||||
+};
|
||||
+
|
||||
+static const char * const pcmcia_cd2_groups[] = {
|
||||
+ "gpio23",
|
||||
+};
|
||||
+
|
||||
+static const char * const pcmcia_vs1_groups[] = {
|
||||
+ "gpio24",
|
||||
+};
|
||||
+
|
||||
+static const char * const pcmcia_vs2_groups[] = {
|
||||
+ "gpio25",
|
||||
+};
|
||||
+
|
||||
+static const char * const ebi_cs2_groups[] = {
|
||||
+ "gpio26",
|
||||
+};
|
||||
+
|
||||
+static const char * const ebi_cs3_groups[] = {
|
||||
+ "gpio27",
|
||||
+};
|
||||
+
|
||||
+static const char * const spi_cs2_groups[] = {
|
||||
+ "gpio28",
|
||||
+};
|
||||
+
|
||||
+static const char * const spi_cs3_groups[] = {
|
||||
+ "gpio29",
|
||||
+};
|
||||
+
|
||||
+static const char * const spi_cs4_groups[] = {
|
||||
+ "gpio30",
|
||||
+};
|
||||
+
|
||||
+static const char * const spi_cs5_groups[] = {
|
||||
+ "gpio31",
|
||||
+};
|
||||
+
|
||||
+static const char * const uart1_groups[] = {
|
||||
+ "uart1_grp",
|
||||
+};
|
||||
+
|
||||
+#define BCM6368_FUN(n, out) \
|
||||
+ { \
|
||||
+ .name = #n, \
|
||||
+ .groups = n##_groups, \
|
||||
+ .num_groups = ARRAY_SIZE(n##_groups), \
|
||||
+ .dir_out = out, \
|
||||
+ }
|
||||
+
|
||||
+#define BCM6368_BASEMODE_FUN(n, val, out) \
|
||||
+ { \
|
||||
+ .name = #n, \
|
||||
+ .groups = n##_groups, \
|
||||
+ .num_groups = ARRAY_SIZE(n##_groups), \
|
||||
+ .basemode = BCM6368_BASEMODE_##val, \
|
||||
+ .dir_out = out, \
|
||||
+ }
|
||||
+
|
||||
+static const struct bcm6368_function bcm6368_funcs[] = {
|
||||
+ BCM6368_FUN(analog_afe_0, 1),
|
||||
+ BCM6368_FUN(analog_afe_1, 1),
|
||||
+ BCM6368_FUN(sys_irq, 1),
|
||||
+ BCM6368_FUN(serial_led_data, 1),
|
||||
+ BCM6368_FUN(serial_led_clk, 1),
|
||||
+ BCM6368_FUN(inet_led, 1),
|
||||
+ BCM6368_FUN(ephy0_led, 1),
|
||||
+ BCM6368_FUN(ephy1_led, 1),
|
||||
+ BCM6368_FUN(ephy2_led, 1),
|
||||
+ BCM6368_FUN(ephy3_led, 1),
|
||||
+ BCM6368_FUN(robosw_led_data, 1),
|
||||
+ BCM6368_FUN(robosw_led_clk, 1),
|
||||
+ BCM6368_FUN(robosw_led0, 1),
|
||||
+ BCM6368_FUN(robosw_led1, 1),
|
||||
+ BCM6368_FUN(usb_device_led, 1),
|
||||
+ BCM6368_FUN(pci_req1, 0),
|
||||
+ BCM6368_FUN(pci_gnt1, 0),
|
||||
+ BCM6368_FUN(pci_intb, 0),
|
||||
+ BCM6368_FUN(pci_req0, 0),
|
||||
+ BCM6368_FUN(pci_gnt0, 0),
|
||||
+ BCM6368_FUN(pcmcia_cd1, 0),
|
||||
+ BCM6368_FUN(pcmcia_cd2, 0),
|
||||
+ BCM6368_FUN(pcmcia_vs1, 0),
|
||||
+ BCM6368_FUN(pcmcia_vs2, 0),
|
||||
+ BCM6368_FUN(ebi_cs2, 1),
|
||||
+ BCM6368_FUN(ebi_cs3, 1),
|
||||
+ BCM6368_FUN(spi_cs2, 1),
|
||||
+ BCM6368_FUN(spi_cs3, 1),
|
||||
+ BCM6368_FUN(spi_cs4, 1),
|
||||
+ BCM6368_FUN(spi_cs5, 1),
|
||||
+ BCM6368_BASEMODE_FUN(uart1, UART1, 0x6),
|
||||
+};
|
||||
+
|
||||
+static int bcm6368_pinctrl_get_group_count(struct pinctrl_dev *pctldev)
|
||||
+{
|
||||
+ return ARRAY_SIZE(bcm6368_groups);
|
||||
+}
|
||||
+
|
||||
+static const char *bcm6368_pinctrl_get_group_name(struct pinctrl_dev *pctldev,
|
||||
+ unsigned group)
|
||||
+{
|
||||
+ return bcm6368_groups[group].name;
|
||||
+}
|
||||
+
|
||||
+static int bcm6368_pinctrl_get_group_pins(struct pinctrl_dev *pctldev,
|
||||
+ unsigned group, const unsigned **pins,
|
||||
+ unsigned *num_pins)
|
||||
+{
|
||||
+ *pins = bcm6368_groups[group].pins;
|
||||
+ *num_pins = bcm6368_groups[group].num_pins;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int bcm6368_pinctrl_get_func_count(struct pinctrl_dev *pctldev)
|
||||
+{
|
||||
+ return ARRAY_SIZE(bcm6368_funcs);
|
||||
+}
|
||||
+
|
||||
+static const char *bcm6368_pinctrl_get_func_name(struct pinctrl_dev *pctldev,
|
||||
+ unsigned selector)
|
||||
+{
|
||||
+ return bcm6368_funcs[selector].name;
|
||||
+}
|
||||
+
|
||||
+static int bcm6368_pinctrl_get_groups(struct pinctrl_dev *pctldev,
|
||||
+ unsigned selector,
|
||||
+ const char * const **groups,
|
||||
+ unsigned * const num_groups)
|
||||
+{
|
||||
+ *groups = bcm6368_funcs[selector].groups;
|
||||
+ *num_groups = bcm6368_funcs[selector].num_groups;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void bcm6368_rmw_mux(struct bcm6368_pinctrl *pctl, void __iomem *reg,
|
||||
+ u32 mask, u32 val)
|
||||
+{
|
||||
+ u32 tmp;
|
||||
+
|
||||
+ tmp = __raw_readl(reg);
|
||||
+ tmp &= ~mask;
|
||||
+ tmp |= (val & mask);
|
||||
+ __raw_writel(tmp, reg);
|
||||
+}
|
||||
+
|
||||
+static int bcm6368_pinctrl_set_mux(struct pinctrl_dev *pctldev,
|
||||
+ unsigned selector, unsigned group)
|
||||
+{
|
||||
+ struct bcm6368_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
|
||||
+ const struct bcm6368_pingroup *grp = &bcm6368_groups[group];
|
||||
+ const struct bcm6368_function *fun = &bcm6368_funcs[selector];
|
||||
+ unsigned long flags;
|
||||
+ int i, pin;
|
||||
+
|
||||
+ spin_lock_irqsave(&pctl->lock, flags);
|
||||
+ if (fun->basemode) {
|
||||
+ u32 mask = 0;
|
||||
+
|
||||
+ for (i = 0; i < grp->num_pins; i++) {
|
||||
+ pin = grp->pins[i];
|
||||
+ if (pin < 32)
|
||||
+ mask |= BIT(pin);
|
||||
+ }
|
||||
+
|
||||
+ bcm6368_rmw_mux(pctl, pctl->mode, mask, 0);
|
||||
+ regmap_field_write(pctl->overlay, fun->basemode);
|
||||
+ } else {
|
||||
+ pin = grp->pins[0];
|
||||
+
|
||||
+ if (bcm6368_pins[pin].drv_data)
|
||||
+ regmap_field_write(pctl->overlay,
|
||||
+ BCM6368_BASEMODE_GPIO);
|
||||
+
|
||||
+ bcm6368_rmw_mux(pctl, pctl->mode, BIT(pin), BIT(pin));
|
||||
+ }
|
||||
+ spin_unlock_irqrestore(&pctl->lock, flags);
|
||||
+
|
||||
+ for (pin = 0; pin < grp->num_pins; pin++) {
|
||||
+ int hw_gpio = bcm6368_pins[pin].number;
|
||||
+ struct gpio_chip *gc = &pctl->gpio[hw_gpio / 32];
|
||||
+
|
||||
+ if (fun->dir_out & BIT(pin))
|
||||
+ gc->direction_output(gc, hw_gpio % 32, 0);
|
||||
+ else
|
||||
+ gc->direction_input(gc, hw_gpio % 32);
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int bcm6368_gpio_request_enable(struct pinctrl_dev *pctldev,
|
||||
+ struct pinctrl_gpio_range *range,
|
||||
+ unsigned offset)
|
||||
+{
|
||||
+ struct bcm6368_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
|
||||
+ unsigned long flags;
|
||||
+
|
||||
+ if (offset >= 32 && !bcm6368_pins[offset].drv_data)
|
||||
+ return 0;
|
||||
+
|
||||
+ spin_lock_irqsave(&pctl->lock, flags);
|
||||
+ /* disable all functions using this pin */
|
||||
+ if (offset < 32)
|
||||
+ bcm6368_rmw_mux(pctl, pctl->mode, BIT(offset), 0);
|
||||
+
|
||||
+ if (bcm6368_pins[offset].drv_data)
|
||||
+ regmap_field_write(pctl->overlay, BCM6368_BASEMODE_GPIO);
|
||||
+
|
||||
+ spin_unlock_irqrestore(&pctl->lock, flags);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static struct pinctrl_ops bcm6368_pctl_ops = {
|
||||
+ .get_groups_count = bcm6368_pinctrl_get_group_count,
|
||||
+ .get_group_name = bcm6368_pinctrl_get_group_name,
|
||||
+ .get_group_pins = bcm6368_pinctrl_get_group_pins,
|
||||
+#ifdef CONFIG_OF
|
||||
+ .dt_node_to_map = pinconf_generic_dt_node_to_map_pin,
|
||||
+ .dt_free_map = pinctrl_utils_free_map,
|
||||
+#endif
|
||||
+};
|
||||
+
|
||||
+static struct pinmux_ops bcm6368_pmx_ops = {
|
||||
+ .get_functions_count = bcm6368_pinctrl_get_func_count,
|
||||
+ .get_function_name = bcm6368_pinctrl_get_func_name,
|
||||
+ .get_function_groups = bcm6368_pinctrl_get_groups,
|
||||
+ .set_mux = bcm6368_pinctrl_set_mux,
|
||||
+ .gpio_request_enable = bcm6368_gpio_request_enable,
|
||||
+ .strict = true,
|
||||
+};
|
||||
+
|
||||
+static int bcm6368_pinctrl_probe(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct bcm6368_pinctrl *pctl;
|
||||
+ struct resource *res;
|
||||
+ void __iomem *mode;
|
||||
+ struct regmap *basemode;
|
||||
+ struct reg_field overlay = REG_FIELD(0, 0, 3);
|
||||
+
|
||||
+ if (pdev->dev.of_node)
|
||||
+ basemode = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
|
||||
+ "brcm,gpiobasemode");
|
||||
+ else
|
||||
+ basemode = syscon_regmap_lookup_by_pdevname("syscon.b00000b8");
|
||||
+
|
||||
+ if (IS_ERR(basemode))
|
||||
+ return PTR_ERR(basemode);
|
||||
+
|
||||
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mode");
|
||||
+ mode = devm_ioremap_resource(&pdev->dev, res);
|
||||
+ if (IS_ERR(mode))
|
||||
+ return PTR_ERR(mode);
|
||||
+
|
||||
+ pctl = devm_kzalloc(&pdev->dev, sizeof(*pctl), GFP_KERNEL);
|
||||
+ if (!pctl)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ pctl->overlay = devm_regmap_field_alloc(&pdev->dev, basemode, overlay);
|
||||
+ if (IS_ERR(pctl->overlay))
|
||||
+ return PTR_ERR(pctl->overlay);
|
||||
+
|
||||
+ spin_lock_init(&pctl->lock);
|
||||
+
|
||||
+ pctl->mode = mode;
|
||||
+
|
||||
+ /* disable all muxes by default */
|
||||
+ __raw_writel(0, pctl->mode);
|
||||
+
|
||||
+ pctl->desc.name = dev_name(&pdev->dev);
|
||||
+ pctl->desc.owner = THIS_MODULE;
|
||||
+ pctl->desc.pctlops = &bcm6368_pctl_ops;
|
||||
+ pctl->desc.pmxops = &bcm6368_pmx_ops;
|
||||
+
|
||||
+ pctl->desc.npins = ARRAY_SIZE(bcm6368_pins);
|
||||
+ pctl->desc.pins = bcm6368_pins;
|
||||
+
|
||||
+ platform_set_drvdata(pdev, pctl);
|
||||
+
|
||||
+ pctl->pctldev = bcm63xx_pinctrl_register(pdev, &pctl->desc, pctl,
|
||||
+ pctl->gpio, BCM6368_NGPIO);
|
||||
+ if (IS_ERR(pctl->pctldev))
|
||||
+ return PTR_ERR(pctl->pctldev);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static const struct of_device_id bcm6368_pinctrl_match[] = {
|
||||
+ { .compatible = "brcm,bcm6368-pinctrl", },
|
||||
+ { },
|
||||
+};
|
||||
+
|
||||
+static struct platform_driver bcm6368_pinctrl_driver = {
|
||||
+ .probe = bcm6368_pinctrl_probe,
|
||||
+ .driver = {
|
||||
+ .name = "bcm6368-pinctrl",
|
||||
+ .of_match_table = bcm6368_pinctrl_match,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+builtin_platform_driver(bcm6368_pinctrl_driver);
|
@ -1,106 +0,0 @@
|
||||
From 28cc80e4ada5d73d5305fd268297825cd8d01936 Mon Sep 17 00:00:00 2001
|
||||
From: Jonas Gorski <jonas.gorski@gmail.com>
|
||||
Date: Wed, 27 Jul 2016 11:37:08 +0200
|
||||
Subject: [PATCH 12/16] Documentation: add BCM63268 pincontroller binding
|
||||
documentation
|
||||
|
||||
Add binding documentation for the pincontrol core found in the BCM63268
|
||||
family SoCs.
|
||||
|
||||
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
|
||||
---
|
||||
.../bindings/pinctrl/brcm,bcm63268-pinctrl.txt | 88 ++++++++++++++++++++++
|
||||
1 file changed, 88 insertions(+)
|
||||
create mode 100644 Documentation/devicetree/bindings/pinctrl/brcm,bcm63268-pinctrl.txt
|
||||
|
||||
--- /dev/null
|
||||
+++ b/Documentation/devicetree/bindings/pinctrl/brcm,bcm63268-pinctrl.txt
|
||||
@@ -0,0 +1,88 @@
|
||||
+* Broadcom BCM63268 pin controller
|
||||
+
|
||||
+Required properties:
|
||||
+- compatible: Must be "brcm,bcm6362-pinctrl".
|
||||
+- reg: Register specifiers of dirout, dat, led, mode, ctrl, basemode registers.
|
||||
+- reg-names: Must be "dirout", "dat", "led", "mode", "ctrl", "basemode".
|
||||
+- gpio-controller: Identifies this node as a GPIO controller.
|
||||
+- #gpio-cells: Must be <2>.
|
||||
+
|
||||
+Example:
|
||||
+
|
||||
+pinctrl: pin-controller@100000c0 {
|
||||
+ compatible = "brcm,bcm63268-pinctrl";
|
||||
+ reg = <0x100000c0 0x8>,
|
||||
+ <0x100000c8 0x8>,
|
||||
+ <0x100000d0 0x4>,
|
||||
+ <0x100000d8 0x4>,
|
||||
+ <0x100000dc 0x4>,
|
||||
+ <0x100000f8 0x4>;
|
||||
+ reg-names = "dirout", "dat", "led", "mode",
|
||||
+ "ctrl", "basemode";
|
||||
+
|
||||
+ gpio-controller;
|
||||
+ #gpio-cells = <2>;
|
||||
+};
|
||||
+
|
||||
+Available pins/groups and functions:
|
||||
+
|
||||
+name pins functions
|
||||
+-----------------------------------------------------------
|
||||
+gpio0 0 led, serial_led_clk
|
||||
+gpio1 1 led, serial_led_data
|
||||
+gpio2 2 led,
|
||||
+gpio3 3 led,
|
||||
+gpio4 4 led,
|
||||
+gpio5 5 led,
|
||||
+gpio6 6 led,
|
||||
+gpio7 7 led,
|
||||
+gpio8 8 led, hsspi_cs6
|
||||
+gpio9 9 led, hsspi_cs7
|
||||
+gpio10 10 led, uart1_scts
|
||||
+gpio11 11 led, uart1_srts
|
||||
+gpio12 12 led, uart1_sdin
|
||||
+gpio13 13 led, uart1_sdout
|
||||
+gpio14 14 led, ntr_pulse_in
|
||||
+gpio15 15 led, dsl_ntr_pulse_out
|
||||
+gpio16 16 led, hsspi_cs4
|
||||
+gpio17 17 led, hsspi_cs5
|
||||
+gpio18 18 led, adsl_spi_miso
|
||||
+gpio19 19 led, adsl_spi_mosi
|
||||
+gpio20 20 led,
|
||||
+gpio21 21 led,
|
||||
+gpio22 22 led, vreg_clk
|
||||
+gpio23 23 led, pcie_clkreq_b
|
||||
+gpio24 24 uart1_scts
|
||||
+gpio25 25 uart1_srts
|
||||
+gpio26 26 uart1_sdin
|
||||
+gpio27 27 uart1_sdout
|
||||
+gpio28 28 ntr_pulse_in
|
||||
+gpio29 29 dsl_ntr_pulse_out
|
||||
+gpio30 30 switch_led_clk
|
||||
+gpio31 31 switch_led_data
|
||||
+gpio32 32 wifi
|
||||
+gpio33 33 wifi
|
||||
+gpio34 34 wifi
|
||||
+gpio35 35 wifi
|
||||
+gpio36 36 wifi
|
||||
+gpio37 37 wifi
|
||||
+gpio38 38 wifi
|
||||
+gpio39 39 wifi
|
||||
+gpio40 40 wifi
|
||||
+gpio41 41 wifi
|
||||
+gpio42 42 wifi
|
||||
+gpio43 43 wifi
|
||||
+gpio44 44 wifi
|
||||
+gpio45 45 wifi
|
||||
+gpio46 46 wifi
|
||||
+gpio47 47 wifi
|
||||
+gpio48 48 wifi
|
||||
+gpio49 49 wifi
|
||||
+gpio50 50 wifi
|
||||
+gpio51 51 wifi
|
||||
+nand_grp 2-7,24-31 nand
|
||||
+dect_pd_grp 8-9 dect_pd
|
||||
+vdsl_phy0_grp 10-11 vdsl_phy0
|
||||
+vdsl_phy1_grp 12-13 vdsl_phy1
|
||||
+vdsl_phy2_grp 24-25 vdsl_phy2
|
||||
+vdsl_phy3_grp 26-27 vdsl_phy3
|
@ -1,736 +0,0 @@
|
||||
From 8665d3ea63649cc155286c75f83f694a930580e5 Mon Sep 17 00:00:00 2001
|
||||
From: Jonas Gorski <jonas.gorski@gmail.com>
|
||||
Date: Fri, 24 Jun 2016 22:19:12 +0200
|
||||
Subject: [PATCH 13/16] pinctrl: add a pincontrol driver for BCM63268
|
||||
|
||||
Add a pincontrol driver for BCM63268. BCM63268 allows muxing GPIOs
|
||||
to different functions. Depending on the mux, these are either single
|
||||
pin configurations or whole pin groups.
|
||||
|
||||
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
|
||||
---
|
||||
drivers/pinctrl/bcm63xx/Makefile | 1 +
|
||||
drivers/pinctrl/bcm63xx/pinctrl-bcm63268.c | 710 +++++++++++++++++++++++++++++
|
||||
2 files changed, 711 insertions(+)
|
||||
create mode 100644 drivers/pinctrl/bcm63xx/pinctrl-bcm63268.c
|
||||
|
||||
--- a/drivers/pinctrl/bcm63xx/Makefile
|
||||
+++ b/drivers/pinctrl/bcm63xx/Makefile
|
||||
@@ -4,3 +4,4 @@ obj-$(CONFIG_PINCTRL_BCM6348) += pinctrl
|
||||
obj-$(CONFIG_PINCTRL_BCM6358) += pinctrl-bcm6358.o
|
||||
obj-$(CONFIG_PINCTRL_BCM6362) += pinctrl-bcm6362.o
|
||||
obj-$(CONFIG_PINCTRL_BCM6368) += pinctrl-bcm6368.o
|
||||
+obj-$(CONFIG_PINCTRL_BCM63268) += pinctrl-bcm63268.o
|
||||
--- /dev/null
|
||||
+++ b/drivers/pinctrl/bcm63xx/pinctrl-bcm63268.c
|
||||
@@ -0,0 +1,710 @@
|
||||
+/*
|
||||
+ * This file is subject to the terms and conditions of the GNU General Public
|
||||
+ * License. See the file "COPYING" in the main directory of this archive
|
||||
+ * for more details.
|
||||
+ *
|
||||
+ * Copyright (C) 2016 Jonas Gorski <jonas.gorski@gmail.com>
|
||||
+ */
|
||||
+
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/spinlock.h>
|
||||
+#include <linux/bitops.h>
|
||||
+#include <linux/gpio.h>
|
||||
+#include <linux/of.h>
|
||||
+#include <linux/of_gpio.h>
|
||||
+#include <linux/slab.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+
|
||||
+#include <linux/pinctrl/pinconf.h>
|
||||
+#include <linux/pinctrl/pinconf-generic.h>
|
||||
+#include <linux/pinctrl/pinmux.h>
|
||||
+#include <linux/pinctrl/machine.h>
|
||||
+
|
||||
+#include "../core.h"
|
||||
+#include "../pinctrl-utils.h"
|
||||
+
|
||||
+#include "pinctrl-bcm63xx.h"
|
||||
+
|
||||
+#define BCM63268_NGPIO 52
|
||||
+
|
||||
+/* GPIO_BASEMODE register */
|
||||
+#define BASEMODE_NAND BIT(2) /* GPIOs 2-7, 24-31 */
|
||||
+#define BASEMODE_GPIO35 BIT(4) /* GPIO 35 */
|
||||
+#define BASEMODE_DECTPD BIT(5) /* GPIOs 8/9 */
|
||||
+#define BASEMODE_VDSL_PHY_0 BIT(6) /* GPIOs 10/11 */
|
||||
+#define BASEMODE_VDSL_PHY_1 BIT(7) /* GPIOs 12/13 */
|
||||
+#define BASEMODE_VDSL_PHY_2 BIT(8) /* GPIOs 24/25 */
|
||||
+#define BASEMODE_VDSL_PHY_3 BIT(9) /* GPIOs 26/27 */
|
||||
+
|
||||
+enum bcm63268_pinctrl_reg {
|
||||
+ BCM63268_LEDCTRL,
|
||||
+ BCM63268_MODE,
|
||||
+ BCM63268_CTRL,
|
||||
+ BCM63268_BASEMODE,
|
||||
+};
|
||||
+
|
||||
+struct bcm63268_pingroup {
|
||||
+ const char *name;
|
||||
+ const unsigned * const pins;
|
||||
+ const unsigned num_pins;
|
||||
+};
|
||||
+
|
||||
+struct bcm63268_function {
|
||||
+ const char *name;
|
||||
+ const char * const *groups;
|
||||
+ const unsigned num_groups;
|
||||
+
|
||||
+ enum bcm63268_pinctrl_reg reg;
|
||||
+ u32 mask;
|
||||
+};
|
||||
+
|
||||
+struct bcm63268_pinctrl {
|
||||
+ struct pinctrl_dev *pctldev;
|
||||
+ struct pinctrl_desc desc;
|
||||
+
|
||||
+ void __iomem *led;
|
||||
+ void __iomem *mode;
|
||||
+ void __iomem *ctrl;
|
||||
+ void __iomem *basemode;
|
||||
+
|
||||
+ /* register access lock */
|
||||
+ spinlock_t lock;
|
||||
+
|
||||
+ struct gpio_chip gpio[2];
|
||||
+};
|
||||
+
|
||||
+#define BCM63268_PIN(a, b, basemode) \
|
||||
+ { \
|
||||
+ .number = a, \
|
||||
+ .name = b, \
|
||||
+ .drv_data = (void *)(basemode) \
|
||||
+ }
|
||||
+
|
||||
+static const struct pinctrl_pin_desc bcm63268_pins[] = {
|
||||
+ PINCTRL_PIN(0, "gpio0"),
|
||||
+ PINCTRL_PIN(1, "gpio1"),
|
||||
+ BCM63268_PIN(2, "gpio2", BASEMODE_NAND),
|
||||
+ BCM63268_PIN(3, "gpio3", BASEMODE_NAND),
|
||||
+ BCM63268_PIN(4, "gpio4", BASEMODE_NAND),
|
||||
+ BCM63268_PIN(5, "gpio5", BASEMODE_NAND),
|
||||
+ BCM63268_PIN(6, "gpio6", BASEMODE_NAND),
|
||||
+ BCM63268_PIN(7, "gpio7", BASEMODE_NAND),
|
||||
+ BCM63268_PIN(8, "gpio8", BASEMODE_DECTPD),
|
||||
+ BCM63268_PIN(9, "gpio9", BASEMODE_DECTPD),
|
||||
+ BCM63268_PIN(10, "gpio10", BASEMODE_VDSL_PHY_0),
|
||||
+ BCM63268_PIN(11, "gpio11", BASEMODE_VDSL_PHY_0),
|
||||
+ BCM63268_PIN(12, "gpio12", BASEMODE_VDSL_PHY_1),
|
||||
+ BCM63268_PIN(13, "gpio13", BASEMODE_VDSL_PHY_1),
|
||||
+ PINCTRL_PIN(14, "gpio14"),
|
||||
+ PINCTRL_PIN(15, "gpio15"),
|
||||
+ PINCTRL_PIN(16, "gpio16"),
|
||||
+ PINCTRL_PIN(17, "gpio17"),
|
||||
+ PINCTRL_PIN(18, "gpio18"),
|
||||
+ PINCTRL_PIN(19, "gpio19"),
|
||||
+ PINCTRL_PIN(20, "gpio20"),
|
||||
+ PINCTRL_PIN(21, "gpio21"),
|
||||
+ PINCTRL_PIN(22, "gpio22"),
|
||||
+ PINCTRL_PIN(23, "gpio23"),
|
||||
+ BCM63268_PIN(24, "gpio24", BASEMODE_NAND | BASEMODE_VDSL_PHY_2),
|
||||
+ BCM63268_PIN(25, "gpio25", BASEMODE_NAND | BASEMODE_VDSL_PHY_2),
|
||||
+ BCM63268_PIN(26, "gpio26", BASEMODE_NAND | BASEMODE_VDSL_PHY_3),
|
||||
+ BCM63268_PIN(27, "gpio27", BASEMODE_NAND | BASEMODE_VDSL_PHY_3),
|
||||
+ BCM63268_PIN(28, "gpio28", BASEMODE_NAND),
|
||||
+ BCM63268_PIN(29, "gpio29", BASEMODE_NAND),
|
||||
+ BCM63268_PIN(30, "gpio30", BASEMODE_NAND),
|
||||
+ BCM63268_PIN(31, "gpio31", BASEMODE_NAND),
|
||||
+ PINCTRL_PIN(32, "gpio32"),
|
||||
+ PINCTRL_PIN(33, "gpio33"),
|
||||
+ PINCTRL_PIN(34, "gpio34"),
|
||||
+ PINCTRL_PIN(35, "gpio35"),
|
||||
+ PINCTRL_PIN(36, "gpio36"),
|
||||
+ PINCTRL_PIN(37, "gpio37"),
|
||||
+ PINCTRL_PIN(38, "gpio38"),
|
||||
+ PINCTRL_PIN(39, "gpio39"),
|
||||
+ PINCTRL_PIN(40, "gpio40"),
|
||||
+ PINCTRL_PIN(41, "gpio41"),
|
||||
+ PINCTRL_PIN(42, "gpio42"),
|
||||
+ PINCTRL_PIN(43, "gpio43"),
|
||||
+ PINCTRL_PIN(44, "gpio44"),
|
||||
+ PINCTRL_PIN(45, "gpio45"),
|
||||
+ PINCTRL_PIN(46, "gpio46"),
|
||||
+ PINCTRL_PIN(47, "gpio47"),
|
||||
+ PINCTRL_PIN(48, "gpio48"),
|
||||
+ PINCTRL_PIN(49, "gpio49"),
|
||||
+ PINCTRL_PIN(50, "gpio50"),
|
||||
+ PINCTRL_PIN(51, "gpio51"),
|
||||
+};
|
||||
+
|
||||
+static unsigned gpio0_pins[] = { 0 };
|
||||
+static unsigned gpio1_pins[] = { 1 };
|
||||
+static unsigned gpio2_pins[] = { 2 };
|
||||
+static unsigned gpio3_pins[] = { 3 };
|
||||
+static unsigned gpio4_pins[] = { 4 };
|
||||
+static unsigned gpio5_pins[] = { 5 };
|
||||
+static unsigned gpio6_pins[] = { 6 };
|
||||
+static unsigned gpio7_pins[] = { 7 };
|
||||
+static unsigned gpio8_pins[] = { 8 };
|
||||
+static unsigned gpio9_pins[] = { 9 };
|
||||
+static unsigned gpio10_pins[] = { 10 };
|
||||
+static unsigned gpio11_pins[] = { 11 };
|
||||
+static unsigned gpio12_pins[] = { 12 };
|
||||
+static unsigned gpio13_pins[] = { 13 };
|
||||
+static unsigned gpio14_pins[] = { 14 };
|
||||
+static unsigned gpio15_pins[] = { 15 };
|
||||
+static unsigned gpio16_pins[] = { 16 };
|
||||
+static unsigned gpio17_pins[] = { 17 };
|
||||
+static unsigned gpio18_pins[] = { 18 };
|
||||
+static unsigned gpio19_pins[] = { 19 };
|
||||
+static unsigned gpio20_pins[] = { 20 };
|
||||
+static unsigned gpio21_pins[] = { 21 };
|
||||
+static unsigned gpio22_pins[] = { 22 };
|
||||
+static unsigned gpio23_pins[] = { 23 };
|
||||
+static unsigned gpio24_pins[] = { 24 };
|
||||
+static unsigned gpio25_pins[] = { 25 };
|
||||
+static unsigned gpio26_pins[] = { 26 };
|
||||
+static unsigned gpio27_pins[] = { 27 };
|
||||
+static unsigned gpio28_pins[] = { 28 };
|
||||
+static unsigned gpio29_pins[] = { 29 };
|
||||
+static unsigned gpio30_pins[] = { 30 };
|
||||
+static unsigned gpio31_pins[] = { 31 };
|
||||
+static unsigned gpio32_pins[] = { 32 };
|
||||
+static unsigned gpio33_pins[] = { 33 };
|
||||
+static unsigned gpio34_pins[] = { 34 };
|
||||
+static unsigned gpio35_pins[] = { 35 };
|
||||
+static unsigned gpio36_pins[] = { 36 };
|
||||
+static unsigned gpio37_pins[] = { 37 };
|
||||
+static unsigned gpio38_pins[] = { 38 };
|
||||
+static unsigned gpio39_pins[] = { 39 };
|
||||
+static unsigned gpio40_pins[] = { 40 };
|
||||
+static unsigned gpio41_pins[] = { 41 };
|
||||
+static unsigned gpio42_pins[] = { 42 };
|
||||
+static unsigned gpio43_pins[] = { 43 };
|
||||
+static unsigned gpio44_pins[] = { 44 };
|
||||
+static unsigned gpio45_pins[] = { 45 };
|
||||
+static unsigned gpio46_pins[] = { 46 };
|
||||
+static unsigned gpio47_pins[] = { 47 };
|
||||
+static unsigned gpio48_pins[] = { 48 };
|
||||
+static unsigned gpio49_pins[] = { 49 };
|
||||
+static unsigned gpio50_pins[] = { 50 };
|
||||
+static unsigned gpio51_pins[] = { 51 };
|
||||
+
|
||||
+static unsigned nand_grp_pins[] = {
|
||||
+ 2, 3, 4, 5, 6, 7, 24,
|
||||
+ 25, 26, 27, 28, 29, 30, 31,
|
||||
+};
|
||||
+
|
||||
+static unsigned dectpd_grp_pins[] = { 8, 9 };
|
||||
+static unsigned vdsl_phy0_grp_pins[] = { 10, 11 };
|
||||
+static unsigned vdsl_phy1_grp_pins[] = { 12, 13 };
|
||||
+static unsigned vdsl_phy2_grp_pins[] = { 24, 25 };
|
||||
+static unsigned vdsl_phy3_grp_pins[] = { 26, 27 };
|
||||
+
|
||||
+#define BCM63268_GROUP(n) \
|
||||
+ { \
|
||||
+ .name = #n, \
|
||||
+ .pins = n##_pins, \
|
||||
+ .num_pins = ARRAY_SIZE(n##_pins), \
|
||||
+ }
|
||||
+
|
||||
+static struct bcm63268_pingroup bcm63268_groups[] = {
|
||||
+ BCM63268_GROUP(gpio0),
|
||||
+ BCM63268_GROUP(gpio1),
|
||||
+ BCM63268_GROUP(gpio2),
|
||||
+ BCM63268_GROUP(gpio3),
|
||||
+ BCM63268_GROUP(gpio4),
|
||||
+ BCM63268_GROUP(gpio5),
|
||||
+ BCM63268_GROUP(gpio6),
|
||||
+ BCM63268_GROUP(gpio7),
|
||||
+ BCM63268_GROUP(gpio8),
|
||||
+ BCM63268_GROUP(gpio9),
|
||||
+ BCM63268_GROUP(gpio10),
|
||||
+ BCM63268_GROUP(gpio11),
|
||||
+ BCM63268_GROUP(gpio12),
|
||||
+ BCM63268_GROUP(gpio13),
|
||||
+ BCM63268_GROUP(gpio14),
|
||||
+ BCM63268_GROUP(gpio15),
|
||||
+ BCM63268_GROUP(gpio16),
|
||||
+ BCM63268_GROUP(gpio17),
|
||||
+ BCM63268_GROUP(gpio18),
|
||||
+ BCM63268_GROUP(gpio19),
|
||||
+ BCM63268_GROUP(gpio20),
|
||||
+ BCM63268_GROUP(gpio21),
|
||||
+ BCM63268_GROUP(gpio22),
|
||||
+ BCM63268_GROUP(gpio23),
|
||||
+ BCM63268_GROUP(gpio24),
|
||||
+ BCM63268_GROUP(gpio25),
|
||||
+ BCM63268_GROUP(gpio26),
|
||||
+ BCM63268_GROUP(gpio27),
|
||||
+ BCM63268_GROUP(gpio28),
|
||||
+ BCM63268_GROUP(gpio29),
|
||||
+ BCM63268_GROUP(gpio30),
|
||||
+ BCM63268_GROUP(gpio31),
|
||||
+ BCM63268_GROUP(gpio32),
|
||||
+ BCM63268_GROUP(gpio33),
|
||||
+ BCM63268_GROUP(gpio34),
|
||||
+ BCM63268_GROUP(gpio35),
|
||||
+ BCM63268_GROUP(gpio36),
|
||||
+ BCM63268_GROUP(gpio37),
|
||||
+ BCM63268_GROUP(gpio38),
|
||||
+ BCM63268_GROUP(gpio39),
|
||||
+ BCM63268_GROUP(gpio40),
|
||||
+ BCM63268_GROUP(gpio41),
|
||||
+ BCM63268_GROUP(gpio42),
|
||||
+ BCM63268_GROUP(gpio43),
|
||||
+ BCM63268_GROUP(gpio44),
|
||||
+ BCM63268_GROUP(gpio45),
|
||||
+ BCM63268_GROUP(gpio46),
|
||||
+ BCM63268_GROUP(gpio47),
|
||||
+ BCM63268_GROUP(gpio48),
|
||||
+ BCM63268_GROUP(gpio49),
|
||||
+ BCM63268_GROUP(gpio50),
|
||||
+ BCM63268_GROUP(gpio51),
|
||||
+
|
||||
+ /* multi pin groups */
|
||||
+ BCM63268_GROUP(nand_grp),
|
||||
+ BCM63268_GROUP(dectpd_grp),
|
||||
+ BCM63268_GROUP(vdsl_phy0_grp),
|
||||
+ BCM63268_GROUP(vdsl_phy1_grp),
|
||||
+ BCM63268_GROUP(vdsl_phy2_grp),
|
||||
+ BCM63268_GROUP(vdsl_phy3_grp),
|
||||
+};
|
||||
+
|
||||
+static const char * const led_groups[] = {
|
||||
+ "gpio0",
|
||||
+ "gpio1",
|
||||
+ "gpio2",
|
||||
+ "gpio3",
|
||||
+ "gpio4",
|
||||
+ "gpio5",
|
||||
+ "gpio6",
|
||||
+ "gpio7",
|
||||
+ "gpio8",
|
||||
+ "gpio9",
|
||||
+ "gpio10",
|
||||
+ "gpio11",
|
||||
+ "gpio12",
|
||||
+ "gpio13",
|
||||
+ "gpio14",
|
||||
+ "gpio15",
|
||||
+ "gpio16",
|
||||
+ "gpio17",
|
||||
+ "gpio18",
|
||||
+ "gpio19",
|
||||
+ "gpio20",
|
||||
+ "gpio21",
|
||||
+ "gpio22",
|
||||
+ "gpio23",
|
||||
+};
|
||||
+
|
||||
+static const char * const serial_led_clk_groups[] = {
|
||||
+ "gpio0",
|
||||
+};
|
||||
+
|
||||
+static const char * const serial_led_data_groups[] = {
|
||||
+ "gpio1",
|
||||
+};
|
||||
+
|
||||
+static const char * const hsspi_cs4_groups[] = {
|
||||
+ "gpio16",
|
||||
+};
|
||||
+
|
||||
+static const char * const hsspi_cs5_groups[] = {
|
||||
+ "gpio17",
|
||||
+};
|
||||
+
|
||||
+static const char * const hsspi_cs6_groups[] = {
|
||||
+ "gpio8",
|
||||
+};
|
||||
+
|
||||
+static const char * const hsspi_cs7_groups[] = {
|
||||
+ "gpio9",
|
||||
+};
|
||||
+
|
||||
+static const char * const uart1_scts_groups[] = {
|
||||
+ "gpio10",
|
||||
+ "gpio24",
|
||||
+};
|
||||
+
|
||||
+static const char * const uart1_srts_groups[] = {
|
||||
+ "gpio11",
|
||||
+ "gpio25",
|
||||
+};
|
||||
+
|
||||
+static const char * const uart1_sdin_groups[] = {
|
||||
+ "gpio12",
|
||||
+ "gpio26",
|
||||
+};
|
||||
+
|
||||
+static const char * const uart1_sdout_groups[] = {
|
||||
+ "gpio13",
|
||||
+ "gpio27",
|
||||
+};
|
||||
+
|
||||
+static const char * const ntr_pulse_in_groups[] = {
|
||||
+ "gpio14",
|
||||
+ "gpio28",
|
||||
+};
|
||||
+
|
||||
+static const char * const dsl_ntr_pulse_out_groups[] = {
|
||||
+ "gpio15",
|
||||
+ "gpio29",
|
||||
+};
|
||||
+
|
||||
+static const char * const adsl_spi_miso_groups[] = {
|
||||
+ "gpio18",
|
||||
+};
|
||||
+
|
||||
+static const char * const adsl_spi_mosi_groups[] = {
|
||||
+ "gpio19",
|
||||
+};
|
||||
+
|
||||
+static const char * const vreg_clk_groups[] = {
|
||||
+ "gpio22",
|
||||
+};
|
||||
+
|
||||
+static const char * const pcie_clkreq_b_groups[] = {
|
||||
+ "gpio23",
|
||||
+};
|
||||
+
|
||||
+static const char * const switch_led_clk_groups[] = {
|
||||
+ "gpio30",
|
||||
+};
|
||||
+
|
||||
+static const char * const switch_led_data_groups[] = {
|
||||
+ "gpio31",
|
||||
+};
|
||||
+
|
||||
+static const char * const wifi_groups[] = {
|
||||
+ "gpio32",
|
||||
+ "gpio33",
|
||||
+ "gpio34",
|
||||
+ "gpio35",
|
||||
+ "gpio36",
|
||||
+ "gpio37",
|
||||
+ "gpio38",
|
||||
+ "gpio39",
|
||||
+ "gpio40",
|
||||
+ "gpio41",
|
||||
+ "gpio42",
|
||||
+ "gpio43",
|
||||
+ "gpio44",
|
||||
+ "gpio45",
|
||||
+ "gpio46",
|
||||
+ "gpio47",
|
||||
+ "gpio48",
|
||||
+ "gpio49",
|
||||
+ "gpio50",
|
||||
+ "gpio51",
|
||||
+};
|
||||
+
|
||||
+static const char * const nand_groups[] = {
|
||||
+ "nand_grp",
|
||||
+};
|
||||
+
|
||||
+static const char * const dectpd_groups[] = {
|
||||
+ "dectpd_grp",
|
||||
+};
|
||||
+
|
||||
+static const char * const vdsl_phy_override_0_groups[] = {
|
||||
+ "vdsl_phy_override_0_grp",
|
||||
+};
|
||||
+
|
||||
+static const char * const vdsl_phy_override_1_groups[] = {
|
||||
+ "vdsl_phy_override_1_grp",
|
||||
+};
|
||||
+
|
||||
+static const char * const vdsl_phy_override_2_groups[] = {
|
||||
+ "vdsl_phy_override_2_grp",
|
||||
+};
|
||||
+
|
||||
+static const char * const vdsl_phy_override_3_groups[] = {
|
||||
+ "vdsl_phy_override_3_grp",
|
||||
+};
|
||||
+
|
||||
+#define BCM63268_LED_FUN(n) \
|
||||
+ { \
|
||||
+ .name = #n, \
|
||||
+ .groups = n##_groups, \
|
||||
+ .num_groups = ARRAY_SIZE(n##_groups), \
|
||||
+ .reg = BCM63268_LEDCTRL, \
|
||||
+ }
|
||||
+
|
||||
+#define BCM63268_MODE_FUN(n) \
|
||||
+ { \
|
||||
+ .name = #n, \
|
||||
+ .groups = n##_groups, \
|
||||
+ .num_groups = ARRAY_SIZE(n##_groups), \
|
||||
+ .reg = BCM63268_MODE, \
|
||||
+ }
|
||||
+
|
||||
+#define BCM63268_CTRL_FUN(n) \
|
||||
+ { \
|
||||
+ .name = #n, \
|
||||
+ .groups = n##_groups, \
|
||||
+ .num_groups = ARRAY_SIZE(n##_groups), \
|
||||
+ .reg = BCM63268_CTRL, \
|
||||
+ }
|
||||
+
|
||||
+#define BCM63268_BASEMODE_FUN(n, val) \
|
||||
+ { \
|
||||
+ .name = #n, \
|
||||
+ .groups = n##_groups, \
|
||||
+ .num_groups = ARRAY_SIZE(n##_groups), \
|
||||
+ .reg = BCM63268_BASEMODE, \
|
||||
+ .mask = val, \
|
||||
+ }
|
||||
+
|
||||
+static const struct bcm63268_function bcm63268_funcs[] = {
|
||||
+ BCM63268_LED_FUN(led),
|
||||
+ BCM63268_MODE_FUN(serial_led_clk),
|
||||
+ BCM63268_MODE_FUN(serial_led_data),
|
||||
+ BCM63268_MODE_FUN(hsspi_cs6),
|
||||
+ BCM63268_MODE_FUN(hsspi_cs7),
|
||||
+ BCM63268_MODE_FUN(uart1_scts),
|
||||
+ BCM63268_MODE_FUN(uart1_srts),
|
||||
+ BCM63268_MODE_FUN(uart1_sdin),
|
||||
+ BCM63268_MODE_FUN(uart1_sdout),
|
||||
+ BCM63268_MODE_FUN(ntr_pulse_in),
|
||||
+ BCM63268_MODE_FUN(dsl_ntr_pulse_out),
|
||||
+ BCM63268_MODE_FUN(hsspi_cs4),
|
||||
+ BCM63268_MODE_FUN(hsspi_cs5),
|
||||
+ BCM63268_MODE_FUN(adsl_spi_miso),
|
||||
+ BCM63268_MODE_FUN(adsl_spi_mosi),
|
||||
+ BCM63268_MODE_FUN(vreg_clk),
|
||||
+ BCM63268_MODE_FUN(pcie_clkreq_b),
|
||||
+ BCM63268_MODE_FUN(switch_led_clk),
|
||||
+ BCM63268_MODE_FUN(switch_led_data),
|
||||
+ BCM63268_CTRL_FUN(wifi),
|
||||
+ BCM63268_BASEMODE_FUN(nand, BASEMODE_NAND),
|
||||
+ BCM63268_BASEMODE_FUN(dectpd, BASEMODE_DECTPD),
|
||||
+ BCM63268_BASEMODE_FUN(vdsl_phy_override_0, BASEMODE_VDSL_PHY_0),
|
||||
+ BCM63268_BASEMODE_FUN(vdsl_phy_override_1, BASEMODE_VDSL_PHY_1),
|
||||
+ BCM63268_BASEMODE_FUN(vdsl_phy_override_2, BASEMODE_VDSL_PHY_2),
|
||||
+ BCM63268_BASEMODE_FUN(vdsl_phy_override_3, BASEMODE_VDSL_PHY_3),
|
||||
+};
|
||||
+
|
||||
+static int bcm63268_pinctrl_get_group_count(struct pinctrl_dev *pctldev)
|
||||
+{
|
||||
+ return ARRAY_SIZE(bcm63268_groups);
|
||||
+}
|
||||
+
|
||||
+static const char *bcm63268_pinctrl_get_group_name(struct pinctrl_dev *pctldev,
|
||||
+ unsigned group)
|
||||
+{
|
||||
+ return bcm63268_groups[group].name;
|
||||
+}
|
||||
+
|
||||
+static int bcm63268_pinctrl_get_group_pins(struct pinctrl_dev *pctldev,
|
||||
+ unsigned group,
|
||||
+ const unsigned **pins,
|
||||
+ unsigned *num_pins)
|
||||
+{
|
||||
+ *pins = bcm63268_groups[group].pins;
|
||||
+ *num_pins = bcm63268_groups[group].num_pins;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int bcm63268_pinctrl_get_func_count(struct pinctrl_dev *pctldev)
|
||||
+{
|
||||
+ return ARRAY_SIZE(bcm63268_funcs);
|
||||
+}
|
||||
+
|
||||
+static const char *bcm63268_pinctrl_get_func_name(struct pinctrl_dev *pctldev,
|
||||
+ unsigned selector)
|
||||
+{
|
||||
+ return bcm63268_funcs[selector].name;
|
||||
+}
|
||||
+
|
||||
+static int bcm63268_pinctrl_get_groups(struct pinctrl_dev *pctldev,
|
||||
+ unsigned selector,
|
||||
+ const char * const **groups,
|
||||
+ unsigned * const num_groups)
|
||||
+{
|
||||
+ *groups = bcm63268_funcs[selector].groups;
|
||||
+ *num_groups = bcm63268_funcs[selector].num_groups;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void bcm63268_rmw_mux(struct bcm63268_pinctrl *pctl, void __iomem *reg,
|
||||
+ u32 mask, u32 val)
|
||||
+{
|
||||
+ unsigned long flags;
|
||||
+ u32 tmp;
|
||||
+
|
||||
+ spin_lock_irqsave(&pctl->lock, flags);
|
||||
+ tmp = __raw_readl(reg);
|
||||
+ tmp &= ~mask;
|
||||
+ tmp |= val;
|
||||
+ __raw_writel(tmp, reg);
|
||||
+
|
||||
+ spin_unlock_irqrestore(&pctl->lock, flags);
|
||||
+}
|
||||
+
|
||||
+static void bcm63268_set_gpio(struct bcm63268_pinctrl *pctl, unsigned pin)
|
||||
+{
|
||||
+ const struct pinctrl_pin_desc *desc = &bcm63268_pins[pin];
|
||||
+ u32 basemode = (unsigned long)desc->drv_data;
|
||||
+ u32 mask = BIT(pin % 32);
|
||||
+
|
||||
+ if (basemode)
|
||||
+ bcm63268_rmw_mux(pctl, pctl->basemode, basemode, 0);
|
||||
+
|
||||
+ if (pin < 32) {
|
||||
+ /* base mode: 0 => gpio, 1 => mux function */
|
||||
+ bcm63268_rmw_mux(pctl, pctl->mode, mask, 0);
|
||||
+
|
||||
+ /* pins 0-23 might be muxed to led */
|
||||
+ if (pin < 24)
|
||||
+ bcm63268_rmw_mux(pctl, pctl->led, mask, 0);
|
||||
+ } else if (pin < 52) {
|
||||
+ /* ctrl reg: 0 => wifi function, 1 => gpio */
|
||||
+ bcm63268_rmw_mux(pctl, pctl->ctrl, mask, mask);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static int bcm63268_pinctrl_set_mux(struct pinctrl_dev *pctldev,
|
||||
+ unsigned selector, unsigned group)
|
||||
+{
|
||||
+ struct bcm63268_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
|
||||
+ const struct bcm63268_pingroup *grp = &bcm63268_groups[group];
|
||||
+ const struct bcm63268_function *f = &bcm63268_funcs[selector];
|
||||
+ unsigned i;
|
||||
+ void __iomem *reg;
|
||||
+ u32 val, mask;
|
||||
+
|
||||
+ for (i = 0; i < grp->num_pins; i++)
|
||||
+ bcm63268_set_gpio(pctl, grp->pins[i]);
|
||||
+
|
||||
+ switch (f->reg) {
|
||||
+ case BCM63268_LEDCTRL:
|
||||
+ reg = pctl->led;
|
||||
+ mask = BIT(grp->pins[0]);
|
||||
+ val = BIT(grp->pins[0]);
|
||||
+ break;
|
||||
+ case BCM63268_MODE:
|
||||
+ reg = pctl->mode;
|
||||
+ mask = BIT(grp->pins[0]);
|
||||
+ val = BIT(grp->pins[0]);
|
||||
+ break;
|
||||
+ case BCM63268_CTRL:
|
||||
+ reg = pctl->ctrl;
|
||||
+ mask = BIT(grp->pins[0]);
|
||||
+ val = 0;
|
||||
+ break;
|
||||
+ case BCM63268_BASEMODE:
|
||||
+ reg = pctl->basemode;
|
||||
+ mask = f->mask;
|
||||
+ val = f->mask;
|
||||
+ break;
|
||||
+ default:
|
||||
+ WARN_ON(1);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ bcm63268_rmw_mux(pctl, reg, mask, val);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int bcm63268_gpio_request_enable(struct pinctrl_dev *pctldev,
|
||||
+ struct pinctrl_gpio_range *range,
|
||||
+ unsigned offset)
|
||||
+{
|
||||
+ struct bcm63268_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
|
||||
+
|
||||
+ /* disable all functions using this pin */
|
||||
+ bcm63268_set_gpio(pctl, offset);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static struct pinctrl_ops bcm63268_pctl_ops = {
|
||||
+ .get_groups_count = bcm63268_pinctrl_get_group_count,
|
||||
+ .get_group_name = bcm63268_pinctrl_get_group_name,
|
||||
+ .get_group_pins = bcm63268_pinctrl_get_group_pins,
|
||||
+#ifdef CONFIG_OF
|
||||
+ .dt_node_to_map = pinconf_generic_dt_node_to_map_pin,
|
||||
+ .dt_free_map = pinctrl_utils_free_map,
|
||||
+#endif
|
||||
+};
|
||||
+
|
||||
+static struct pinmux_ops bcm63268_pmx_ops = {
|
||||
+ .get_functions_count = bcm63268_pinctrl_get_func_count,
|
||||
+ .get_function_name = bcm63268_pinctrl_get_func_name,
|
||||
+ .get_function_groups = bcm63268_pinctrl_get_groups,
|
||||
+ .set_mux = bcm63268_pinctrl_set_mux,
|
||||
+ .gpio_request_enable = bcm63268_gpio_request_enable,
|
||||
+ .strict = true,
|
||||
+};
|
||||
+
|
||||
+static int bcm63268_pinctrl_probe(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct bcm63268_pinctrl *pctl;
|
||||
+ struct resource *res;
|
||||
+ void __iomem *led, *mode, *ctrl, *basemode;
|
||||
+
|
||||
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "led");
|
||||
+ led = devm_ioremap_resource(&pdev->dev, res);
|
||||
+ if (IS_ERR(led))
|
||||
+ return PTR_ERR(led);
|
||||
+
|
||||
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mode");
|
||||
+ mode = devm_ioremap_resource(&pdev->dev, res);
|
||||
+ if (IS_ERR(mode))
|
||||
+ return PTR_ERR(mode);
|
||||
+
|
||||
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ctrl");
|
||||
+ ctrl = devm_ioremap_resource(&pdev->dev, res);
|
||||
+ if (IS_ERR(ctrl))
|
||||
+ return PTR_ERR(ctrl);
|
||||
+
|
||||
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "basemode");
|
||||
+ basemode = devm_ioremap_resource(&pdev->dev, res);
|
||||
+ if (IS_ERR(basemode))
|
||||
+ return PTR_ERR(basemode);
|
||||
+
|
||||
+ pctl = devm_kzalloc(&pdev->dev, sizeof(*pctl), GFP_KERNEL);
|
||||
+ if (!pctl)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ spin_lock_init(&pctl->lock);
|
||||
+
|
||||
+ pctl->led = led;
|
||||
+ pctl->mode = mode;
|
||||
+ pctl->ctrl = ctrl;
|
||||
+ pctl->basemode = basemode;
|
||||
+
|
||||
+ pctl->desc.name = dev_name(&pdev->dev);
|
||||
+ pctl->desc.owner = THIS_MODULE;
|
||||
+ pctl->desc.pctlops = &bcm63268_pctl_ops;
|
||||
+ pctl->desc.pmxops = &bcm63268_pmx_ops;
|
||||
+
|
||||
+ pctl->desc.npins = ARRAY_SIZE(bcm63268_pins);
|
||||
+ pctl->desc.pins = bcm63268_pins;
|
||||
+
|
||||
+ platform_set_drvdata(pdev, pctl);
|
||||
+
|
||||
+ pctl->pctldev = bcm63xx_pinctrl_register(pdev, &pctl->desc, pctl,
|
||||
+ pctl->gpio, BCM63268_NGPIO);
|
||||
+ if (IS_ERR(pctl->pctldev))
|
||||
+ return PTR_ERR(pctl->pctldev);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static const struct of_device_id bcm63268_pinctrl_match[] = {
|
||||
+ { .compatible = "brcm,bcm63268-pinctrl", },
|
||||
+ { },
|
||||
+};
|
||||
+
|
||||
+static struct platform_driver bcm63268_pinctrl_driver = {
|
||||
+ .probe = bcm63268_pinctrl_probe,
|
||||
+ .driver = {
|
||||
+ .name = "bcm63268-pinctrl",
|
||||
+ .of_match_table = bcm63268_pinctrl_match,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+builtin_platform_driver(bcm63268_pinctrl_driver);
|
@ -1,66 +0,0 @@
|
||||
From 6ac09efa8f0e189ffe7dd7b0889289de56ee44cc Mon Sep 17 00:00:00 2001
|
||||
From: Jonas Gorski <jogo@openwrt.org>
|
||||
Date: Sun, 19 Jan 2014 12:18:03 +0100
|
||||
Subject: [PATCH] USB: EHCI: allow limiting ports for ehci-platform
|
||||
|
||||
In the same way as the ohci platform driver allows limiting ports,
|
||||
enable the same for ehci. This prevents a mismatch in the available
|
||||
ports between ehci/ohci on USB 2.0 controllers.
|
||||
|
||||
This is needed if the USB host controller always reports the maximum
|
||||
number of ports regardless of the number of available ports (because
|
||||
one might be set to be usb device).
|
||||
|
||||
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
|
||||
---
|
||||
drivers/usb/host/ehci-hcd.c | 4 ++++
|
||||
drivers/usb/host/ehci-platform.c | 2 ++
|
||||
drivers/usb/host/ehci.h | 1 +
|
||||
include/linux/usb/ehci_pdriver.h | 1 +
|
||||
4 files changed, 8 insertions(+)
|
||||
|
||||
--- a/drivers/usb/host/ehci-hcd.c
|
||||
+++ b/drivers/usb/host/ehci-hcd.c
|
||||
@@ -666,6 +666,10 @@ int ehci_setup(struct usb_hcd *hcd)
|
||||
|
||||
/* cache this readonly data; minimize chip reads */
|
||||
ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
|
||||
+ if (ehci->num_ports) {
|
||||
+ ehci->hcs_params &= ~0xf; /* bits 3:0, ports on HC */
|
||||
+ ehci->hcs_params |= ehci->num_ports;
|
||||
+ }
|
||||
|
||||
ehci->sbrn = HCD_USB2;
|
||||
|
||||
--- a/drivers/usb/host/ehci-platform.c
|
||||
+++ b/drivers/usb/host/ehci-platform.c
|
||||
@@ -60,6 +60,9 @@ static int ehci_platform_reset(struct us
|
||||
|
||||
ehci->has_synopsys_hc_bug = pdata->has_synopsys_hc_bug;
|
||||
|
||||
+ if (pdata->num_ports && pdata->num_ports <= 15)
|
||||
+ ehci->num_ports = pdata->num_ports;
|
||||
+
|
||||
if (pdata->pre_setup) {
|
||||
retval = pdata->pre_setup(hcd);
|
||||
if (retval < 0)
|
||||
--- a/drivers/usb/host/ehci.h
|
||||
+++ b/drivers/usb/host/ehci.h
|
||||
@@ -213,6 +213,7 @@ struct ehci_hcd { /* one per controlle
|
||||
u32 command;
|
||||
|
||||
/* SILICON QUIRKS */
|
||||
+ unsigned int num_ports;
|
||||
unsigned no_selective_suspend:1;
|
||||
unsigned has_fsl_port_bug:1; /* FreeScale */
|
||||
unsigned has_fsl_hs_errata:1; /* Freescale HS quirk */
|
||||
--- a/include/linux/usb/ehci_pdriver.h
|
||||
+++ b/include/linux/usb/ehci_pdriver.h
|
||||
@@ -42,6 +42,7 @@ struct usb_hcd;
|
||||
*/
|
||||
struct usb_ehci_pdata {
|
||||
int caps_offset;
|
||||
+ unsigned int num_ports;
|
||||
unsigned has_tt:1;
|
||||
unsigned has_synopsys_hc_bug:1;
|
||||
unsigned big_endian_desc:1;
|
@ -1,492 +0,0 @@
|
||||
From 5a50cb0d53344a2429831b00925d6183d4d332e1 Mon Sep 17 00:00:00 2001
|
||||
From: Jonas Gorski <jogo@openwrt.org>
|
||||
Date: Sun, 9 Mar 2014 03:54:05 +0100
|
||||
Subject: [PATCH 40/44] MIPS: BCM63XX: move device registration code into its
|
||||
own file
|
||||
|
||||
Move device registration code into its own file to allow sharing it
|
||||
between board implementations.
|
||||
|
||||
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
|
||||
---
|
||||
arch/mips/bcm63xx/boards/Makefile | 1 +
|
||||
arch/mips/bcm63xx/boards/board_bcm963xx.c | 188 +-------------------------
|
||||
arch/mips/bcm63xx/boards/board_common.c | 215 ++++++++++++++++++++++++++++++
|
||||
arch/mips/bcm63xx/boards/board_common.h | 8 ++
|
||||
4 files changed, 223 insertions(+), 183 deletions(-)
|
||||
create mode 100644 arch/mips/bcm63xx/boards/board_common.c
|
||||
create mode 100644 arch/mips/bcm63xx/boards/board_common.h
|
||||
|
||||
--- a/arch/mips/bcm63xx/boards/Makefile
|
||||
+++ b/arch/mips/bcm63xx/boards/Makefile
|
||||
@@ -1 +1,2 @@
|
||||
+obj-y += board_common.o
|
||||
obj-$(CONFIG_BOARD_BCM963XX) += board_bcm963xx.o
|
||||
--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
|
||||
+++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
|
||||
@@ -12,34 +12,21 @@
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/string.h>
|
||||
-#include <linux/platform_device.h>
|
||||
-#include <linux/ssb/ssb.h>
|
||||
#include <asm/addrspace.h>
|
||||
#include <bcm63xx_board.h>
|
||||
#include <bcm63xx_cpu.h>
|
||||
-#include <bcm63xx_dev_uart.h>
|
||||
#include <bcm63xx_regs.h>
|
||||
#include <bcm63xx_io.h>
|
||||
#include <bcm63xx_nvram.h>
|
||||
-#include <bcm63xx_dev_pci.h>
|
||||
-#include <bcm63xx_dev_enet.h>
|
||||
-#include <bcm63xx_dev_dsp.h>
|
||||
-#include <bcm63xx_dev_flash.h>
|
||||
-#include <bcm63xx_dev_hsspi.h>
|
||||
-#include <bcm63xx_dev_pcmcia.h>
|
||||
-#include <bcm63xx_dev_spi.h>
|
||||
-#include <bcm63xx_dev_usb_ehci.h>
|
||||
-#include <bcm63xx_dev_usb_ohci.h>
|
||||
-#include <bcm63xx_dev_usb_usbd.h>
|
||||
#include <board_bcm963xx.h>
|
||||
|
||||
+#include "board_common.h"
|
||||
+
|
||||
#include <uapi/linux/bcm933xx_hcs.h>
|
||||
|
||||
|
||||
#define HCS_OFFSET_128K 0x20000
|
||||
|
||||
-static struct board_info board;
|
||||
-
|
||||
/*
|
||||
* known 3368 boards
|
||||
*/
|
||||
@@ -712,52 +699,6 @@ static const struct board_info __initcon
|
||||
};
|
||||
|
||||
/*
|
||||
- * Register a sane SPROMv2 to make the on-board
|
||||
- * bcm4318 WLAN work
|
||||
- */
|
||||
-#ifdef CONFIG_SSB_PCIHOST
|
||||
-static struct ssb_sprom bcm63xx_sprom = {
|
||||
- .revision = 0x02,
|
||||
- .board_rev = 0x17,
|
||||
- .country_code = 0x0,
|
||||
- .ant_available_bg = 0x3,
|
||||
- .pa0b0 = 0x15ae,
|
||||
- .pa0b1 = 0xfa85,
|
||||
- .pa0b2 = 0xfe8d,
|
||||
- .pa1b0 = 0xffff,
|
||||
- .pa1b1 = 0xffff,
|
||||
- .pa1b2 = 0xffff,
|
||||
- .gpio0 = 0xff,
|
||||
- .gpio1 = 0xff,
|
||||
- .gpio2 = 0xff,
|
||||
- .gpio3 = 0xff,
|
||||
- .maxpwr_bg = 0x004c,
|
||||
- .itssi_bg = 0x00,
|
||||
- .boardflags_lo = 0x2848,
|
||||
- .boardflags_hi = 0x0000,
|
||||
-};
|
||||
-
|
||||
-int bcm63xx_get_fallback_sprom(struct ssb_bus *bus, struct ssb_sprom *out)
|
||||
-{
|
||||
- if (bus->bustype == SSB_BUSTYPE_PCI) {
|
||||
- memcpy(out, &bcm63xx_sprom, sizeof(struct ssb_sprom));
|
||||
- return 0;
|
||||
- } else {
|
||||
- pr_err("unable to fill SPROM for given bustype\n");
|
||||
- return -EINVAL;
|
||||
- }
|
||||
-}
|
||||
-#endif
|
||||
-
|
||||
-/*
|
||||
- * return board name for /proc/cpuinfo
|
||||
- */
|
||||
-const char *board_get_name(void)
|
||||
-{
|
||||
- return board.name;
|
||||
-}
|
||||
-
|
||||
-/*
|
||||
* early init callback, read nvram data from flash and checksum it
|
||||
*/
|
||||
void __init board_prom_init(void)
|
||||
@@ -802,140 +743,15 @@ void __init board_prom_init(void)
|
||||
if (strncmp(board_name, bcm963xx_boards[i]->name, 16))
|
||||
continue;
|
||||
/* copy, board desc array is marked initdata */
|
||||
- memcpy(&board, bcm963xx_boards[i], sizeof(board));
|
||||
+ board_early_setup(bcm963xx_boards[i]);
|
||||
break;
|
||||
}
|
||||
|
||||
- /* bail out if board is not found, will complain later */
|
||||
- if (!board.name[0]) {
|
||||
+ /* warn if board is not found, will complain later */
|
||||
+ if (i == ARRAY_SIZE(bcm963xx_boards)) {
|
||||
char name[17];
|
||||
memcpy(name, board_name, 16);
|
||||
name[16] = 0;
|
||||
pr_err("unknown bcm963xx board: %s\n", name);
|
||||
- return;
|
||||
- }
|
||||
-
|
||||
- /* setup pin multiplexing depending on board enabled device,
|
||||
- * this has to be done this early since PCI init is done
|
||||
- * inside arch_initcall */
|
||||
- val = 0;
|
||||
-
|
||||
-#ifdef CONFIG_PCI
|
||||
- if (board.has_pci) {
|
||||
- bcm63xx_pci_enabled = 1;
|
||||
- if (BCMCPU_IS_6348())
|
||||
- val |= GPIO_MODE_6348_G2_PCI;
|
||||
- }
|
||||
-#endif
|
||||
-
|
||||
- if (board.has_pccard) {
|
||||
- if (BCMCPU_IS_6348())
|
||||
- val |= GPIO_MODE_6348_G1_MII_PCCARD;
|
||||
- }
|
||||
-
|
||||
- if (board.has_enet0 && !board.enet0.use_internal_phy) {
|
||||
- if (BCMCPU_IS_6348())
|
||||
- val |= GPIO_MODE_6348_G3_EXT_MII |
|
||||
- GPIO_MODE_6348_G0_EXT_MII;
|
||||
- }
|
||||
-
|
||||
- if (board.has_enet1 && !board.enet1.use_internal_phy) {
|
||||
- if (BCMCPU_IS_6348())
|
||||
- val |= GPIO_MODE_6348_G3_EXT_MII |
|
||||
- GPIO_MODE_6348_G0_EXT_MII;
|
||||
- }
|
||||
-
|
||||
- bcm_gpio_writel(val, GPIO_MODE_REG);
|
||||
-}
|
||||
-
|
||||
-/*
|
||||
- * second stage init callback, good time to panic if we couldn't
|
||||
- * identify on which board we're running since early printk is working
|
||||
- */
|
||||
-void __init board_setup(void)
|
||||
-{
|
||||
- if (!board.name[0])
|
||||
- panic("unable to detect bcm963xx board");
|
||||
- pr_info("board name: %s\n", board.name);
|
||||
-
|
||||
- /* make sure we're running on expected cpu */
|
||||
- if (bcm63xx_get_cpu_id() != board.expected_cpu_id)
|
||||
- panic("unexpected CPU for bcm963xx board");
|
||||
-}
|
||||
-
|
||||
-static struct gpio_led_platform_data bcm63xx_led_data;
|
||||
-
|
||||
-static struct platform_device bcm63xx_gpio_leds = {
|
||||
- .name = "leds-gpio",
|
||||
- .id = 0,
|
||||
- .dev.platform_data = &bcm63xx_led_data,
|
||||
-};
|
||||
-
|
||||
-/*
|
||||
- * third stage init callback, register all board devices.
|
||||
- */
|
||||
-int __init board_register_devices(void)
|
||||
-{
|
||||
- if (board.has_uart0)
|
||||
- bcm63xx_uart_register(0);
|
||||
-
|
||||
- if (board.has_uart1)
|
||||
- bcm63xx_uart_register(1);
|
||||
-
|
||||
- if (board.has_pccard)
|
||||
- bcm63xx_pcmcia_register();
|
||||
-
|
||||
- if (board.has_enet0 &&
|
||||
- !bcm63xx_nvram_get_mac_address(board.enet0.mac_addr))
|
||||
- bcm63xx_enet_register(0, &board.enet0);
|
||||
-
|
||||
- if (board.has_enet1 &&
|
||||
- !bcm63xx_nvram_get_mac_address(board.enet1.mac_addr))
|
||||
- bcm63xx_enet_register(1, &board.enet1);
|
||||
-
|
||||
- if (board.has_enetsw &&
|
||||
- !bcm63xx_nvram_get_mac_address(board.enetsw.mac_addr))
|
||||
- bcm63xx_enetsw_register(&board.enetsw);
|
||||
-
|
||||
- if (board.has_usbd)
|
||||
- bcm63xx_usbd_register(&board.usbd);
|
||||
-
|
||||
- if (board.has_ehci0)
|
||||
- bcm63xx_ehci_register();
|
||||
-
|
||||
- if (board.has_ohci0)
|
||||
- bcm63xx_ohci_register();
|
||||
-
|
||||
- if (board.has_dsp)
|
||||
- bcm63xx_dsp_register(&board.dsp);
|
||||
-
|
||||
- /* Generate MAC address for WLAN and register our SPROM,
|
||||
- * do this after registering enet devices
|
||||
- */
|
||||
-#ifdef CONFIG_SSB_PCIHOST
|
||||
- if (!bcm63xx_nvram_get_mac_address(bcm63xx_sprom.il0mac)) {
|
||||
- memcpy(bcm63xx_sprom.et0mac, bcm63xx_sprom.il0mac, ETH_ALEN);
|
||||
- memcpy(bcm63xx_sprom.et1mac, bcm63xx_sprom.il0mac, ETH_ALEN);
|
||||
- if (ssb_arch_register_fallback_sprom(
|
||||
- &bcm63xx_get_fallback_sprom) < 0)
|
||||
- pr_err("failed to register fallback SPROM\n");
|
||||
}
|
||||
-#endif
|
||||
-
|
||||
- bcm63xx_spi_register();
|
||||
-
|
||||
- bcm63xx_hsspi_register();
|
||||
-
|
||||
- bcm63xx_flash_register();
|
||||
-
|
||||
- bcm63xx_led_data.num_leds = ARRAY_SIZE(board.leds);
|
||||
- bcm63xx_led_data.leds = board.leds;
|
||||
-
|
||||
- platform_device_register(&bcm63xx_gpio_leds);
|
||||
-
|
||||
- if (board.ephy_reset_gpio && board.ephy_reset_gpio_flags)
|
||||
- gpio_request_one(board.ephy_reset_gpio,
|
||||
- board.ephy_reset_gpio_flags, "ephy-reset");
|
||||
-
|
||||
- return 0;
|
||||
}
|
||||
--- /dev/null
|
||||
+++ b/arch/mips/bcm63xx/boards/board_common.c
|
||||
@@ -0,0 +1,218 @@
|
||||
+/*
|
||||
+ * This file is subject to the terms and conditions of the GNU General Public
|
||||
+ * License. See the file "COPYING" in the main directory of this archive
|
||||
+ * for more details.
|
||||
+ *
|
||||
+ * Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
|
||||
+ * Copyright (C) 2008 Florian Fainelli <florian@openwrt.org>
|
||||
+ */
|
||||
+
|
||||
+#include <linux/init.h>
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/string.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+#include <linux/ssb/ssb.h>
|
||||
+#include <asm/addrspace.h>
|
||||
+#include <bcm63xx_board.h>
|
||||
+#include <bcm63xx_cpu.h>
|
||||
+#include <bcm63xx_dev_uart.h>
|
||||
+#include <bcm63xx_regs.h>
|
||||
+#include <bcm63xx_io.h>
|
||||
+#include <bcm63xx_nvram.h>
|
||||
+#include <bcm63xx_gpio.h>
|
||||
+#include <bcm63xx_dev_pci.h>
|
||||
+#include <bcm63xx_dev_enet.h>
|
||||
+#include <bcm63xx_dev_dsp.h>
|
||||
+#include <bcm63xx_dev_flash.h>
|
||||
+#include <bcm63xx_dev_hsspi.h>
|
||||
+#include <bcm63xx_dev_pcmcia.h>
|
||||
+#include <bcm63xx_dev_spi.h>
|
||||
+#include <bcm63xx_dev_usb_ehci.h>
|
||||
+#include <bcm63xx_dev_usb_ohci.h>
|
||||
+#include <bcm63xx_dev_usb_usbd.h>
|
||||
+#include <board_bcm963xx.h>
|
||||
+
|
||||
+#define PFX "board: "
|
||||
+
|
||||
+static struct board_info board;
|
||||
+
|
||||
+/*
|
||||
+ * Register a sane SPROMv2 to make the on-board
|
||||
+ * bcm4318 WLAN work
|
||||
+ */
|
||||
+#ifdef CONFIG_SSB_PCIHOST
|
||||
+static struct ssb_sprom bcm63xx_sprom = {
|
||||
+ .revision = 0x02,
|
||||
+ .board_rev = 0x17,
|
||||
+ .country_code = 0x0,
|
||||
+ .ant_available_bg = 0x3,
|
||||
+ .pa0b0 = 0x15ae,
|
||||
+ .pa0b1 = 0xfa85,
|
||||
+ .pa0b2 = 0xfe8d,
|
||||
+ .pa1b0 = 0xffff,
|
||||
+ .pa1b1 = 0xffff,
|
||||
+ .pa1b2 = 0xffff,
|
||||
+ .gpio0 = 0xff,
|
||||
+ .gpio1 = 0xff,
|
||||
+ .gpio2 = 0xff,
|
||||
+ .gpio3 = 0xff,
|
||||
+ .maxpwr_bg = 0x004c,
|
||||
+ .itssi_bg = 0x00,
|
||||
+ .boardflags_lo = 0x2848,
|
||||
+ .boardflags_hi = 0x0000,
|
||||
+};
|
||||
+
|
||||
+int bcm63xx_get_fallback_sprom(struct ssb_bus *bus, struct ssb_sprom *out)
|
||||
+{
|
||||
+ if (bus->bustype == SSB_BUSTYPE_PCI) {
|
||||
+ memcpy(out, &bcm63xx_sprom, sizeof(struct ssb_sprom));
|
||||
+ return 0;
|
||||
+ } else {
|
||||
+ printk(KERN_ERR PFX "unable to fill SPROM for given bustype.\n");
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
+/*
|
||||
+ * return board name for /proc/cpuinfo
|
||||
+ */
|
||||
+const char *board_get_name(void)
|
||||
+{
|
||||
+ return board.name;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * setup board for device registration
|
||||
+ */
|
||||
+void __init board_early_setup(const struct board_info *target)
|
||||
+{
|
||||
+ u32 val;
|
||||
+
|
||||
+ memcpy(&board, target, sizeof(board));
|
||||
+
|
||||
+ /* setup pin multiplexing depending on board enabled device,
|
||||
+ * this has to be done this early since PCI init is done
|
||||
+ * inside arch_initcall */
|
||||
+ val = 0;
|
||||
+
|
||||
+#ifdef CONFIG_PCI
|
||||
+ if (board.has_pci) {
|
||||
+ bcm63xx_pci_enabled = 1;
|
||||
+ if (BCMCPU_IS_6348())
|
||||
+ val |= GPIO_MODE_6348_G2_PCI;
|
||||
+ }
|
||||
+#endif
|
||||
+
|
||||
+ if (board.has_pccard) {
|
||||
+ if (BCMCPU_IS_6348())
|
||||
+ val |= GPIO_MODE_6348_G1_MII_PCCARD;
|
||||
+ }
|
||||
+
|
||||
+ if (board.has_enet0 && !board.enet0.use_internal_phy) {
|
||||
+ if (BCMCPU_IS_6348())
|
||||
+ val |= GPIO_MODE_6348_G3_EXT_MII |
|
||||
+ GPIO_MODE_6348_G0_EXT_MII;
|
||||
+ }
|
||||
+
|
||||
+ if (board.has_enet1 && !board.enet1.use_internal_phy) {
|
||||
+ if (BCMCPU_IS_6348())
|
||||
+ val |= GPIO_MODE_6348_G3_EXT_MII |
|
||||
+ GPIO_MODE_6348_G0_EXT_MII;
|
||||
+ }
|
||||
+
|
||||
+ bcm_gpio_writel(val, GPIO_MODE_REG);
|
||||
+}
|
||||
+
|
||||
+
|
||||
+/*
|
||||
+ * second stage init callback, good time to panic if we couldn't
|
||||
+ * identify on which board we're running since early printk is working
|
||||
+ */
|
||||
+void __init board_setup(void)
|
||||
+{
|
||||
+ if (!board.name[0])
|
||||
+ panic("unable to detect bcm963xx board");
|
||||
+ printk(KERN_INFO PFX "board name: %s\n", board.name);
|
||||
+
|
||||
+ /* make sure we're running on expected cpu */
|
||||
+ if (bcm63xx_get_cpu_id() != board.expected_cpu_id)
|
||||
+ panic("unexpected CPU for bcm963xx board");
|
||||
+}
|
||||
+
|
||||
+static struct gpio_led_platform_data bcm63xx_led_data;
|
||||
+
|
||||
+static struct platform_device bcm63xx_gpio_leds = {
|
||||
+ .name = "leds-gpio",
|
||||
+ .id = 0,
|
||||
+ .dev.platform_data = &bcm63xx_led_data,
|
||||
+};
|
||||
+
|
||||
+/*
|
||||
+ * third stage init callback, register all board devices.
|
||||
+ */
|
||||
+int __init board_register_devices(void)
|
||||
+{
|
||||
+ if (board.has_uart0)
|
||||
+ bcm63xx_uart_register(0);
|
||||
+
|
||||
+ if (board.has_uart1)
|
||||
+ bcm63xx_uart_register(1);
|
||||
+
|
||||
+ if (board.has_pccard)
|
||||
+ bcm63xx_pcmcia_register();
|
||||
+
|
||||
+ if (board.has_enet0 &&
|
||||
+ !bcm63xx_nvram_get_mac_address(board.enet0.mac_addr))
|
||||
+ bcm63xx_enet_register(0, &board.enet0);
|
||||
+
|
||||
+ if (board.has_enet1 &&
|
||||
+ !bcm63xx_nvram_get_mac_address(board.enet1.mac_addr))
|
||||
+ bcm63xx_enet_register(1, &board.enet1);
|
||||
+
|
||||
+ if (board.has_enetsw &&
|
||||
+ !bcm63xx_nvram_get_mac_address(board.enetsw.mac_addr))
|
||||
+ bcm63xx_enetsw_register(&board.enetsw);
|
||||
+
|
||||
+ if (board.has_usbd)
|
||||
+ bcm63xx_usbd_register(&board.usbd);
|
||||
+
|
||||
+ if (board.has_ehci0)
|
||||
+ bcm63xx_ehci_register();
|
||||
+
|
||||
+ if (board.has_ohci0)
|
||||
+ bcm63xx_ohci_register();
|
||||
+
|
||||
+ if (board.has_dsp)
|
||||
+ bcm63xx_dsp_register(&board.dsp);
|
||||
+
|
||||
+ /* Generate MAC address for WLAN and register our SPROM,
|
||||
+ * do this after registering enet devices
|
||||
+ */
|
||||
+#ifdef CONFIG_SSB_PCIHOST
|
||||
+ if (!bcm63xx_nvram_get_mac_address(bcm63xx_sprom.il0mac)) {
|
||||
+ memcpy(bcm63xx_sprom.et0mac, bcm63xx_sprom.il0mac, ETH_ALEN);
|
||||
+ memcpy(bcm63xx_sprom.et1mac, bcm63xx_sprom.il0mac, ETH_ALEN);
|
||||
+ if (ssb_arch_register_fallback_sprom(
|
||||
+ &bcm63xx_get_fallback_sprom) < 0)
|
||||
+ pr_err(PFX "failed to register fallback SPROM\n");
|
||||
+ }
|
||||
+#endif
|
||||
+
|
||||
+ bcm63xx_spi_register();
|
||||
+
|
||||
+ bcm63xx_hsspi_register();
|
||||
+
|
||||
+ bcm63xx_flash_register();
|
||||
+
|
||||
+ bcm63xx_led_data.num_leds = ARRAY_SIZE(board.leds);
|
||||
+ bcm63xx_led_data.leds = board.leds;
|
||||
+
|
||||
+ platform_device_register(&bcm63xx_gpio_leds);
|
||||
+
|
||||
+ if (board.ephy_reset_gpio && board.ephy_reset_gpio_flags)
|
||||
+ gpio_request_one(board.ephy_reset_gpio,
|
||||
+ board.ephy_reset_gpio_flags, "ephy-reset");
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
--- /dev/null
|
||||
+++ b/arch/mips/bcm63xx/boards/board_common.h
|
||||
@@ -0,0 +1,8 @@
|
||||
+#ifndef __BOARD_COMMON_H
|
||||
+#define __BOARD_COMMON_H
|
||||
+
|
||||
+#include <board_bcm963xx.h>
|
||||
+
|
||||
+void board_early_setup(const struct board_info *board);
|
||||
+
|
||||
+#endif /* __BOARD_COMMON_H */
|
@ -1,100 +0,0 @@
|
||||
From 4e9c34a37bd3442b286ba55441bfe22c1ac5b65f Mon Sep 17 00:00:00 2001
|
||||
From: Jonas Gorski <jogo@openwrt.org>
|
||||
Date: Sun, 9 Mar 2014 04:08:06 +0100
|
||||
Subject: [PATCH 41/44] MIPS: BCM63XX: pass a mac addresss allocator to board
|
||||
setup
|
||||
|
||||
Pass a mac address allocator to board setup code to allow board
|
||||
implementations to work with third party bootloaders not using nvram
|
||||
for configuration storage.
|
||||
|
||||
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
|
||||
---
|
||||
arch/mips/bcm63xx/boards/board_bcm963xx.c | 3 ++-
|
||||
arch/mips/bcm63xx/boards/board_common.c | 16 ++++++++++------
|
||||
arch/mips/bcm63xx/boards/board_common.h | 3 ++-
|
||||
3 files changed, 14 insertions(+), 8 deletions(-)
|
||||
|
||||
--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
|
||||
+++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
|
||||
@@ -743,7 +743,8 @@ void __init board_prom_init(void)
|
||||
if (strncmp(board_name, bcm963xx_boards[i]->name, 16))
|
||||
continue;
|
||||
/* copy, board desc array is marked initdata */
|
||||
- board_early_setup(bcm963xx_boards[i]);
|
||||
+ board_early_setup(bcm963xx_boards[i],
|
||||
+ bcm63xx_nvram_get_mac_address);
|
||||
break;
|
||||
}
|
||||
|
||||
--- a/arch/mips/bcm63xx/boards/board_common.c
|
||||
+++ b/arch/mips/bcm63xx/boards/board_common.c
|
||||
@@ -18,7 +18,6 @@
|
||||
#include <bcm63xx_dev_uart.h>
|
||||
#include <bcm63xx_regs.h>
|
||||
#include <bcm63xx_io.h>
|
||||
-#include <bcm63xx_nvram.h>
|
||||
#include <bcm63xx_gpio.h>
|
||||
#include <bcm63xx_dev_pci.h>
|
||||
#include <bcm63xx_dev_enet.h>
|
||||
@@ -82,15 +81,20 @@ const char *board_get_name(void)
|
||||
return board.name;
|
||||
}
|
||||
|
||||
+static int (*board_get_mac_address)(u8 mac[ETH_ALEN]);
|
||||
+
|
||||
/*
|
||||
* setup board for device registration
|
||||
*/
|
||||
-void __init board_early_setup(const struct board_info *target)
|
||||
+void __init board_early_setup(const struct board_info *target,
|
||||
+ int (*get_mac_address)(u8 mac[ETH_ALEN]))
|
||||
{
|
||||
u32 val;
|
||||
|
||||
memcpy(&board, target, sizeof(board));
|
||||
|
||||
+ board_get_mac_address = get_mac_address;
|
||||
+
|
||||
/* setup pin multiplexing depending on board enabled device,
|
||||
* this has to be done this early since PCI init is done
|
||||
* inside arch_initcall */
|
||||
@@ -163,15 +167,15 @@ int __init board_register_devices(void)
|
||||
bcm63xx_pcmcia_register();
|
||||
|
||||
if (board.has_enet0 &&
|
||||
- !bcm63xx_nvram_get_mac_address(board.enet0.mac_addr))
|
||||
+ !board_get_mac_address(board.enet0.mac_addr))
|
||||
bcm63xx_enet_register(0, &board.enet0);
|
||||
|
||||
if (board.has_enet1 &&
|
||||
- !bcm63xx_nvram_get_mac_address(board.enet1.mac_addr))
|
||||
+ !board_get_mac_address(board.enet1.mac_addr))
|
||||
bcm63xx_enet_register(1, &board.enet1);
|
||||
|
||||
if (board.has_enetsw &&
|
||||
- !bcm63xx_nvram_get_mac_address(board.enetsw.mac_addr))
|
||||
+ !board_get_mac_address(board.enetsw.mac_addr))
|
||||
bcm63xx_enetsw_register(&board.enetsw);
|
||||
|
||||
if (board.has_usbd)
|
||||
@@ -190,7 +194,7 @@ int __init board_register_devices(void)
|
||||
* do this after registering enet devices
|
||||
*/
|
||||
#ifdef CONFIG_SSB_PCIHOST
|
||||
- if (!bcm63xx_nvram_get_mac_address(bcm63xx_sprom.il0mac)) {
|
||||
+ if (!board_get_mac_address(bcm63xx_sprom.il0mac)) {
|
||||
memcpy(bcm63xx_sprom.et0mac, bcm63xx_sprom.il0mac, ETH_ALEN);
|
||||
memcpy(bcm63xx_sprom.et1mac, bcm63xx_sprom.il0mac, ETH_ALEN);
|
||||
if (ssb_arch_register_fallback_sprom(
|
||||
--- a/arch/mips/bcm63xx/boards/board_common.h
|
||||
+++ b/arch/mips/bcm63xx/boards/board_common.h
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include <board_bcm963xx.h>
|
||||
|
||||
-void board_early_setup(const struct board_info *board);
|
||||
+void board_early_setup(const struct board_info *board,
|
||||
+ int (*get_mac_address)(u8 mac[ETH_ALEN]));
|
||||
|
||||
#endif /* __BOARD_COMMON_H */
|
@ -1,27 +0,0 @@
|
||||
--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
|
||||
+++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
|
||||
@@ -723,10 +723,20 @@ void __init board_prom_init(void)
|
||||
|
||||
/* dump cfe version */
|
||||
cfe = boot_addr + BCM963XX_CFE_VERSION_OFFSET;
|
||||
- if (!memcmp(cfe, "cfe-v", 5))
|
||||
- snprintf(cfe_version, sizeof(cfe_version), "%u.%u.%u-%u.%u",
|
||||
- cfe[5], cfe[6], cfe[7], cfe[8], cfe[9]);
|
||||
- else
|
||||
+ if (strstarts(cfe, "cfe-")) {
|
||||
+ if(cfe[4] == 'v') {
|
||||
+ if(cfe[5] == 'd')
|
||||
+ snprintf(cfe_version, 11, "%s", (char *) &cfe[5]);
|
||||
+ else if (cfe[10] > 0)
|
||||
+ snprintf(cfe_version, sizeof(cfe_version), "%u.%u.%u-%u.%u-%u",
|
||||
+ cfe[5], cfe[6], cfe[7], cfe[8], cfe[9], cfe[10]);
|
||||
+ else
|
||||
+ snprintf(cfe_version, sizeof(cfe_version), "%u.%u.%u-%u.%u",
|
||||
+ cfe[5], cfe[6], cfe[7], cfe[8], cfe[9]);
|
||||
+ } else {
|
||||
+ snprintf(cfe_version, 12, "%s", (char *) &cfe[4]);
|
||||
+ }
|
||||
+ } else
|
||||
strcpy(cfe_version, "unknown");
|
||||
pr_info("CFE version: %s\n", cfe_version);
|
||||
|
@ -1,20 +0,0 @@
|
||||
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_board.h
|
||||
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_board.h
|
||||
@@ -1,6 +1,8 @@
|
||||
#ifndef BCM63XX_BOARD_H_
|
||||
#define BCM63XX_BOARD_H_
|
||||
|
||||
+#include <asm/bootinfo.h>
|
||||
+
|
||||
const char *board_get_name(void);
|
||||
|
||||
void board_prom_init(void);
|
||||
@@ -9,4 +11,8 @@ void board_setup(void);
|
||||
|
||||
int board_register_devices(void);
|
||||
|
||||
+static inline bool bcm63xx_is_cfe_present(void) {
|
||||
+ return fw_arg3 == 0x43464531;
|
||||
+}
|
||||
+
|
||||
#endif /* ! BCM63XX_BOARD_H_ */
|
@ -1,51 +0,0 @@
|
||||
--- a/drivers/mtd/bcm63xxpart.c
|
||||
+++ b/drivers/mtd/bcm63xxpart.c
|
||||
@@ -35,7 +35,7 @@
|
||||
|
||||
#include <asm/mach-bcm63xx/bcm63xx_nvram.h>
|
||||
#include <asm/mach-bcm63xx/bcm963xx_tag.h>
|
||||
-#include <asm/mach-bcm63xx/board_bcm963xx.h>
|
||||
+#include <asm/mach-bcm63xx/bcm63xx_board.h>
|
||||
|
||||
#define BCM63XX_EXTENDED_SIZE 0xBFC00000 /* Extended flash address */
|
||||
|
||||
@@ -43,30 +43,6 @@
|
||||
|
||||
#define BCM63XX_CFE_MAGIC_OFFSET 0x4e0
|
||||
|
||||
-static int bcm63xx_detect_cfe(struct mtd_info *master)
|
||||
-{
|
||||
- char buf[9];
|
||||
- int ret;
|
||||
- size_t retlen;
|
||||
-
|
||||
- ret = mtd_read(master, BCM963XX_CFE_VERSION_OFFSET, 5, &retlen,
|
||||
- (void *)buf);
|
||||
- buf[retlen] = 0;
|
||||
-
|
||||
- if (ret)
|
||||
- return ret;
|
||||
-
|
||||
- if (strncmp("cfe-v", buf, 5) == 0)
|
||||
- return 0;
|
||||
-
|
||||
- /* very old CFE's do not have the cfe-v string, so check for magic */
|
||||
- ret = mtd_read(master, BCM63XX_CFE_MAGIC_OFFSET, 8, &retlen,
|
||||
- (void *)buf);
|
||||
- buf[retlen] = 0;
|
||||
-
|
||||
- return strncmp("CFE1CFE1", buf, 8);
|
||||
-}
|
||||
-
|
||||
static int bcm63xx_parse_cfe_partitions(struct mtd_info *master,
|
||||
struct mtd_partition **pparts,
|
||||
struct mtd_part_parser_data *data)
|
||||
@@ -85,7 +61,7 @@ static int bcm63xx_parse_cfe_partitions(
|
||||
u32 computed_crc;
|
||||
bool rootfs_first = false;
|
||||
|
||||
- if (bcm63xx_detect_cfe(master))
|
||||
+ if (!bcm63xx_is_cfe_present())
|
||||
return -EINVAL;
|
||||
|
||||
cfe_erasesize = max_t(uint32_t, master->erasesize,
|
@ -1,455 +0,0 @@
|
||||
From 301744ecbeece89ab3a9d6beef7802fa22598f00 Mon Sep 17 00:00:00 2001
|
||||
From: Jonas Gorski <jogo@openwrt.org>
|
||||
Date: Sun, 30 Nov 2014 14:53:12 +0100
|
||||
Subject: [PATCH 1/5] irqchip: add support for bcm6345-style periphery irq
|
||||
controller
|
||||
|
||||
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
|
||||
---
|
||||
.../brcm,bcm6345-periph-intc.txt | 50 +++
|
||||
drivers/irqchip/Kconfig | 4 +
|
||||
drivers/irqchip/Makefile | 1 +
|
||||
drivers/irqchip/irq-bcm6345-periph.c | 339 ++++++++++++++++++++
|
||||
include/linux/irqchip/irq-bcm6345-periph.h | 16 +
|
||||
5 files changed, 410 insertions(+)
|
||||
create mode 100644 Documentation/devicetree/bindings/interrupt-controller/brcm,bcm6345-periph-intc.txt
|
||||
create mode 100644 drivers/irqchip/irq-bcm6345-periph.c
|
||||
create mode 100644 include/linux/irqchip/irq-bcm6345-periph.h
|
||||
|
||||
--- /dev/null
|
||||
+++ b/Documentation/devicetree/bindings/interrupt-controller/brcm,bcm6345-periph-intc.txt
|
||||
@@ -0,0 +1,50 @@
|
||||
+Broadcom BCM6345 Level 1 periphery interrupt controller
|
||||
+
|
||||
+This block is a interrupt controller that is typically connected directly
|
||||
+to one of the HW INT lines on each CPU. Every BCM63XX xDSL chip since
|
||||
+BCM6345 has contained this hardware.
|
||||
+
|
||||
+Key elements of the hardware design include:
|
||||
+
|
||||
+- 32, 64, or 128 incoming level IRQ lines
|
||||
+
|
||||
+- All onchip peripherals are wired directly to an L2 input
|
||||
+
|
||||
+- A separate instance of the register set for each CPU, allowing individual
|
||||
+ peripheral IRQs to be routed to any CPU
|
||||
+
|
||||
+- No atomic mask/unmask operations
|
||||
+
|
||||
+- No polarity/level/edge settings
|
||||
+
|
||||
+- No FIFO or priority encoder logic; software is expected to read all
|
||||
+ 1-4 status words to determine which IRQs are pending
|
||||
+
|
||||
+Required properties:
|
||||
+
|
||||
+- compatible: Should be "brcm,bcm6345-periph-intc".
|
||||
+- reg: Specifies the base physical address and size of the registers.
|
||||
+ Multiple register addresses may be specified, and must match the amount of
|
||||
+ parent interrupts.
|
||||
+- interrupt-controller: Identifies the node as an interrupt controller.
|
||||
+- #interrupt-cells: Specifies the number of cells needed to encode an interrupt
|
||||
+ source, should be 1.
|
||||
+- interrupt-parent: Specifies the phandle to the parent interrupt controller
|
||||
+ this one is cascaded from.
|
||||
+- interrupts: Specifies the interrupt line(s) in the interrupt-parent controller
|
||||
+ node, valid values depend on the type of parent interrupt controller.
|
||||
+ Multiple lines are used to route interrupts to different cpus, with the first
|
||||
+ assumed to be for the boot CPU.
|
||||
+
|
||||
+Example:
|
||||
+
|
||||
+periph_intc: interrupt-controller@f0406800 {
|
||||
+ compatible = "brcm,bcm6345-periph-intc";
|
||||
+ reg = <0x10000020 0x10>, <0x10000030 0x10>;
|
||||
+
|
||||
+ interrupt-controller;
|
||||
+ #interrupt-cells = <1>;
|
||||
+
|
||||
+ interrupt-parent = <&cpu_intc>;
|
||||
+ interrupts = <2>, <3>;
|
||||
+};
|
||||
--- a/drivers/irqchip/Kconfig
|
||||
+++ b/drivers/irqchip/Kconfig
|
||||
@@ -80,6 +80,10 @@ config BRCMSTB_L2_IRQ
|
||||
select GENERIC_IRQ_CHIP
|
||||
select IRQ_DOMAIN
|
||||
|
||||
+config BCM6345_PERIPH_IRQ
|
||||
+ bool
|
||||
+ select IRQ_DOMAIN
|
||||
+
|
||||
config DW_APB_ICTL
|
||||
bool
|
||||
select GENERIC_IRQ_CHIP
|
||||
--- a/drivers/irqchip/Makefile
|
||||
+++ b/drivers/irqchip/Makefile
|
||||
@@ -9,6 +9,7 @@ obj-$(CONFIG_ARCH_MVEBU) += irq-armada-
|
||||
obj-$(CONFIG_IRQ_MXS) += irq-mxs.o
|
||||
obj-$(CONFIG_ARCH_TEGRA) += irq-tegra.o
|
||||
obj-$(CONFIG_ARCH_S3C24XX) += irq-s3c24xx.o
|
||||
+obj-$(CONFIG_BCM6345_PERIPH_IRQ) += irq-bcm6345-periph.o
|
||||
obj-$(CONFIG_DW_APB_ICTL) += irq-dw-apb-ictl.o
|
||||
obj-$(CONFIG_METAG) += irq-metag-ext.o
|
||||
obj-$(CONFIG_METAG_PERFCOUNTER_IRQS) += irq-metag.o
|
||||
--- /dev/null
|
||||
+++ b/drivers/irqchip/irq-bcm6345-periph.c
|
||||
@@ -0,0 +1,339 @@
|
||||
+/*
|
||||
+ * This file is subject to the terms and conditions of the GNU General Public
|
||||
+ * License. See the file "COPYING" in the main directory of this archive
|
||||
+ * for more details.
|
||||
+ *
|
||||
+ * Copyright (C) 2014 Jonas Gorski <jogo@openwrt.org>
|
||||
+ */
|
||||
+
|
||||
+#include <linux/ioport.h>
|
||||
+#include <linux/irq.h>
|
||||
+#include <linux/irqchip.h>
|
||||
+#include <linux/irqchip/chained_irq.h>
|
||||
+#include <linux/irqchip/irq-bcm6345-periph.h>
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/of.h>
|
||||
+#include <linux/of_irq.h>
|
||||
+#include <linux/of_address.h>
|
||||
+#include <linux/slab.h>
|
||||
+#include <linux/spinlock.h>
|
||||
+
|
||||
+#ifdef CONFIG_BCM63XX
|
||||
+#include <asm/mach-bcm63xx/bcm63xx_irq.h>
|
||||
+
|
||||
+#define VIRQ_BASE IRQ_INTERNAL_BASE
|
||||
+#else
|
||||
+#define VIRQ_BASE 0
|
||||
+#endif
|
||||
+
|
||||
+#define MAX_WORDS 4
|
||||
+#define MAX_PARENT_IRQS 2
|
||||
+#define IRQS_PER_WORD 32
|
||||
+
|
||||
+struct intc_block {
|
||||
+ int parent_irq;
|
||||
+ void __iomem *base;
|
||||
+ void __iomem *en_reg[MAX_WORDS];
|
||||
+ void __iomem *status_reg[MAX_WORDS];
|
||||
+ u32 mask_cache[MAX_WORDS];
|
||||
+};
|
||||
+
|
||||
+struct intc_data {
|
||||
+ struct irq_chip chip;
|
||||
+ struct intc_block block[MAX_PARENT_IRQS];
|
||||
+
|
||||
+ int num_words;
|
||||
+
|
||||
+ struct irq_domain *domain;
|
||||
+ raw_spinlock_t lock;
|
||||
+};
|
||||
+
|
||||
+static void bcm6345_periph_irq_handle(struct irq_desc *desc)
|
||||
+{
|
||||
+ struct intc_data *data = irq_desc_get_handler_data(desc);
|
||||
+ struct irq_chip *chip = irq_desc_get_chip(desc);
|
||||
+ struct intc_block *block;
|
||||
+ unsigned int irq = irq_desc_get_irq(desc);
|
||||
+ unsigned int idx;
|
||||
+
|
||||
+ chained_irq_enter(chip, desc);
|
||||
+
|
||||
+ for (idx = 0; idx < MAX_PARENT_IRQS; idx++)
|
||||
+ if (irq == data->block[idx].parent_irq)
|
||||
+ block = &data->block[idx];
|
||||
+
|
||||
+ for (idx = 0; idx < data->num_words; idx++) {
|
||||
+ int base = idx * IRQS_PER_WORD;
|
||||
+ unsigned long pending;
|
||||
+ int hw_irq;
|
||||
+
|
||||
+ raw_spin_lock(&data->lock);
|
||||
+ pending = __raw_readl(block->en_reg[idx]) &
|
||||
+ __raw_readl(block->status_reg[idx]);
|
||||
+ raw_spin_unlock(&data->lock);
|
||||
+
|
||||
+ for_each_set_bit(hw_irq, &pending, IRQS_PER_WORD) {
|
||||
+ int virq;
|
||||
+
|
||||
+ virq = irq_find_mapping(data->domain, base + hw_irq);
|
||||
+ generic_handle_irq(virq);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ chained_irq_exit(chip, desc);
|
||||
+}
|
||||
+
|
||||
+static void __bcm6345_periph_enable(struct intc_block *block, int reg, int bit,
|
||||
+ bool enable)
|
||||
+{
|
||||
+ u32 val;
|
||||
+
|
||||
+ val = __raw_readl(block->en_reg[reg]);
|
||||
+ if (enable)
|
||||
+ val |= BIT(bit);
|
||||
+ else
|
||||
+ val &= ~BIT(bit);
|
||||
+ __raw_writel(val, block->en_reg[reg]);
|
||||
+}
|
||||
+
|
||||
+static void bcm6345_periph_irq_mask(struct irq_data *data)
|
||||
+{
|
||||
+ unsigned int i, reg, bit;
|
||||
+ struct intc_data *priv = data->domain->host_data;
|
||||
+ irq_hw_number_t hwirq = irqd_to_hwirq(data);
|
||||
+
|
||||
+ reg = hwirq / IRQS_PER_WORD;
|
||||
+ bit = hwirq % IRQS_PER_WORD;
|
||||
+
|
||||
+ raw_spin_lock(&priv->lock);
|
||||
+ for (i = 0; i < MAX_PARENT_IRQS; i++) {
|
||||
+ struct intc_block *block = &priv->block[i];
|
||||
+
|
||||
+ if (!block->parent_irq)
|
||||
+ break;
|
||||
+
|
||||
+ __bcm6345_periph_enable(block, reg, bit, false);
|
||||
+ }
|
||||
+ raw_spin_unlock(&priv->lock);
|
||||
+}
|
||||
+
|
||||
+static void bcm6345_periph_irq_unmask(struct irq_data *data)
|
||||
+{
|
||||
+ struct intc_data *priv = data->domain->host_data;
|
||||
+ irq_hw_number_t hwirq = irqd_to_hwirq(data);
|
||||
+ unsigned int i, reg, bit;
|
||||
+
|
||||
+ reg = hwirq / IRQS_PER_WORD;
|
||||
+ bit = hwirq % IRQS_PER_WORD;
|
||||
+
|
||||
+ raw_spin_lock(&priv->lock);
|
||||
+ for (i = 0; i < MAX_PARENT_IRQS; i++) {
|
||||
+ struct intc_block *block = &priv->block[i];
|
||||
+
|
||||
+ if (!block->parent_irq)
|
||||
+ break;
|
||||
+
|
||||
+ if (block->mask_cache[reg] & BIT(bit))
|
||||
+ __bcm6345_periph_enable(block, reg, bit, true);
|
||||
+ else
|
||||
+ __bcm6345_periph_enable(block, reg, bit, false);
|
||||
+ }
|
||||
+ raw_spin_unlock(&priv->lock);
|
||||
+}
|
||||
+
|
||||
+#ifdef CONFIG_SMP
|
||||
+static int bcm6345_periph_set_affinity(struct irq_data *data,
|
||||
+ const struct cpumask *mask, bool force)
|
||||
+{
|
||||
+ irq_hw_number_t hwirq = irqd_to_hwirq(data);
|
||||
+ struct intc_data *priv = data->domain->host_data;
|
||||
+ unsigned int i, reg, bit;
|
||||
+ unsigned long flags;
|
||||
+ bool enabled;
|
||||
+ int cpu;
|
||||
+
|
||||
+ reg = hwirq / IRQS_PER_WORD;
|
||||
+ bit = hwirq % IRQS_PER_WORD;
|
||||
+
|
||||
+ /* we could route to more than one cpu, but performance
|
||||
+ suffers, so fix it to one.
|
||||
+ */
|
||||
+ cpu = cpumask_any_and(mask, cpu_online_mask);
|
||||
+ if (cpu >= nr_cpu_ids)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ if (cpu >= MAX_PARENT_IRQS)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ if (!priv->block[cpu].parent_irq)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ raw_spin_lock_irqsave(&priv->lock, flags);
|
||||
+ enabled = !irqd_irq_masked(data);
|
||||
+ for (i = 0; i < MAX_PARENT_IRQS; i++) {
|
||||
+ struct intc_block *block = &priv->block[i];
|
||||
+
|
||||
+ if (!block->parent_irq)
|
||||
+ break;
|
||||
+
|
||||
+ if (i == cpu) {
|
||||
+ block->mask_cache[reg] |= BIT(bit);
|
||||
+ __bcm6345_periph_enable(block, reg, bit, enabled);
|
||||
+ } else {
|
||||
+ block->mask_cache[reg] &= ~BIT(bit);
|
||||
+ __bcm6345_periph_enable(block, reg, bit, false);
|
||||
+ }
|
||||
+ }
|
||||
+ raw_spin_unlock_irqrestore(&priv->lock, flags);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
+static int bcm6345_periph_map(struct irq_domain *d, unsigned int irq,
|
||||
+ irq_hw_number_t hw)
|
||||
+{
|
||||
+ struct intc_data *priv = d->host_data;
|
||||
+
|
||||
+ irq_set_chip_and_handler(irq, &priv->chip, handle_level_irq);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static const struct irq_domain_ops bcm6345_periph_domain_ops = {
|
||||
+ .xlate = irq_domain_xlate_onecell,
|
||||
+ .map = bcm6345_periph_map,
|
||||
+};
|
||||
+
|
||||
+static int __init __bcm6345_periph_intc_init(struct device_node *node,
|
||||
+ int num_blocks, int *irq,
|
||||
+ void __iomem **base, int num_words)
|
||||
+{
|
||||
+ struct intc_data *data;
|
||||
+ unsigned int i, w, status_offset;
|
||||
+
|
||||
+ data = kzalloc(sizeof(*data), GFP_KERNEL);
|
||||
+ if (!data)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ raw_spin_lock_init(&data->lock);
|
||||
+
|
||||
+ status_offset = num_words * sizeof(u32);
|
||||
+
|
||||
+ for (i = 0; i < num_blocks; i++) {
|
||||
+ struct intc_block *block = &data->block[i];
|
||||
+
|
||||
+ block->parent_irq = irq[i];
|
||||
+ block->base = base[i];
|
||||
+
|
||||
+ for (w = 0; w < num_words; w++) {
|
||||
+ int word_offset = sizeof(u32) * ((num_words - w) - 1);
|
||||
+
|
||||
+ block->en_reg[w] = base[i] + word_offset;
|
||||
+ block->status_reg[w] = base[i] + status_offset;
|
||||
+ block->status_reg[w] += word_offset;
|
||||
+
|
||||
+ /* route all interrupts to line 0 by default */
|
||||
+ if (i == 0)
|
||||
+ block->mask_cache[w] = 0xffffffff;
|
||||
+ }
|
||||
+
|
||||
+ irq_set_handler_data(block->parent_irq, data);
|
||||
+ irq_set_chained_handler(block->parent_irq,
|
||||
+ bcm6345_periph_irq_handle);
|
||||
+ }
|
||||
+
|
||||
+ data->num_words = num_words;
|
||||
+
|
||||
+ data->chip.name = "bcm6345-periph-intc";
|
||||
+ data->chip.irq_mask = bcm6345_periph_irq_mask;
|
||||
+ data->chip.irq_unmask = bcm6345_periph_irq_unmask;
|
||||
+
|
||||
+#ifdef CONFIG_SMP
|
||||
+ if (num_blocks > 1)
|
||||
+ data->chip.irq_set_affinity = bcm6345_periph_set_affinity;
|
||||
+#endif
|
||||
+
|
||||
+ data->domain = irq_domain_add_simple(node, IRQS_PER_WORD * num_words,
|
||||
+ VIRQ_BASE,
|
||||
+ &bcm6345_periph_domain_ops, data);
|
||||
+ if (!data->domain) {
|
||||
+ kfree(data);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+void __init bcm6345_periph_intc_init(int num_blocks, int *irq,
|
||||
+ void __iomem **base, int num_words)
|
||||
+{
|
||||
+ __bcm6345_periph_intc_init(NULL, num_blocks, irq, base, num_words);
|
||||
+}
|
||||
+
|
||||
+#ifdef CONFIG_OF
|
||||
+static int __init bcm6345_periph_of_init(struct device_node *node,
|
||||
+ struct device_node *parent)
|
||||
+{
|
||||
+ struct resource res;
|
||||
+ int num_irqs, ret = -EINVAL;
|
||||
+ int irqs[MAX_PARENT_IRQS] = { 0 };
|
||||
+ void __iomem *bases[MAX_PARENT_IRQS] = { NULL };
|
||||
+ int words = 0;
|
||||
+ int i;
|
||||
+
|
||||
+ num_irqs = of_irq_count(node);
|
||||
+
|
||||
+ if (num_irqs < 1 || num_irqs > MAX_PARENT_IRQS)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ for (i = 0; i < num_irqs; i++) {
|
||||
+ resource_size_t size;
|
||||
+
|
||||
+ irqs[i] = irq_of_parse_and_map(node, i);
|
||||
+ if (!irqs[i])
|
||||
+ goto out_unmap;
|
||||
+
|
||||
+ if (of_address_to_resource(node, i, &res))
|
||||
+ goto out_unmap;
|
||||
+
|
||||
+ size = resource_size(&res);
|
||||
+ switch (size) {
|
||||
+ case 8:
|
||||
+ case 16:
|
||||
+ case 32:
|
||||
+ size = size / 8;
|
||||
+ break;
|
||||
+ default:
|
||||
+ goto out_unmap;
|
||||
+ }
|
||||
+
|
||||
+ if (words && words != size) {
|
||||
+ ret = -EINVAL;
|
||||
+ goto out_unmap;
|
||||
+ }
|
||||
+ words = size;
|
||||
+
|
||||
+ bases[i] = of_iomap(node, i);
|
||||
+ if (!bases[i]) {
|
||||
+ ret = -ENOMEM;
|
||||
+ goto out_unmap;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ ret = __bcm6345_periph_intc_init(node, num_irqs, irqs, bases, words);
|
||||
+ if (!ret)
|
||||
+ return 0;
|
||||
+
|
||||
+out_unmap:
|
||||
+ for (i = 0; i < num_irqs; i++) {
|
||||
+ iounmap(bases[i]);
|
||||
+ irq_dispose_mapping(irqs[i]);
|
||||
+ }
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+IRQCHIP_DECLARE(bcm6345_periph_intc, "brcm,bcm6345-l1-intc",
|
||||
+ bcm6345_periph_of_init);
|
||||
+#endif
|
||||
--- /dev/null
|
||||
+++ b/include/linux/irqchip/irq-bcm6345-periph.h
|
||||
@@ -0,0 +1,16 @@
|
||||
+/*
|
||||
+ * This file is subject to the terms and conditions of the GNU General Public
|
||||
+ * License. See the file "COPYING" in the main directory of this archive
|
||||
+ * for more details.
|
||||
+ *
|
||||
+ * Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
|
||||
+ * Copyright (C) 2008 Nicolas Schichan <nschichan@freebox.fr>
|
||||
+ */
|
||||
+
|
||||
+#ifndef __INCLUDE_LINUX_IRQCHIP_IRQ_BCM6345_PERIPH_H
|
||||
+#define __INCLUDE_LINUX_IRQCHIP_IRQ_BCM6345_PERIPH_H
|
||||
+
|
||||
+void bcm6345_periph_intc_init(int num_blocks, int *irq, void __iomem **base,
|
||||
+ int num_words);
|
||||
+
|
||||
+#endif /* __INCLUDE_LINUX_IRQCHIP_IRQ_BCM6345_PERIPH_H */
|
@ -1,394 +0,0 @@
|
||||
From cf908990d4a8ccdb73ee4484aa8cadad379ca314 Mon Sep 17 00:00:00 2001
|
||||
From: Jonas Gorski <jogo@openwrt.org>
|
||||
Date: Sun, 30 Nov 2014 14:54:27 +0100
|
||||
Subject: [PATCH 2/5] irqchip: add support for bcm6345-style external
|
||||
interrupt controller
|
||||
|
||||
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
|
||||
---
|
||||
.../interrupt-controller/brcm,bcm6345-ext-intc.txt | 29 ++
|
||||
drivers/irqchip/Kconfig | 4 +
|
||||
drivers/irqchip/Makefile | 1 +
|
||||
drivers/irqchip/irq-bcm6345-ext.c | 287 ++++++++++++++++++++
|
||||
include/linux/irqchip/irq-bcm6345-ext.h | 14 +
|
||||
5 files changed, 335 insertions(+)
|
||||
create mode 100644 Documentation/devicetree/bindings/interrupt-controller/brcm,bcm6345-ext-intc.txt
|
||||
create mode 100644 drivers/irqchip/irq-bcm6345-ext.c
|
||||
create mode 100644 include/linux/irqchip/irq-bcm6345-ext.h
|
||||
|
||||
--- /dev/null
|
||||
+++ b/Documentation/devicetree/bindings/interrupt-controller/brcm,bcm6345-ext-intc.txt
|
||||
@@ -0,0 +1,29 @@
|
||||
+Broadcom BCM6345-style external interrupt controller
|
||||
+
|
||||
+Required properties:
|
||||
+
|
||||
+- compatible: Should be "brcm,bcm6345-ext-intc" or "brcm,bcm6318-ext-intc".
|
||||
+- reg: Specifies the base physical addresses and size of the registers.
|
||||
+- interrupt-controller: identifies the node as an interrupt controller.
|
||||
+- #interrupt-cells: Specifies the number of cells needed to encode an interrupt
|
||||
+ source, Should be 2.
|
||||
+- interrupt-parent: Specifies the phandle to the parent interrupt controller
|
||||
+ this one is cascaded from.
|
||||
+- interrupts: Specifies the interrupt line(s) in the interrupt-parent controller
|
||||
+ node, valid values depend on the type of parent interrupt controller.
|
||||
+
|
||||
+Optional properties:
|
||||
+
|
||||
+- brcm,field-width: Size of each field (mask, clear, sense, ...) in bits in the
|
||||
+ register. Defaults to 4.
|
||||
+
|
||||
+Example:
|
||||
+
|
||||
+ext_intc: interrupt-controller@10000018 {
|
||||
+ compatible = "brcm,bcm6345-ext-intc";
|
||||
+ interrupt-parent = <&periph_intc>;
|
||||
+ #interrupt-cells = <2>;
|
||||
+ reg = <0x10000018 0x4>;
|
||||
+ interrupt-controller;
|
||||
+ interrupts = <24>, <25>, <26>, <27>;
|
||||
+};
|
||||
--- a/drivers/irqchip/Kconfig
|
||||
+++ b/drivers/irqchip/Kconfig
|
||||
@@ -80,6 +80,10 @@ config BRCMSTB_L2_IRQ
|
||||
select GENERIC_IRQ_CHIP
|
||||
select IRQ_DOMAIN
|
||||
|
||||
+config BCM6345_EXT_IRQ
|
||||
+ bool
|
||||
+ select IRQ_DOMAIN
|
||||
+
|
||||
config BCM6345_PERIPH_IRQ
|
||||
bool
|
||||
select IRQ_DOMAIN
|
||||
--- a/drivers/irqchip/Makefile
|
||||
+++ b/drivers/irqchip/Makefile
|
||||
@@ -9,6 +9,7 @@ obj-$(CONFIG_ARCH_MVEBU) += irq-armada-
|
||||
obj-$(CONFIG_IRQ_MXS) += irq-mxs.o
|
||||
obj-$(CONFIG_ARCH_TEGRA) += irq-tegra.o
|
||||
obj-$(CONFIG_ARCH_S3C24XX) += irq-s3c24xx.o
|
||||
+obj-$(CONFIG_BCM6345_EXT_IRQ) += irq-bcm6345-ext.o
|
||||
obj-$(CONFIG_BCM6345_PERIPH_IRQ) += irq-bcm6345-periph.o
|
||||
obj-$(CONFIG_DW_APB_ICTL) += irq-dw-apb-ictl.o
|
||||
obj-$(CONFIG_METAG) += irq-metag-ext.o
|
||||
--- /dev/null
|
||||
+++ b/drivers/irqchip/irq-bcm6345-ext.c
|
||||
@@ -0,0 +1,301 @@
|
||||
+/*
|
||||
+ * This file is subject to the terms and conditions of the GNU General Public
|
||||
+ * License. See the file "COPYING" in the main directory of this archive
|
||||
+ * for more details.
|
||||
+ *
|
||||
+ * Copyright (C) 2014 Jonas Gorski <jogo@openwrt.org>
|
||||
+ */
|
||||
+
|
||||
+#include <linux/ioport.h>
|
||||
+#include <linux/irq.h>
|
||||
+#include <linux/irqchip.h>
|
||||
+#include <linux/irqchip/chained_irq.h>
|
||||
+#include <linux/irqchip/irq-bcm6345-ext.h>
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/of.h>
|
||||
+#include <linux/of_irq.h>
|
||||
+#include <linux/of_address.h>
|
||||
+#include <linux/slab.h>
|
||||
+#include <linux/spinlock.h>
|
||||
+
|
||||
+#ifdef CONFIG_BCM63XX
|
||||
+#include <asm/mach-bcm63xx/bcm63xx_irq.h>
|
||||
+
|
||||
+#define VIRQ_BASE IRQ_EXTERNAL_BASE
|
||||
+#else
|
||||
+#define VIRQ_BASE 0
|
||||
+#endif
|
||||
+
|
||||
+#define MAX_IRQS 4
|
||||
+
|
||||
+#define EXTIRQ_CFG_SENSE 0
|
||||
+#define EXTIRQ_CFG_STAT 1
|
||||
+#define EXTIRQ_CFG_CLEAR 2
|
||||
+#define EXTIRQ_CFG_MASK 3
|
||||
+#define EXTIRQ_CFG_BOTHEDGE 4
|
||||
+#define EXTIRQ_CFG_LEVELSENSE 5
|
||||
+
|
||||
+struct intc_data {
|
||||
+ struct irq_chip chip;
|
||||
+ struct irq_domain *domain;
|
||||
+ raw_spinlock_t lock;
|
||||
+
|
||||
+ int parent_irq[MAX_IRQS];
|
||||
+ void __iomem *reg;
|
||||
+ int shift;
|
||||
+ unsigned int toggle_clear_on_ack:1;
|
||||
+};
|
||||
+
|
||||
+static void bcm6345_ext_intc_irq_handle(struct irq_desc *desc)
|
||||
+{
|
||||
+ struct intc_data *data = irq_desc_get_handler_data(desc);
|
||||
+ struct irq_chip *chip = irq_desc_get_chip(desc);
|
||||
+ unsigned int irq = irq_desc_get_irq(desc);
|
||||
+ unsigned int idx;
|
||||
+
|
||||
+ chained_irq_enter(chip, desc);
|
||||
+
|
||||
+ for (idx = 0; idx < MAX_IRQS; idx++) {
|
||||
+ if (data->parent_irq[idx] != irq)
|
||||
+ continue;
|
||||
+
|
||||
+ generic_handle_irq(irq_find_mapping(data->domain, idx));
|
||||
+ }
|
||||
+
|
||||
+ chained_irq_exit(chip, desc);
|
||||
+}
|
||||
+
|
||||
+static void bcm6345_ext_intc_irq_ack(struct irq_data *data)
|
||||
+{
|
||||
+ struct intc_data *priv = data->domain->host_data;
|
||||
+ irq_hw_number_t hwirq = irqd_to_hwirq(data);
|
||||
+ u32 reg;
|
||||
+
|
||||
+ raw_spin_lock(&priv->lock);
|
||||
+ reg = __raw_readl(priv->reg);
|
||||
+ __raw_writel(reg | (1 << (hwirq + EXTIRQ_CFG_CLEAR * priv->shift)),
|
||||
+ priv->reg);
|
||||
+ if (priv->toggle_clear_on_ack)
|
||||
+ __raw_writel(reg, priv->reg);
|
||||
+ raw_spin_unlock(&priv->lock);
|
||||
+}
|
||||
+
|
||||
+static void bcm6345_ext_intc_irq_mask(struct irq_data *data)
|
||||
+{
|
||||
+ struct intc_data *priv = data->domain->host_data;
|
||||
+ irq_hw_number_t hwirq = irqd_to_hwirq(data);
|
||||
+ u32 reg;
|
||||
+
|
||||
+ raw_spin_lock(&priv->lock);
|
||||
+ reg = __raw_readl(priv->reg);
|
||||
+ reg &= ~(1 << (hwirq + EXTIRQ_CFG_MASK * priv->shift));
|
||||
+ __raw_writel(reg, priv->reg);
|
||||
+ raw_spin_unlock(&priv->lock);
|
||||
+}
|
||||
+
|
||||
+static void bcm6345_ext_intc_irq_unmask(struct irq_data *data)
|
||||
+{
|
||||
+ struct intc_data *priv = data->domain->host_data;
|
||||
+ irq_hw_number_t hwirq = irqd_to_hwirq(data);
|
||||
+ u32 reg;
|
||||
+
|
||||
+ raw_spin_lock(&priv->lock);
|
||||
+ reg = __raw_readl(priv->reg);
|
||||
+ reg |= 1 << (hwirq + EXTIRQ_CFG_MASK * priv->shift);
|
||||
+ __raw_writel(reg, priv->reg);
|
||||
+ raw_spin_unlock(&priv->lock);
|
||||
+}
|
||||
+
|
||||
+static int bcm6345_ext_intc_set_type(struct irq_data *data,
|
||||
+ unsigned int flow_type)
|
||||
+{
|
||||
+ struct intc_data *priv = data->domain->host_data;
|
||||
+ irq_hw_number_t hwirq = irqd_to_hwirq(data);
|
||||
+ bool levelsense = 0, sense = 0, bothedge = 0;
|
||||
+ u32 reg;
|
||||
+
|
||||
+ flow_type &= IRQ_TYPE_SENSE_MASK;
|
||||
+
|
||||
+ if (flow_type == IRQ_TYPE_NONE)
|
||||
+ flow_type = IRQ_TYPE_LEVEL_LOW;
|
||||
+
|
||||
+ switch (flow_type) {
|
||||
+ case IRQ_TYPE_EDGE_BOTH:
|
||||
+ bothedge = 1;
|
||||
+ break;
|
||||
+
|
||||
+ case IRQ_TYPE_EDGE_RISING:
|
||||
+ sense = 1;
|
||||
+ break;
|
||||
+
|
||||
+ case IRQ_TYPE_EDGE_FALLING:
|
||||
+ break;
|
||||
+
|
||||
+ case IRQ_TYPE_LEVEL_HIGH:
|
||||
+ levelsense = 1;
|
||||
+ sense = 1;
|
||||
+ break;
|
||||
+
|
||||
+ case IRQ_TYPE_LEVEL_LOW:
|
||||
+ levelsense = 1;
|
||||
+ break;
|
||||
+
|
||||
+ default:
|
||||
+ pr_err("bogus flow type combination given!\n");
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ raw_spin_lock(&priv->lock);
|
||||
+ reg = __raw_readl(priv->reg);
|
||||
+
|
||||
+ if (levelsense)
|
||||
+ reg |= 1 << (hwirq + EXTIRQ_CFG_LEVELSENSE * priv->shift);
|
||||
+ else
|
||||
+ reg &= ~(1 << (hwirq + EXTIRQ_CFG_LEVELSENSE * priv->shift));
|
||||
+ if (sense)
|
||||
+ reg |= 1 << (hwirq + EXTIRQ_CFG_SENSE * priv->shift);
|
||||
+ else
|
||||
+ reg &= ~(1 << (hwirq + EXTIRQ_CFG_SENSE * priv->shift));
|
||||
+ if (bothedge)
|
||||
+ reg |= 1 << (hwirq + EXTIRQ_CFG_BOTHEDGE * priv->shift);
|
||||
+ else
|
||||
+ reg &= ~(1 << (hwirq + EXTIRQ_CFG_BOTHEDGE * priv->shift));
|
||||
+
|
||||
+ __raw_writel(reg, priv->reg);
|
||||
+ raw_spin_unlock(&priv->lock);
|
||||
+
|
||||
+ irqd_set_trigger_type(data, flow_type);
|
||||
+ if (flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
|
||||
+ irq_set_handler_locked(data, handle_level_irq);
|
||||
+ else
|
||||
+ irq_set_handler_locked(data, handle_edge_irq);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int bcm6345_ext_intc_map(struct irq_domain *d, unsigned int irq,
|
||||
+ irq_hw_number_t hw)
|
||||
+{
|
||||
+ struct intc_data *priv = d->host_data;
|
||||
+
|
||||
+ irq_set_chip_and_handler(irq, &priv->chip, handle_level_irq);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static const struct irq_domain_ops bcm6345_ext_domain_ops = {
|
||||
+ .xlate = irq_domain_xlate_twocell,
|
||||
+ .map = bcm6345_ext_intc_map,
|
||||
+};
|
||||
+
|
||||
+static int __init __bcm6345_ext_intc_init(struct device_node *node,
|
||||
+ int num_irqs, int *irqs,
|
||||
+ void __iomem *reg, int shift,
|
||||
+ bool toggle_clear_on_ack)
|
||||
+{
|
||||
+ struct intc_data *data;
|
||||
+ unsigned int i;
|
||||
+ int start = VIRQ_BASE;
|
||||
+
|
||||
+ data = kzalloc(sizeof(*data), GFP_KERNEL);
|
||||
+ if (!data)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ raw_spin_lock_init(&data->lock);
|
||||
+
|
||||
+ for (i = 0; i < num_irqs; i++) {
|
||||
+ data->parent_irq[i] = irqs[i];
|
||||
+
|
||||
+ irq_set_handler_data(irqs[i], data);
|
||||
+ irq_set_chained_handler(irqs[i], bcm6345_ext_intc_irq_handle);
|
||||
+ }
|
||||
+
|
||||
+ data->reg = reg;
|
||||
+ data->shift = shift;
|
||||
+ data->toggle_clear_on_ack = toggle_clear_on_ack;
|
||||
+
|
||||
+ data->chip.name = "bcm6345-ext-intc";
|
||||
+ data->chip.irq_ack = bcm6345_ext_intc_irq_ack;
|
||||
+ data->chip.irq_mask = bcm6345_ext_intc_irq_mask;
|
||||
+ data->chip.irq_unmask = bcm6345_ext_intc_irq_unmask;
|
||||
+ data->chip.irq_set_type = bcm6345_ext_intc_set_type;
|
||||
+
|
||||
+ /*
|
||||
+ * If we have less than 4 irqs, this is the second controller on
|
||||
+ * bcm63xx. So increase the VIRQ start to not overlap with the first
|
||||
+ * one, but only do so if we actually use a non-zero start.
|
||||
+ *
|
||||
+ * This can be removed when bcm63xx has no legacy users anymore.
|
||||
+ */
|
||||
+ if (start && num_irqs < 4)
|
||||
+ start += 4;
|
||||
+
|
||||
+ data->domain = irq_domain_add_simple(node, num_irqs, start,
|
||||
+ &bcm6345_ext_domain_ops, data);
|
||||
+ if (!data->domain) {
|
||||
+ kfree(data);
|
||||
+ return -ENOMEM;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+void __init bcm6345_ext_intc_init(int num_irqs, int *irqs, void __iomem *reg,
|
||||
+ int shift)
|
||||
+{
|
||||
+ __bcm6345_ext_intc_init(NULL, num_irqs, irqs, reg, shift, false);
|
||||
+}
|
||||
+
|
||||
+#ifdef CONFIG_OF
|
||||
+static int __init bcm6345_ext_intc_of_init(struct device_node *node,
|
||||
+ struct device_node *parent)
|
||||
+{
|
||||
+ int num_irqs, ret = -EINVAL;
|
||||
+ unsigned i;
|
||||
+ void __iomem *base;
|
||||
+ int irqs[MAX_IRQS] = { 0 };
|
||||
+ u32 shift;
|
||||
+ bool toggle_clear_on_ack = false;
|
||||
+
|
||||
+ num_irqs = of_irq_count(node);
|
||||
+
|
||||
+ if (!num_irqs || num_irqs > MAX_IRQS)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ if (of_property_read_u32(node, "brcm,field-width", &shift))
|
||||
+ shift = 4;
|
||||
+
|
||||
+ /* on BCM6318 setting CLEAR seems to continuously mask interrupts */
|
||||
+ if (of_device_is_compatible(node, "brcm,bcm6318-ext-intc"))
|
||||
+ toggle_clear_on_ack = true;
|
||||
+
|
||||
+ for (i = 0; i < num_irqs; i++) {
|
||||
+ irqs[i] = irq_of_parse_and_map(node, i);
|
||||
+ if (!irqs[i]) {
|
||||
+ ret = -ENOMEM;
|
||||
+ goto out_unmap;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ base = of_iomap(node, 0);
|
||||
+ if (!base)
|
||||
+ goto out_unmap;
|
||||
+
|
||||
+ ret = __bcm6345_ext_intc_init(node, num_irqs, irqs, base, shift,
|
||||
+ toggle_clear_on_ack);
|
||||
+ if (!ret)
|
||||
+ return 0;
|
||||
+out_unmap:
|
||||
+ iounmap(base);
|
||||
+
|
||||
+ for (i = 0; i < num_irqs; i++)
|
||||
+ irq_dispose_mapping(irqs[i]);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+IRQCHIP_DECLARE(bcm6318_ext_intc, "brcm,bcm6318-ext-intc",
|
||||
+ bcm6345_ext_intc_of_init);
|
||||
+IRQCHIP_DECLARE(bcm6345_ext_intc, "brcm,bcm6345-ext-intc",
|
||||
+ bcm6345_ext_intc_of_init);
|
||||
+#endif
|
||||
--- /dev/null
|
||||
+++ b/include/linux/irqchip/irq-bcm6345-ext.h
|
||||
@@ -0,0 +1,14 @@
|
||||
+/*
|
||||
+ * This file is subject to the terms and conditions of the GNU General Public
|
||||
+ * License. See the file "COPYING" in the main directory of this archive
|
||||
+ * for more details.
|
||||
+ *
|
||||
+ * Copyright (C) 2014 Jonas Gorski <jogo@openwrt.org>
|
||||
+ */
|
||||
+
|
||||
+#ifndef __INCLUDE_LINUX_IRQCHIP_IRQ_BCM6345_EXT_H
|
||||
+#define __INCLUDE_LINUX_IRQCHIP_IRQ_BCM6345_EXT_H
|
||||
+
|
||||
+void bcm6345_ext_intc_init(int n_irqs, int *irqs, void __iomem *reg, int shift);
|
||||
+
|
||||
+#endif /* __INCLUDE_LINUX_IRQCHIP_IRQ_BCM6345_EXT_H */
|
@ -1,695 +0,0 @@
|
||||
From d2d2489e0a4b740abd980e9d1cad952d15bc2d9e Mon Sep 17 00:00:00 2001
|
||||
From: Jonas Gorski <jogo@openwrt.org>
|
||||
Date: Sun, 30 Nov 2014 14:55:02 +0100
|
||||
Subject: [PATCH] MIPS: BCM63XX: switch to IRQ_DOMAIN
|
||||
|
||||
Now that we have working IRQ_DOMAIN drivers for both interrupt controllers,
|
||||
switch to using them.
|
||||
|
||||
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
|
||||
---
|
||||
arch/mips/Kconfig | 3 +
|
||||
arch/mips/bcm63xx/irq.c | 612 +++++++++---------------------------------------
|
||||
2 files changed, 108 insertions(+), 507 deletions(-)
|
||||
|
||||
--- a/arch/mips/Kconfig
|
||||
+++ b/arch/mips/Kconfig
|
||||
@@ -207,6 +207,9 @@ config BCM63XX
|
||||
select SYNC_R4K
|
||||
select DMA_NONCOHERENT
|
||||
select IRQ_MIPS_CPU
|
||||
+ select BCM6345_EXT_IRQ
|
||||
+ select BCM6345_PERIPH_IRQ
|
||||
+ select IRQ_DOMAIN
|
||||
select SYS_SUPPORTS_32BIT_KERNEL
|
||||
select SYS_SUPPORTS_BIG_ENDIAN
|
||||
select SYS_HAS_EARLY_PRINTK
|
||||
--- a/arch/mips/bcm63xx/irq.c
|
||||
+++ b/arch/mips/bcm63xx/irq.c
|
||||
@@ -12,7 +12,9 @@
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/irq.h>
|
||||
-#include <linux/spinlock.h>
|
||||
+#include <linux/irqchip.h>
|
||||
+#include <linux/irqchip/irq-bcm6345-ext.h>
|
||||
+#include <linux/irqchip/irq-bcm6345-periph.h>
|
||||
#include <asm/irq_cpu.h>
|
||||
#include <asm/mipsregs.h>
|
||||
#include <bcm63xx_cpu.h>
|
||||
@@ -20,544 +22,140 @@
|
||||
#include <bcm63xx_io.h>
|
||||
#include <bcm63xx_irq.h>
|
||||
|
||||
-
|
||||
-static DEFINE_SPINLOCK(ipic_lock);
|
||||
-static DEFINE_SPINLOCK(epic_lock);
|
||||
-
|
||||
-static u32 irq_stat_addr[2];
|
||||
-static u32 irq_mask_addr[2];
|
||||
-static void (*dispatch_internal)(int cpu);
|
||||
-static int is_ext_irq_cascaded;
|
||||
-static unsigned int ext_irq_count;
|
||||
-static unsigned int ext_irq_start, ext_irq_end;
|
||||
-static unsigned int ext_irq_cfg_reg1, ext_irq_cfg_reg2;
|
||||
-static void (*internal_irq_mask)(struct irq_data *d);
|
||||
-static void (*internal_irq_unmask)(struct irq_data *d, const struct cpumask *m);
|
||||
-
|
||||
-
|
||||
-static inline u32 get_ext_irq_perf_reg(int irq)
|
||||
-{
|
||||
- if (irq < 4)
|
||||
- return ext_irq_cfg_reg1;
|
||||
- return ext_irq_cfg_reg2;
|
||||
-}
|
||||
-
|
||||
-static inline void handle_internal(int intbit)
|
||||
-{
|
||||
- if (is_ext_irq_cascaded &&
|
||||
- intbit >= ext_irq_start && intbit <= ext_irq_end)
|
||||
- do_IRQ(intbit - ext_irq_start + IRQ_EXTERNAL_BASE);
|
||||
- else
|
||||
- do_IRQ(intbit + IRQ_INTERNAL_BASE);
|
||||
-}
|
||||
-
|
||||
-static inline int enable_irq_for_cpu(int cpu, struct irq_data *d,
|
||||
- const struct cpumask *m)
|
||||
-{
|
||||
- bool enable = cpu_online(cpu);
|
||||
-
|
||||
-#ifdef CONFIG_SMP
|
||||
- if (m)
|
||||
- enable &= cpumask_test_cpu(cpu, m);
|
||||
- else if (irqd_affinity_was_set(d))
|
||||
- enable &= cpumask_test_cpu(cpu, irq_data_get_affinity_mask(d));
|
||||
-#endif
|
||||
- return enable;
|
||||
-}
|
||||
-
|
||||
-/*
|
||||
- * dispatch internal devices IRQ (uart, enet, watchdog, ...). do not
|
||||
- * prioritize any interrupt relatively to another. the static counter
|
||||
- * will resume the loop where it ended the last time we left this
|
||||
- * function.
|
||||
- */
|
||||
-
|
||||
-#define BUILD_IPIC_INTERNAL(width) \
|
||||
-void __dispatch_internal_##width(int cpu) \
|
||||
-{ \
|
||||
- u32 pending[width / 32]; \
|
||||
- unsigned int src, tgt; \
|
||||
- bool irqs_pending = false; \
|
||||
- static unsigned int i[2]; \
|
||||
- unsigned int *next = &i[cpu]; \
|
||||
- unsigned long flags; \
|
||||
- \
|
||||
- /* read registers in reverse order */ \
|
||||
- spin_lock_irqsave(&ipic_lock, flags); \
|
||||
- for (src = 0, tgt = (width / 32); src < (width / 32); src++) { \
|
||||
- u32 val; \
|
||||
- \
|
||||
- val = bcm_readl(irq_stat_addr[cpu] + src * sizeof(u32)); \
|
||||
- val &= bcm_readl(irq_mask_addr[cpu] + src * sizeof(u32)); \
|
||||
- pending[--tgt] = val; \
|
||||
- \
|
||||
- if (val) \
|
||||
- irqs_pending = true; \
|
||||
- } \
|
||||
- spin_unlock_irqrestore(&ipic_lock, flags); \
|
||||
- \
|
||||
- if (!irqs_pending) \
|
||||
- return; \
|
||||
- \
|
||||
- while (1) { \
|
||||
- unsigned int to_call = *next; \
|
||||
- \
|
||||
- *next = (*next + 1) & (width - 1); \
|
||||
- if (pending[to_call / 32] & (1 << (to_call & 0x1f))) { \
|
||||
- handle_internal(to_call); \
|
||||
- break; \
|
||||
- } \
|
||||
- } \
|
||||
-} \
|
||||
- \
|
||||
-static void __internal_irq_mask_##width(struct irq_data *d) \
|
||||
-{ \
|
||||
- u32 val; \
|
||||
- unsigned irq = d->irq - IRQ_INTERNAL_BASE; \
|
||||
- unsigned reg = (irq / 32) ^ (width/32 - 1); \
|
||||
- unsigned bit = irq & 0x1f; \
|
||||
- unsigned long flags; \
|
||||
- int cpu; \
|
||||
- \
|
||||
- spin_lock_irqsave(&ipic_lock, flags); \
|
||||
- for_each_present_cpu(cpu) { \
|
||||
- if (!irq_mask_addr[cpu]) \
|
||||
- break; \
|
||||
- \
|
||||
- val = bcm_readl(irq_mask_addr[cpu] + reg * sizeof(u32));\
|
||||
- val &= ~(1 << bit); \
|
||||
- bcm_writel(val, irq_mask_addr[cpu] + reg * sizeof(u32));\
|
||||
- } \
|
||||
- spin_unlock_irqrestore(&ipic_lock, flags); \
|
||||
-} \
|
||||
- \
|
||||
-static void __internal_irq_unmask_##width(struct irq_data *d, \
|
||||
- const struct cpumask *m) \
|
||||
-{ \
|
||||
- u32 val; \
|
||||
- unsigned irq = d->irq - IRQ_INTERNAL_BASE; \
|
||||
- unsigned reg = (irq / 32) ^ (width/32 - 1); \
|
||||
- unsigned bit = irq & 0x1f; \
|
||||
- unsigned long flags; \
|
||||
- int cpu; \
|
||||
- \
|
||||
- spin_lock_irqsave(&ipic_lock, flags); \
|
||||
- for_each_present_cpu(cpu) { \
|
||||
- if (!irq_mask_addr[cpu]) \
|
||||
- break; \
|
||||
- \
|
||||
- val = bcm_readl(irq_mask_addr[cpu] + reg * sizeof(u32));\
|
||||
- if (enable_irq_for_cpu(cpu, d, m)) \
|
||||
- val |= (1 << bit); \
|
||||
- else \
|
||||
- val &= ~(1 << bit); \
|
||||
- bcm_writel(val, irq_mask_addr[cpu] + reg * sizeof(u32));\
|
||||
- } \
|
||||
- spin_unlock_irqrestore(&ipic_lock, flags); \
|
||||
-}
|
||||
-
|
||||
-BUILD_IPIC_INTERNAL(32);
|
||||
-BUILD_IPIC_INTERNAL(64);
|
||||
-
|
||||
-asmlinkage void plat_irq_dispatch(void)
|
||||
-{
|
||||
- u32 cause;
|
||||
-
|
||||
- do {
|
||||
- cause = read_c0_cause() & read_c0_status() & ST0_IM;
|
||||
-
|
||||
- if (!cause)
|
||||
- break;
|
||||
-
|
||||
- if (cause & CAUSEF_IP7)
|
||||
- do_IRQ(7);
|
||||
- if (cause & CAUSEF_IP0)
|
||||
- do_IRQ(0);
|
||||
- if (cause & CAUSEF_IP1)
|
||||
- do_IRQ(1);
|
||||
- if (cause & CAUSEF_IP2)
|
||||
- dispatch_internal(0);
|
||||
- if (is_ext_irq_cascaded) {
|
||||
- if (cause & CAUSEF_IP3)
|
||||
- dispatch_internal(1);
|
||||
- } else {
|
||||
- if (cause & CAUSEF_IP3)
|
||||
- do_IRQ(IRQ_EXT_0);
|
||||
- if (cause & CAUSEF_IP4)
|
||||
- do_IRQ(IRQ_EXT_1);
|
||||
- if (cause & CAUSEF_IP5)
|
||||
- do_IRQ(IRQ_EXT_2);
|
||||
- if (cause & CAUSEF_IP6)
|
||||
- do_IRQ(IRQ_EXT_3);
|
||||
- }
|
||||
- } while (1);
|
||||
-}
|
||||
-
|
||||
-/*
|
||||
- * internal IRQs operations: only mask/unmask on PERF irq mask
|
||||
- * register.
|
||||
- */
|
||||
-static void bcm63xx_internal_irq_mask(struct irq_data *d)
|
||||
-{
|
||||
- internal_irq_mask(d);
|
||||
-}
|
||||
-
|
||||
-static void bcm63xx_internal_irq_unmask(struct irq_data *d)
|
||||
-{
|
||||
- internal_irq_unmask(d, NULL);
|
||||
-}
|
||||
-
|
||||
-/*
|
||||
- * external IRQs operations: mask/unmask and clear on PERF external
|
||||
- * irq control register.
|
||||
- */
|
||||
-static void bcm63xx_external_irq_mask(struct irq_data *d)
|
||||
-{
|
||||
- unsigned int irq = d->irq - IRQ_EXTERNAL_BASE;
|
||||
- u32 reg, regaddr;
|
||||
- unsigned long flags;
|
||||
-
|
||||
- regaddr = get_ext_irq_perf_reg(irq);
|
||||
- spin_lock_irqsave(&epic_lock, flags);
|
||||
- reg = bcm_perf_readl(regaddr);
|
||||
-
|
||||
- if (BCMCPU_IS_6348())
|
||||
- reg &= ~EXTIRQ_CFG_MASK_6348(irq % 4);
|
||||
- else
|
||||
- reg &= ~EXTIRQ_CFG_MASK(irq % 4);
|
||||
-
|
||||
- bcm_perf_writel(reg, regaddr);
|
||||
- spin_unlock_irqrestore(&epic_lock, flags);
|
||||
-
|
||||
- if (is_ext_irq_cascaded)
|
||||
- internal_irq_mask(irq_get_irq_data(irq + ext_irq_start));
|
||||
-}
|
||||
-
|
||||
-static void bcm63xx_external_irq_unmask(struct irq_data *d)
|
||||
-{
|
||||
- unsigned int irq = d->irq - IRQ_EXTERNAL_BASE;
|
||||
- u32 reg, regaddr;
|
||||
- unsigned long flags;
|
||||
-
|
||||
- regaddr = get_ext_irq_perf_reg(irq);
|
||||
- spin_lock_irqsave(&epic_lock, flags);
|
||||
- reg = bcm_perf_readl(regaddr);
|
||||
-
|
||||
- if (BCMCPU_IS_6348())
|
||||
- reg |= EXTIRQ_CFG_MASK_6348(irq % 4);
|
||||
- else
|
||||
- reg |= EXTIRQ_CFG_MASK(irq % 4);
|
||||
-
|
||||
- bcm_perf_writel(reg, regaddr);
|
||||
- spin_unlock_irqrestore(&epic_lock, flags);
|
||||
-
|
||||
- if (is_ext_irq_cascaded)
|
||||
- internal_irq_unmask(irq_get_irq_data(irq + ext_irq_start),
|
||||
- NULL);
|
||||
-}
|
||||
-
|
||||
-static void bcm63xx_external_irq_clear(struct irq_data *d)
|
||||
-{
|
||||
- unsigned int irq = d->irq - IRQ_EXTERNAL_BASE;
|
||||
- u32 reg, regaddr;
|
||||
- unsigned long flags;
|
||||
-
|
||||
- regaddr = get_ext_irq_perf_reg(irq);
|
||||
- spin_lock_irqsave(&epic_lock, flags);
|
||||
- reg = bcm_perf_readl(regaddr);
|
||||
-
|
||||
- if (BCMCPU_IS_6348())
|
||||
- reg |= EXTIRQ_CFG_CLEAR_6348(irq % 4);
|
||||
- else
|
||||
- reg |= EXTIRQ_CFG_CLEAR(irq % 4);
|
||||
-
|
||||
- bcm_perf_writel(reg, regaddr);
|
||||
- spin_unlock_irqrestore(&epic_lock, flags);
|
||||
-}
|
||||
-
|
||||
-static int bcm63xx_external_irq_set_type(struct irq_data *d,
|
||||
- unsigned int flow_type)
|
||||
-{
|
||||
- unsigned int irq = d->irq - IRQ_EXTERNAL_BASE;
|
||||
- u32 reg, regaddr;
|
||||
- int levelsense, sense, bothedge;
|
||||
- unsigned long flags;
|
||||
-
|
||||
- flow_type &= IRQ_TYPE_SENSE_MASK;
|
||||
-
|
||||
- if (flow_type == IRQ_TYPE_NONE)
|
||||
- flow_type = IRQ_TYPE_LEVEL_LOW;
|
||||
-
|
||||
- levelsense = sense = bothedge = 0;
|
||||
- switch (flow_type) {
|
||||
- case IRQ_TYPE_EDGE_BOTH:
|
||||
- bothedge = 1;
|
||||
- break;
|
||||
-
|
||||
- case IRQ_TYPE_EDGE_RISING:
|
||||
- sense = 1;
|
||||
- break;
|
||||
-
|
||||
- case IRQ_TYPE_EDGE_FALLING:
|
||||
- break;
|
||||
-
|
||||
- case IRQ_TYPE_LEVEL_HIGH:
|
||||
- levelsense = 1;
|
||||
- sense = 1;
|
||||
- break;
|
||||
-
|
||||
- case IRQ_TYPE_LEVEL_LOW:
|
||||
- levelsense = 1;
|
||||
- break;
|
||||
-
|
||||
- default:
|
||||
- pr_err("bogus flow type combination given !\n");
|
||||
- return -EINVAL;
|
||||
- }
|
||||
-
|
||||
- regaddr = get_ext_irq_perf_reg(irq);
|
||||
- spin_lock_irqsave(&epic_lock, flags);
|
||||
- reg = bcm_perf_readl(regaddr);
|
||||
- irq %= 4;
|
||||
-
|
||||
- switch (bcm63xx_get_cpu_id()) {
|
||||
- case BCM6348_CPU_ID:
|
||||
- if (levelsense)
|
||||
- reg |= EXTIRQ_CFG_LEVELSENSE_6348(irq);
|
||||
- else
|
||||
- reg &= ~EXTIRQ_CFG_LEVELSENSE_6348(irq);
|
||||
- if (sense)
|
||||
- reg |= EXTIRQ_CFG_SENSE_6348(irq);
|
||||
- else
|
||||
- reg &= ~EXTIRQ_CFG_SENSE_6348(irq);
|
||||
- if (bothedge)
|
||||
- reg |= EXTIRQ_CFG_BOTHEDGE_6348(irq);
|
||||
- else
|
||||
- reg &= ~EXTIRQ_CFG_BOTHEDGE_6348(irq);
|
||||
- break;
|
||||
-
|
||||
- case BCM3368_CPU_ID:
|
||||
- case BCM6328_CPU_ID:
|
||||
- case BCM6338_CPU_ID:
|
||||
- case BCM6345_CPU_ID:
|
||||
- case BCM6358_CPU_ID:
|
||||
- case BCM6362_CPU_ID:
|
||||
- case BCM6368_CPU_ID:
|
||||
- if (levelsense)
|
||||
- reg |= EXTIRQ_CFG_LEVELSENSE(irq);
|
||||
- else
|
||||
- reg &= ~EXTIRQ_CFG_LEVELSENSE(irq);
|
||||
- if (sense)
|
||||
- reg |= EXTIRQ_CFG_SENSE(irq);
|
||||
- else
|
||||
- reg &= ~EXTIRQ_CFG_SENSE(irq);
|
||||
- if (bothedge)
|
||||
- reg |= EXTIRQ_CFG_BOTHEDGE(irq);
|
||||
- else
|
||||
- reg &= ~EXTIRQ_CFG_BOTHEDGE(irq);
|
||||
- break;
|
||||
- default:
|
||||
- BUG();
|
||||
- }
|
||||
-
|
||||
- bcm_perf_writel(reg, regaddr);
|
||||
- spin_unlock_irqrestore(&epic_lock, flags);
|
||||
-
|
||||
- irqd_set_trigger_type(d, flow_type);
|
||||
- if (flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
|
||||
- irq_set_handler_locked(d, handle_level_irq);
|
||||
- else
|
||||
- irq_set_handler_locked(d, handle_edge_irq);
|
||||
-
|
||||
- return IRQ_SET_MASK_OK_NOCOPY;
|
||||
-}
|
||||
-
|
||||
-#ifdef CONFIG_SMP
|
||||
-static int bcm63xx_internal_set_affinity(struct irq_data *data,
|
||||
- const struct cpumask *dest,
|
||||
- bool force)
|
||||
-{
|
||||
- if (!irqd_irq_disabled(data))
|
||||
- internal_irq_unmask(data, dest);
|
||||
-
|
||||
- return 0;
|
||||
-}
|
||||
-#endif
|
||||
-
|
||||
-static struct irq_chip bcm63xx_internal_irq_chip = {
|
||||
- .name = "bcm63xx_ipic",
|
||||
- .irq_mask = bcm63xx_internal_irq_mask,
|
||||
- .irq_unmask = bcm63xx_internal_irq_unmask,
|
||||
-};
|
||||
-
|
||||
-static struct irq_chip bcm63xx_external_irq_chip = {
|
||||
- .name = "bcm63xx_epic",
|
||||
- .irq_ack = bcm63xx_external_irq_clear,
|
||||
-
|
||||
- .irq_mask = bcm63xx_external_irq_mask,
|
||||
- .irq_unmask = bcm63xx_external_irq_unmask,
|
||||
-
|
||||
- .irq_set_type = bcm63xx_external_irq_set_type,
|
||||
-};
|
||||
-
|
||||
-static struct irqaction cpu_ip2_cascade_action = {
|
||||
- .handler = no_action,
|
||||
- .name = "cascade_ip2",
|
||||
- .flags = IRQF_NO_THREAD,
|
||||
-};
|
||||
-
|
||||
-#ifdef CONFIG_SMP
|
||||
-static struct irqaction cpu_ip3_cascade_action = {
|
||||
- .handler = no_action,
|
||||
- .name = "cascade_ip3",
|
||||
- .flags = IRQF_NO_THREAD,
|
||||
-};
|
||||
-#endif
|
||||
-
|
||||
-static struct irqaction cpu_ext_cascade_action = {
|
||||
- .handler = no_action,
|
||||
- .name = "cascade_extirq",
|
||||
- .flags = IRQF_NO_THREAD,
|
||||
-};
|
||||
-
|
||||
-static void bcm63xx_init_irq(void)
|
||||
+void __init arch_init_irq(void)
|
||||
{
|
||||
- int irq_bits;
|
||||
-
|
||||
- irq_stat_addr[0] = bcm63xx_regset_address(RSET_PERF);
|
||||
- irq_mask_addr[0] = bcm63xx_regset_address(RSET_PERF);
|
||||
- irq_stat_addr[1] = bcm63xx_regset_address(RSET_PERF);
|
||||
- irq_mask_addr[1] = bcm63xx_regset_address(RSET_PERF);
|
||||
+ void __iomem *periph_bases[2];
|
||||
+ void __iomem *ext_intc_bases[2];
|
||||
+ int periph_irq_count, periph_width, ext_irq_count, ext_shift;
|
||||
+ int periph_irqs[2] = { 2, 3 };
|
||||
+ int ext_irqs[6];
|
||||
+
|
||||
+ periph_bases[0] = (void __iomem *)bcm63xx_regset_address(RSET_PERF);
|
||||
+ periph_bases[1] = (void __iomem *)bcm63xx_regset_address(RSET_PERF);
|
||||
+ ext_intc_bases[0] = (void __iomem *)bcm63xx_regset_address(RSET_PERF);
|
||||
+ ext_intc_bases[1] = (void __iomem *)bcm63xx_regset_address(RSET_PERF);
|
||||
|
||||
switch (bcm63xx_get_cpu_id()) {
|
||||
case BCM3368_CPU_ID:
|
||||
- irq_stat_addr[0] += PERF_IRQSTAT_3368_REG;
|
||||
- irq_mask_addr[0] += PERF_IRQMASK_3368_REG;
|
||||
- irq_stat_addr[1] = 0;
|
||||
- irq_mask_addr[1] = 0;
|
||||
- irq_bits = 32;
|
||||
- ext_irq_count = 4;
|
||||
- ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_3368;
|
||||
+ periph_bases[0] += PERF_IRQMASK_3368_REG;
|
||||
+ periph_irq_count = 1;
|
||||
+ periph_width = 1;
|
||||
+
|
||||
+ ext_intc_bases[0] += PERF_EXTIRQ_CFG_REG_3368;
|
||||
+ ext_irq_count = 4;
|
||||
+ ext_irqs[0] = BCM_3368_EXT_IRQ0;
|
||||
+ ext_irqs[1] = BCM_3368_EXT_IRQ1;
|
||||
+ ext_irqs[2] = BCM_3368_EXT_IRQ2;
|
||||
+ ext_irqs[3] = BCM_3368_EXT_IRQ3;
|
||||
+ ext_shift = 4;
|
||||
break;
|
||||
case BCM6328_CPU_ID:
|
||||
- irq_stat_addr[0] += PERF_IRQSTAT_6328_REG(0);
|
||||
- irq_mask_addr[0] += PERF_IRQMASK_6328_REG(0);
|
||||
- irq_stat_addr[1] += PERF_IRQSTAT_6328_REG(1);
|
||||
- irq_mask_addr[1] += PERF_IRQMASK_6328_REG(1);
|
||||
- irq_bits = 64;
|
||||
- ext_irq_count = 4;
|
||||
- is_ext_irq_cascaded = 1;
|
||||
- ext_irq_start = BCM_6328_EXT_IRQ0 - IRQ_INTERNAL_BASE;
|
||||
- ext_irq_end = BCM_6328_EXT_IRQ3 - IRQ_INTERNAL_BASE;
|
||||
- ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6328;
|
||||
+ periph_bases[0] += PERF_IRQMASK_6328_REG(0);
|
||||
+ periph_bases[1] += PERF_IRQMASK_6328_REG(1);
|
||||
+ periph_irq_count = 2;
|
||||
+ periph_width = 2;
|
||||
+
|
||||
+ ext_intc_bases[0] += PERF_EXTIRQ_CFG_REG_6328;
|
||||
+ ext_irq_count = 4;
|
||||
+ ext_irqs[0] = BCM_6328_EXT_IRQ0;
|
||||
+ ext_irqs[1] = BCM_6328_EXT_IRQ1;
|
||||
+ ext_irqs[2] = BCM_6328_EXT_IRQ2;
|
||||
+ ext_irqs[3] = BCM_6328_EXT_IRQ3;
|
||||
+ ext_shift = 4;
|
||||
break;
|
||||
case BCM6338_CPU_ID:
|
||||
- irq_stat_addr[0] += PERF_IRQSTAT_6338_REG;
|
||||
- irq_mask_addr[0] += PERF_IRQMASK_6338_REG;
|
||||
- irq_stat_addr[1] = 0;
|
||||
- irq_mask_addr[1] = 0;
|
||||
- irq_bits = 32;
|
||||
- ext_irq_count = 4;
|
||||
- ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6338;
|
||||
+ periph_bases[0] += PERF_IRQMASK_6338_REG;
|
||||
+ periph_irq_count = 1;
|
||||
+ periph_width = 1;
|
||||
+
|
||||
+ ext_intc_bases[0] += PERF_EXTIRQ_CFG_REG_6338;
|
||||
+ ext_irq_count = 4;
|
||||
+ ext_irqs[0] = 3;
|
||||
+ ext_irqs[1] = 4;
|
||||
+ ext_irqs[2] = 5;
|
||||
+ ext_irqs[3] = 6;
|
||||
+ ext_shift = 4;
|
||||
break;
|
||||
case BCM6345_CPU_ID:
|
||||
- irq_stat_addr[0] += PERF_IRQSTAT_6345_REG;
|
||||
- irq_mask_addr[0] += PERF_IRQMASK_6345_REG;
|
||||
- irq_stat_addr[1] = 0;
|
||||
- irq_mask_addr[1] = 0;
|
||||
- irq_bits = 32;
|
||||
- ext_irq_count = 4;
|
||||
- ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6345;
|
||||
+ periph_bases[0] += PERF_IRQMASK_6345_REG;
|
||||
+ periph_irq_count = 1;
|
||||
+ periph_width = 1;
|
||||
+
|
||||
+ ext_intc_bases[0] += PERF_EXTIRQ_CFG_REG_6345;
|
||||
+ ext_irq_count = 4;
|
||||
+ ext_irqs[0] = 3;
|
||||
+ ext_irqs[1] = 4;
|
||||
+ ext_irqs[2] = 5;
|
||||
+ ext_irqs[3] = 6;
|
||||
+ ext_shift = 4;
|
||||
break;
|
||||
case BCM6348_CPU_ID:
|
||||
- irq_stat_addr[0] += PERF_IRQSTAT_6348_REG;
|
||||
- irq_mask_addr[0] += PERF_IRQMASK_6348_REG;
|
||||
- irq_stat_addr[1] = 0;
|
||||
- irq_mask_addr[1] = 0;
|
||||
- irq_bits = 32;
|
||||
- ext_irq_count = 4;
|
||||
- ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6348;
|
||||
+ periph_bases[0] += PERF_IRQMASK_6348_REG;
|
||||
+ periph_irq_count = 1;
|
||||
+ periph_width = 1;
|
||||
+
|
||||
+ ext_intc_bases[0] += PERF_EXTIRQ_CFG_REG_6348;
|
||||
+ ext_irq_count = 4;
|
||||
+ ext_irqs[0] = 3;
|
||||
+ ext_irqs[1] = 4;
|
||||
+ ext_irqs[2] = 5;
|
||||
+ ext_irqs[3] = 6;
|
||||
+ ext_shift = 5;
|
||||
break;
|
||||
case BCM6358_CPU_ID:
|
||||
- irq_stat_addr[0] += PERF_IRQSTAT_6358_REG(0);
|
||||
- irq_mask_addr[0] += PERF_IRQMASK_6358_REG(0);
|
||||
- irq_stat_addr[1] += PERF_IRQSTAT_6358_REG(1);
|
||||
- irq_mask_addr[1] += PERF_IRQMASK_6358_REG(1);
|
||||
- irq_bits = 32;
|
||||
- ext_irq_count = 4;
|
||||
- is_ext_irq_cascaded = 1;
|
||||
- ext_irq_start = BCM_6358_EXT_IRQ0 - IRQ_INTERNAL_BASE;
|
||||
- ext_irq_end = BCM_6358_EXT_IRQ3 - IRQ_INTERNAL_BASE;
|
||||
- ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6358;
|
||||
+ periph_bases[0] += PERF_IRQMASK_6358_REG(0);
|
||||
+ periph_bases[1] += PERF_IRQMASK_6358_REG(1);
|
||||
+ periph_irq_count = 2;
|
||||
+ periph_width = 1;
|
||||
+
|
||||
+ ext_intc_bases[0] += PERF_EXTIRQ_CFG_REG_6358;
|
||||
+ ext_irq_count = 4;
|
||||
+ ext_irqs[0] = BCM_6358_EXT_IRQ0;
|
||||
+ ext_irqs[1] = BCM_6358_EXT_IRQ1;
|
||||
+ ext_irqs[2] = BCM_6358_EXT_IRQ2;
|
||||
+ ext_irqs[3] = BCM_6358_EXT_IRQ3;
|
||||
+ ext_shift = 4;
|
||||
break;
|
||||
case BCM6362_CPU_ID:
|
||||
- irq_stat_addr[0] += PERF_IRQSTAT_6362_REG(0);
|
||||
- irq_mask_addr[0] += PERF_IRQMASK_6362_REG(0);
|
||||
- irq_stat_addr[1] += PERF_IRQSTAT_6362_REG(1);
|
||||
- irq_mask_addr[1] += PERF_IRQMASK_6362_REG(1);
|
||||
- irq_bits = 64;
|
||||
- ext_irq_count = 4;
|
||||
- is_ext_irq_cascaded = 1;
|
||||
- ext_irq_start = BCM_6362_EXT_IRQ0 - IRQ_INTERNAL_BASE;
|
||||
- ext_irq_end = BCM_6362_EXT_IRQ3 - IRQ_INTERNAL_BASE;
|
||||
- ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6362;
|
||||
+ periph_bases[0] += PERF_IRQMASK_6362_REG(0);
|
||||
+ periph_bases[1] += PERF_IRQMASK_6362_REG(1);
|
||||
+ periph_irq_count = 2;
|
||||
+ periph_width = 2;
|
||||
+
|
||||
+ ext_intc_bases[0] += PERF_EXTIRQ_CFG_REG_6362;
|
||||
+ ext_irq_count = 4;
|
||||
+ ext_irqs[0] = BCM_6362_EXT_IRQ0;
|
||||
+ ext_irqs[1] = BCM_6362_EXT_IRQ1;
|
||||
+ ext_irqs[2] = BCM_6362_EXT_IRQ2;
|
||||
+ ext_irqs[3] = BCM_6362_EXT_IRQ3;
|
||||
+ ext_shift = 4;
|
||||
break;
|
||||
case BCM6368_CPU_ID:
|
||||
- irq_stat_addr[0] += PERF_IRQSTAT_6368_REG(0);
|
||||
- irq_mask_addr[0] += PERF_IRQMASK_6368_REG(0);
|
||||
- irq_stat_addr[1] += PERF_IRQSTAT_6368_REG(1);
|
||||
- irq_mask_addr[1] += PERF_IRQMASK_6368_REG(1);
|
||||
- irq_bits = 64;
|
||||
+ periph_bases[0] += PERF_IRQMASK_6368_REG(0);
|
||||
+ periph_bases[1] += PERF_IRQMASK_6368_REG(1);
|
||||
+ periph_irq_count = 2;
|
||||
+ periph_width = 2;
|
||||
+
|
||||
+ ext_intc_bases[0] += PERF_EXTIRQ_CFG_REG_6368;
|
||||
+ ext_intc_bases[1] += PERF_EXTIRQ_CFG_REG2_6368;
|
||||
ext_irq_count = 6;
|
||||
- is_ext_irq_cascaded = 1;
|
||||
- ext_irq_start = BCM_6368_EXT_IRQ0 - IRQ_INTERNAL_BASE;
|
||||
- ext_irq_end = BCM_6368_EXT_IRQ5 - IRQ_INTERNAL_BASE;
|
||||
- ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6368;
|
||||
- ext_irq_cfg_reg2 = PERF_EXTIRQ_CFG_REG2_6368;
|
||||
+ ext_irqs[0] = BCM_6368_EXT_IRQ0;
|
||||
+ ext_irqs[1] = BCM_6368_EXT_IRQ1;
|
||||
+ ext_irqs[2] = BCM_6368_EXT_IRQ2;
|
||||
+ ext_irqs[3] = BCM_6368_EXT_IRQ3;
|
||||
+ ext_irqs[4] = BCM_6368_EXT_IRQ4;
|
||||
+ ext_irqs[5] = BCM_6368_EXT_IRQ5;
|
||||
+ ext_shift = 4;
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
|
||||
- if (irq_bits == 32) {
|
||||
- dispatch_internal = __dispatch_internal_32;
|
||||
- internal_irq_mask = __internal_irq_mask_32;
|
||||
- internal_irq_unmask = __internal_irq_unmask_32;
|
||||
- } else {
|
||||
- dispatch_internal = __dispatch_internal_64;
|
||||
- internal_irq_mask = __internal_irq_mask_64;
|
||||
- internal_irq_unmask = __internal_irq_unmask_64;
|
||||
- }
|
||||
-}
|
||||
-
|
||||
-void __init arch_init_irq(void)
|
||||
-{
|
||||
- int i;
|
||||
-
|
||||
- bcm63xx_init_irq();
|
||||
mips_cpu_irq_init();
|
||||
- for (i = IRQ_INTERNAL_BASE; i < NR_IRQS; ++i)
|
||||
- irq_set_chip_and_handler(i, &bcm63xx_internal_irq_chip,
|
||||
- handle_level_irq);
|
||||
-
|
||||
- for (i = IRQ_EXTERNAL_BASE; i < IRQ_EXTERNAL_BASE + ext_irq_count; ++i)
|
||||
- irq_set_chip_and_handler(i, &bcm63xx_external_irq_chip,
|
||||
- handle_edge_irq);
|
||||
-
|
||||
- if (!is_ext_irq_cascaded) {
|
||||
- for (i = 3; i < 3 + ext_irq_count; ++i)
|
||||
- setup_irq(MIPS_CPU_IRQ_BASE + i, &cpu_ext_cascade_action);
|
||||
- }
|
||||
-
|
||||
- setup_irq(MIPS_CPU_IRQ_BASE + 2, &cpu_ip2_cascade_action);
|
||||
-#ifdef CONFIG_SMP
|
||||
- if (is_ext_irq_cascaded) {
|
||||
- setup_irq(MIPS_CPU_IRQ_BASE + 3, &cpu_ip3_cascade_action);
|
||||
- bcm63xx_internal_irq_chip.irq_set_affinity =
|
||||
- bcm63xx_internal_set_affinity;
|
||||
-
|
||||
- cpumask_clear(irq_default_affinity);
|
||||
- cpumask_set_cpu(smp_processor_id(), irq_default_affinity);
|
||||
- }
|
||||
-#endif
|
||||
+ bcm6345_periph_intc_init(periph_irq_count, periph_irqs, periph_bases,
|
||||
+ periph_width);
|
||||
+ bcm6345_ext_intc_init(4, ext_irqs, ext_intc_bases[0], ext_shift);
|
||||
+ if (ext_irq_count > 4)
|
||||
+ bcm6345_ext_intc_init(2, &ext_irqs[4], ext_intc_bases[1],
|
||||
+ ext_shift);
|
||||
}
|
@ -1,57 +0,0 @@
|
||||
From 4fd286c3e5a5bebab0391cf1937695b3ed6721a3 Mon Sep 17 00:00:00 2001
|
||||
From: Jonas Gorski <jogo@openwrt.org>
|
||||
Date: Sun, 30 Nov 2014 20:20:30 +0100
|
||||
Subject: [PATCH 4/5] MIPS: BCM63XX: wire up BCM6358's external interrupts 4
|
||||
and 5
|
||||
|
||||
Due to the external interrupts being non consecutive, the previous
|
||||
implementation did not support them. Now that we treat both registers
|
||||
as separate irq controllers, there is no such limitation anymore and
|
||||
we can expose them for drivers to use.
|
||||
|
||||
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
|
||||
---
|
||||
arch/mips/bcm63xx/irq.c | 5 ++++-
|
||||
arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h | 2 ++
|
||||
arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h | 1 +
|
||||
3 files changed, 7 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/arch/mips/bcm63xx/irq.c
|
||||
+++ b/arch/mips/bcm63xx/irq.c
|
||||
@@ -109,11 +109,14 @@ void __init arch_init_irq(void)
|
||||
periph_width = 1;
|
||||
|
||||
ext_intc_bases[0] += PERF_EXTIRQ_CFG_REG_6358;
|
||||
- ext_irq_count = 4;
|
||||
+ ext_intc_bases[1] += PERF_EXTIRQ_CFG_REG2_6358;
|
||||
+ ext_irq_count = 6;
|
||||
ext_irqs[0] = BCM_6358_EXT_IRQ0;
|
||||
ext_irqs[1] = BCM_6358_EXT_IRQ1;
|
||||
ext_irqs[2] = BCM_6358_EXT_IRQ2;
|
||||
ext_irqs[3] = BCM_6358_EXT_IRQ3;
|
||||
+ ext_irqs[4] = BCM_6358_EXT_IRQ4;
|
||||
+ ext_irqs[5] = BCM_6358_EXT_IRQ5;
|
||||
ext_shift = 4;
|
||||
break;
|
||||
case BCM6362_CPU_ID:
|
||||
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h
|
||||
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h
|
||||
@@ -895,6 +895,8 @@ enum bcm63xx_irq {
|
||||
#define BCM_6358_EXT_IRQ1 (IRQ_INTERNAL_BASE + 26)
|
||||
#define BCM_6358_EXT_IRQ2 (IRQ_INTERNAL_BASE + 27)
|
||||
#define BCM_6358_EXT_IRQ3 (IRQ_INTERNAL_BASE + 28)
|
||||
+#define BCM_6358_EXT_IRQ4 (IRQ_INTERNAL_BASE + 20)
|
||||
+#define BCM_6358_EXT_IRQ5 (IRQ_INTERNAL_BASE + 21)
|
||||
|
||||
/*
|
||||
* 6362 irqs
|
||||
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
|
||||
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
|
||||
@@ -243,6 +243,7 @@
|
||||
#define PERF_EXTIRQ_CFG_REG_6362 0x18
|
||||
#define PERF_EXTIRQ_CFG_REG_6368 0x18
|
||||
|
||||
+#define PERF_EXTIRQ_CFG_REG2_6358 0x1c
|
||||
#define PERF_EXTIRQ_CFG_REG2_6368 0x1c
|
||||
|
||||
/* for 6348 only */
|
@ -1,77 +0,0 @@
|
||||
From c50acd37b425a8a907a6f7f93aa2e658256e79ce Mon Sep 17 00:00:00 2001
|
||||
From: Jonas Gorski <jogo@openwrt.org>
|
||||
Date: Sat, 7 Dec 2013 14:08:36 +0100
|
||||
Subject: [PATCH 40/53] MIPS: BCM63XX: add a new cpu variant helper
|
||||
|
||||
---
|
||||
arch/mips/bcm63xx/cpu.c | 10 ++++++++++
|
||||
arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h | 18 ++++++++++++++++++
|
||||
2 files changed, 28 insertions(+)
|
||||
|
||||
--- a/arch/mips/bcm63xx/cpu.c
|
||||
+++ b/arch/mips/bcm63xx/cpu.c
|
||||
@@ -27,6 +27,8 @@ EXPORT_SYMBOL(bcm63xx_irqs);
|
||||
u16 bcm63xx_cpu_id __read_mostly;
|
||||
EXPORT_SYMBOL(bcm63xx_cpu_id);
|
||||
|
||||
+static u32 bcm63xx_cpu_variant __read_mostly;
|
||||
+
|
||||
static u8 bcm63xx_cpu_rev;
|
||||
static unsigned int bcm63xx_cpu_freq;
|
||||
static unsigned int bcm63xx_memory_size;
|
||||
@@ -99,6 +101,13 @@ static const int bcm6368_irqs[] = {
|
||||
|
||||
};
|
||||
|
||||
+u32 bcm63xx_get_cpu_variant(void)
|
||||
+{
|
||||
+ return bcm63xx_cpu_variant;
|
||||
+}
|
||||
+
|
||||
+EXPORT_SYMBOL(bcm63xx_get_cpu_variant);
|
||||
+
|
||||
u8 bcm63xx_get_cpu_rev(void)
|
||||
{
|
||||
return bcm63xx_cpu_rev;
|
||||
@@ -333,6 +342,7 @@ void __init bcm63xx_cpu_init(void)
|
||||
/* read out CPU type */
|
||||
tmp = bcm_readl(chipid_reg);
|
||||
bcm63xx_cpu_id = (tmp & REV_CHIPID_MASK) >> REV_CHIPID_SHIFT;
|
||||
+ bcm63xx_cpu_variant = bcm63xx_cpu_id;
|
||||
bcm63xx_cpu_rev = (tmp & REV_REVID_MASK) >> REV_REVID_SHIFT;
|
||||
|
||||
switch (bcm63xx_cpu_id) {
|
||||
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h
|
||||
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h
|
||||
@@ -19,6 +19,7 @@
|
||||
#define BCM6368_CPU_ID 0x6368
|
||||
|
||||
void __init bcm63xx_cpu_init(void);
|
||||
+u32 bcm63xx_get_cpu_variant(void);
|
||||
u8 bcm63xx_get_cpu_rev(void);
|
||||
unsigned int bcm63xx_get_cpu_freq(void);
|
||||
|
||||
@@ -82,6 +83,23 @@ static inline u16 __pure bcm63xx_get_cpu
|
||||
#define BCMCPU_IS_6362() (bcm63xx_get_cpu_id() == BCM6362_CPU_ID)
|
||||
#define BCMCPU_IS_6368() (bcm63xx_get_cpu_id() == BCM6368_CPU_ID)
|
||||
|
||||
+#define BCMCPU_VARIANT_IS_3368() \
|
||||
+ (bcm63xx_get_cpu_variant() == BCM3368_CPU_ID)
|
||||
+#define BCMCPU_VARIANT_IS_6328() \
|
||||
+ (bcm63xx_get_cpu_variant() == BCM6328_CPU_ID)
|
||||
+#define BCMCPU_VARIANT_IS_6338() \
|
||||
+ (bcm63xx_get_cpu_variant() == BCM6338_CPU_ID)
|
||||
+#define BCMCPU_VARIANT_IS_6345() \
|
||||
+ (bcm63xx_get_cpu_variant() == BCM6345_CPU_ID)
|
||||
+#define BCMCPU_VARIANT_IS_6348() \
|
||||
+ (bcm63xx_get_cpu_variant() == BCM6348_CPU_ID)
|
||||
+#define BCMCPU_VARIANT_IS_6358() \
|
||||
+ (bcm63xx_get_cpu_cariant() == BCM6358_CPU_ID)
|
||||
+#define BCMCPU_VARIANT_IS_6362() \
|
||||
+ (bcm63xx_get_cpu_variant() == BCM6362_CPU_ID)
|
||||
+#define BCMCPU_VARIANT_IS_6368() \
|
||||
+ (bcm63xx_get_cpu_variant() == BCM6368_CPU_ID)
|
||||
+
|
||||
/*
|
||||
* While registers sets are (mostly) the same across 63xx CPU, base
|
||||
* address of these sets do change.
|
@ -1,23 +0,0 @@
|
||||
From 3bd8e2535265f06f79ed9c0ad788405441e091dc Mon Sep 17 00:00:00 2001
|
||||
From: Jonas Gorski <jogo@openwrt.org>
|
||||
Date: Sat, 7 Dec 2013 14:22:41 +0100
|
||||
Subject: [PATCH 21/45] MIPS: BCM63XX: define variant id field
|
||||
|
||||
Some SoC have a variant id field in the chip id register.
|
||||
|
||||
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
|
||||
---
|
||||
arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
|
||||
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
|
||||
@@ -9,6 +9,8 @@
|
||||
#define PERF_REV_REG 0x0
|
||||
#define REV_CHIPID_SHIFT 16
|
||||
#define REV_CHIPID_MASK (0xffff << REV_CHIPID_SHIFT)
|
||||
+#define REV_VARID_SHIFT 12
|
||||
+#define REV_VARID_MASK (0xf << REV_VARID_SHIFT)
|
||||
#define REV_REVID_SHIFT 0
|
||||
#define REV_REVID_MASK (0xff << REV_REVID_SHIFT)
|
||||
|
@ -1,68 +0,0 @@
|
||||
From d59120f23279ef62a48d9f94847254b061d0a8b6 Mon Sep 17 00:00:00 2001
|
||||
From: Jonas Gorski <jogo@openwrt.org>
|
||||
Date: Sat, 7 Dec 2013 14:30:59 +0100
|
||||
Subject: [PATCH 22/45] MIPS: BCM63XX: detect BCM6328 variants
|
||||
|
||||
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
|
||||
---
|
||||
arch/mips/bcm63xx/cpu.c | 10 ++++++++++
|
||||
arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h | 8 ++++++--
|
||||
2 files changed, 16 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/arch/mips/bcm63xx/cpu.c
|
||||
+++ b/arch/mips/bcm63xx/cpu.c
|
||||
@@ -305,6 +305,7 @@ void __init bcm63xx_cpu_init(void)
|
||||
unsigned int tmp;
|
||||
unsigned int cpu = smp_processor_id();
|
||||
u32 chipid_reg;
|
||||
+ u8 __maybe_unused varid = 0;
|
||||
|
||||
/* soc registers location depends on cpu type */
|
||||
chipid_reg = 0;
|
||||
@@ -344,6 +345,7 @@ void __init bcm63xx_cpu_init(void)
|
||||
bcm63xx_cpu_id = (tmp & REV_CHIPID_MASK) >> REV_CHIPID_SHIFT;
|
||||
bcm63xx_cpu_variant = bcm63xx_cpu_id;
|
||||
bcm63xx_cpu_rev = (tmp & REV_REVID_MASK) >> REV_REVID_SHIFT;
|
||||
+ varid = (tmp & REV_VARID_MASK) >> REV_VARID_SHIFT;
|
||||
|
||||
switch (bcm63xx_cpu_id) {
|
||||
case BCM3368_CPU_ID:
|
||||
@@ -353,6 +355,14 @@ void __init bcm63xx_cpu_init(void)
|
||||
case BCM6328_CPU_ID:
|
||||
bcm63xx_regs_base = bcm6328_regs_base;
|
||||
bcm63xx_irqs = bcm6328_irqs;
|
||||
+
|
||||
+ if (varid == 1)
|
||||
+ bcm63xx_cpu_variant = BCM63281_CPU_ID;
|
||||
+ else if (varid == 3)
|
||||
+ bcm63xx_cpu_variant = BCM63283_CPU_ID;
|
||||
+ else
|
||||
+ pr_warn("unknown BCM6328 variant: %x\n", varid);
|
||||
+
|
||||
break;
|
||||
case BCM6338_CPU_ID:
|
||||
bcm63xx_regs_base = bcm6338_regs_base;
|
||||
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h
|
||||
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h
|
||||
@@ -11,6 +11,8 @@
|
||||
*/
|
||||
#define BCM3368_CPU_ID 0x3368
|
||||
#define BCM6328_CPU_ID 0x6328
|
||||
+#define BCM63281_CPU_ID 0x63281
|
||||
+#define BCM63283_CPU_ID 0x63283
|
||||
#define BCM6338_CPU_ID 0x6338
|
||||
#define BCM6345_CPU_ID 0x6345
|
||||
#define BCM6348_CPU_ID 0x6348
|
||||
@@ -85,8 +87,10 @@ static inline u16 __pure bcm63xx_get_cpu
|
||||
|
||||
#define BCMCPU_VARIANT_IS_3368() \
|
||||
(bcm63xx_get_cpu_variant() == BCM3368_CPU_ID)
|
||||
-#define BCMCPU_VARIANT_IS_6328() \
|
||||
- (bcm63xx_get_cpu_variant() == BCM6328_CPU_ID)
|
||||
+#define BCMCPU_VARIANT_IS_63281() \
|
||||
+ (bcm63xx_get_cpu_variant() == BCM63281_CPU_ID)
|
||||
+#define BCMCPU_VARIANT_IS_63283() \
|
||||
+ (bcm63xx_get_cpu_variant() == BCM63283_CPU_ID)
|
||||
#define BCMCPU_VARIANT_IS_6338() \
|
||||
(bcm63xx_get_cpu_variant() == BCM6338_CPU_ID)
|
||||
#define BCMCPU_VARIANT_IS_6345() \
|
@ -1,46 +0,0 @@
|
||||
From 04458c3db8eb79da21ecde40ab36a1dde52bef06 Mon Sep 17 00:00:00 2001
|
||||
From: Jonas Gorski <jogo@openwrt.org>
|
||||
Date: Sat, 7 Dec 2013 14:33:28 +0100
|
||||
Subject: [PATCH 23/45] MIPS: BCM63XX: detect BCM6362 variants
|
||||
|
||||
---
|
||||
arch/mips/bcm63xx/cpu.c | 8 ++++++++
|
||||
arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h | 3 +++
|
||||
2 files changed, 11 insertions(+)
|
||||
|
||||
--- a/arch/mips/bcm63xx/cpu.c
|
||||
+++ b/arch/mips/bcm63xx/cpu.c
|
||||
@@ -383,6 +383,14 @@ void __init bcm63xx_cpu_init(void)
|
||||
case BCM6362_CPU_ID:
|
||||
bcm63xx_regs_base = bcm6362_regs_base;
|
||||
bcm63xx_irqs = bcm6362_irqs;
|
||||
+
|
||||
+ if (varid == 1)
|
||||
+ bcm63xx_cpu_variant = BCM6362_CPU_ID;
|
||||
+ else if (varid == 2)
|
||||
+ bcm63xx_cpu_variant = BCM6361_CPU_ID;
|
||||
+ else
|
||||
+ pr_warn("unknown BCM6362 variant: %x\n", varid);
|
||||
+
|
||||
break;
|
||||
case BCM6368_CPU_ID:
|
||||
bcm63xx_regs_base = bcm6368_regs_base;
|
||||
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h
|
||||
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h
|
||||
@@ -17,6 +17,7 @@
|
||||
#define BCM6345_CPU_ID 0x6345
|
||||
#define BCM6348_CPU_ID 0x6348
|
||||
#define BCM6358_CPU_ID 0x6358
|
||||
+#define BCM6361_CPU_ID 0x6361
|
||||
#define BCM6362_CPU_ID 0x6362
|
||||
#define BCM6368_CPU_ID 0x6368
|
||||
|
||||
@@ -99,6 +100,8 @@ static inline u16 __pure bcm63xx_get_cpu
|
||||
(bcm63xx_get_cpu_variant() == BCM6348_CPU_ID)
|
||||
#define BCMCPU_VARIANT_IS_6358() \
|
||||
(bcm63xx_get_cpu_cariant() == BCM6358_CPU_ID)
|
||||
+#define BCMCPU_VARIANT_IS_6361() \
|
||||
+ (bcm63xx_get_cpu_variant() == BCM6361_CPU_ID)
|
||||
#define BCMCPU_VARIANT_IS_6362() \
|
||||
(bcm63xx_get_cpu_variant() == BCM6362_CPU_ID)
|
||||
#define BCMCPU_VARIANT_IS_6368() \
|
@ -1,48 +0,0 @@
|
||||
From 825cc67e56b5e624a05f6850a86d91508b786848 Mon Sep 17 00:00:00 2001
|
||||
From: Jonas Gorski <jogo@openwrt.org>
|
||||
Date: Sat, 7 Dec 2013 14:36:56 +0100
|
||||
Subject: [PATCH 24/44] MIPS: BCM63XX: detect BCM6368 variants
|
||||
|
||||
The DSL-less BCM6368 variant BCM6367 uses a different chip id. Apart
|
||||
from missing DSL, there is no difference to BCM6368, so treat it such.
|
||||
|
||||
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
|
||||
---
|
||||
arch/mips/bcm63xx/cpu.c | 4 ++++
|
||||
arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h | 3 +++
|
||||
2 files changed, 7 insertions(+)
|
||||
|
||||
--- a/arch/mips/bcm63xx/cpu.c
|
||||
+++ b/arch/mips/bcm63xx/cpu.c
|
||||
@@ -393,8 +393,12 @@ void __init bcm63xx_cpu_init(void)
|
||||
|
||||
break;
|
||||
case BCM6368_CPU_ID:
|
||||
+ case BCM6369_CPU_ID:
|
||||
bcm63xx_regs_base = bcm6368_regs_base;
|
||||
bcm63xx_irqs = bcm6368_irqs;
|
||||
+
|
||||
+ /* BCM6369 is a BCM6368 without xDSL, so treat it the same */
|
||||
+ bcm63xx_cpu_id = BCM6368_CPU_ID;
|
||||
break;
|
||||
default:
|
||||
panic("unsupported broadcom CPU %x", bcm63xx_cpu_id);
|
||||
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h
|
||||
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h
|
||||
@@ -20,6 +20,7 @@
|
||||
#define BCM6361_CPU_ID 0x6361
|
||||
#define BCM6362_CPU_ID 0x6362
|
||||
#define BCM6368_CPU_ID 0x6368
|
||||
+#define BCM6369_CPU_ID 0x6369
|
||||
|
||||
void __init bcm63xx_cpu_init(void);
|
||||
u32 bcm63xx_get_cpu_variant(void);
|
||||
@@ -106,6 +107,8 @@ static inline u16 __pure bcm63xx_get_cpu
|
||||
(bcm63xx_get_cpu_variant() == BCM6362_CPU_ID)
|
||||
#define BCMCPU_VARIANT_IS_6368() \
|
||||
(bcm63xx_get_cpu_variant() == BCM6368_CPU_ID)
|
||||
+#define BCMCPU_VARIANT_IS_6369() \
|
||||
+ (bcm63xx_get_cpu_variant() == BCM6369_CPU_ID)
|
||||
|
||||
/*
|
||||
* While registers sets are (mostly) the same across 63xx CPU, base
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user