ARM: Marvell MMP driver patches for v5.5

This tag includes the MMP3 USB2 PHY driver. The branch is based on
 mmp-soc-for-v5.5-2 because the driver depends on changes in MMP SoC
 support.
 -----BEGIN PGP SIGNATURE-----
 
 iQFDBAABCAAtFiEENyn6vISEy07peidTpxZjkszkJRYFAl2ofwsPHGxrdW5kcmFr
 QHYzLnNrAAoJEKcWY5LM5CUWzYsH/iLvSgoDVR+TLxEYQJcpdCCC3tfxBUDYrCvA
 hfpf7SuaNHexgrqSl194eoMJ8nmnvcEimGrj3Xgr1iJXge4ECv/fti+aQT1rOUOL
 EThqYPDQennCEjfNFBJVAk7mLSHVjrN0d4ItTl11Oxk38rYQFtlq2Z0gNOVU2eJG
 n8Orbkwxck2ILDnYfWodPnYAZXa5FOozdp7zOP1sGRztohLTY6JG1vCC++ylM3T3
 1HxxwVxGNDzLsgjs/R4A4eSmmHIPQ0BlGi6QCJOcqmXGYelUDPHNnDpo58itC7sQ
 D2ClZkEKDqdE4uheknUe+q/gzya6eALqwaBsVVYhBZmLSMBLdgQ=
 =3qa/
 -----END PGP SIGNATURE-----

Merge tag 'mmp-drivers-for-v5.5' of git://git.kernel.org/pub/scm/linux/kernel/git/lkundrak/linux-mmp into arm/drivers

ARM: Marvell MMP driver patches for v5.5

This tag includes the MMP3 USB2 PHY driver. The branch is based on
mmp-soc-for-v5.5-2 because the driver depends on changes in MMP SoC
support.

* tag 'mmp-drivers-for-v5.5' of git://git.kernel.org/pub/scm/linux/kernel/git/lkundrak/linux-mmp:
  MAINTAINERS: phy: add entry for USB PHY drivers on MMP SoCs
  phy: Add USB2 PHY driver for Marvell MMP3 SoC
  MAINTAINERS: mmp: add Git repository
  ARM: mmp: remove MMP3 USB PHY registers from regs-usb.h
  ARM: mmp: move cputype.h to include/linux/soc/
  ARM: mmp: add SMP support
  ARM: mmp: add support for MMP3 SoC
  ARM: mmp: define MMP_CHIPID by the means of CIU_REG()
  ARM: mmp: DT: convert timer driver to use TIMER_OF_DECLARE
  ARM: mmp: map the PGU as well
  ARM: mmp: don't select CACHE_TAUROS2 on all ARCH_MMP
  ARM: l2c: add definition for FWA in PL310 aux register

Link: https://lore.kernel.org/r/7cee3ddbb553ba7fe6e1420e0dbc5adb4922b317.camel@v3.sk
Signed-off-by: Olof Johansson <olof@lixom.net>
This commit is contained in:
Olof Johansson 2019-10-21 15:31:06 -07:00
commit d0862daf0f
27 changed files with 484 additions and 142 deletions

View file

@ -10917,9 +10917,18 @@ F: drivers/media/radio/radio-miropcm20*
MMP SUPPORT
R: Lubomir Rintel <lkundrak@v3.sk>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
T: git git://git.kernel.org/pub/scm/linux/kernel/git/lkundrak/linux-mmp.git
S: Odd Fixes
F: arch/arm/boot/dts/mmp*
F: arch/arm/mach-mmp/
F: linux/soc/mmp/
MMP USB PHY DRIVERS
R: Lubomir Rintel <lkundrak@v3.sk>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
F: drivers/phy/marvell/phy-mmp3-usb.c
F: drivers/phy/marvell/phy-pxa-usb.c
MMU GATHER AND TLB INVALIDATION
M: Will Deacon <will@kernel.org>

View file

@ -118,6 +118,8 @@
#define L310_AUX_CTRL_STORE_LIMITATION BIT(11) /* R2P0+ */
#define L310_AUX_CTRL_EXCLUSIVE_CACHE BIT(12)
#define L310_AUX_CTRL_ASSOCIATIVITY_16 BIT(16)
#define L310_AUX_CTRL_FWA_SHIFT 23
#define L310_AUX_CTRL_FWA_MASK (3 << 23)
#define L310_AUX_CTRL_CACHE_REPLACE_RR BIT(25) /* R2P0+ */
#define L310_AUX_CTRL_NS_LOCKDOWN BIT(26)
#define L310_AUX_CTRL_NS_INT_CTRL BIT(27)

View file

