diff options
Diffstat (limited to 'target/linux/brcm63xx')
25 files changed, 1342 insertions, 944 deletions
diff --git a/target/linux/brcm63xx/modules.mk b/target/linux/brcm63xx/modules.mk index e48d298bf0..2f09f48874 100644 --- a/target/linux/brcm63xx/modules.mk +++ b/target/linux/brcm63xx/modules.mk @@ -10,8 +10,13 @@ define KernelPackage/bcm63xx-spi TITLE:=Broadcom BCM63xx SPI driver DEPENDS:=@TARGET_brcm63xx +kmod-spi-bitbang KCONFIG:=CONFIG_SPI_BCM63XX - FILES:=$(LINUX_DIR)/drivers/spi/bcm63xx_spi.ko - AUTOLOAD:=$(call AutoLoad,92,bcm63xx_spi) + ifeq ($(strip $(call CompareKernelPatchVer,$(KERNEL_PATCHVER),ge,3.3)),1) + FILES:=$(LINUX_DIR)/drivers/spi/spi-bcm63xx.ko + AUTOLOAD:=$(call AutoLoad,92,spi-bcm63xx) + else + FILES:=$(LINUX_DIR)/drivers/spi/bcm63xx_spi.ko + AUTOLOAD:=$(call AutoLoad,92,bcm63xx_spi) + endif endef define KernelPackage/bcm63xx-spi/description diff --git a/target/linux/brcm63xx/patches-3.3/001-MIPS-BCM63XX-fix-platform_devices-id.patch b/target/linux/brcm63xx/patches-3.3/001-MIPS-BCM63XX-fix-platform_devices-id.patch new file mode 100644 index 0000000000..f83490e6cc --- /dev/null +++ b/target/linux/brcm63xx/patches-3.3/001-MIPS-BCM63XX-fix-platform_devices-id.patch @@ -0,0 +1,36 @@ +From cbcfe65e357666106c3c6250baf9c5ce33f3e3e3 Mon Sep 17 00:00:00 2001 +From: Florian Fainelli <florian@openwrt.org> +Date: Wed, 25 Jan 2012 17:39:53 +0100 +Subject: [PATCH 03/63] MIPS: BCM63XX: fix platform_devices id + +There is only one watchdog and VoIP DSP platform devices per board, use +-1 as the platform_device id accordingly. + +Signed-off-by: Florian Fainelli <florian@openwrt.org> +--- + arch/mips/bcm63xx/dev-dsp.c | 2 +- + arch/mips/bcm63xx/dev-wdt.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +--- a/arch/mips/bcm63xx/dev-dsp.c ++++ b/arch/mips/bcm63xx/dev-dsp.c +@@ -31,7 +31,7 @@ static struct resource voip_dsp_resource + + static struct platform_device bcm63xx_voip_dsp_device = { + .name = "bcm63xx-voip-dsp", +- .id = 0, ++ .id = -1, + .num_resources = ARRAY_SIZE(voip_dsp_resources), + .resource = voip_dsp_resources, + }; +--- a/arch/mips/bcm63xx/dev-wdt.c ++++ b/arch/mips/bcm63xx/dev-wdt.c +@@ -21,7 +21,7 @@ static struct resource wdt_resources[] = + + static struct platform_device bcm63xx_wdt_device = { + .name = "bcm63xx-wdt", +- .id = 0, ++ .id = -1, + .num_resources = ARRAY_SIZE(wdt_resources), + .resource = wdt_resources, + }; diff --git a/target/linux/brcm63xx/patches-3.3/002-MIPS-BCM63XX-be-consistent-in-clock-bits-enable-nami.patch b/target/linux/brcm63xx/patches-3.3/002-MIPS-BCM63XX-be-consistent-in-clock-bits-enable-nami.patch new file mode 100644 index 0000000000..439d11ea1d --- /dev/null +++ b/target/linux/brcm63xx/patches-3.3/002-MIPS-BCM63XX-be-consistent-in-clock-bits-enable-nami.patch @@ -0,0 +1,93 @@ +From db1cc4ee366bf0528fcb8b4afa65dec915d98889 Mon Sep 17 00:00:00 2001 +From: Florian Fainelli <florian@openwrt.org> +Date: Wed, 25 Jan 2012 17:39:55 +0100 +Subject: [PATCH 04/63] MIPS: BCM63XX: be consistent in clock bits enable naming + +Remove the _CLK suffix from the BCM6368 clock bits definitions to be +consistent with what is already present. + +Signed-off-by: Florian Fainelli <florian@openwrt.org> +--- + arch/mips/bcm63xx/clk.c | 6 ++-- + arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h | 36 ++++++++++---------- + 2 files changed, 21 insertions(+), 21 deletions(-) + +--- a/arch/mips/bcm63xx/clk.c ++++ b/arch/mips/bcm63xx/clk.c +@@ -120,7 +120,7 @@ static void enetsw_set(struct clk *clk, + { + if (!BCMCPU_IS_6368()) + return; +- bcm_hwclock_set(CKCTL_6368_ROBOSW_CLK_EN | ++ bcm_hwclock_set(CKCTL_6368_ROBOSW_EN | + CKCTL_6368_SWPKT_USB_EN | + CKCTL_6368_SWPKT_SAR_EN, enable); + if (enable) { +@@ -163,7 +163,7 @@ static void usbh_set(struct clk *clk, in + if (BCMCPU_IS_6348()) + bcm_hwclock_set(CKCTL_6348_USBH_EN, enable); + else if (BCMCPU_IS_6368()) +- bcm_hwclock_set(CKCTL_6368_USBH_CLK_EN, enable); ++ bcm_hwclock_set(CKCTL_6368_USBH_EN, enable); + } + + static struct clk clk_usbh = { +@@ -199,7 +199,7 @@ static void xtm_set(struct clk *clk, int + if (!BCMCPU_IS_6368()) + return; + +- bcm_hwclock_set(CKCTL_6368_SAR_CLK_EN | ++ bcm_hwclock_set(CKCTL_6368_SAR_EN | + CKCTL_6368_SWPKT_SAR_EN, enable); + + if (enable) { +--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h ++++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h +@@ -90,29 +90,29 @@ + #define CKCTL_6368_PHYMIPS_EN (1 << 6) + #define CKCTL_6368_SWPKT_USB_EN (1 << 7) + #define CKCTL_6368_SWPKT_SAR_EN (1 << 8) +-#define CKCTL_6368_SPI_CLK_EN (1 << 9) +-#define CKCTL_6368_USBD_CLK_EN (1 << 10) +-#define CKCTL_6368_SAR_CLK_EN (1 << 11) +-#define CKCTL_6368_ROBOSW_CLK_EN (1 << 12) +-#define CKCTL_6368_UTOPIA_CLK_EN (1 << 13) +-#define CKCTL_6368_PCM_CLK_EN (1 << 14) +-#define CKCTL_6368_USBH_CLK_EN (1 << 15) ++#define CKCTL_6368_SPI_EN (1 << 9) ++#define CKCTL_6368_USBD_EN (1 << 10) ++#define CKCTL_6368_SAR_EN (1 << 11) ++#define CKCTL_6368_ROBOSW_EN (1 << 12) ++#define CKCTL_6368_UTOPIA_EN (1 << 13) ++#define CKCTL_6368_PCM_EN (1 << 14) ++#define CKCTL_6368_USBH_EN (1 << 15) + #define CKCTL_6368_DISABLE_GLESS_EN (1 << 16) +-#define CKCTL_6368_NAND_CLK_EN (1 << 17) +-#define CKCTL_6368_IPSEC_CLK_EN (1 << 17) ++#define CKCTL_6368_NAND_EN (1 << 17) ++#define CKCTL_6368_IPSEC_EN (1 << 17) + + #define CKCTL_6368_ALL_SAFE_EN (CKCTL_6368_SWPKT_USB_EN | \ + CKCTL_6368_SWPKT_SAR_EN | \ +- CKCTL_6368_SPI_CLK_EN | \ +- CKCTL_6368_USBD_CLK_EN | \ +- CKCTL_6368_SAR_CLK_EN | \ +- CKCTL_6368_ROBOSW_CLK_EN | \ +- CKCTL_6368_UTOPIA_CLK_EN | \ +- CKCTL_6368_PCM_CLK_EN | \ +- CKCTL_6368_USBH_CLK_EN | \ ++ CKCTL_6368_SPI_EN | \ ++ CKCTL_6368_USBD_EN | \ ++ CKCTL_6368_SAR_EN | \ ++ CKCTL_6368_ROBOSW_EN | \ ++ CKCTL_6368_UTOPIA_EN | \ ++ CKCTL_6368_PCM_EN | \ ++ CKCTL_6368_USBH_EN | \ + CKCTL_6368_DISABLE_GLESS_EN | \ +- CKCTL_6368_NAND_CLK_EN | \ +- CKCTL_6368_IPSEC_CLK_EN) ++ CKCTL_6368_NAND_EN | \ ++ CKCTL_6368_IPSEC_EN) + + /* System PLL Control register */ + #define PERF_SYS_PLL_CTL_REG 0x8 diff --git a/target/linux/brcm63xx/patches-3.3/003-MIPS-BCM63XX-add-IRQ_SPI-and-CPU-specific-SPI-IRQ-va.patch b/target/linux/brcm63xx/patches-3.3/003-MIPS-BCM63XX-add-IRQ_SPI-and-CPU-specific-SPI-IRQ-va.patch new file mode 100644 index 0000000000..b4c787c52a --- /dev/null +++ b/target/linux/brcm63xx/patches-3.3/003-MIPS-BCM63XX-add-IRQ_SPI-and-CPU-specific-SPI-IRQ-va.patch @@ -0,0 +1,68 @@ +From 04456614952a9a848192253439b4e361f0321cb5 Mon Sep 17 00:00:00 2001 +From: Florian Fainelli <florian@openwrt.org> +Date: Wed, 25 Jan 2012 17:39:51 +0100 +Subject: [PATCH 05/63] MIPS: BCM63XX: add IRQ_SPI and CPU specific SPI IRQ values + +Signed-off-by: Florian Fainelli <florian@openwrt.org> +--- + arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h | 7 +++++++ + 1 files changed, 7 insertions(+), 0 deletions(-) + +--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h ++++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h +@@ -478,6 +478,7 @@ static inline unsigned long bcm63xx_regs + */ + enum bcm63xx_irq { + IRQ_TIMER = 0, ++ IRQ_SPI, + IRQ_UART0, + IRQ_UART1, + IRQ_DSL, +@@ -509,6 +510,7 @@ enum bcm63xx_irq { + * 6338 irqs + */ + #define BCM_6338_TIMER_IRQ (IRQ_INTERNAL_BASE + 0) ++#define BCM_6338_SPI_IRQ (IRQ_INTERNAL_BASE + 1) + #define BCM_6338_UART0_IRQ (IRQ_INTERNAL_BASE + 2) + #define BCM_6338_UART1_IRQ 0 + #define BCM_6338_DSL_IRQ (IRQ_INTERNAL_BASE + 5) +@@ -539,6 +541,7 @@ enum bcm63xx_irq { + * 6345 irqs + */ + #define BCM_6345_TIMER_IRQ (IRQ_INTERNAL_BASE + 0) ++#define BCM_6345_SPI_IRQ 0 + #define BCM_6345_UART0_IRQ (IRQ_INTERNAL_BASE + 2) + #define BCM_6345_UART1_IRQ 0 + #define BCM_6345_DSL_IRQ (IRQ_INTERNAL_BASE + 3) +@@ -569,6 +572,7 @@ enum bcm63xx_irq { + * 6348 irqs + */ + #define BCM_6348_TIMER_IRQ (IRQ_INTERNAL_BASE + 0) ++#define BCM_6348_SPI_IRQ (IRQ_INTERNAL_BASE + 1) + #define BCM_6348_UART0_IRQ (IRQ_INTERNAL_BASE + 2) + #define BCM_6348_UART1_IRQ 0 + #define BCM_6348_DSL_IRQ (IRQ_INTERNAL_BASE + 4) +@@ -599,6 +603,7 @@ enum bcm63xx_irq { + * 6358 irqs + */ + #define BCM_6358_TIMER_IRQ (IRQ_INTERNAL_BASE + 0) ++#define BCM_6358_SPI_IRQ (IRQ_INTERNAL_BASE + 1) + #define BCM_6358_UART0_IRQ (IRQ_INTERNAL_BASE + 2) + #define BCM_6358_UART1_IRQ (IRQ_INTERNAL_BASE + 3) + #define BCM_6358_DSL_IRQ (IRQ_INTERNAL_BASE + 29) +@@ -638,6 +643,7 @@ enum bcm63xx_irq { + #define BCM_6368_HIGH_IRQ_BASE (IRQ_INTERNAL_BASE + 32) + + #define BCM_6368_TIMER_IRQ (IRQ_INTERNAL_BASE + 0) ++#define BCM_6368_SPI_IRQ (IRQ_INTERNAL_BASE + 1) + #define BCM_6368_UART0_IRQ (IRQ_INTERNAL_BASE + 2) + #define BCM_6368_UART1_IRQ (IRQ_INTERNAL_BASE + 3) + #define BCM_6368_DSL_IRQ (IRQ_INTERNAL_BASE + 4) +@@ -677,6 +683,7 @@ extern const int *bcm63xx_irqs; + + #define __GEN_CPU_IRQ_TABLE(__cpu) \ + [IRQ_TIMER] = BCM_## __cpu ##_TIMER_IRQ, \ ++ [IRQ_SPI] = BCM_## __cpu ##_SPI_IRQ, \ + [IRQ_UART0] = BCM_## __cpu ##_UART0_IRQ, \ + [IRQ_UART1] = BCM_## __cpu ##_UART1_IRQ, \ + [IRQ_DSL] = BCM_## __cpu ##_DSL_IRQ, \ diff --git a/target/linux/brcm63xx/patches-3.3/004-MIPS-BCM63XX-define-BCM6358-SPI-base-address.patch b/target/linux/brcm63xx/patches-3.3/004-MIPS-BCM63XX-define-BCM6358-SPI-base-address.patch new file mode 100644 index 0000000000..0c314da743 --- /dev/null +++ b/target/linux/brcm63xx/patches-3.3/004-MIPS-BCM63XX-define-BCM6358-SPI-base-address.patch @@ -0,0 +1,21 @@ +From bfd78dda2ad5afb4434ebe99c05528614065bdb1 Mon Sep 17 00:00:00 2001 +From: Florian Fainelli <florian@openwrt.org> +Date: Wed, 25 Jan 2012 17:39:56 +0100 +Subject: [PATCH 06/63] MIPS: BCM63XX: define BCM6358 SPI base address + +Signed-off-by: Florian Fainelli <florian@openwrt.org> +--- + arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h ++++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h +@@ -289,7 +289,7 @@ enum bcm63xx_regs_set { + #define BCM_6358_UART0_BASE (0xfffe0100) + #define BCM_6358_UART1_BASE (0xfffe0120) + #define BCM_6358_GPIO_BASE (0xfffe0080) +-#define BCM_6358_SPI_BASE (0xdeadbeef) ++#define BCM_6358_SPI_BASE (0xfffe0800) + #define BCM_6358_SPI2_BASE (0xfffe0800) + #define BCM_6358_UDC0_BASE (0xfffe0800) + #define BCM_6358_OHCI0_BASE (0xfffe1400) diff --git a/target/linux/brcm63xx/patches-3.3/005-MIPS-BCM63XX-add-BCM6368-SPI-clock-mask.patch b/target/linux/brcm63xx/patches-3.3/005-MIPS-BCM63XX-add-BCM6368-SPI-clock-mask.patch new file mode 100644 index 0000000000..b7fac84480 --- /dev/null +++ b/target/linux/brcm63xx/patches-3.3/005-MIPS-BCM63XX-add-BCM6368-SPI-clock-mask.patch @@ -0,0 +1,26 @@ +From 9b990ee00f70bdd6a731dbe264d5acb453a6c5e2 Mon Sep 17 00:00:00 2001 +From: Florian Fainelli <florian@openwrt.org> +Date: Wed, 25 Jan 2012 17:39:57 +0100 +Subject: [PATCH 07/63] MIPS: BCM63XX: add BCM6368 SPI clock mask + +Signed-off-by: Florian Fainelli <florian@openwrt.org> +--- + arch/mips/bcm63xx/clk.c | 6 ++++-- + 1 files changed, 4 insertions(+), 2 deletions(-) + +--- a/arch/mips/bcm63xx/clk.c ++++ b/arch/mips/bcm63xx/clk.c +@@ -181,9 +181,11 @@ static void spi_set(struct clk *clk, int + mask = CKCTL_6338_SPI_EN; + else if (BCMCPU_IS_6348()) + mask = CKCTL_6348_SPI_EN; +- else +- /* BCMCPU_IS_6358 */ ++ else if (BCMCPU_IS_6358()) + mask = CKCTL_6358_SPI_EN; ++ else ++ /* BCMCPU_IS_6368 */ ++ mask = CKCTL_6368_SPI_EN; + bcm_hwclock_set(mask, enable); + } + diff --git a/target/linux/brcm63xx/patches-3.3/006-MIPS-BCM63XX-define-SPI-register-sizes.patch b/target/linux/brcm63xx/patches-3.3/006-MIPS-BCM63XX-define-SPI-register-sizes.patch new file mode 100644 index 0000000000..0eab43a186 --- /dev/null +++ b/target/linux/brcm63xx/patches-3.3/006-MIPS-BCM63XX-define-SPI-register-sizes.patch @@ -0,0 +1,26 @@ +From 16ba44545156e4e7cc1e812ad93e562ce92fd74c Mon Sep 17 00:00:00 2001 +From: Florian Fainelli <florian@openwrt.org> +Date: Wed, 25 Jan 2012 17:40:00 +0100 +Subject: [PATCH 08/63] MIPS: BCM63XX: define SPI register sizes. + +There are two distinct sizes for the SPI register depending on the SoC +generation (6338 & 6348 vs 6358 & 6368). + +Signed-off-by: Florian Fainelli <florian@openwrt.org> +--- + arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h | 4 ++++ + 1 files changed, 4 insertions(+), 0 deletions(-) + +--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h ++++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h +@@ -135,6 +135,10 @@ enum bcm63xx_regs_set { + #define RSET_DSL_LMEM_SIZE (64 * 1024 * 4) + #define RSET_DSL_SIZE 4096 + #define RSET_WDT_SIZE 12 ++#define BCM_6338_RSET_SPI_SIZE 64 ++#define BCM_6348_RSET_SPI_SIZE 64 ++#define BCM_6358_RSET_SPI_SIZE 1804 ++#define BCM_6368_RSET_SPI_SIZE 1804 + #define RSET_ENET_SIZE 2048 + #define RSET_ENETDMA_SIZE 2048 + #define RSET_ENETSW_SIZE 65536 diff --git a/target/linux/brcm63xx/patches-3.3/007-MIPS-BCM63XX-remove-SPI2-register.patch b/target/linux/brcm63xx/patches-3.3/007-MIPS-BCM63XX-remove-SPI2-register.patch new file mode 100644 index 0000000000..cafef10dbb --- /dev/null +++ b/target/linux/brcm63xx/patches-3.3/007-MIPS-BCM63XX-remove-SPI2-register.patch @@ -0,0 +1,83 @@ +From 32511e7dfab9b9cabe2772e3f5430559294a8d1c Mon Sep 17 00:00:00 2001 +From: Florian Fainelli <florian@openwrt.org> +Date: Wed, 25 Jan 2012 17:40:01 +0100 +Subject: [PATCH 09/63] MIPS: BCM63XX: remove SPI2 register + +This register was introduced with the support of the BCM6368 CPU in the idea +that its internal layout was different from the other CPUs SPI controller. +The controller is actually the same as the one present on BCM6358 so we can +remove this register and use the usual SPI register instead. + +Signed-off-by: Florian Fainelli <florian@openwrt.org> +--- + arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h | 10 +--------- + 1 files changed, 1 insertions(+), 9 deletions(-) + +--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h ++++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h +@@ -102,7 +102,6 @@ enum bcm63xx_regs_set { + RSET_UART1, + RSET_GPIO, + RSET_SPI, +- RSET_SPI2, + RSET_UDC0, + RSET_OHCI0, + RSET_OHCI_PRIV, +@@ -166,7 +165,6 @@ enum bcm63xx_regs_set { + #define BCM_6338_UART1_BASE (0xdeadbeef) + #define BCM_6338_GPIO_BASE (0xfffe0400) + #define BCM_6338_SPI_BASE (0xfffe0c00) +-#define BCM_6338_SPI2_BASE (0xdeadbeef) + #define BCM_6338_UDC0_BASE (0xdeadbeef) + #define BCM_6338_USBDMA_BASE (0xfffe2400) + #define BCM_6338_OHCI0_BASE (0xdeadbeef) +@@ -210,7 +208,6 @@ enum bcm63xx_regs_set { + #define BCM_6345_UART1_BASE (0xdeadbeef) + #define BCM_6345_GPIO_BASE (0xfffe0400) + #define BCM_6345_SPI_BASE (0xdeadbeef) +-#define BCM_6345_SPI2_BASE (0xdeadbeef) + #define BCM_6345_UDC0_BASE (0xdeadbeef) + #define BCM_6345_USBDMA_BASE (0xfffe2800) + #define BCM_6345_ENET0_BASE (0xfffe1800) +@@ -253,7 +250,6 @@ enum bcm63xx_regs_set { + #define BCM_6348_UART1_BASE (0xdeadbeef) + #define BCM_6348_GPIO_BASE (0xfffe0400) + #define BCM_6348_SPI_BASE (0xfffe0c00) +-#define BCM_6348_SPI2_BASE (0xdeadbeef) + #define BCM_6348_UDC0_BASE (0xfffe1000) + #define BCM_6348_OHCI0_BASE (0xfffe1b00) + #define BCM_6348_OHCI_PRIV_BASE (0xfffe1c00) +@@ -294,7 +290,6 @@ enum bcm63xx_regs_set { + #define BCM_6358_UART1_BASE (0xfffe0120) + #define BCM_6358_GPIO_BASE (0xfffe0080) + #define BCM_6358_SPI_BASE (0xfffe0800) +-#define BCM_6358_SPI2_BASE (0xfffe0800) + #define BCM_6358_UDC0_BASE (0xfffe0800) + #define BCM_6358_OHCI0_BASE (0xfffe1400) + #define BCM_6358_OHCI_PRIV_BASE (0xdeadbeef) +@@ -335,8 +330,7 @@ enum bcm63xx_regs_set { + #define BCM_6368_UART0_BASE (0xb0000100) + #define BCM_6368_UART1_BASE (0xb0000120) + #define BCM_6368_GPIO_BASE (0xb0000080) +-#define BCM_6368_SPI_BASE (0xdeadbeef) +-#define BCM_6368_SPI2_BASE (0xb0000800) ++#define BCM_6368_SPI_BASE (0xb0000800) + #define BCM_6368_UDC0_BASE (0xdeadbeef) + #define BCM_6368_OHCI0_BASE (0xb0001600) + #define BCM_6368_OHCI_PRIV_BASE (0xdeadbeef) +@@ -383,7 +377,6 @@ extern const unsigned long *bcm63xx_regs + __GEN_RSET_BASE(__cpu, UART1) \ + __GEN_RSET_BASE(__cpu, GPIO) \ + __GEN_RSET_BASE(__cpu, SPI) \ +- __GEN_RSET_BASE(__cpu, SPI2) \ + __GEN_RSET_BASE(__cpu, UDC0) \ + __GEN_RSET_BASE(__cpu, OHCI0) \ + __GEN_RSET_BASE(__cpu, OHCI_PRIV) \ +@@ -422,7 +415,6 @@ extern const unsigned long *bcm63xx_regs + [RSET_UART1] = BCM_## __cpu ##_UART1_BASE, \ + [RSET_GPIO] = BCM_## __cpu ##_GPIO_BASE, \ + [RSET_SPI] = BCM_## __cpu ##_SPI_BASE, \ +- [RSET_SPI2] = BCM_## __cpu ##_SPI2_BASE, \ + [RSET_UDC0] = BCM_## __cpu ##_UDC0_BASE, \ + [RSET_OHCI0] = BCM_## __cpu ##_OHCI0_BASE, \ + [RSET_OHCI_PRIV] = BCM_## __cpu ##_OHCI_PRIV_BASE, \ diff --git a/target/linux/brcm63xx/patches-3.3/008-MIPS-BCM63XX-define-internal-registers-offsets-of-th.patch b/target/linux/brcm63xx/patches-3.3/008-MIPS-BCM63XX-define-internal-registers-offsets-of-th.patch new file mode 100644 index 0000000000..d3968fc815 --- /dev/null +++ b/target/linux/brcm63xx/patches-3.3/008-MIPS-BCM63XX-define-internal-registers-offsets-of-th.patch @@ -0,0 +1,140 @@ +From 81f9e7d6aa1dde65483387ba9e9823ef44f90435 Mon Sep 17 00:00:00 2001 +From: Florian Fainelli <florian@openwrt.org> +Date: Wed, 25 Jan 2012 17:40:03 +0100 +Subject: [PATCH 10/63] MIPS: BCM63XX: define internal registers offsets of the SPI controller + +BCM6338, BCM6348, BCM6358 and BCM6368 basically use the same SPI controller +though the internal registers are shuffled, which still allows a common +driver to drive that IP block. + +Signed-off-by: Florian Fainelli <florian@openwrt.org> +--- + arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h | 119 +++++++++++++++++++++ + 1 files changed, 119 insertions(+), 0 deletions(-) + +--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h ++++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h +@@ -973,4 +973,123 @@ + #define M2M_SRCID_REG(x) ((x) * 0x40 + 0x14) + #define M2M_DSTID_REG(x) ((x) * 0x40 + 0x18) + ++/************************************************************************* ++ * _REG relative to RSET_SPI ++ *************************************************************************/ ++ ++/* BCM 6338 SPI core */ ++#define SPI_6338_CMD 0x00 /* 16-bits register */ ++#define SPI_6338_INT_STATUS 0x02 ++#define SPI_6338_INT_MASK_ST 0x03 ++#define SPI_6338_INT_MASK 0x04 ++#define SPI_6338_ST 0x05 ++#define SPI_6338_CLK_CFG 0x06 ++#define SPI_6338_FILL_BYTE 0x07 ++#define SPI_6338_MSG_TAIL 0x09 ++#define SPI_6338_RX_TAIL 0x0b ++#define SPI_6338_MSG_CTL 0x40 ++#define SPI_6338_MSG_DATA 0x41 ++#define SPI_6338_MSG_DATA_SIZE 0x3f ++#define SPI_6338_RX_DATA 0x80 ++#define SPI_6338_RX_DATA_SIZE 0x3f ++ ++/* BCM 6348 SPI core */ ++#define SPI_6348_CMD 0x00 /* 16-bits register */ ++#define SPI_6348_INT_STATUS 0x02 ++#define SPI_6348_INT_MASK_ST 0x03 ++#define SPI_6348_INT_MASK 0x04 ++#define SPI_6348_ST 0x05 ++#define SPI_6348_CLK_CFG 0x06 ++#define SPI_6348_FILL_BYTE 0x07 ++#define SPI_6348_MSG_TAIL 0x09 ++#define SPI_6348_RX_TAIL 0x0b ++#define SPI_6348_MSG_CTL 0x40 ++#define SPI_6348_MSG_DATA 0x41 ++#define SPI_6348_MSG_DATA_SIZE 0x3f ++#define SPI_6348_RX_DATA 0x80 ++#define SPI_6348_RX_DATA_SIZE 0x3f ++ ++/* BCM 6358 SPI core */ ++#define SPI_6358_MSG_CTL 0x00 /* 16-bits register */ ++#define SPI_6358_MSG_DATA 0x02 ++#define SPI_6358_MSG_DATA_SIZE 0x21e ++#define SPI_6358_RX_DATA 0x400 ++#define SPI_6358_RX_DATA_SIZE 0x220 ++#define SPI_6358_CMD 0x700 /* 16-bits register */ ++#define SPI_6358_INT_STATUS 0x702 ++#define SPI_6358_INT_MASK_ST 0x703 ++#define SPI_6358_INT_MASK 0x704 ++#define SPI_6358_ST 0x705 ++#define SPI_6358_CLK_CFG 0x706 ++#define SPI_6358_FILL_BYTE 0x707 ++#define SPI_6358_MSG_TAIL 0x709 ++#define SPI_6358_RX_TAIL 0x70B ++ ++/* BCM 6358 SPI core */ ++#define SPI_6368_MSG_CTL 0x00 /* 16-bits register */ ++#define SPI_6368_MSG_DATA 0x02 ++#define SPI_6368_MSG_DATA_SIZE 0x21e ++#define SPI_6368_RX_DATA 0x400 ++#define SPI_6368_RX_DATA_SIZE 0x220 ++#define SPI_6368_CMD 0x700 /* 16-bits register */ ++#define SPI_6368_INT_STATUS 0x702 ++#define SPI_6368_INT_MASK_ST 0x703 ++#define SPI_6368_INT_MASK 0x704 ++#define SPI_6368_ST 0x705 ++#define SPI_6368_CLK_CFG 0x706 ++#define SPI_6368_FILL_BYTE 0x707 ++#define SPI_6368_MSG_TAIL 0x709 ++#define SPI_6368_RX_TAIL 0x70B ++ ++/* Shared SPI definitions */ ++ ++/* Message configuration */ ++#define SPI_FD_RW 0x00 ++#define SPI_HD_W 0x01 ++#define SPI_HD_R 0x02 ++#define SPI_BYTE_CNT_SHIFT 0 ++#define SPI_MSG_TYPE_SHIFT 14 ++ ++/* Command */ ++#define SPI_CMD_NOOP 0x00 ++#define SPI_CMD_SOFT_RESET 0x01 ++#define SPI_CMD_HARD_RESET 0x02 ++#define SPI_CMD_START_IMMEDIATE 0x03 ++#define SPI_CMD_COMMAND_SHIFT 0 ++#define SPI_CMD_COMMAND_MASK 0x000f ++#define SPI_CMD_DEVICE_ID_SHIFT 4 ++#define SPI_CMD_PREPEND_BYTE_CNT_SHIFT 8 ++#define SPI_CMD_ONE_BYTE_SHIFT 11 ++#define SPI_CMD_ONE_WIRE_SHIFT 12 ++#define SPI_DEV_ID_0 0 ++#define SPI_DEV_ID_1 1 ++#define SPI_DEV_ID_2 2 ++#define SPI_DEV_ID_3 3 ++ ++/* Interrupt mask */ ++#define SPI_INTR_CMD_DONE 0x01 ++#define SPI_INTR_RX_OVERFLOW 0x02 ++#define SPI_INTR_TX_UNDERFLOW 0x04 ++#define SPI_INTR_TX_OVERFLOW 0x08 ++#define SPI_INTR_RX_UNDERFLOW 0x10 ++#define SPI_INTR_CLEAR_ALL 0x1f ++ ++/* Status */ ++#define SPI_RX_EMPTY 0x02 ++#define SPI_CMD_BUSY 0x04 ++#define SPI_SERIAL_BUSY 0x08 ++ ++/* Clock configuration */ ++#define SPI_CLK_20MHZ 0x00 ++#define SPI_CLK_0_391MHZ 0x01 ++#define SPI_CLK_0_781MHZ 0x02 /* default */ ++#define SPI_CLK_1_563MHZ 0x03 ++#define SPI_CLK_3_125MHZ 0x04 ++#define SPI_CLK_6_250MHZ 0x05 ++#define SPI_CLK_12_50MHZ 0x06 ++#define SPI_CLK_MASK 0x07 ++#define SPI_SSOFFTIME_MASK 0x38 ++#define SPI_SSOFFTIME_SHIFT 3 ++#define SPI_BYTE_SWAP 0x80 ++ + #endif /* BCM63XX_REGS_H_ */ diff --git a/target/linux/brcm63xx/patches-3.3/009-MIPS-BCM63XX-add-stub-to-register-the-SPI-platform-d.patch b/target/linux/brcm63xx/patches-3.3/009-MIPS-BCM63XX-add-stub-to-register-the-SPI-platform-d.patch new file mode 100644 index 0000000000..a46041fd6b --- /dev/null +++ b/target/linux/brcm63xx/patches-3.3/009-MIPS-BCM63XX-add-stub-to-register-the-SPI-platform-d.patch @@ -0,0 +1,243 @@ +From af84327888c7081662a6b949754fc54d32a50503 Mon Sep 17 00:00:00 2001 +From: Florian Fainelli <florian@openwrt.org> +Date: Wed, 25 Jan 2012 17:40:04 +0100 +Subject: [PATCH 11/63] MIPS: BCM63XX: add stub to register the SPI platform driver + +This patch adds the necessary stub to register the SPI platform driver. +Since the registers are shuffled between the 4 BCM63xx CPUs supported by +this SPI driver we also need to generate the internal register layout and +export this layout for the driver to use it properly. + +Signed-off-by: Florian Fainelli <florian@openwrt.org> +--- + arch/mips/bcm63xx/Makefile | 3 +- + arch/mips/bcm63xx/dev-spi.c | 119 ++++++++++++++++++++ + .../include/asm/mach-bcm63xx/bcm63xx_dev_spi.h | 89 +++++++++++++++ + 3 files changed, 210 insertions(+), 1 deletions(-) + create mode 100644 arch/mips/bcm63xx/dev-spi.c + create mode 100644 arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_spi.h + +--- a/arch/mips/bcm63xx/Makefile ++++ b/arch/mips/bcm63xx/Makefile +@@ -1,5 +1,6 @@ + obj-y += clk.o cpu.o cs.o gpio.o irq.o prom.o setup.o timer.o \ +- dev-dsp.o dev-enet.o dev-pcmcia.o dev-uart.o dev-wdt.o ++ dev-dsp.o dev-enet.o dev-pcmcia.o dev-spi.o dev-uart.o \ ++ dev-wdt.o + obj-$(CONFIG_EARLY_PRINTK) += early_printk.o + + obj-y += boards/ +--- /dev/null ++++ b/arch/mips/bcm63xx/dev-spi.c +@@ -0,0 +1,119 @@ ++/* ++ * 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) 2009-2011 Florian Fainelli <florian@openwrt.org> ++ * Copyright (C) 2010 Tanguy Bouzeloc <tanguy.bouzeloc@efixo.com> ++ */ ++ ++#include <linux/init.h> ++#include <linux/kernel.h> ++#include <linux/export.h> ++#include <linux/platform_device.h> ++#include <linux/err.h> ++#include <linux/clk.h> ++ ++#include <bcm63xx_cpu.h> ++#include <bcm63xx_dev_spi.h> ++#include <bcm63xx_regs.h> ++ ++#ifdef BCMCPU_RUNTIME_DETECT ++/* ++ * register offsets ++ */ ++static const unsigned long bcm6338_regs_spi[] = { ++ __GEN_SPI_REGS_TABLE(6338) ++}; ++ ++static const unsigned long bcm6348_regs_spi[] = { ++ __GEN_SPI_REGS_TABLE(6348) ++}; ++ ++static const unsigned long bcm6358_regs_spi[] = { ++ __GEN_SPI_REGS_TABLE(6358) ++}; ++ ++static const unsigned long bcm6368_regs_spi[] = { ++ __GEN_SPI_REGS_TABLE(6368) ++}; ++ ++const unsigned long *bcm63xx_regs_spi; ++EXPORT_SYMBOL(bcm63xx_regs_spi); ++ ++static __init void bcm63xx_spi_regs_init(void) ++{ ++ if (BCMCPU_IS_6338()) ++ bcm63xx_regs_spi = bcm6338_regs_spi; ++ if (BCMCPU_IS_6348()) ++ bcm63xx_regs_spi = bcm6348_regs_spi; ++ if (BCMCPU_IS_6358()) ++ bcm63xx_regs_spi = bcm6358_regs_spi; ++ if (BCMCPU_IS_6368()) ++ bcm63xx_regs_spi = bcm6368_regs_spi; ++} ++#else ++static __init void bcm63xx_spi_regs_init(void) { } ++#endif ++ ++static struct resource spi_resources[] = { ++ { ++ .start = -1, /* filled at runtime */ ++ .end = -1, /* filled at runtime */ ++ .flags = IORESOURCE_MEM, ++ }, ++ { ++ .start = -1, /* filled at runtime */ ++ .flags = IORESOURCE_IRQ, ++ }, ++}; ++ ++static struct bcm63xx_spi_pdata spi_pdata = { ++ .bus_num = 0, ++ .num_chipselect = 8, ++}; ++ ++static struct platform_device bcm63xx_spi_device = { ++ .name = "bcm63xx-spi", ++ .id = -1, ++ .num_resources = ARRAY_SIZE(spi_resources), ++ .resource = spi_resources, ++ .dev = { ++ .platform_data = &spi_pdata, ++ }, ++}; ++ ++int __init bcm63xx_spi_register(void) ++{ ++ struct clk *periph_clk; ++ ++ if (BCMCPU_IS_6345()) ++ return -ENODEV; ++ ++ periph_clk = clk_get(NULL, "periph"); ++ if (IS_ERR(periph_clk)) { ++ pr_err("unable to get periph clock\n"); ++ return -ENODEV; ++ } ++ ++ /* Set bus frequency */ ++ spi_pdata.speed_hz = clk_get_rate(periph_clk); ++ ++ spi_resources[0].start = bcm63xx_regset_address(RSET_SPI); ++ spi_resources[0].end = spi_resources[0].start; ++ spi_resources[1].start = bcm63xx_get_irq_number(IRQ_SPI); ++ ++ if (BCMCPU_IS_6338() || BCMCPU_IS_6348()) { ++ spi_resources[0].end += BCM_6338_RSET_SPI_SIZE - 1; ++ spi_pdata.fifo_size = SPI_6338_MSG_DATA_SIZE; ++ } ++ ++ if (BCMCPU_IS_6358() || BCMCPU_IS_6368()) { ++ spi_resources[0].end += BCM_6358_RSET_SPI_SIZE - 1; ++ spi_pdata.fifo_size = SPI_6358_MSG_DATA_SIZE; ++ } ++ ++ bcm63xx_spi_regs_init(); ++ ++ return platform_device_register(&bcm63xx_spi_device); ++} +--- /dev/null ++++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_spi.h +@@ -0,0 +1,89 @@ ++#ifndef BCM63XX_DEV_SPI_H ++#define BCM63XX_DEV_SPI_H ++ ++#include <linux/types.h> ++#include <bcm63xx_io.h> ++#include <bcm63xx_regs.h> ++ ++int __init bcm63xx_spi_register(void); ++ ++struct bcm63xx_spi_pdata { ++ unsigned int fifo_size; ++ int bus_num; ++ int num_chipselect; ++ u32 speed_hz; ++}; ++ ++enum bcm63xx_regs_spi { ++ SPI_CMD, ++ SPI_INT_STATUS, ++ SPI_INT_MASK_ST, ++ SPI_INT_MASK, ++ SPI_ST, ++ SPI_CLK_CFG, ++ SPI_FILL_BYTE, ++ SPI_MSG_TAIL, ++ SPI_RX_TAIL, ++ SPI_MSG_CTL, ++ SPI_MSG_DATA, ++ SPI_RX_DATA, ++}; ++ ++#define __GEN_SPI_RSET_BASE(__cpu, __rset) \ ++ case SPI_## __rset: \ ++ return SPI_## __cpu ##_## __rset; ++ ++#define __GEN_SPI_RSET(__cpu) \ ++ switch (reg) { \ ++ __GEN_SPI_RSET_BASE(__cpu, CMD) \ ++ __GEN_SPI_RSET_BASE(__cpu, INT_STATUS) \ ++ __GEN_SPI_RSET_BASE(__cpu, INT_MASK_ST) \ ++ __GEN_SPI_RSET_BASE(__cpu, INT_MASK) \ ++ __GEN_SPI_RSET_BASE(__cpu, ST) \ ++ __GEN_SPI_RSET_BASE(__cpu, CLK_CFG) \ ++ __GEN_SPI_RSET_BASE(__cpu, FILL_BYTE) \ ++ __GEN_SPI_RSET_BASE(__cpu, MSG_TAIL) \ ++ __GEN_SPI_RSET_BASE(__cpu, RX_TAIL) \ ++ __GEN_SPI_RSET_BASE(__cpu, MSG_CTL) \ ++ __GEN_SPI_RSET_BASE(__cpu, MSG_DATA) \ ++ __GEN_SPI_RSET_BASE(__cpu, RX_DATA) \ ++ } ++ ++#define __GEN_SPI_REGS_TABLE(__cpu) \ ++ [SPI_CMD] = SPI_## __cpu ##_CMD, \ ++ [SPI_INT_STATUS] = SPI_## __cpu ##_INT_STATUS, \ ++ [SPI_INT_MASK_ST] = SPI_## __cpu ##_INT_MASK_ST, \ ++ [SPI_INT_MASK] = SPI_## __cpu ##_INT_MASK, \ ++ [SPI_ST] = SPI_## __cpu ##_ST, \ ++ [SPI_CLK_CFG] = SPI_## __cpu ##_CLK_CFG, \ ++ [SPI_FILL_BYTE] = SPI_## __cpu ##_FILL_BYTE, \ ++ [SPI_MSG_TAIL] = SPI_## __cpu ##_MSG_TAIL, \ ++ [SPI_RX_TAIL] = SPI_## __cpu ##_RX_TAIL, \ ++ [SPI_MSG_CTL] = SPI_## __cpu ##_MSG_CTL, \ ++ [SPI_MSG_DATA] = SPI_## __cpu ##_MSG_DATA, \ ++ [SPI_RX_DATA] = SPI_## __cpu ##_RX_DATA, ++ ++static inline unsigned long bcm63xx_spireg(enum bcm63xx_regs_spi reg) ++{ ++#ifdef BCMCPU_RUNTIME_DETECT ++ extern const unsigned long *bcm63xx_regs_spi; ++ ++ return bcm63xx_regs_spi[reg]; ++#else ++#ifdef CONFIG_BCM63XX_CPU_6338 ++ __GEN_SPI_RSET(6338) ++#endif ++#ifdef CONFIG_BCM63XX_CPU_6348 ++ __GEN_SPI_RSET(6348) ++#endif ++#ifdef CONFIG_BCM63XX_CPU_6358 ++ __GEN_SPI_RSET(6358) ++#endif ++#ifdef CONFIG_BCM63XX_CPU_6368 ++ __GEN_SPI_RSET(6368) ++#endif ++#endif ++ return 0; ++} ++ ++#endif /* BCM63XX_DEV_SPI_H */ diff --git a/target/linux/brcm63xx/patches-3.3/010-MIPS-BCM63XX-make-board-setup-code-register-the-spi-.patch b/target/linux/brcm63xx/patches-3.3/010-MIPS-BCM63XX-make-board-setup-code-register-the-spi-.patch new file mode 100644 index 0000000000..516569679c --- /dev/null +++ b/target/linux/brcm63xx/patches-3.3/010-MIPS-BCM63XX-make-board-setup-code-register-the-spi-.patch @@ -0,0 +1,29 @@ +From fab0cbda27ab2400d6a461bf144007a0d5337527 Mon Sep 17 00:00:00 2001 +From: Florian Fainelli <florian@openwrt.org> +Date: Wed, 25 Jan 2012 17:40:05 +0100 +Subject: [PATCH 12/63] MIPS: BCM63XX: make board setup code register the spi platform device + +Signed-off-by: Florian Fainelli <florian@openwrt.org> +--- + arch/mips/bcm63xx/boards/board_bcm963xx.c | 3 +++ + 1 files changed, 3 insertions(+), 0 deletions(-) + +--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c ++++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c +@@ -25,6 +25,7 @@ + #include <bcm63xx_dev_enet.h> + #include <bcm63xx_dev_dsp.h> + #include <bcm63xx_dev_pcmcia.h> ++#include <bcm63xx_dev_spi.h> + #include <board_bcm963xx.h> + + #define PFX "board_bcm963xx: " +@@ -890,6 +891,8 @@ int __init board_register_devices(void) + } + #endif + ++ bcm63xx_spi_register(); ++ + /* read base address of boot chip select (0) */ + val = bcm_mpi_readl(MPI_CSBASE_REG(0)); + val &= MPI_CSBASE_BASE_MASK; diff --git a/target/linux/brcm63xx/patches-3.3/011-spi-add-Broadcom-BCM63xx-SPI-controller-driver.patch b/target/linux/brcm63xx/patches-3.3/011-spi-add-Broadcom-BCM63xx-SPI-controller-driver.patch new file mode 100644 index 0000000000..24f63de62f --- /dev/null +++ b/target/linux/brcm63xx/patches-3.3/011-spi-add-Broadcom-BCM63xx-SPI-controller-driver.patch @@ -0,0 +1,532 @@ +From 5f592b818a2c5731bb12137e7cffc3aa6e24ee5a Mon Sep 17 00:00:00 2001 +From: Florian Fainelli <florian@openwrt.org> +Date: Wed, 1 Feb 2012 09:14:09 +0000 +Subject: [PATCH 13/63] spi: add Broadcom BCM63xx SPI controller driver + +This patch adds support for the SPI controller found on the Broadcom BCM63xx +SoCs. + +Signed-off-by: Tanguy Bouzeloc <tanguy.bouzeloc@efixo.com> +Signed-off-by: Florian Fainelli <florian@openwrt.org> +Acked-by: Grant Likely <grant.likely@secretlab.ca> +--- + drivers/spi/Kconfig | 6 + + drivers/spi/Makefile | 1 + + drivers/spi/spi-bcm63xx.c | 486 +++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 493 insertions(+), 0 deletions(-) + create mode 100644 drivers/spi/spi-bcm63xx.c + +--- a/drivers/spi/Kconfig ++++ b/drivers/spi/Kconfig +@@ -94,6 +94,12 @@ config SPI_AU1550 + If you say yes to this option, support will be included for the + PSC SPI controller found on Au1550, Au1200 and Au1300 series. + ++config SPI_BCM63XX ++ tristate "Broadcom BCM63xx SPI controller" ++ depends on BCM63XX ++ help ++ Enable support for the SPI controller on the Broadcom BCM63xx SoCs. ++ + config SPI_BITBANG + tristate "Utilities for Bitbanging SPI masters" + help +--- a/drivers/spi/Makefile ++++ b/drivers/spi/Makefile +@@ -14,6 +14,7 @@ obj-$(CONFIG_SPI_ALTERA) += spi-altera. + obj-$(CONFIG_SPI_ATMEL) += spi-atmel.o + obj-$(CONFIG_SPI_ATH79) += spi-ath79.o + obj-$(CONFIG_SPI_AU1550) += spi-au1550.o ++obj-$(CONFIG_SPI_BCM63XX) += spi-bcm63xx.o + obj-$(CONFIG_SPI_BFIN) += spi-bfin5xx.o + obj-$(CONFIG_SPI_BFIN_SPORT) += spi-bfin-sport.o + obj-$(CONFIG_SPI_BITBANG) += spi-bitbang.o +--- /dev/null ++++ b/drivers/spi/spi-bcm63xx.c +@@ -0,0 +1,486 @@ ++/* ++ * Broadcom BCM63xx SPI controller support ++ * ++ * Copyright (C) 2009-2011 Florian Fainelli <florian@openwrt.org> ++ * Copyright (C) 2010 Tanguy Bouzeloc <tanguy.bouzeloc@efixo.com> ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * as published by the Free Software Foundation; either version 2 ++ * of the License, or (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the ++ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ++ */ ++ ++#include <linux/kernel.h> ++#include <linux/init.h> ++#include <linux/clk.h> ++#include <linux/io.h> ++#include <linux/module.h> ++#include <linux/platform_device.h> ++#include <linux/delay.h> ++#include <linux/interrupt.h> ++#include <linux/spi/spi.h> ++#include <linux/completion.h> ++#include <linux/err.h> ++ ++#include <bcm63xx_dev_spi.h> ++ ++#define PFX KBUILD_MODNAME ++#define DRV_VER "0.1.2" ++ ++struct bcm63xx_spi { ++ spinlock_t lock; ++ int stopping; ++ struct completion done; ++ ++ void __iomem *regs; ++ int irq; ++ ++ /* Platform data */ ++ u32 speed_hz; ++ unsigned fifo_size; ++ ++ /* Data buffers */ ++ const unsigned char *tx_ptr; ++ unsigned char *rx_ptr; ++ ++ /* data iomem */ ++ u8 __iomem *tx_io; ++ const u8 __iomem *rx_io; ++ ++ int remaining_bytes; ++ ++ struct clk *clk; ++ struct platform_device *pdev; ++}; ++ ++static inline u8 bcm_spi_readb(struct bcm63xx_spi *bs, ++ unsigned int offset) ++{ ++ return bcm_readb(bs->regs + bcm63xx_spireg(offset)); ++} ++ ++static inline u16 bcm_spi_readw(struct bcm63xx_spi *bs, ++ unsigned int offset) ++{ ++ return bcm_readw(bs->regs + bcm63xx_spireg(offset)); ++} ++ ++static inline void bcm_spi_writeb(struct bcm63xx_spi *bs, ++ u8 value, unsigned int offset) ++{ ++ bcm_writeb(value, bs->regs + bcm63xx_spireg(offset)); ++} ++ ++static inline void bcm_spi_writew(struct bcm63xx_spi *bs, ++ u16 value, unsigned int offset) ++{ ++ bcm_writew(value, bs->regs + bcm63xx_spireg(offset)); ++} ++ ++static const unsigned bcm63xx_spi_freq_table[SPI_CLK_MASK][2] = { ++ { 20000000, SPI_CLK_20MHZ }, ++ { 12500000, SPI_CLK_12_50MHZ }, ++ { 6250000, SPI_CLK_6_250MHZ }, ++ { 3125000, SPI_CLK_3_125MHZ }, ++ { 1563000, SPI_CLK_1_563MHZ }, ++ { 781000, SPI_CLK_0_781MHZ }, ++ { 391000, SPI_CLK_0_391MHZ } ++}; ++ ++static int bcm63xx_spi_setup_transfer(struct spi_device *spi, ++ struct spi_transfer *t) ++{ ++ struct bcm63xx_spi *bs = spi_master_get_devdata(spi->master); ++ u8 bits_per_word; ++ u8 clk_cfg, reg; ++ u32 hz; ++ int i; ++ ++ bits_per_word = (t) ? t->bits_per_word : spi->bits_per_word; ++ hz = (t) ? t->speed_hz : spi->max_speed_hz; ++ if (bits_per_word != 8) { ++ dev_err(&spi->dev, "%s, unsupported bits_per_word=%d\n", ++ __func__, bits_per_word); ++ return -EINVAL; ++ } ++ ++ if (spi->chip_select > spi->master->num_chipselect) { ++ dev_err(&spi->dev, "%s, unsupported slave %d\n", ++ __func__, spi->chip_select); ++ return -EINVAL; ++ } ++ ++ /* Find the closest clock configuration */ ++ for (i = 0; i < SPI_CLK_MASK; i++) { ++ if (hz <= bcm63xx_spi_freq_table[i][0]) { ++ clk_cfg = bcm63xx_spi_freq_table[i][1]; ++ break; ++ } ++ } ++ ++ /* No matching configuration found, default to lowest */ ++ if (i == SPI_CLK_MASK) ++ clk_cfg = SPI_CLK_0_391MHZ; ++ ++ /* clear existing clock configuration bits of the register */ ++ reg = bcm_spi_readb(bs, SPI_CLK_CFG); ++ reg &= ~SPI_CLK_MASK; ++ reg |= clk_cfg; ++ ++ bcm_spi_writeb(bs, reg, SPI_CLK_CFG); ++ dev_dbg(&spi->dev, "Setting clock register to %02x (hz %d)\n", ++ clk_cfg, hz); ++ ++ return 0; ++} ++ ++/* the spi->mode bits understood by this driver: */ ++#define MODEBITS (SPI_CPOL | SPI_CPHA) ++ ++static int bcm63xx_spi_setup(struct spi_device *spi) ++{ ++ struct bcm63xx_spi *bs; ++ int ret; ++ ++ bs = spi_master_get_devdata(spi->master); ++ ++ if (bs->stopping) ++ return -ESHUTDOWN; ++ ++ if (!spi->bits_per_word) ++ spi->bits_per_word = 8; ++ ++ if (spi->mode & ~MODEBITS) { ++ dev_err(&spi->dev, "%s, unsupported mode bits %x\n", ++ __func__, spi->mode & ~MODEBITS); ++ return -EINVAL; ++ } ++ ++ ret = bcm63xx_spi_setup_transfer(spi, NULL); ++ if (ret < 0) { ++ dev_err(&spi->dev, "setup: unsupported mode bits %x\n", ++ spi->mode & ~MODEBITS); ++ return ret; ++ } ++ ++ dev_dbg(&spi->dev, "%s, mode %d, %u bits/w, %u nsec/bit\n", ++ __func__, spi->mode & MODEBITS, spi->bits_per_word, 0); ++ ++ return 0; ++} ++ ++/* Fill the TX FIFO with as many bytes as possible */ ++static void bcm63xx_spi_fill_tx_fifo(struct bcm63xx_spi *bs) ++{ ++ u8 size; ++ ++ /* Fill the Tx FIFO with as many bytes as possible */ ++ size = bs->remaining_bytes < bs->fifo_size ? bs->remaining_bytes : ++ bs->fifo_size; ++ memcpy_toio(bs->tx_io, bs->tx_ptr, size); ++ bs->remaining_bytes -= size; ++} ++ ++static int bcm63xx_txrx_bufs(struct spi_device *spi, struct spi_transfer *t) ++{ ++ struct bcm63xx_spi *bs = spi_master_get_devdata(spi->master); ++ u16 msg_ctl; ++ u16 cmd; ++ ++ dev_dbg(&spi->dev, "txrx: tx %p, rx %p, len %d\n", ++ t->tx_buf, t->rx_buf, t->len); ++ ++ /* Transmitter is inhibited */ ++ bs->tx_ptr = t->tx_buf; ++ bs->rx_ptr = t->rx_buf; ++ init_completion(&bs->done); ++ ++ if (t->tx_buf) { ++ bs->remaining_bytes = t->len; ++ bcm63xx_spi_fill_tx_fifo(bs); ++ } ++ ++ /* Enable the command done interrupt which ++ * we use to determine completion of a command */ ++ bcm_spi_writeb(bs, SPI_INTR_CMD_DONE, SPI_INT_MASK); ++ ++ /* Fill in the Message control register */ ++ msg_ctl = (t->len << SPI_BYTE_CNT_SHIFT); ++ ++ if (t->rx_buf && t->tx_buf) ++ msg_ctl |= (SPI_FD_RW << SPI_MSG_TYPE_SHIFT); ++ else if (t->rx_buf) ++ msg_ctl |= (SPI_HD_R << SPI_MSG_TYPE_SHIFT); ++ else if (t->tx_buf) ++ msg_ctl |= (SPI_HD_W << SPI_MSG_TYPE_SHIFT); ++ ++ bcm_spi_writew(bs, msg_ctl, SPI_MSG_CTL); ++ ++ /* Issue the transfer */ ++ cmd = SPI_CMD_START_IMMEDIATE; ++ cmd |= (0 << SPI_CMD_PREPEND_BYTE_CNT_SHIFT); ++ cmd |= (spi->chip_select << SPI_CMD_DEVICE_ID_SHIFT); ++ bcm_spi_writew(bs, cmd, SPI_CMD); ++ wait_for_completion(&bs->done); ++ ++ /* Disable the CMD_DONE interrupt */ ++ bcm_spi_writeb(bs, 0, SPI_INT_MASK); ++ ++ return t->len - bs->remaining_bytes; ++} ++ ++static int bcm63xx_transfer(struct spi_device *spi, struct spi_message *m) ++{ ++ struct bcm63xx_spi *bs = spi_master_get_devdata(spi->master); ++ struct spi_transfer *t; ++ int ret = 0; ++ ++ if (unlikely(list_empty(&m->transfers))) ++ return -EINVAL; ++ ++ if (bs->stopping) ++ return -ESHUTDOWN; ++ ++ list_for_each_entry(t, &m->transfers, transfer_list) { ++ ret += bcm63xx_txrx_bufs(spi, t); ++ } ++ ++ m->complete(m->context); ++ ++ return ret; ++} ++ ++/* This driver supports single master mode only. Hence ++ * CMD_DONE is the only interrupt we care about ++ */ ++static irqreturn_t bcm63xx_spi_interrupt(int irq, void *dev_id) ++{ ++ struct spi_master *master = (struct spi_master *)dev_id; ++ struct bcm63xx_spi *bs = spi_master_get_devdata(master); ++ u8 intr; ++ u16 cmd; ++ ++ /* Read interupts and clear them immediately */ ++ intr = bcm_spi_readb(bs, SPI_INT_STATUS); ++ bcm_spi_writeb(bs, SPI_INTR_CLEAR_ALL, SPI_INT_STATUS); ++ bcm_spi_writeb(bs, 0, SPI_INT_MASK); ++ ++ /* A tansfer completed */ ++ if (intr & SPI_INTR_CMD_DONE) { ++ u8 rx_tail; ++ ++ rx_tail = bcm_spi_readb(bs, SPI_RX_TAIL); ++ ++ /* Read out all the data */ ++ if (rx_tail) ++ memcpy_fromio(bs->rx_ptr, bs->rx_io, rx_tail); ++ ++ /* See if there is more data to send */ ++ if (bs->remaining_bytes > 0) { ++ bcm63xx_spi_fill_tx_fifo(bs); ++ ++ /* Start the transfer */ ++ bcm_spi_writew(bs, SPI_HD_W << SPI_MSG_TYPE_SHIFT, ++ SPI_MSG_CTL); ++ cmd = bcm_spi_readw(bs, SPI_CMD); ++ cmd |= SPI_CMD_START_IMMEDIATE; ++ cmd |= (0 << SPI_CMD_PREPEND_BYTE_CNT_SHIFT); ++ bcm_spi_writeb(bs, SPI_INTR_CMD_DONE, SPI_INT_MASK); ++ bcm_spi_writew(bs, cmd, SPI_CMD); ++ } else { ++ complete(&bs->done); ++ } ++ } ++ ++ return IRQ_HANDLED; ++} ++ ++ ++static int __devinit bcm63xx_spi_probe(struct platform_device *pdev) ++{ ++ struct resource *r; ++ struct device *dev = &pdev->dev; ++ struct bcm63xx_spi_pdata *pdata = pdev->dev.platform_data; ++ int irq; ++ struct spi_master *master; ++ struct clk *clk; ++ struct bcm63xx_spi *bs; ++ int ret; ++ ++ r = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!r) { ++ dev_err(dev, "no iomem\n"); ++ ret = -ENXIO; ++ goto out; ++ } ++ ++ irq = platform_get_irq(pdev, 0); ++ if (irq < 0) { ++ dev_err(dev, "no irq\n"); ++ ret = -ENXIO; ++ goto out; ++ } ++ ++ clk = clk_get(dev, "spi"); ++ if (IS_ERR(clk)) { ++ dev_err(dev, "no clock for device\n"); ++ ret = PTR_ERR(clk); ++ goto out; ++ } ++ ++ master = spi_alloc_master(dev, sizeof(*bs)); ++ if (!master) { ++ dev_err(dev, "out of memory\n"); ++ ret = -ENOMEM; ++ goto out_clk; ++ } ++ ++ bs = spi_master_get_devdata(master); ++ init_completion(&bs->done); ++ ++ platform_set_drvdata(pdev, master); ++ bs->pdev = pdev; ++ ++ if (!devm_request_mem_region(&pdev->dev, r->start, ++ resource_size(r), PFX)) { ++ dev_err(dev, "iomem request failed\n"); ++ ret = -ENXIO; ++ goto out_err; ++ } ++ ++ bs->regs = devm_ioremap_nocache(&pdev->dev, r->start, ++ resource_size(r)); ++ if (!bs->regs) { ++ dev_err(dev, "unable to ioremap regs\n"); ++ ret = -ENOMEM; ++ goto out_err; ++ } ++ ++ bs->irq = irq; ++ bs->clk = clk; ++ bs->fifo_size = pdata->fifo_size; ++ ++ ret = devm_request_irq(&pdev->dev, irq, bcm63xx_spi_interrupt, 0, ++ pdev->name, master); ++ if (ret) { ++ dev_err(dev, "unable to request irq\n"); ++ goto out_err; ++ } ++ ++ master->bus_num = pdata->bus_num; ++ master->num_chipselect = pdata->num_chipselect; ++ master->setup = bcm63xx_spi_setup; ++ master->transfer = bcm63xx_transfer; ++ bs->speed_hz = pdata->speed_hz; ++ bs->stopping = 0; ++ bs->tx_io = (u8 *)(bs->regs + bcm63xx_spireg(SPI_MSG_DATA)); ++ bs->rx_io = (const u8 *)(bs->regs + bcm63xx_spireg(SPI_RX_DATA)); ++ spin_lock_init(&bs->lock); ++ ++ /* Initialize hardware */ ++ clk_enable(bs->clk); ++ bcm_spi_writeb(bs, SPI_INTR_CLEAR_ALL, SPI_INT_STATUS); ++ ++ /* register and we are done */ ++ ret = spi_register_master(master); ++ if (ret) { ++ dev_err(dev, "spi register failed\n"); ++ goto out_clk_disable; ++ } ++ ++ dev_info(dev, "at 0x%08x (irq %d, FIFOs size %d) v%s\n", ++ r->start, irq, bs->fifo_size, DRV_VER); ++ ++ return 0; ++ ++out_clk_disable: ++ clk_disable(clk); ++out_err: ++ platform_set_drvdata(pdev, NULL); ++ spi_master_put(master); ++out_clk: ++ clk_put(clk); ++out: ++ return ret; ++} ++ ++static int __devexit bcm63xx_spi_remove(struct platform_device *pdev) ++{ ++ struct spi_master *master = platform_get_drvdata(pdev); ++ struct bcm63xx_spi *bs = spi_master_get_devdata(master); ++ ++ /* reset spi block */ ++ bcm_spi_writeb(bs, 0, SPI_INT_MASK); ++ spin_lock(&bs->lock); ++ bs->stopping = 1; ++ ++ /* HW shutdown */ ++ clk_disable(bs->clk); ++ clk_put(bs->clk); ++ ++ spin_unlock(&bs->lock); ++ platform_set_drvdata(pdev, 0); ++ spi_unregister_master(master); ++ ++ return 0; ++} ++ ++#ifdef CONFIG_PM ++static int bcm63xx_spi_suspend(struct device *dev) ++{ ++ struct spi_master *master = ++ platform_get_drvdata(to_platform_device(dev)); ++ struct bcm63xx_spi *bs = spi_master_get_devdata(master); ++ ++ clk_disable(bs->clk); ++ ++ return 0; ++} ++ ++static int bcm63xx_spi_resume(struct device *dev) ++{ ++ struct spi_master *master = ++ platform_get_drvdata(to_platform_device(dev)); ++ struct bcm63xx_spi *bs = spi_master_get_devdata(master); ++ ++ clk_enable(bs->clk); ++ ++ return 0; ++} ++ ++static const struct dev_pm_ops bcm63xx_spi_pm_ops = { ++ .suspend = bcm63xx_spi_suspend, ++ .resume = bcm63xx_spi_resume, ++}; ++ ++#define BCM63XX_SPI_PM_OPS (&bcm63xx_spi_pm_ops) ++#else ++#define BCM63XX_SPI_PM_OPS NULL ++#endif ++ ++static struct platform_driver bcm63xx_spi_driver = { ++ .driver = { ++ .name = "bcm63xx-spi", ++ .owner = THIS_MODULE, ++ .pm = BCM63XX_SPI_PM_OPS, ++ }, ++ .probe = bcm63xx_spi_probe, ++ .remove = __devexit_p(bcm63xx_spi_remove), ++}; ++ ++module_platform_driver(bcm63xx_spi_driver); ++ ++MODULE_ALIAS("platform:bcm63xx_spi"); ++MODULE_AUTHOR("Florian Fainelli <florian@openwrt.org>"); ++MODULE_AUTHOR("Tanguy Bouzeloc <tanguy.bouzeloc@efixo.com>"); ++MODULE_DESCRIPTION("Broadcom BCM63xx SPI Controller driver"); ++MODULE_LICENSE("GPL"); diff --git a/target/linux/brcm63xx/patches-3.3/300-reset_buttons.patch b/target/linux/brcm63xx/patches-3.3/300-reset_buttons.patch index ed0c56e627..ef57ff8bfa 100644 --- a/target/linux/brcm63xx/patches-3.3/300-reset_buttons.patch +++ b/target/linux/brcm63xx/patches-3.3/300-reset_buttons.patch @@ -9,7 +9,7 @@ #include <asm/addrspace.h> #include <bcm63xx_board.h> #include <bcm63xx_cpu.h> -@@ -294,6 +296,16 @@ static struct board_info __initdata boar +@@ -295,6 +297,16 @@ static struct board_info __initdata boar .active_low = 1, }, }, @@ -26,7 +26,7 @@ }; static struct board_info __initdata board_96348gw = { -@@ -352,6 +364,16 @@ static struct board_info __initdata boar +@@ -353,6 +365,16 @@ static struct board_info __initdata boar .active_low = 1, }, }, @@ -43,7 +43,7 @@ }; static struct board_info __initdata board_FAST2404 = { -@@ -850,12 +872,23 @@ static struct platform_device bcm63xx_gp +@@ -851,12 +873,23 @@ static struct platform_device bcm63xx_gp .dev.platform_data = &bcm63xx_led_data, }; @@ -67,7 +67,7 @@ if (board.has_uart0) bcm63xx_uart_register(0); -@@ -904,5 +937,16 @@ int __init board_register_devices(void) +@@ -907,5 +940,16 @@ int __init board_register_devices(void) platform_device_register(&bcm63xx_gpio_leds); diff --git a/target/linux/brcm63xx/patches-3.3/301-led_count.patch b/target/linux/brcm63xx/patches-3.3/301-led_count.patch index 6dfa42d994..11ed8924c1 100644 --- a/target/linux/brcm63xx/patches-3.3/301-led_count.patch +++ b/target/linux/brcm63xx/patches-3.3/301-led_count.patch @@ -1,6 +1,6 @@ --- a/arch/mips/bcm63xx/boards/board_bcm963xx.c +++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c -@@ -889,6 +889,7 @@ int __init board_register_devices(void) +@@ -890,6 +890,7 @@ int __init board_register_devices(void) { u32 val; int button_count = 0; @@ -8,7 +8,7 @@ if (board.has_uart0) bcm63xx_uart_register(0); -@@ -932,7 +933,11 @@ int __init board_register_devices(void) +@@ -935,7 +936,11 @@ int __init board_register_devices(void) platform_device_register(&mtd_dev); diff --git a/target/linux/brcm63xx/patches-3.3/302-extended-platform-devices.patch b/target/linux/brcm63xx/patches-3.3/302-extended-platform-devices.patch index 157899469e..8e0ecafe39 100644 --- a/target/linux/brcm63xx/patches-3.3/302-extended-platform-devices.patch +++ b/target/linux/brcm63xx/patches-3.3/302-extended-platform-devices.patch @@ -1,8 +1,8 @@ --- a/arch/mips/bcm63xx/boards/board_bcm963xx.c +++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c -@@ -924,6 +924,9 @@ int __init board_register_devices(void) - } - #endif +@@ -927,6 +927,9 @@ int __init board_register_devices(void) + + bcm63xx_spi_register(); + if (board.num_devs) + platform_add_devices(board.devs, board.num_devs); diff --git a/target/linux/brcm63xx/patches-3.3/303-spi-board-info.patch b/target/linux/brcm63xx/patches-3.3/303-spi-board-info.patch index 6218acd8e0..796852103a 100644 --- a/target/linux/brcm63xx/patches-3.3/303-spi-board-info.patch +++ b/target/linux/brcm63xx/patches-3.3/303-spi-board-info.patch @@ -1,6 +1,6 @@ --- a/arch/mips/bcm63xx/boards/board_bcm963xx.c +++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c -@@ -927,6 +927,9 @@ int __init board_register_devices(void) +@@ -930,6 +930,9 @@ int __init board_register_devices(void) if (board.num_devs) platform_add_devices(board.devs, board.num_devs); diff --git a/target/linux/brcm63xx/patches-3.3/304-boardid_fixup.patch b/target/linux/brcm63xx/patches-3.3/304-boardid_fixup.patch index 96b871dbfb..227a852797 100644 --- a/target/linux/brcm63xx/patches-3.3/304-boardid_fixup.patch +++ b/target/linux/brcm63xx/patches-3.3/304-boardid_fixup.patch @@ -1,8 +1,8 @@ --- a/arch/mips/bcm63xx/boards/board_bcm963xx.c +++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c -@@ -28,9 +28,13 @@ - #include <bcm63xx_dev_dsp.h> +@@ -29,9 +29,13 @@ #include <bcm63xx_dev_pcmcia.h> + #include <bcm63xx_dev_spi.h> #include <board_bcm963xx.h> +#include <bcm_tag.h> @@ -14,7 +14,7 @@ static struct bcm963xx_nvram nvram; static unsigned int mac_addr_used; static struct board_info board; -@@ -721,6 +725,29 @@ static int board_get_mac_address(u8 *mac +@@ -722,6 +726,29 @@ static int board_get_mac_address(u8 *mac return 0; } @@ -44,7 +44,7 @@ /* * early init callback, read nvram data from flash and checksum it */ -@@ -762,6 +789,11 @@ void __init board_prom_init(void) +@@ -763,6 +790,11 @@ void __init board_prom_init(void) return; } diff --git a/target/linux/brcm63xx/patches-3.3/402-add_bcm63xx_ohci_controller.patch b/target/linux/brcm63xx/patches-3.3/400-ohci-add-driver-for-bcm63xx-integrated-controller.patch index 34b251b97f..debbb13cd8 100644 --- a/target/linux/brcm63xx/patches-3.3/402-add_bcm63xx_ohci_controller.patch +++ b/target/linux/brcm63xx/patches-3.3/400-ohci-add-driver-for-bcm63xx-integrated-controller.patch @@ -1,7 +1,7 @@ -From f4aa3db2fb59983d45a9038daabad76102d32fc4 Mon Sep 17 00:00:00 2001 +From 7b510c5754d3c46e1287803f51e8ecb177414438 Mon Sep 17 00:00:00 2001 From: Maxime Bizon <mbizon@freebox.fr> Date: Fri, 10 Jun 2011 19:14:30 +0200 -Subject: [PATCH 20/57] ohci: add driver for bcm63xx integrated controller. +Subject: [PATCH 23/63] ohci: add driver for bcm63xx integrated controller. --- drivers/usb/host/Kconfig | 9 ++ diff --git a/target/linux/brcm63xx/patches-3.3/400-usb-ohci-support.patch b/target/linux/brcm63xx/patches-3.3/401-MIPS-BCM63XX-register-ohci-device.patch index 2913199bf8..06a3d98f5d 100644 --- a/target/linux/brcm63xx/patches-3.3/400-usb-ohci-support.patch +++ b/target/linux/brcm63xx/patches-3.3/401-MIPS-BCM63XX-register-ohci-device.patch @@ -1,7 +1,7 @@ -From 4ce192d5860760140439a3f305bc32f5e2316aa8 Mon Sep 17 00:00:00 2001 +From ab96f20ca1c3c8e7e5acd82d1e50823a5d572675 Mon Sep 17 00:00:00 2001 From: Maxime Bizon <mbizon@freebox.fr> Date: Tue, 24 May 2011 21:47:41 +0200 -Subject: [PATCH 21/57] MIPS: BCM63XX: register ohci device. +Subject: [PATCH 24/63] MIPS: BCM63XX: register ohci device. --- arch/mips/bcm63xx/Kconfig | 9 ++-- @@ -48,25 +48,25 @@ Subject: [PATCH 21/57] MIPS: BCM63XX: register ohci device. source "arch/mips/bcm63xx/boards/Kconfig" --- a/arch/mips/bcm63xx/Makefile +++ b/arch/mips/bcm63xx/Makefile -@@ -1,5 +1,6 @@ +@@ -1,6 +1,6 @@ obj-y += clk.o cpu.o cs.o gpio.o irq.o prom.o setup.o timer.o \ -- dev-dsp.o dev-enet.o dev-pcmcia.o dev-uart.o dev-wdt.o -+ dev-dsp.o dev-enet.o dev-pcmcia.o dev-uart.o \ + dev-dsp.o dev-enet.o dev-pcmcia.o dev-spi.o dev-uart.o \ +- dev-wdt.o + dev-usb-ohci.o dev-wdt.o obj-$(CONFIG_EARLY_PRINTK) += early_printk.o obj-y += boards/ --- a/arch/mips/bcm63xx/boards/board_bcm963xx.c +++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c -@@ -27,6 +27,7 @@ - #include <bcm63xx_dev_enet.h> +@@ -28,6 +28,7 @@ #include <bcm63xx_dev_dsp.h> #include <bcm63xx_dev_pcmcia.h> + #include <bcm63xx_dev_spi.h> +#include <bcm63xx_dev_usb_ohci.h> #include <board_bcm963xx.h> #include <bcm_tag.h> -@@ -940,6 +941,9 @@ int __init board_register_devices(void) +@@ -941,6 +942,9 @@ int __init board_register_devices(void) !board_get_mac_address(board.enet1.mac_addr)) bcm63xx_enet_register(1, &board.enet1); diff --git a/target/linux/brcm63xx/patches-3.3/403-add_bcm63xx_ehci_controller.patch b/target/linux/brcm63xx/patches-3.3/402-ehci-add-driver-for-bcm63xx-integrated-controller.patch index 969c3b78a4..b4de9fa53c 100644 --- a/target/linux/brcm63xx/patches-3.3/403-add_bcm63xx_ehci_controller.patch +++ b/target/linux/brcm63xx/patches-3.3/402-ehci-add-driver-for-bcm63xx-integrated-controller.patch @@ -1,7 +1,7 @@ -From 0f7d8ff44dc9e7048c141e6589bb590438cfc656 Mon Sep 17 00:00:00 2001 +From db58271d5152aa1d3894fdef13ca04379139d5d9 Mon Sep 17 00:00:00 2001 From: Maxime Bizon <mbizon@freebox.fr> Date: Fri, 10 Jun 2011 19:15:47 +0200 -Subject: [PATCH 22/57] ehci: add driver for bcm63xx integrated controller. +Subject: [PATCH 25/63] ehci: add driver for bcm63xx integrated controller. --- drivers/usb/host/Kconfig | 10 ++- diff --git a/target/linux/brcm63xx/patches-3.3/401-usb-ehci-support.patch b/target/linux/brcm63xx/patches-3.3/403-MIPS-BCM63XX-register-ehci-device.patch index e8b231e75e..1b6afd23f2 100644 --- a/target/linux/brcm63xx/patches-3.3/401-usb-ehci-support.patch +++ b/target/linux/brcm63xx/patches-3.3/403-MIPS-BCM63XX-register-ehci-device.patch @@ -1,7 +1,7 @@ -From 00fefa81d4919c72470ad68f05bc9e239108ca1b Mon Sep 17 00:00:00 2001 +From a2d78246e4cb45b5978fc682aad19c0fff0cd20d Mon Sep 17 00:00:00 2001 From: Maxime Bizon <mbizon@freebox.fr> Date: Tue, 24 May 2011 21:50:33 +0200 -Subject: [PATCH 23/57] MIPS: BCM63XX: register ehci device. +Subject: [PATCH 26/63] MIPS: BCM63XX: register ehci device. --- arch/mips/bcm63xx/Kconfig | 2 + @@ -33,7 +33,7 @@ Subject: [PATCH 23/57] MIPS: BCM63XX: register ehci device. +++ b/arch/mips/bcm63xx/Makefile @@ -1,6 +1,6 @@ obj-y += clk.o cpu.o cs.o gpio.o irq.o prom.o setup.o timer.o \ - dev-dsp.o dev-enet.o dev-pcmcia.o dev-uart.o \ + dev-dsp.o dev-enet.o dev-pcmcia.o dev-spi.o dev-uart.o \ - dev-usb-ohci.o dev-wdt.o + dev-usb-ehci.o dev-usb-ohci.o dev-wdt.o obj-$(CONFIG_EARLY_PRINTK) += early_printk.o @@ -41,15 +41,15 @@ Subject: [PATCH 23/57] MIPS: BCM63XX: register ehci device. obj-y += boards/ --- a/arch/mips/bcm63xx/boards/board_bcm963xx.c +++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c -@@ -28,6 +28,7 @@ - #include <bcm63xx_dev_dsp.h> +@@ -29,6 +29,7 @@ #include <bcm63xx_dev_pcmcia.h> + #include <bcm63xx_dev_spi.h> #include <bcm63xx_dev_usb_ohci.h> +#include <bcm63xx_dev_usb_ehci.h> #include <board_bcm963xx.h> #include <bcm_tag.h> -@@ -941,6 +942,9 @@ int __init board_register_devices(void) +@@ -942,6 +943,9 @@ int __init board_register_devices(void) !board_get_mac_address(board.enet1.mac_addr)) bcm63xx_enet_register(1, &board.enet1); diff --git a/target/linux/brcm63xx/patches-3.3/404-bcm963xx_flashmap.patch b/target/linux/brcm63xx/patches-3.3/404-bcm963xx_flashmap.patch index d058e185cb..4800d94fcf 100644 --- a/target/linux/brcm63xx/patches-3.3/404-bcm963xx_flashmap.patch +++ b/target/linux/brcm63xx/patches-3.3/404-bcm963xx_flashmap.patch @@ -12,7 +12,7 @@ Signed-off-by: Axel Gembe <ago@bastart.eu.org> --- a/arch/mips/bcm63xx/boards/board_bcm963xx.c +++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c -@@ -872,7 +872,7 @@ static struct mtd_partition mtd_partitio +@@ -873,7 +873,7 @@ static struct mtd_partition mtd_partitio } }; diff --git a/target/linux/brcm63xx/patches-3.3/408-6358-enet1-external-mii-clk.patch b/target/linux/brcm63xx/patches-3.3/408-6358-enet1-external-mii-clk.patch index 96e7ef1bf5..f98c6babea 100644 --- a/target/linux/brcm63xx/patches-3.3/408-6358-enet1-external-mii-clk.patch +++ b/target/linux/brcm63xx/patches-3.3/408-6358-enet1-external-mii-clk.patch @@ -1,6 +1,6 @@ --- a/arch/mips/bcm63xx/boards/board_bcm963xx.c +++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c -@@ -844,6 +844,8 @@ void __init board_prom_init(void) +@@ -845,6 +845,8 @@ void __init board_prom_init(void) if (BCMCPU_IS_6348()) val |= GPIO_MODE_6348_G3_EXT_MII | GPIO_MODE_6348_G0_EXT_MII; diff --git a/target/linux/brcm63xx/patches-3.3/409-spi.patch b/target/linux/brcm63xx/patches-3.3/409-spi.patch deleted file mode 100644 index 6fa06749ff..0000000000 --- a/target/linux/brcm63xx/patches-3.3/409-spi.patch +++ /dev/null @@ -1,904 +0,0 @@ ---- /dev/null -+++ b/arch/mips/bcm63xx/dev-spi.c -@@ -0,0 +1,99 @@ -+/* -+ * 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) 2009-2011 Florian Fainelli <florian@openwrt.org> -+ * Copyright (C) 2010 Tanguy Bouzeloc <tanguy.bouzeloc@efixo.com> -+ */ -+ -+#include <linux/init.h> -+#include <linux/kernel.h> -+#include <linux/platform_device.h> -+#include <linux/export.h> -+ -+#include <bcm63xx_cpu.h> -+#include <bcm63xx_dev_spi.h> -+#include <bcm63xx_regs.h> -+ -+#ifdef BCMCPU_RUNTIME_DETECT -+/* -+ * register offsets -+ */ -+static const unsigned long bcm96338_regs_spi[] = { -+ __GEN_SPI_REGS_TABLE(6338) -+}; -+ -+static const unsigned long bcm96348_regs_spi[] = { -+ __GEN_SPI_REGS_TABLE(6348) -+}; -+ -+static const unsigned long bcm96358_regs_spi[] = { -+ __GEN_SPI_REGS_TABLE(6358) -+}; -+ -+const unsigned long *bcm63xx_regs_spi; -+EXPORT_SYMBOL(bcm63xx_regs_spi); -+ -+static __init void bcm63xx_spi_regs_init(void) -+{ -+ if (BCMCPU_IS_6338()) -+ bcm63xx_regs_spi = bcm96338_regs_spi; -+ if (BCMCPU_IS_6348()) -+ bcm63xx_regs_spi = bcm96348_regs_spi; -+ if (BCMCPU_IS_6358()) -+ bcm63xx_regs_spi = bcm96358_regs_spi; -+} -+#else -+static __init void bcm63xx_spi_regs_init(void) { } -+#endif -+ -+static struct resource spi_resources[] = { -+ { -+ .start = -1, /* filled at runtime */ -+ .end = -1, /* filled at runtime */ -+ .flags = IORESOURCE_MEM, -+ }, -+ { -+ .start = -1, /* filled at runtime */ -+ .flags = IORESOURCE_IRQ, -+ }, -+}; -+ -+static struct bcm63xx_spi_pdata spi_pdata = { -+ .bus_num = 0, -+ .num_chipselect = 8, -+ .speed_hz = 50000000, /* Fclk */ -+}; -+ -+static struct platform_device bcm63xx_spi_device = { -+ .name = "bcm63xx-spi", -+ .id = 0, -+ .num_resources = ARRAY_SIZE(spi_resources), -+ .resource = spi_resources, -+ .dev = { -+ .platform_data = &spi_pdata, -+ }, -+}; -+ -+int __init bcm63xx_spi_register(void) -+{ -+ spi_resources[0].start = bcm63xx_regset_address(RSET_SPI); -+ spi_resources[0].end = spi_resources[0].start; -+ spi_resources[0].end += RSET_SPI_SIZE - 1; -+ spi_resources[1].start = bcm63xx_get_irq_number(IRQ_SPI); -+ -+ if (BCMCPU_IS_6345()) -+ return -ENODEV; -+ -+ /* Fill in platform data */ -+ if (BCMCPU_IS_6338() || BCMCPU_IS_6348()) -+ spi_pdata.fifo_size = SPI_BCM_6338_SPI_MSG_DATA_SIZE; -+ -+ if (BCMCPU_IS_6358()) -+ spi_pdata.fifo_size = SPI_BCM_6358_SPI_MSG_DATA_SIZE; -+ -+ bcm63xx_spi_regs_init(); -+ -+ return platform_device_register(&bcm63xx_spi_device); -+} ---- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h -+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h -@@ -138,6 +138,7 @@ enum bcm63xx_regs_set { - #define RSET_ENET_SIZE 2048 - #define RSET_ENETDMA_SIZE 2048 - #define RSET_ENETSW_SIZE 65536 -+#define RSET_SPI_SIZE 256 - #define RSET_UART_SIZE 24 - #define RSET_UDC_SIZE 256 - #define RSET_OHCI_SIZE 256 -@@ -289,7 +290,7 @@ enum bcm63xx_regs_set { - #define BCM_6358_UART0_BASE (0xfffe0100) - #define BCM_6358_UART1_BASE (0xfffe0120) - #define BCM_6358_GPIO_BASE (0xfffe0080) --#define BCM_6358_SPI_BASE (0xdeadbeef) -+#define BCM_6358_SPI_BASE (0xfffe0800) - #define BCM_6358_SPI2_BASE (0xfffe0800) - #define BCM_6358_UDC0_BASE (0xfffe0800) - #define BCM_6358_OHCI0_BASE (0xfffe1400) -@@ -478,6 +479,7 @@ static inline unsigned long bcm63xx_regs - */ - enum bcm63xx_irq { - IRQ_TIMER = 0, -+ IRQ_SPI, - IRQ_UART0, - IRQ_UART1, - IRQ_DSL, -@@ -569,6 +571,7 @@ enum bcm63xx_irq { - * 6348 irqs - */ - #define BCM_6348_TIMER_IRQ (IRQ_INTERNAL_BASE + 0) -+#define BCM_6348_SPI_IRQ (IRQ_INTERNAL_BASE + 1) - #define BCM_6348_UART0_IRQ (IRQ_INTERNAL_BASE + 2) - #define BCM_6348_UART1_IRQ 0 - #define BCM_6348_DSL_IRQ (IRQ_INTERNAL_BASE + 4) -@@ -599,6 +602,7 @@ enum bcm63xx_irq { - * 6358 irqs - */ - #define BCM_6358_TIMER_IRQ (IRQ_INTERNAL_BASE + 0) -+#define BCM_6358_SPI_IRQ (IRQ_INTERNAL_BASE + 1) - #define BCM_6358_UART0_IRQ (IRQ_INTERNAL_BASE + 2) - #define BCM_6358_UART1_IRQ (IRQ_INTERNAL_BASE + 3) - #define BCM_6358_DSL_IRQ (IRQ_INTERNAL_BASE + 29) ---- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h -+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h -@@ -976,4 +976,116 @@ - #define M2M_SRCID_REG(x) ((x) * 0x40 + 0x14) - #define M2M_DSTID_REG(x) ((x) * 0x40 + 0x18) - -+/************************************************************************* -+ * _REG relative to RSET_SPI -+ *************************************************************************/ -+ -+/* BCM 6338 SPI core */ -+#define SPI_BCM_6338_SPI_CMD 0x00 /* 16-bits register */ -+#define SPI_BCM_6338_SPI_INT_STATUS 0x02 -+#define SPI_BCM_6338_SPI_INT_MASK_ST 0x03 -+#define SPI_BCM_6338_SPI_INT_MASK 0x04 -+#define SPI_BCM_6338_SPI_ST 0x05 -+#define SPI_BCM_6338_SPI_CLK_CFG 0x06 -+#define SPI_BCM_6338_SPI_FILL_BYTE 0x07 -+#define SPI_BCM_6338_SPI_MSG_TAIL 0x09 -+#define SPI_BCM_6338_SPI_RX_TAIL 0x0b -+#define SPI_BCM_6338_SPI_MSG_CTL 0x40 -+#define SPI_BCM_6338_SPI_MSG_DATA 0x41 -+#define SPI_BCM_6338_SPI_MSG_DATA_SIZE 0x3f -+#define SPI_BCM_6338_SPI_RX_DATA 0x80 -+#define SPI_BCM_6338_SPI_RX_DATA_SIZE 0x3f -+ -+/* BCM 6348 SPI core */ -+#define SPI_BCM_6348_SPI_CMD 0x00 /* 16-bits register */ -+#define SPI_BCM_6348_SPI_INT_STATUS 0x02 -+#define SPI_BCM_6348_SPI_INT_MASK_ST 0x03 -+#define SPI_BCM_6348_SPI_INT_MASK 0x04 -+#define SPI_BCM_6348_SPI_ST 0x05 -+#define SPI_BCM_6348_SPI_CLK_CFG 0x06 -+#define SPI_BCM_6348_SPI_FILL_BYTE 0x07 -+#define SPI_BCM_6348_SPI_MSG_TAIL 0x09 -+#define SPI_BCM_6348_SPI_RX_TAIL 0x0b -+#define SPI_BCM_6348_SPI_MSG_CTL 0x40 -+#define SPI_BCM_6348_SPI_MSG_DATA 0x41 -+#define SPI_BCM_6348_SPI_MSG_DATA_SIZE 0x3f -+#define SPI_BCM_6348_SPI_RX_DATA 0x80 -+#define SPI_BCM_6348_SPI_RX_DATA_SIZE 0x3f -+ -+/* BCM 6358 SPI core */ -+#define SPI_BCM_6358_SPI_MSG_CTL 0x00 /* 16-bits register */ -+ -+#define SPI_BCM_6358_SPI_MSG_DATA 0x02 -+#define SPI_BCM_6358_SPI_MSG_DATA_SIZE 0x21e -+ -+#define SPI_BCM_6358_SPI_RX_DATA 0x400 -+#define SPI_BCM_6358_SPI_RX_DATA_SIZE 0x220 -+ -+#define SPI_BCM_6358_SPI_CMD 0x700 /* 16-bits register */ -+ -+#define SPI_BCM_6358_SPI_INT_STATUS 0x702 -+#define SPI_BCM_6358_SPI_INT_MASK_ST 0x703 -+ -+#define SPI_BCM_6358_SPI_INT_MASK 0x704 -+ -+#define SPI_BCM_6358_SPI_ST 0x705 -+ -+#define SPI_BCM_6358_SPI_CLK_CFG 0x706 -+ -+#define SPI_BCM_6358_SPI_FILL_BYTE 0x707 -+#define SPI_BCM_6358_SPI_MSG_TAIL 0x709 -+#define SPI_BCM_6358_SPI_RX_TAIL 0x70B -+ -+/* Shared SPI definitions */ -+ -+/* Message configuration */ -+#define SPI_FD_RW 0x00 -+#define SPI_HD_W 0x01 -+#define SPI_HD_R 0x02 -+#define SPI_BYTE_CNT_SHIFT 0 -+#define SPI_MSG_TYPE_SHIFT 14 -+ -+/* Command */ -+#define SPI_CMD_NOOP 0x00 -+#define SPI_CMD_SOFT_RESET 0x01 -+#define SPI_CMD_HARD_RESET 0x02 -+#define SPI_CMD_START_IMMEDIATE 0x03 -+#define SPI_CMD_COMMAND_SHIFT 0 -+#define SPI_CMD_COMMAND_MASK 0x000f -+#define SPI_CMD_DEVICE_ID_SHIFT 4 -+#define SPI_CMD_PREPEND_BYTE_CNT_SHIFT 8 -+#define SPI_CMD_ONE_BYTE_SHIFT 11 -+#define SPI_CMD_ONE_WIRE_SHIFT 12 -+#define SPI_DEV_ID_0 0 -+#define SPI_DEV_ID_1 1 -+#define SPI_DEV_ID_2 2 -+#define SPI_DEV_ID_3 3 -+ -+/* Interrupt mask */ -+#define SPI_INTR_CMD_DONE 0x01 -+#define SPI_INTR_RX_OVERFLOW 0x02 -+#define SPI_INTR_TX_UNDERFLOW 0x04 -+#define SPI_INTR_TX_OVERFLOW 0x08 -+#define SPI_INTR_RX_UNDERFLOW 0x10 -+#define SPI_INTR_CLEAR_ALL 0x1f -+ -+/* Status */ -+#define SPI_RX_EMPTY 0x02 -+#define SPI_CMD_BUSY 0x04 -+#define SPI_SERIAL_BUSY 0x08 -+ -+/* Clock configuration */ -+#define SPI_CLK_20MHZ 0x00 -+#define SPI_CLK_0_391MHZ 0x01 -+#define SPI_CLK_0_781MHZ 0x02 /* default */ -+#define SPI_CLK_1_563MHZ 0x03 -+#define SPI_CLK_3_125MHZ 0x04 -+#define SPI_CLK_6_250MHZ 0x05 -+#define SPI_CLK_12_50MHZ 0x06 -+#define SPI_CLK_25MHZ 0x07 -+#define SPI_CLK_MASK 0x07 -+#define SPI_SSOFFTIME_MASK 0x38 -+#define SPI_SSOFFTIME_SHIFT 3 -+#define SPI_BYTE_SWAP 0x80 -+ - #endif /* BCM63XX_REGS_H_ */ ---- /dev/null -+++ b/drivers/spi/bcm63xx_spi.c -@@ -0,0 +1,496 @@ -+/* -+ * Broadcom BCM63xx SPI controller support -+ * -+ * Copyright (C) 2009 Florian Fainelli <florian@openwrt.org> -+ * Copyright (C) 2010 Tanguy Bouzeloc <tanguy.bouzeloc@efixo.com> -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * as published by the Free Software Foundation; either version 2 -+ * of the License, or (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the -+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, -+ */ -+ -+#include <linux/kernel.h> -+#include <linux/init.h> -+#include <linux/clk.h> -+#include <linux/module.h> -+#include <linux/platform_device.h> -+#include <linux/delay.h> -+#include <linux/interrupt.h> -+#include <linux/spi/spi.h> -+#include <linux/completion.h> -+#include <linux/err.h> -+ -+#include <bcm63xx_dev_spi.h> -+ -+#define PFX KBUILD_MODNAME -+#define DRV_VER "0.1.2" -+ -+struct bcm63xx_spi { -+ spinlock_t lock; -+ int stopping; -+ struct completion done; -+ -+ void __iomem *regs; -+ int irq; -+ -+ /* Platform data */ -+ u32 speed_hz; -+ unsigned fifo_size; -+ -+ /* Data buffers */ -+ const unsigned char *tx_ptr; -+ unsigned char *rx_ptr; -+ -+ /* data iomem */ -+ u8 __iomem *tx_io; -+ const u8 __iomem *rx_io; -+ -+ int remaining_bytes; -+ -+ struct clk *clk; -+ struct platform_device *pdev; -+}; -+ -+static inline u8 bcm_spi_readb(struct bcm63xx_spi *bs, -+ unsigned int offset) -+{ -+ return bcm_readw(bs->regs + bcm63xx_spireg(offset)); -+} -+ -+static inline u16 bcm_spi_readw(struct bcm63xx_spi *bs, -+ unsigned int offset) -+{ -+ return bcm_readw(bs->regs + bcm63xx_spireg(offset)); -+} -+ -+static inline void bcm_spi_writeb(struct bcm63xx_spi *bs, -+ u8 value, unsigned int offset) -+{ -+ bcm_writeb(value, bs->regs + bcm63xx_spireg(offset)); -+} -+ -+static inline void bcm_spi_writew(struct bcm63xx_spi *bs, -+ u16 value, unsigned int offset) -+{ -+ bcm_writew(value, bs->regs + bcm63xx_spireg(offset)); -+} -+ -+static int bcm63xx_spi_setup_transfer(struct spi_device *spi, -+ struct spi_transfer *t) -+{ -+ u8 bits_per_word; -+ u8 clk_cfg; -+ u32 hz; -+ unsigned int div; -+ -+ struct bcm63xx_spi *bs = spi_master_get_devdata(spi->master); -+ -+ bits_per_word = (t) ? t->bits_per_word : spi->bits_per_word; -+ hz = (t) ? t->speed_hz : spi->max_speed_hz; -+ if (bits_per_word != 8) { -+ dev_err(&spi->dev, "%s, unsupported bits_per_word=%d\n", -+ __func__, bits_per_word); -+ return -EINVAL; -+ } -+ -+ if (spi->chip_select > spi->master->num_chipselect) { -+ dev_err(&spi->dev, "%s, unsupported slave %d\n", -+ __func__, spi->chip_select); -+ return -EINVAL; -+ } -+ -+ /* Check clock setting */ -+ div = (bs->speed_hz / hz); -+ switch (div) { -+ case 2: -+ clk_cfg = SPI_CLK_25MHZ; -+ break; -+ case 4: -+ clk_cfg = SPI_CLK_12_50MHZ; -+ break; -+ case 8: -+ clk_cfg = SPI_CLK_6_250MHZ; -+ break; -+ case 16: -+ clk_cfg = SPI_CLK_3_125MHZ; -+ break; -+ case 32: -+ clk_cfg = SPI_CLK_1_563MHZ; -+ break; -+ case 64: -+ clk_cfg = SPI_CLK_0_781MHZ; -+ break; -+ case 128: -+ default: -+ /* Set to slowest mode for compatibility */ -+ clk_cfg = SPI_CLK_0_391MHZ; -+ break; -+ } -+ -+ bcm_spi_writeb(bs, clk_cfg, SPI_CLK_CFG); -+ dev_dbg(&spi->dev, "Setting clock register to %d (hz %d, cmd %02x)\n", -+ div, hz, clk_cfg); -+ -+ return 0; -+} -+ -+/* the spi->mode bits understood by this driver: */ -+#define MODEBITS (SPI_CPOL | SPI_CPHA) -+ -+static int bcm63xx_spi_setup(struct spi_device *spi) -+{ -+ struct bcm63xx_spi *bs; -+ int ret; -+ -+ bs = spi_master_get_devdata(spi->master); -+ -+ if (bs->stopping) -+ return -ESHUTDOWN; -+ -+ if (!spi->bits_per_word) -+ spi->bits_per_word = 8; -+ -+ if (spi->mode & ~MODEBITS) { -+ dev_err(&spi->dev, "%s, unsupported mode bits %x\n", -+ __func__, spi->mode & ~MODEBITS); -+ return -EINVAL; -+ } -+ -+ ret = bcm63xx_spi_setup_transfer(spi, NULL); -+ if (ret < 0) { -+ dev_err(&spi->dev, "setup: unsupported mode bits %x\n", -+ spi->mode & ~MODEBITS); -+ return ret; -+ } -+ -+ dev_dbg(&spi->dev, "%s, mode %d, %u bits/w, %u nsec/bit\n", -+ __func__, spi->mode & MODEBITS, spi->bits_per_word, 0); -+ -+ return 0; -+} -+ -+/* Fill the TX FIFO with as many bytes as possible */ -+static void bcm63xx_spi_fill_tx_fifo(struct bcm63xx_spi *bs) -+{ -+ u8 size; -+ -+ /* Fill the Tx FIFO with as many bytes as possible */ -+ size = bs->remaining_bytes < bs->fifo_size ? bs->remaining_bytes : -+ bs->fifo_size; -+ memcpy_toio(bs->tx_io, bs->tx_ptr, size); -+ bs->remaining_bytes -= size; -+} -+ -+static int bcm63xx_txrx_bufs(struct spi_device *spi, struct spi_transfer *t) -+{ -+ struct bcm63xx_spi *bs = spi_master_get_devdata(spi->master); -+ u16 msg_ctl; -+ u16 cmd; -+ -+ dev_dbg(&spi->dev, "txrx: tx %p, rx %p, len %d\n", -+ t->tx_buf, t->rx_buf, t->len); -+ -+ /* Transmitter is inhibited */ -+ bs->tx_ptr = t->tx_buf; -+ bs->rx_ptr = t->rx_buf; -+ init_completion(&bs->done); -+ -+ if (t->tx_buf) { -+ bs->remaining_bytes = t->len; -+ bcm63xx_spi_fill_tx_fifo(bs); -+ } -+ -+ /* Enable the command done interrupt which -+ * we use to determine completion of a command */ -+ bcm_spi_writeb(bs, SPI_INTR_CMD_DONE, SPI_INT_MASK); -+ -+ /* Fill in the Message control register */ -+ msg_ctl = (t->len << SPI_BYTE_CNT_SHIFT); -+ -+ if (t->rx_buf && t->tx_buf) -+ msg_ctl |= (SPI_FD_RW << SPI_MSG_TYPE_SHIFT); -+ else if (t->rx_buf) -+ msg_ctl |= (SPI_HD_R << SPI_MSG_TYPE_SHIFT); -+ else if (t->tx_buf) -+ msg_ctl |= (SPI_HD_W << SPI_MSG_TYPE_SHIFT); -+ -+ bcm_spi_writew(bs, msg_ctl, SPI_MSG_CTL); -+ -+ /* Issue the transfer */ -+ cmd = SPI_CMD_START_IMMEDIATE; -+ cmd |= (0 << SPI_CMD_PREPEND_BYTE_CNT_SHIFT); -+ cmd |= (spi->chip_select << SPI_CMD_DEVICE_ID_SHIFT); -+ bcm_spi_writew(bs, cmd, SPI_CMD); -+ wait_for_completion(&bs->done); -+ -+ /* Disable the CMD_DONE interrupt */ -+ bcm_spi_writeb(bs, 0, SPI_INT_MASK); -+ -+ return t->len - bs->remaining_bytes; -+} -+ -+static int bcm63xx_transfer(struct spi_device *spi, struct spi_message *m) -+{ -+ struct bcm63xx_spi *bs = spi_master_get_devdata(spi->master); -+ struct spi_transfer *t; -+ int ret = 0; -+ -+ if (unlikely(list_empty(&m->transfers))) -+ return -EINVAL; -+ -+ if (bs->stopping) -+ return -ESHUTDOWN; -+ -+ list_for_each_entry(t, &m->transfers, transfer_list) { -+ ret += bcm63xx_txrx_bufs(spi, t); -+ } -+ -+ m->complete(m->context); -+ -+ return ret; -+} -+ -+/* This driver supports single master mode only. Hence -+ * CMD_DONE is the only interrupt we care about -+ */ -+static irqreturn_t bcm63xx_spi_interrupt(int irq, void *dev_id) -+{ -+ struct spi_master *master = (struct spi_master *)dev_id; -+ struct bcm63xx_spi *bs = spi_master_get_devdata(master); -+ u8 intr; -+ u16 cmd; -+ -+ /* Read interupts and clear them immediately */ -+ intr = bcm_spi_readb(bs, SPI_INT_STATUS); -+ bcm_spi_writeb(bs, SPI_INTR_CLEAR_ALL, SPI_INT_STATUS); -+ bcm_spi_writeb(bs, 0, SPI_INT_MASK); -+ -+ /* A tansfer completed */ -+ if (intr & SPI_INTR_CMD_DONE) { -+ u8 rx_tail; -+ -+ rx_tail = bcm_spi_readb(bs, SPI_RX_TAIL); -+ -+ /* Read out all the data */ -+ if (rx_tail) -+ memcpy_fromio(bs->rx_ptr, bs->rx_io, rx_tail); -+ -+ /* See if there is more data to send */ -+ if (bs->remaining_bytes > 0) { -+ bcm63xx_spi_fill_tx_fifo(bs); -+ -+ /* Start the transfer */ -+ bcm_spi_writew(bs, SPI_HD_W << SPI_MSG_TYPE_SHIFT, -+ SPI_MSG_CTL); -+ cmd = bcm_spi_readw(bs, SPI_CMD); -+ cmd |= SPI_CMD_START_IMMEDIATE; -+ cmd |= (0 << SPI_CMD_PREPEND_BYTE_CNT_SHIFT); -+ bcm_spi_writeb(bs, SPI_INTR_CMD_DONE, SPI_INT_MASK); -+ bcm_spi_writew(bs, cmd, SPI_CMD); -+ } else { -+ complete(&bs->done); -+ } -+ } -+ -+ return IRQ_HANDLED; -+} -+ -+ -+static int __init bcm63xx_spi_probe(struct platform_device *pdev) -+{ -+ struct resource *r; -+ struct device *dev = &pdev->dev; -+ struct bcm63xx_spi_pdata *pdata = pdev->dev.platform_data; -+ int irq; -+ struct spi_master *master; -+ struct clk *clk; -+ struct bcm63xx_spi *bs; -+ int ret; -+ -+ r = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ if (!r) { -+ dev_err(dev, "no iomem\n"); -+ ret = -ENXIO; -+ goto out; -+ } -+ -+ irq = platform_get_irq(pdev, 0); -+ if (irq < 0) { -+ dev_err(dev, "no irq\n"); -+ ret = -ENXIO; -+ goto out; -+ } -+ -+ clk = clk_get(dev, "spi"); -+ if (IS_ERR(clk)) { -+ dev_err(dev, "no clock for device\n"); -+ ret = -ENODEV; -+ goto out; -+ } -+ -+ master = spi_alloc_master(dev, sizeof(*bs)); -+ if (!master) { -+ dev_err(dev, "out of memory\n"); -+ ret = -ENOMEM; -+ goto out_free; -+ } -+ -+ bs = spi_master_get_devdata(master); -+ init_completion(&bs->done); -+ -+ platform_set_drvdata(pdev, master); -+ bs->pdev = pdev; -+ -+ if (!request_mem_region(r->start, r->end - r->start, PFX)) { -+ dev_err(dev, "iomem request failed\n"); -+ ret = -ENXIO; -+ goto out_put_master; -+ } -+ -+ bs->regs = ioremap_nocache(r->start, r->end - r->start); -+ if (!bs->regs) { -+ dev_err(dev, "unable to ioremap regs\n"); -+ ret = -ENOMEM; -+ goto out_put_master; -+ } -+ bs->irq = irq; -+ bs->clk = clk; -+ bs->fifo_size = pdata->fifo_size; -+ -+ ret = request_irq(irq, bcm63xx_spi_interrupt, 0, pdev->name, master); -+ if (ret) { -+ dev_err(dev, "unable to request irq\n"); -+ goto out_unmap; -+ } -+ -+ master->bus_num = pdata->bus_num; -+ master->num_chipselect = pdata->num_chipselect; -+ master->setup = bcm63xx_spi_setup; -+ master->transfer = bcm63xx_transfer; -+ bs->speed_hz = pdata->speed_hz; -+ bs->stopping = 0; -+ bs->tx_io = (u8*)(bs->regs + bcm63xx_spireg(SPI_MSG_DATA)); -+ bs->rx_io = (const u8*)(bs->regs + bcm63xx_spireg(SPI_RX_DATA)); -+ spin_lock_init(&bs->lock); -+ -+ /* Initialize hardware */ -+ clk_enable(bs->clk); -+ bcm_spi_writeb(bs, SPI_INTR_CLEAR_ALL, SPI_INT_STATUS); -+ -+ /* register and we are done */ -+ ret = spi_register_master(master); -+ if (ret) { -+ dev_err(dev, "spi register failed\n"); -+ goto out_reset_hw; -+ } -+ -+ dev_info(dev, "at 0x%08x (irq %d, FIFOs size %d) v%s\n", -+ r->start, irq, bs->fifo_size, DRV_VER); -+ -+ return 0; -+ -+out_reset_hw: -+ clk_disable(clk); -+ free_irq(irq, master); -+out_unmap: -+ iounmap(bs->regs); -+out_put_master: -+ spi_master_put(master); -+out_free: -+ clk_put(clk); -+out: -+ return ret; -+} -+ -+static int __exit bcm63xx_spi_remove(struct platform_device *pdev) -+{ -+ struct spi_master *master = platform_get_drvdata(pdev); -+ struct bcm63xx_spi *bs = spi_master_get_devdata(master); -+ struct resource *r = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ -+ /* reset spi block */ -+ bcm_spi_writeb(bs, 0, SPI_INT_MASK); -+ spin_lock(&bs->lock); -+ bs->stopping = 1; -+ -+ /* HW shutdown */ -+ clk_disable(bs->clk); -+ clk_put(bs->clk); -+ -+ spin_unlock(&bs->lock); -+ -+ free_irq(bs->irq, master); -+ iounmap(bs->regs); -+ release_mem_region(r->start, r->end - r->start); -+ platform_set_drvdata(pdev, 0); -+ spi_unregister_master(master); -+ -+ return 0; -+} -+ -+#ifdef CONFIG_PM -+static int bcm63xx_spi_suspend(struct platform_device *pdev, pm_message_t mesg) -+{ -+ struct spi_master *master = platform_get_drvdata(pdev); -+ struct bcm63xx_spi *bs = spi_master_get_devdata(master); -+ -+ clk_disable(bs->clk); -+ -+ return 0; -+} -+ -+static int bcm63xx_spi_resume(struct platform_device *pdev) -+{ -+ struct spi_master *master = platform_get_drvdata(pdev); -+ struct bcm63xx_spi *bs = spi_master_get_devdata(master); -+ -+ clk_enable(bs->clk); -+ -+ return 0; -+} -+#else -+#define bcm63xx_spi_suspend NULL -+#define bcm63xx_spi_resume NULL -+#endif -+ -+static struct platform_driver bcm63xx_spi_driver = { -+ .driver = { -+ .name = "bcm63xx-spi", -+ .owner = THIS_MODULE, -+ }, -+ .probe = bcm63xx_spi_probe, -+ .remove = __exit_p(bcm63xx_spi_remove), -+ .suspend = bcm63xx_spi_suspend, -+ .resume = bcm63xx_spi_resume, -+}; -+ -+ -+static int __init bcm63xx_spi_init(void) -+{ -+ return platform_driver_register(&bcm63xx_spi_driver); -+} -+ -+static void __exit bcm63xx_spi_exit(void) -+{ -+ platform_driver_unregister(&bcm63xx_spi_driver); -+} -+ -+module_init(bcm63xx_spi_init); -+module_exit(bcm63xx_spi_exit); -+ -+MODULE_ALIAS("platform:bcm63xx_spi"); -+MODULE_AUTHOR("Florian Fainelli <florian@openwrt.org>"); -+MODULE_AUTHOR("Tanguy Bouzeloc <tanguy.bouzeloc@efixo.com>"); -+MODULE_DESCRIPTION("Broadcom BCM63xx SPI Controller driver"); -+MODULE_LICENSE("GPL"); -+MODULE_VERSION(DRV_VER); ---- a/drivers/spi/Kconfig -+++ b/drivers/spi/Kconfig -@@ -74,6 +74,12 @@ config SPI_ATMEL - This selects a driver for the Atmel SPI Controller, present on - many AT32 (AVR32) and AT91 (ARM) chips. - -+config SPI_BCM63XX -+ tristate "Broadcom BCM63xx SPI controller" -+ depends on BCM63XX -+ help -+ This is the SPI controller master driver for Broadcom BCM63xx SoC. -+ - config SPI_BFIN - tristate "SPI controller driver for ADI Blackfin5xx" - depends on BLACKFIN ---- a/drivers/spi/Makefile -+++ b/drivers/spi/Makefile -@@ -14,6 +14,7 @@ obj-$(CONFIG_SPI_ALTERA) += spi-altera. - obj-$(CONFIG_SPI_ATMEL) += spi-atmel.o - obj-$(CONFIG_SPI_ATH79) += spi-ath79.o - obj-$(CONFIG_SPI_AU1550) += spi-au1550.o -+obj-$(CONFIG_SPI_BCM63XX) += bcm63xx_spi.o - obj-$(CONFIG_SPI_BFIN) += spi-bfin5xx.o - obj-$(CONFIG_SPI_BFIN_SPORT) += spi-bfin-sport.o - obj-$(CONFIG_SPI_BITBANG) += spi-bitbang.o ---- /dev/null -+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_spi.h -@@ -0,0 +1,85 @@ -+#ifndef BCM63XX_DEV_SPI_H -+#define BCM63XX_DEV_SPI_H -+ -+#include <linux/types.h> -+#include <bcm63xx_io.h> -+#include <bcm63xx_regs.h> -+ -+int __init bcm63xx_spi_register(void); -+ -+struct bcm63xx_spi_pdata { -+ unsigned int fifo_size; -+ int bus_num; -+ int num_chipselect; -+ u32 speed_hz; -+}; -+ -+enum bcm63xx_regs_spi { -+ SPI_CMD, -+ SPI_INT_STATUS, -+ SPI_INT_MASK_ST, -+ SPI_INT_MASK, -+ SPI_ST, -+ SPI_CLK_CFG, -+ SPI_FILL_BYTE, -+ SPI_MSG_TAIL, -+ SPI_RX_TAIL, -+ SPI_MSG_CTL, -+ SPI_MSG_DATA, -+ SPI_RX_DATA, -+}; -+ -+#define __GEN_SPI_RSET_BASE(__cpu, __rset) \ -+ case SPI_## __rset: \ -+ return SPI_BCM_## __cpu ##_SPI_## __rset; -+ -+#define __GEN_SPI_RSET(__cpu) \ -+ switch (reg) { \ -+ __GEN_SPI_RSET_BASE(__cpu, CMD) \ -+ __GEN_SPI_RSET_BASE(__cpu, INT_STATUS) \ -+ __GEN_SPI_RSET_BASE(__cpu, INT_MASK_ST) \ -+ __GEN_SPI_RSET_BASE(__cpu, INT_MASK) \ -+ __GEN_SPI_RSET_BASE(__cpu, ST) \ -+ __GEN_SPI_RSET_BASE(__cpu, CLK_CFG) \ -+ __GEN_SPI_RSET_BASE(__cpu, FILL_BYTE) \ -+ __GEN_SPI_RSET_BASE(__cpu, MSG_TAIL) \ -+ __GEN_SPI_RSET_BASE(__cpu, RX_TAIL) \ -+ __GEN_SPI_RSET_BASE(__cpu, MSG_CTL) \ -+ __GEN_SPI_RSET_BASE(__cpu, MSG_DATA) \ -+ __GEN_SPI_RSET_BASE(__cpu, RX_DATA) \ -+ } -+ -+#define __GEN_SPI_REGS_TABLE(__cpu) \ -+ [SPI_CMD] = SPI_BCM_## __cpu ##_SPI_CMD, \ -+ [SPI_INT_STATUS] = SPI_BCM_## __cpu ##_SPI_INT_STATUS, \ -+ [SPI_INT_MASK_ST] = SPI_BCM_## __cpu ##_SPI_INT_MASK_ST, \ -+ [SPI_INT_MASK] = SPI_BCM_## __cpu ##_SPI_INT_MASK, \ -+ [SPI_ST] = SPI_BCM_## __cpu ##_SPI_ST, \ -+ [SPI_CLK_CFG] = SPI_BCM_## __cpu ##_SPI_CLK_CFG, \ -+ [SPI_FILL_BYTE] = SPI_BCM_## __cpu ##_SPI_FILL_BYTE, \ -+ [SPI_MSG_TAIL] = SPI_BCM_## __cpu ##_SPI_MSG_TAIL, \ -+ [SPI_RX_TAIL] = SPI_BCM_## __cpu ##_SPI_RX_TAIL, \ -+ [SPI_MSG_CTL] = SPI_BCM_## __cpu ##_SPI_MSG_CTL, \ -+ [SPI_MSG_DATA] = SPI_BCM_## __cpu ##_SPI_MSG_DATA, \ -+ [SPI_RX_DATA] = SPI_BCM_## __cpu ##_SPI_RX_DATA, -+ -+static inline unsigned long bcm63xx_spireg(enum bcm63xx_regs_spi reg) -+{ -+#ifdef BCMCPU_RUNTIME_DETECT -+ extern const unsigned long *bcm63xx_regs_spi; -+ return bcm63xx_regs_spi[reg]; -+#else -+#ifdef CONFIG_BCM63XX_CPU_6338 -+ __GEN_SPI_RSET(6338) -+#endif -+#ifdef CONFIG_BCM63XX_CPU_6348 -+ __GEN_SPI_RSET(6348) -+#endif -+#ifdef CONFIG_BCM63XX_CPU_6358 -+ __GEN_SPI_RSET(6358) -+#endif -+#endif -+ return 0; -+} -+ -+#endif /* BCM63XX_DEV_SPI_H */ ---- a/arch/mips/bcm63xx/Makefile -+++ b/arch/mips/bcm63xx/Makefile -@@ -1,5 +1,5 @@ - obj-y += clk.o cpu.o cs.o gpio.o irq.o prom.o setup.o timer.o \ -- dev-dsp.o dev-enet.o dev-pcmcia.o dev-uart.o \ -+ dev-dsp.o dev-enet.o dev-pcmcia.o dev-spi.o dev-uart.o \ - dev-usb-ehci.o dev-usb-ohci.o dev-wdt.o - obj-$(CONFIG_EARLY_PRINTK) += early_printk.o - ---- a/arch/mips/bcm63xx/boards/board_bcm963xx.c -+++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c -@@ -29,6 +29,7 @@ - #include <bcm63xx_dev_pcmcia.h> - #include <bcm63xx_dev_usb_ohci.h> - #include <bcm63xx_dev_usb_ehci.h> -+#include <bcm63xx_dev_spi.h> - #include <board_bcm963xx.h> - #include <bcm_tag.h> - -@@ -972,6 +973,8 @@ int __init board_register_devices(void) - if (board.num_spis) - spi_register_board_info(board.spis, board.num_spis); - -+ bcm63xx_spi_register(); -+ - /* read base address of boot chip select (0) */ - val = bcm_mpi_readl(MPI_CSBASE_REG(0)); - val &= MPI_CSBASE_BASE_MASK; diff --git a/target/linux/brcm63xx/patches-3.3/414-bcm63xx_enet-split-dma-registers-access.patch b/target/linux/brcm63xx/patches-3.3/414-bcm63xx_enet-split-dma-registers-access.patch index 483ff38140..7550f6d233 100644 --- a/target/linux/brcm63xx/patches-3.3/414-bcm63xx_enet-split-dma-registers-access.patch +++ b/target/linux/brcm63xx/patches-3.3/414-bcm63xx_enet-split-dma-registers-access.patch @@ -50,17 +50,17 @@ Subject: [PATCH 30/63] bcm63xx_enet: split dma registers access. if (ret) --- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h +++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h -@@ -136,7 +136,9 @@ enum bcm63xx_regs_set { - #define RSET_DSL_SIZE 4096 - #define RSET_WDT_SIZE 12 +@@ -139,7 +139,9 @@ enum bcm63xx_regs_set { + #define BCM_6358_RSET_SPI_SIZE 1804 + #define BCM_6368_RSET_SPI_SIZE 1804 #define RSET_ENET_SIZE 2048 -#define RSET_ENETDMA_SIZE 2048 +#define RSET_ENETDMA_SIZE 256 +#define RSET_ENETDMAC_SIZE(chans) (16 * (chans)) +#define RSET_ENETDMAS_SIZE(chans) (16 * (chans)) #define RSET_ENETSW_SIZE 65536 - #define RSET_SPI_SIZE 256 #define RSET_UART_SIZE 24 + #define RSET_UDC_SIZE 256 --- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c +++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c @@ -41,8 +41,8 @@ static int copybreak __read_mostly = 128 |