@ -1,13 +1,13 @@
# SPDX-License-Identifier: GPL-2.0-only
menuconfig ARCH_MMP
bool "Marvell PXA168/910/MMP2"
bool "Marvell PXA168/910/MMP2/MMP3"
depends on ARCH_MULTI_V5 || ARCH_MULTI_V7
select GPIO_PXA
select GPIOLIB
select PINCTRL
select PLAT_PXA
help
Support for Marvell's PXA168/PXA910(MMP) and MMP2 processor line.
Support for Marvell's PXA168/PXA910(MMP), MMP2, and MMP3 processor lines.
if ARCH_MMP
@ -129,6 +129,24 @@ config MACH_MMP2_DT
Include support for Marvell MMP2 based platforms using
the device tree.
config MACH_MMP3_DT
bool "Support MMP3 (ARMv7) platforms"
depends on ARCH_MULTI_V7
select ARM_GIC
select HAVE_ARM_SCU if SMP
select HAVE_ARM_TWD if SMP
select CACHE_L2X0
select PINCTRL
select PINCTRL_SINGLE
select ARCH_HAS_RESET_CONTROLLER
select CPU_PJ4B
select PM_GENERIC_DOMAINS if PM
select PM_GENERIC_DOMAINS_OF if PM && OF
help
Say 'Y' here if you want to include support for platforms
with Marvell MMP3 processor, also known as PXA2128 or
Armada 620.
endmenu
config CPU_PXA168

View file

@ -22,6 +22,9 @@ ifeq ($(CONFIG_PM),y)
obj-$(CONFIG_CPU_PXA910) += pm-pxa910.o
obj-$(CONFIG_CPU_MMP2) += pm-mmp2.o
endif
ifeq ($(CONFIG_SMP),y)
obj-$(CONFIG_MACH_MMP3_DT) += platsmp.o
endif
# board support
obj-$(CONFIG_MACH_ASPENITE) += aspenite.o
@ -34,5 +37,6 @@ obj-$(CONFIG_MACH_FLINT) += flint.o
obj-$(CONFIG_MACH_MARVELL_JASPER) += jasper.o
obj-$(CONFIG_MACH_MMP_DT) += mmp-dt.o
obj-$(CONFIG_MACH_MMP2_DT) += mmp2-dt.o
obj-$(CONFIG_MACH_MMP3_DT) += mmp3.o
obj-$(CONFIG_MACH_TETON_BGA) += teton_bga.o
obj-$(CONFIG_MACH_GPLUGD) += gplugd.o

View file

@ -20,6 +20,10 @@
#define AXI_VIRT_BASE IOMEM(0xfe200000)
#define AXI_PHYS_SIZE 0x00200000
#define PGU_PHYS_BASE 0xe0000000
#define PGU_VIRT_BASE IOMEM(0xfe400000)
#define PGU_PHYS_SIZE 0x00100000
/* Static Memory Controller - Chip Select 0 and 1 */
#define SMC_CS0_PHYS_BASE 0x80000000
#define SMC_CS0_PHYS_SIZE 0x10000000
@ -38,4 +42,7 @@
#define CIU_VIRT_BASE (AXI_VIRT_BASE + 0x82c00)
#define CIU_REG(x) (CIU_VIRT_BASE + (x))
#define SCU_VIRT_BASE (PGU_VIRT_BASE)
#define SCU_REG(x) (SCU_VIRT_BASE + (x))
#endif /* __ASM_MACH_ADDR_MAP_H */

View file

@ -13,11 +13,11 @@
#include <asm/mach/map.h>
#include <asm/system_misc.h>
#include "addr-map.h"
#include "cputype.h"
#include <linux/soc/mmp/cputype.h>
#include "common.h"
#define MMP_CHIPID (AXI_VIRT_BASE + 0x82c00)
#define MMP_CHIPID CIU_REG(0x00)
unsigned int mmp_chip_id;
EXPORT_SYMBOL(mmp_chip_id);
@ -36,6 +36,15 @@ static struct map_desc standard_io_desc[] __initdata = {
},
};
static struct map_desc mmp2_io_desc[] __initdata = {
{
.pfn = __phys_to_pfn(PGU_PHYS_BASE),
.virtual = (unsigned long)PGU_VIRT_BASE,
.length = PGU_PHYS_SIZE,
.type = MT_DEVICE,
},
};
void __init mmp_map_io(void)
{
iotable_init(standard_io_desc, ARRAY_SIZE(standard_io_desc));
@ -44,6 +53,12 @@ void __init mmp_map_io(void)
mmp_chip_id = __raw_readl(MMP_CHIPID);
}
void __init mmp2_map_io(void)
{
mmp_map_io();
iotable_init(mmp2_io_desc, ARRAY_SIZE(mmp2_io_desc));
}
void mmp_restart(enum reboot_mode mode, const char *cmd)
{
soft_restart(0);

View file

@ -5,4 +5,5 @@
extern void mmp_timer_init(int irq, unsigned long rate);
extern void __init mmp_map_io(void);
extern void __init mmp2_map_io(void);
extern void mmp_restart(enum reboot_mode, const char *);

View file

@ -11,7 +11,7 @@
#include <asm/irq.h>
#include "irqs.h"
#include "devices.h"
#include "cputype.h"
#include <linux/soc/mmp/cputype.h>
#include "regs-usb.h"
int __init pxa_register_device(struct pxa_device_desc *desc,

View file

@ -9,14 +9,13 @@
#include <linux/irqchip.h>
#include <linux/of_platform.h>
#include <linux/clk-provider.h>
#include <linux/clocksource.h>
#include <asm/mach/arch.h>
#include <asm/mach/time.h>
#include <asm/hardware/cache-tauros2.h>
#include "common.h"
extern void __init mmp_dt_init_timer(void);
static const char *const pxa168_dt_board_compat[] __initconst = {
"mrvl,pxa168-aspenite",
NULL,
@ -32,8 +31,8 @@ static void __init mmp_init_time(void)
#ifdef CONFIG_CACHE_TAUROS2
tauros2_init(0);
#endif
mmp_dt_init_timer();
of_clk_init(NULL);
timer_probe();
}
DT_MACHINE_START(PXA168_DT, "Marvell PXA168 (Device Tree Support)")

View file

@ -10,21 +10,20 @@
#include <linux/irqchip.h>
#include <linux/of_platform.h>
#include <linux/clk-provider.h>
#include <linux/clocksource.h>
#include <asm/mach/arch.h>
#include <asm/mach/time.h>
#include <asm/hardware/cache-tauros2.h>
#include "common.h"
extern void __init mmp_dt_init_timer(void);
static void __init mmp_init_time(void)
{
#ifdef CONFIG_CACHE_TAUROS2
tauros2_init(0);
#endif
of_clk_init(NULL);
mmp_dt_init_timer();
timer_probe();
}
static const char *const mmp2_dt_board_compat[] __initconst = {
@ -33,7 +32,7 @@ static const char *const mmp2_dt_board_compat[] __initconst = {
};
DT_MACHINE_START(MMP2_DT, "Marvell MMP2 (Device Tree Support)")
.map_io = mmp_map_io,
.map_io = mmp2_map_io,
.init_time = mmp_init_time,
.dt_compat = mmp2_dt_board_compat,
MACHINE_END

View file

@ -20,7 +20,7 @@
#include <asm/mach/time.h>
#include "addr-map.h"
#include "regs-apbc.h"
#include "cputype.h"
#include <linux/soc/mmp/cputype.h>
#include "irqs.h"
#include "mfp.h"
#include "devices.h"

29
arch/arm/mach-mmp/mmp3.c Normal file
View file

@ -0,0 +1,29 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Marvell MMP3 aka PXA2128 aka 88AP2128 support
*
* Copyright (C) 2019 Lubomir Rintel <lkundrak@v3.sk>
*/
#include <linux/io.h>
#include <linux/irqchip.h>
#include <linux/of_platform.h>
#include <linux/clk-provider.h>
#include <asm/mach/arch.h>
#include <asm/hardware/cache-l2x0.h>
#include "common.h"
static const char *const mmp3_dt_board_compat[] __initconst = {
"marvell,mmp3",
NULL,
};
DT_MACHINE_START(MMP2_DT, "Marvell MMP3")
.map_io = mmp2_map_io,
.dt_compat = mmp3_dt_board_compat,
.l2c_aux_val = 1 << L310_AUX_CTRL_FWA_SHIFT |
L310_AUX_CTRL_DATA_PREFETCH |
L310_AUX_CTRL_INSTR_PREFETCH,
.l2c_aux_mask = 0xc20fffff,
MACHINE_END

View file

@ -0,0 +1,32 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (C) 2019 Lubomir Rintel <lkundrak@v3.sk>
*/
#include <linux/io.h>
#include <asm/smp_scu.h>
#include <asm/smp.h>
#include "addr-map.h"
#define SW_BRANCH_VIRT_ADDR CIU_REG(0x24)
static int mmp3_boot_secondary(unsigned int cpu, struct task_struct *idle)
{
/*
* Apparently, the boot ROM on the second core spins on this
* register becoming non-zero and then jumps to the address written
* there. No IPIs involved.
*/
__raw_writel(__pa_symbol(secondary_startup), SW_BRANCH_VIRT_ADDR);
return 0;
}
static void mmp3_smp_prepare_cpus(unsigned int max_cpus)
{
scu_enable(SCU_VIRT_BASE);
}
static const struct smp_operations mmp3_smp_ops __initconst = {
.smp_prepare_cpus = mmp3_smp_prepare_cpus,
.smp_boot_secondary = mmp3_boot_secondary,
};
CPU_METHOD_OF_DECLARE(mmp3_smp, "marvell,mmp3-smp", &mmp3_smp_ops);

View file

@ -17,7 +17,7 @@
#include <linux/interrupt.h>
#include <asm/mach-types.h>
#include "cputype.h"
#include <linux/soc/mmp/cputype.h>
#include "addr-map.h"
#include "pm-mmp2.h"
#include "regs-icu.h"

View file

@ -18,7 +18,7 @@
#include <asm/mach-types.h>
#include <asm/outercache.h>
#include "cputype.h"
#include <linux/soc/mmp/cputype.h>
#include "addr-map.h"
#include "pm-pxa910.h"
#include "regs-icu.h"

View file

@ -21,7 +21,7 @@
#include "addr-map.h"
#include "clock.h"
#include "common.h"
#include "cputype.h"
#include <linux/soc/mmp/cputype.h>
#include "devices.h"
#include "irqs.h"
#include "mfp.h"

View file

@ -18,7 +18,7 @@
#include <asm/mach/time.h>
#include "addr-map.h"
#include "regs-apbc.h"
#include "cputype.h"
#include <linux/soc/mmp/cputype.h>
#include "irqs.h"
#include "mfp.h"
#include "devices.h"

View file

@ -121,100 +121,6 @@
#define UTMI_OTG_ADDON_OTG_ON (1 << 0)
/* For MMP3 USB Phy */
#define USB2_PLL_REG0 0x4
#define USB2_PLL_REG1 0x8
#define USB2_TX_REG0 0x10
#define USB2_TX_REG1 0x14
#define USB2_TX_REG2 0x18
#define USB2_RX_REG0 0x20
#define USB2_RX_REG1 0x24
#define USB2_RX_REG2 0x28
#define USB2_ANA_REG0 0x30
#define USB2_ANA_REG1 0x34
#define USB2_ANA_REG2 0x38
#define USB2_DIG_REG0 0x3C
#define USB2_DIG_REG1 0x40
#define USB2_DIG_REG2 0x44
#define USB2_DIG_REG3 0x48
#define USB2_TEST_REG0 0x4C
#define USB2_TEST_REG1 0x50
#define USB2_TEST_REG2 0x54
#define USB2_CHARGER_REG0 0x58
#define USB2_OTG_REG0 0x5C
#define USB2_PHY_MON0 0x60
#define USB2_RESETVE_REG0 0x64
#define USB2_ICID_REG0 0x78
#define USB2_ICID_REG1 0x7C
/* USB2_PLL_REG0 */
/* This is for Ax stepping */
#define USB2_PLL_FBDIV_SHIFT_MMP3 0
#define USB2_PLL_FBDIV_MASK_MMP3 (0xFF << 0)
#define USB2_PLL_REFDIV_SHIFT_MMP3 8
#define USB2_PLL_REFDIV_MASK_MMP3 (0xF << 8)
#define USB2_PLL_VDD12_SHIFT_MMP3 12
#define USB2_PLL_VDD18_SHIFT_MMP3 14
/* This is for B0 stepping */
#define USB2_PLL_FBDIV_SHIFT_MMP3_B0 0
#define USB2_PLL_REFDIV_SHIFT_MMP3_B0 9
#define USB2_PLL_VDD18_SHIFT_MMP3_B0 14
#define USB2_PLL_FBDIV_MASK_MMP3_B0 0x01FF
#define USB2_PLL_REFDIV_MASK_MMP3_B0 0x3E00
#define USB2_PLL_CAL12_SHIFT_MMP3 0
#define USB2_PLL_CALI12_MASK_MMP3 (0x3 << 0)
#define USB2_PLL_VCOCAL_START_SHIFT_MMP3 2
#define USB2_PLL_KVCO_SHIFT_MMP3 4
#define USB2_PLL_KVCO_MASK_MMP3 (0x7<<4)
#define USB2_PLL_ICP_SHIFT_MMP3 8
#define USB2_PLL_ICP_MASK_MMP3 (0x7<<8)
#define USB2_PLL_LOCK_BYPASS_SHIFT_MMP3 12
#define USB2_PLL_PU_PLL_SHIFT_MMP3 13
#define USB2_PLL_PU_PLL_MASK (0x1 << 13)
#define USB2_PLL_READY_MASK_MMP3 (0x1 << 15)
/* USB2_TX_REG0 */
#define USB2_TX_IMPCAL_VTH_SHIFT_MMP3 8
#define USB2_TX_IMPCAL_VTH_MASK_MMP3 (0x7 << 8)
#define USB2_TX_RCAL_START_SHIFT_MMP3 13
/* USB2_TX_REG1 */
#define USB2_TX_CK60_PHSEL_SHIFT_MMP3 0
#define USB2_TX_CK60_PHSEL_MASK_MMP3 (0xf << 0)
#define USB2_TX_AMP_SHIFT_MMP3 4
#define USB2_TX_AMP_MASK_MMP3 (0x7 << 4)
#define USB2_TX_VDD12_SHIFT_MMP3 8
#define USB2_TX_VDD12_MASK_MMP3 (0x3 << 8)
/* USB2_TX_REG2 */
#define USB2_TX_DRV_SLEWRATE_SHIFT 10
/* USB2_RX_REG0 */
#define USB2_RX_SQ_THRESH_SHIFT_MMP3 4
#define USB2_RX_SQ_THRESH_MASK_MMP3 (0xf << 4)
#define USB2_RX_SQ_LENGTH_SHIFT_MMP3 10
#define USB2_RX_SQ_LENGTH_MASK_MMP3 (0x3 << 10)
/* USB2_ANA_REG1*/
#define USB2_ANA_PU_ANA_SHIFT_MMP3 14
/* USB2_OTG_REG0 */
#define USB2_OTG_PU_OTG_SHIFT_MMP3 3
/* fsic registers */
#define FSIC_MISC 0x4
#define FSIC_INT 0x28

View file

@ -33,7 +33,7 @@
#include "regs-timers.h"
#include "regs-apbc.h"
#include "irqs.h"
#include "cputype.h"
#include <linux/soc/mmp/cputype.h>
#include "clock.h"
#define TIMERS_VIRT_BASE TIMERS1_VIRT_BASE
@ -155,7 +155,8 @@ static void __init timer_config(void)
__raw_writel(0x0, mmp_timer_base + TMR_CER); /* disable */
ccr &= (cpu_is_mmp2()) ? (TMR_CCR_CS_0(0) | TMR_CCR_CS_1(0)) :
ccr &= (cpu_is_mmp2() || cpu_is_mmp3()) ?
(TMR_CCR_CS_0(0) | TMR_CCR_CS_1(0)) :
(TMR_CCR_CS_0(3) | TMR_CCR_CS_1(3));
__raw_writel(ccr, mmp_timer_base + TMR_CCR);
@ -195,30 +196,17 @@ void __init mmp_timer_init(int irq, unsigned long rate)
clockevents_config_and_register(&ckevt, rate, MIN_DELTA, MAX_DELTA);
}
#ifdef CONFIG_OF
static const struct of_device_id mmp_timer_dt_ids[] = {
{ .compatible = "mrvl,mmp-timer", },
{}
};
void __init mmp_dt_init_timer(void)
static int __init mmp_dt_init_timer(struct device_node *np)
{
struct device_node *np;
struct clk *clk;
int irq, ret;
unsigned long rate;
np = of_find_matching_node(NULL, mmp_timer_dt_ids);
if (!np) {
ret = -ENODEV;
goto out;
}
clk = of_clk_get(np, 0);
if (!IS_ERR(clk)) {
ret = clk_prepare_enable(clk);
if (ret)
goto out;
return ret;
rate = clk_get_rate(clk) / 2;
} else if (cpu_is_pj4()) {
rate = 6500000;
@ -227,18 +215,15 @@ void __init mmp_dt_init_timer(void)
}
irq = irq_of_parse_and_map(np, 0);
if (!irq) {
ret = -EINVAL;
goto out;
}
if (!irq)
return -EINVAL;
mmp_timer_base = of_iomap(np, 0);
if (!mmp_timer_base) {
ret = -ENOMEM;
goto out;
}
if (!mmp_timer_base)
return -ENOMEM;
mmp_timer_init(irq, rate);
return;
out:
pr_err("Failed to get timer from device tree with error:%d\n", ret);
return 0;
}
#endif
TIMER_OF_DECLARE(mmp_timer, "mrvl,mmp-timer", mmp_dt_init_timer);

View file

@ -1041,7 +1041,7 @@ endif
config CACHE_TAUROS2
bool "Enable the Tauros2 L2 cache controller"
depends on (ARCH_DOVE || ARCH_MMP || CPU_PJ4)
depends on (CPU_MOHAWK || CPU_PJ4)
default y
select OUTER_CACHE
help

View file

@ -292,6 +292,11 @@ config COMMON_CLK_STM32H7
help
Support for stm32h7 SoC family clocks
config COMMON_CLK_MMP2
def_bool COMMON_CLK && (MACH_MMP2_DT || MACH_MMP3_DT)
help
Support for Marvell MMP2 and MMP3 SoC clocks
config COMMON_CLK_BD718XX
tristate "Clock driver for ROHM BD718x7 PMIC"
depends on MFD_ROHM_BD718XX || MFD_ROHM_BD70528

View file

@ -8,7 +8,7 @@ obj-y += clk-apbc.o clk-apmu.o clk-frac.o clk-mix.o clk-gate.o clk.o
obj-$(CONFIG_RESET_CONTROLLER) += reset.o
obj-$(CONFIG_MACH_MMP_DT) += clk-of-pxa168.o clk-of-pxa910.o
obj-$(CONFIG_MACH_MMP2_DT) += clk-of-mmp2.o
obj-$(CONFIG_COMMON_CLK_MMP2) += clk-of-mmp2.o
obj-$(CONFIG_CPU_PXA168) += clk-pxa168.o
obj-$(CONFIG_CPU_PXA910) += clk-pxa910.o

View file

@ -103,3 +103,14 @@ config PHY_PXA_USB
The PHY driver will be used by Marvell udc/ehci/otg driver.
To compile this driver as a module, choose M here.
config PHY_MMP3_USB
tristate "Marvell MMP3 USB PHY Driver"
depends on MACH_MMP3_DT || COMPILE_TEST
select GENERIC_PHY
help
Enable this to support Marvell MMP3 USB PHY driver for Marvell
SoC. This driver will do the PHY initialization and shutdown.
The PHY driver will be used by Marvell udc/ehci/otg driver.
To compile this driver as a module, choose M here.

View file

@ -2,6 +2,7 @@
obj-$(CONFIG_ARMADA375_USBCLUSTER_PHY) += phy-armada375-usb2.o
obj-$(CONFIG_PHY_BERLIN_SATA) += phy-berlin-sata.o
obj-$(CONFIG_PHY_BERLIN_USB) += phy-berlin-usb.o
obj-$(CONFIG_PHY_MMP3_USB) += phy-mmp3-usb.o
obj-$(CONFIG_PHY_MVEBU_A3700_COMPHY) += phy-mvebu-a3700-comphy.o
obj-$(CONFIG_PHY_MVEBU_A3700_UTMI) += phy-mvebu-a3700-utmi.o
obj-$(CONFIG_PHY_MVEBU_A38X_COMPHY) += phy-armada38x-comphy.o

View file

@ -0,0 +1,291 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2011 Marvell International Ltd. All rights reserved.
* Copyright (C) 2018,2019 Lubomir Rintel <lkundrak@v3.sk>
*/
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/phy/phy.h>
#include <linux/platform_device.h>
#include <linux/soc/mmp/cputype.h>
#define USB2_PLL_REG0 0x4
#define USB2_PLL_REG1 0x8
#define USB2_TX_REG0 0x10
#define USB2_TX_REG1 0x14
#define USB2_TX_REG2 0x18
#define USB2_RX_REG0 0x20
#define USB2_RX_REG1 0x24
#define USB2_RX_REG2 0x28
#define USB2_ANA_REG0 0x30
#define USB2_ANA_REG1 0x34
#define USB2_ANA_REG2 0x38
#define USB2_DIG_REG0 0x3C
#define USB2_DIG_REG1 0x40
#define USB2_DIG_REG2 0x44
#define USB2_DIG_REG3 0x48
#define USB2_TEST_REG0 0x4C
#define USB2_TEST_REG1 0x50
#define USB2_TEST_REG2 0x54
#define USB2_CHARGER_REG0 0x58
#define USB2_OTG_REG0 0x5C
#define USB2_PHY_MON0 0x60
#define USB2_RESETVE_REG0 0x64
#define USB2_ICID_REG0 0x78
#define USB2_ICID_REG1 0x7C
/* USB2_PLL_REG0 */
/* This is for Ax stepping */
#define USB2_PLL_FBDIV_SHIFT_MMP3 0
#define USB2_PLL_FBDIV_MASK_MMP3 (0xFF << 0)
#define USB2_PLL_REFDIV_SHIFT_MMP3 8
#define USB2_PLL_REFDIV_MASK_MMP3 (0xF << 8)
#define USB2_PLL_VDD12_SHIFT_MMP3 12
#define USB2_PLL_VDD18_SHIFT_MMP3 14
/* This is for B0 stepping */
#define USB2_PLL_FBDIV_SHIFT_MMP3_B0 0
#define USB2_PLL_REFDIV_SHIFT_MMP3_B0 9
#define USB2_PLL_VDD18_SHIFT_MMP3_B0 14
#define USB2_PLL_FBDIV_MASK_MMP3_B0 0x01FF
#define USB2_PLL_REFDIV_MASK_MMP3_B0 0x3E00
#define USB2_PLL_CAL12_SHIFT_MMP3 0
#define USB2_PLL_CALI12_MASK_MMP3 (0x3 << 0)
#define USB2_PLL_VCOCAL_START_SHIFT_MMP3 2
#define USB2_PLL_KVCO_SHIFT_MMP3 4
#define USB2_PLL_KVCO_MASK_MMP3 (0x7<<4)
#define USB2_PLL_ICP_SHIFT_MMP3 8
#define USB2_PLL_ICP_MASK_MMP3 (0x7<<8)
#define USB2_PLL_LOCK_BYPASS_SHIFT_MMP3 12
#define USB2_PLL_PU_PLL_SHIFT_MMP3 13
#define USB2_PLL_PU_PLL_MASK (0x1 << 13)
#define USB2_PLL_READY_MASK_MMP3 (0x1 << 15)
/* USB2_TX_REG0 */
#define USB2_TX_IMPCAL_VTH_SHIFT_MMP3 8
#define USB2_TX_IMPCAL_VTH_MASK_MMP3 (0x7 << 8)
#define USB2_TX_RCAL_START_SHIFT_MMP3 13
/* USB2_TX_REG1 */
#define USB2_TX_CK60_PHSEL_SHIFT_MMP3 0
#define USB2_TX_CK60_PHSEL_MASK_MMP3 (0xf << 0)
#define USB2_TX_AMP_SHIFT_MMP3 4
#define USB2_TX_AMP_MASK_MMP3 (0x7 << 4)
#define USB2_TX_VDD12_SHIFT_MMP3 8
#define USB2_TX_VDD12_MASK_MMP3 (0x3 << 8)
/* USB2_TX_REG2 */
#define USB2_TX_DRV_SLEWRATE_SHIFT 10
/* USB2_RX_REG0 */
#define USB2_RX_SQ_THRESH_SHIFT_MMP3 4
#define USB2_RX_SQ_THRESH_MASK_MMP3 (0xf << 4)
#define USB2_RX_SQ_LENGTH_SHIFT_MMP3 10
#define USB2_RX_SQ_LENGTH_MASK_MMP3 (0x3 << 10)
/* USB2_ANA_REG1*/
#define USB2_ANA_PU_ANA_SHIFT_MMP3 14
/* USB2_OTG_REG0 */
#define USB2_OTG_PU_OTG_SHIFT_MMP3 3
struct mmp3_usb_phy {
struct phy *phy;
void __iomem *base;
};
static unsigned int u2o_get(void __iomem *base, unsigned int offset)
{
return readl_relaxed(base + offset);
}
static void u2o_set(void __iomem *base, unsigned int offset,
unsigned int value)
{
u32 reg;
reg = readl_relaxed(base + offset);
reg |= value;
writel_relaxed(reg, base + offset);
readl_relaxed(base + offset);
}
static void u2o_clear(void __iomem *base, unsigned int offset,
unsigned int value)
{
u32 reg;
reg = readl_relaxed(base + offset);
reg &= ~value;
writel_relaxed(reg, base + offset);
readl_relaxed(base + offset);
}
static int mmp3_usb_phy_init(struct phy *phy)
{
struct mmp3_usb_phy *mmp3_usb_phy = phy_get_drvdata(phy);
void __iomem *base = mmp3_usb_phy->base;
if (cpu_is_mmp3_a0()) {
u2o_clear(base, USB2_PLL_REG0, (USB2_PLL_FBDIV_MASK_MMP3
| USB2_PLL_REFDIV_MASK_MMP3));
u2o_set(base, USB2_PLL_REG0,
0xd << USB2_PLL_REFDIV_SHIFT_MMP3
| 0xf0 << USB2_PLL_FBDIV_SHIFT_MMP3);
} else if (cpu_is_mmp3_b0()) {
u2o_clear(base, USB2_PLL_REG0, USB2_PLL_REFDIV_MASK_MMP3_B0
| USB2_PLL_FBDIV_MASK_MMP3_B0);
u2o_set(base, USB2_PLL_REG0,
0xd << USB2_PLL_REFDIV_SHIFT_MMP3_B0
| 0xf0 << USB2_PLL_FBDIV_SHIFT_MMP3_B0);
} else {
dev_err(&phy->dev, "unsupported silicon revision\n");
return -ENODEV;
}
u2o_clear(base, USB2_PLL_REG1, USB2_PLL_PU_PLL_MASK
| USB2_PLL_ICP_MASK_MMP3
| USB2_PLL_KVCO_MASK_MMP3
| USB2_PLL_CALI12_MASK_MMP3);
u2o_set(base, USB2_PLL_REG1, 1 << USB2_PLL_PU_PLL_SHIFT_MMP3
| 1 << USB2_PLL_LOCK_BYPASS_SHIFT_MMP3
| 3 << USB2_PLL_ICP_SHIFT_MMP3
| 3 << USB2_PLL_KVCO_SHIFT_MMP3
| 3 << USB2_PLL_CAL12_SHIFT_MMP3);
u2o_clear(base, USB2_TX_REG0, USB2_TX_IMPCAL_VTH_MASK_MMP3);
u2o_set(base, USB2_TX_REG0, 2 << USB2_TX_IMPCAL_VTH_SHIFT_MMP3);
u2o_clear(base, USB2_TX_REG1, USB2_TX_VDD12_MASK_MMP3
| USB2_TX_AMP_MASK_MMP3
| USB2_TX_CK60_PHSEL_MASK_MMP3);
u2o_set(base, USB2_TX_REG1, 3 << USB2_TX_VDD12_SHIFT_MMP3
| 4 << USB2_TX_AMP_SHIFT_MMP3
| 4 << USB2_TX_CK60_PHSEL_SHIFT_MMP3);
u2o_clear(base, USB2_TX_REG2, 3 << USB2_TX_DRV_SLEWRATE_SHIFT);
u2o_set(base, USB2_TX_REG2, 2 << USB2_TX_DRV_SLEWRATE_SHIFT);
u2o_clear(base, USB2_RX_REG0, USB2_RX_SQ_THRESH_MASK_MMP3);
u2o_set(base, USB2_RX_REG0, 0xa << USB2_RX_SQ_THRESH_SHIFT_MMP3);
u2o_set(base, USB2_ANA_REG1, 0x1 << USB2_ANA_PU_ANA_SHIFT_MMP3);
u2o_set(base, USB2_OTG_REG0, 0x1 << USB2_OTG_PU_OTG_SHIFT_MMP3);
return 0;
}
static int mmp3_usb_phy_calibrate(struct phy *phy)
{
struct mmp3_usb_phy *mmp3_usb_phy = phy_get_drvdata(phy);
void __iomem *base = mmp3_usb_phy->base;
int loops;
/*
* PLL VCO and TX Impedance Calibration Timing:
*
* _____________________________________
* PU __________|
* _____________________________
* VCOCAL START _________|
* ___
* REG_RCAL_START ________________| |________|_______
* | 200us | 400us | 40| 400us | USB PHY READY
*/
udelay(200);
u2o_set(base, USB2_PLL_REG1, 1 << USB2_PLL_VCOCAL_START_SHIFT_MMP3);
udelay(400);
u2o_set(base, USB2_TX_REG0, 1 << USB2_TX_RCAL_START_SHIFT_MMP3);
udelay(40);
u2o_clear(base, USB2_TX_REG0, 1 << USB2_TX_RCAL_START_SHIFT_MMP3);
udelay(400);
loops = 0;
while ((u2o_get(base, USB2_PLL_REG1) & USB2_PLL_READY_MASK_MMP3) == 0) {
mdelay(1);
loops++;
if (loops > 100) {
dev_err(&phy->dev, "PLL_READY not set after 100mS.\n");
return -ETIMEDOUT;
}
}
return 0;
}
static const struct phy_ops mmp3_usb_phy_ops = {
.init = mmp3_usb_phy_init,
.calibrate = mmp3_usb_phy_calibrate,
.owner = THIS_MODULE,
};
static const struct of_device_id mmp3_usb_phy_of_match[] = {
{ .compatible = "marvell,mmp3-usb-phy", },
{ },
};
MODULE_DEVICE_TABLE(of, mmp3_usb_phy_of_match);
static int mmp3_usb_phy_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct resource *resource;
struct mmp3_usb_phy *mmp3_usb_phy;
struct phy_provider *provider;
mmp3_usb_phy = devm_kzalloc(dev, sizeof(*mmp3_usb_phy), GFP_KERNEL);
if (!mmp3_usb_phy)
return -ENOMEM;
resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
mmp3_usb_phy->base = devm_ioremap_resource(dev, resource);
if (IS_ERR(mmp3_usb_phy->base)) {
dev_err(dev, "failed to remap PHY regs\n");
return PTR_ERR(mmp3_usb_phy->base);
}
mmp3_usb_phy->phy = devm_phy_create(dev, NULL, &mmp3_usb_phy_ops);
if (IS_ERR(mmp3_usb_phy->phy)) {
dev_err(dev, "failed to create PHY\n");
return PTR_ERR(mmp3_usb_phy->phy);
}
phy_set_drvdata(mmp3_usb_phy->phy, mmp3_usb_phy);
provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
if (IS_ERR(provider)) {
dev_err(dev, "failed to register PHY provider\n");
return PTR_ERR(provider);
}
return 0;
}
static struct platform_driver mmp3_usb_phy_driver = {
.probe = mmp3_usb_phy_probe,
.driver = {
.name = "mmp3-usb-phy",
.of_match_table = mmp3_usb_phy_of_match,
},
};
module_platform_driver(mmp3_usb_phy_driver);
MODULE_AUTHOR("Lubomir Rintel <lkundrak@v3.sk>");
MODULE_DESCRIPTION("Marvell MMP3 USB PHY Driver");
MODULE_LICENSE("GPL v2");

View file

@ -633,6 +633,7 @@ header-test- += linux/soc/amlogic/meson-canvas.h
header-test- += linux/soc/brcmstb/brcmstb.h
header-test- += linux/soc/ixp4xx/npe.h
header-test- += linux/soc/mediatek/infracfg.h
header-test- += linux/soc/mmp/cputype.h
header-test- += linux/soc/qcom/smd-rpm.h
header-test- += linux/soc/qcom/smem.h
header-test- += linux/soc/qcom/smem_state.h

View file

@ -18,6 +18,8 @@
* MMP2 Z0 0x560f5811 0x00F00410
* MMP2 Z1 0x560f5811 0x00E00410
* MMP2 A0 0x560f5811 0x00A0A610
* MMP3 A0 0x562f5842 0x00A02128
* MMP3 B0 0x562f5842 0x00B02128
*/
extern unsigned int mmp_chip_id;
@ -55,4 +57,29 @@ static inline int cpu_is_mmp2(void)
#define cpu_is_mmp2() (0)
#endif
#ifdef CONFIG_MACH_MMP3_DT
static inline int cpu_is_mmp3(void)
{
return (((read_cpuid_id() >> 8) & 0xff) == 0x58) &&
((mmp_chip_id & 0xffff) == 0x2128);
}
static inline int cpu_is_mmp3_a0(void)
{
return (cpu_is_mmp3() &&
((mmp_chip_id & 0x00ff0000) == 0x00a00000));
}
static inline int cpu_is_mmp3_b0(void)
{
return (cpu_is_mmp3() &&
((mmp_chip_id & 0x00ff0000) == 0x00b00000));
}
#else
#define cpu_is_mmp3() (0)
#define cpu_is_mmp3_a0() (0)
#define cpu_is_mmp3_b0() (0)
#endif
#endif /* __ASM_MACH_CPUTYPE_H */