diff options
author | Peter Griffin <peter.griffin@linaro.org> | 2014-07-01 12:01:34 +0100 |
---|---|---|
committer | Peter Griffin <peter.griffin@linaro.org> | 2014-07-01 12:01:34 +0100 |
commit | f7661e2e8bc6a95ffd00084ae0db1b10fba3553d (patch) | |
tree | e40e63c72eaa061a4dfdfdf2e34811ceb6ea892d | |
parent | aea64967e7870fb00fb1d354941198caa005dce3 (diff) |
Got USB working, but need new PHY drivers!usb-picophy-usb-phy
-rw-r--r-- | Documentation/devicetree/bindings/mmc/sdhci-st.txt.reset | 33 | ||||
-rw-r--r-- | Documentation/devicetree/bindings/usb/phy-st-usb3.txt | 36 | ||||
-rw-r--r-- | Documentation/devicetree/bindings/usb/phy-stih407-usb2.txt | 23 | ||||
-rw-r--r-- | arch/arm/boot/dts/stih407-b2120.dts | 4 | ||||
-rw-r--r-- | arch/arm/boot/dts/stih407.dtsi | 52 | ||||
-rw-r--r-- | arch/arm/configs/sti_defconfig | 154 | ||||
-rw-r--r-- | arch/arm/mach-sti/Kconfig | 11 | ||||
-rw-r--r-- | drivers/reset/sti/reset-stih407.c | 2 | ||||
-rw-r--r-- | drivers/reset/sti/reset-syscfg.c | 23 | ||||
-rw-r--r-- | drivers/reset/sti/reset-syscfg.h | 4 | ||||
-rw-r--r-- | drivers/usb/dwc3/core.c | 24 | ||||
-rw-r--r-- | drivers/usb/dwc3/dwc3-st.c | 28 | ||||
-rw-r--r-- | drivers/usb/phy/Kconfig | 2 | ||||
-rw-r--r-- | drivers/usb/phy/Makefile | 2 | ||||
-rw-r--r-- | drivers/usb/phy/phy-st-usb3.c | 317 | ||||
-rw-r--r-- | drivers/usb/phy/phy-stih407-usb2.c | 3 |
16 files changed, 713 insertions, 5 deletions
diff --git a/Documentation/devicetree/bindings/mmc/sdhci-st.txt.reset b/Documentation/devicetree/bindings/mmc/sdhci-st.txt.reset new file mode 100644 index 000000000000..1fe852353e06 --- /dev/null +++ b/Documentation/devicetree/bindings/mmc/sdhci-st.txt.reset @@ -0,0 +1,33 @@ +* STMicroelectronics sdhci-st MMC/SD controller + +This file documents the differences between the core properties in +Documentation/devicetree/bindings/mmc/mmc.txt and the properties +used by the sdhci-st driver. + +Required properties: +- compatible : Must be "st,sdhci" +- clock-names : Should be "mmc" + See: Documentation/devicetree/bindings/resource-names.txt +- clocks : Phandle of the clock used by the sdhci controler + See: Documentation/devicetree/bindings/clock/clock-bindings.txt + +Optional properties: +- reset: Phandle of the reset provider plus reset specifier + See: Documentation/devicetree/bindings/reset/reset.txt +- non-removable: non-removable slot + See: Documentation/devicetree/bindings/mmc/mmc.txt + +Example: + +mmc0: sdhci@fe81e000 { + compatible = "st,sdhci"; + status = "disabled"; + reg = <0xfe81e000 0x1000>; + interrupts = <GIC_SPI 127 IRQ_TYPE_NONE>; + interrupt-names = "mmcirq"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_mmc0>; + clock-names = "mmc"; + clocks = <&clk_s_a1_ls 1>; + resets = <&softreset STIH416_MMC_SOFTRESET> +}; diff --git a/Documentation/devicetree/bindings/usb/phy-st-usb3.txt b/Documentation/devicetree/bindings/usb/phy-st-usb3.txt new file mode 100644 index 000000000000..341bb630be2f --- /dev/null +++ b/Documentation/devicetree/bindings/usb/phy-st-usb3.txt @@ -0,0 +1,36 @@ +ST USB-PHY controllers + +The DWC3 port#2 can be used with a MiPHY2 to manage USB3 devices. + +This is to document the DT parameters to be passed from the blob in that case. + +Required properties: + +MiPHY2: +- compatible : should be "st,stih407-usb3phy" +- reg : base physical address of the phy registers and length of memory mapped + region. + It must have: "usb3-uport", "pipew"; + So MiPHY and pipe wrapper. +- st,syscfg: sysconfig register to manage the device. +- resets: to reset the device. + +Optional property: +- st,auto-calibration: boolean property to advice system to perform + autocalibration on device disconnection. + This will allow to setup the proper callback in the + phy-st-usb3.c source. To setup only for those socs that + support autocalibration. + +Example: + +/* miPHY2 */ +usb3_phy: usb3_phy@0 { + compatible = "st,stih407-usb3phy"; + #phy-cells = <0>; + resets = <&softreset STIH407_USB3_MIPHY2_SOFTRESET>; + reg = <0x08f90000 0xff>, <0x08f95000 0xff>; + reg-names = "usb3-uport", "pipew"; + st,syscfg = <&syscfg_core>; + st,auto-calibration; +}; diff --git a/Documentation/devicetree/bindings/usb/phy-stih407-usb2.txt b/Documentation/devicetree/bindings/usb/phy-stih407-usb2.txt new file mode 100644 index 000000000000..fcb207bb7db9 --- /dev/null +++ b/Documentation/devicetree/bindings/usb/phy-stih407-usb2.txt @@ -0,0 +1,23 @@ +ST STiH407 USB-PHY controller + +On STiH407, we have to use the DWC3 port#2 with a picoPHY to manage USB2 +devices. + +This is to document the DT parameters to be passed from the blob in that case. + +Required properties: + +picoPHY: +- compatible : should be "st,stih407-usb2phy" +- st,syscfg: sysconfig register to manage phy parameter at driver level. +- resets: to reset the device. + +Example: + +/* picoPHY */ +usb2_phy: usb2phy@0 { + compatible = "st,stih407-usb2phy"; + #phy-cells = <0>; + st,syscfg = <&syscfg_core>; + resets = <&softreset STIH407_PICOPHY_SOFTRESET>; +}; diff --git a/arch/arm/boot/dts/stih407-b2120.dts b/arch/arm/boot/dts/stih407-b2120.dts index fe69f92e5f82..181e9785df8a 100644 --- a/arch/arm/boot/dts/stih407-b2120.dts +++ b/arch/arm/boot/dts/stih407-b2120.dts @@ -74,5 +74,9 @@ st,i2c-min-scl-pulse-width-us = <0>; st,i2c-min-sda-pulse-width-us = <5>; }; + + st_dwc3: dwc3@8f94000 { + status = "okay"; + }; }; }; diff --git a/arch/arm/boot/dts/stih407.dtsi b/arch/arm/boot/dts/stih407.dtsi index 4f9024f19866..3cff212a8f97 100644 --- a/arch/arm/boot/dts/stih407.dtsi +++ b/arch/arm/boot/dts/stih407.dtsi @@ -8,6 +8,7 @@ */ #include "stih407-clock.dtsi" #include "stih407-pinctrl.dtsi" +#include <dt-bindings/reset-controller/stih407-resets.h> / { #address-cells = <1>; #size-cells = <1>; @@ -63,6 +64,16 @@ ranges; compatible = "simple-bus"; + powerdown: powerdown-controller { + #reset-cells = <1>; + compatible = "st,stih407-powerdown"; + }; + + softreset: softreset-controller { + #reset-cells = <1>; + compatible = "st,stih407-softreset"; + }; + syscfg_sbc: sbc-syscfg@9620000 { compatible = "st,stih407-sbc-syscfg", "syscon"; reg = <0x9620000 0x1000>; @@ -259,5 +270,46 @@ status = "disabled"; }; + + /* picoPHY */ + usb2_phy: usb2phy@0 { + compatible = "st,stih407-usb2phy"; + #phy-cells = <0>; + st,syscfg = <&syscfg_core>; + resets = <&softreset STIH407_PICOPHY_SOFTRESET>; + }; + + /* miPHY2 */ + usb3_phy: usb3_phy@0 { + compatible = "st,sti-usb3phy"; + #phy-cells = <0>; + resets = <&softreset STIH407_USB3_MIPHY2_SOFTRESET>; + reg = <0x08f90000 0xff>, <0x08f95000 0xff>; + reg-names = "usb3-uport", "pipew"; + st,syscfg = <&syscfg_core>; + st,auto-calibration; + }; + + st_dwc3: dwc3@8f94000 { + status = "disabled"; + compatible = "st,stih407-dwc3"; + reg = <0x08f94000 0x1000>, <0x110 0x4>; + reg-names = "reg-glue", "syscfg-reg"; + st,syscfg = <&syscfg_core>; + resets = <&powerdown STIH407_USB3_POWERDOWN>; + #address-cells = <1>; + #size-cells = <1>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usb3>; + ranges; + + dwc3: dwc3@9900000 { + compatible = "synopsys,dwc3"; + reg = <0x09900000 0x100000>; + interrupts = <GIC_SPI 155 IRQ_TYPE_NONE>; + + usb-phy = <&usb2_phy>, <&usb3_phy>; + }; + }; }; }; diff --git a/arch/arm/configs/sti_defconfig b/arch/arm/configs/sti_defconfig new file mode 100644 index 000000000000..61feda50507f --- /dev/null +++ b/arch/arm/configs/sti_defconfig @@ -0,0 +1,154 @@ +CONFIG_SYSVIPC=y +CONFIG_POSIX_MQUEUE=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_CGROUPS=y +CONFIG_CGROUP_FREEZER=y +CONFIG_CGROUP_DEVICE=y +CONFIG_CPUSETS=y +CONFIG_CGROUP_CPUACCT=y +CONFIG_RESOURCE_COUNTERS=y +CONFIG_MEMCG=y +CONFIG_MEMCG_SWAP=y +CONFIG_MEMCG_KMEM=y +CONFIG_PERF_EVENTS=y +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_ARCH_STI=y +CONFIG_PCI=y +CONFIG_PCI_MSI=y +CONFIG_PCI_ST=y +CONFIG_SMP=y +CONFIG_PREEMPT=y +CONFIG_AEABI=y +CONFIG_HIGHMEM=y +CONFIG_HIGHPTE=y +CONFIG_ARM_APPENDED_DTB=y +CONFIG_CPU_FREQ=y +CONFIG_GENERIC_CPUFREQ_CPU0=y +CONFIG_VFP=y +CONFIG_NEON=y +CONFIG_PM_OPP=y +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_INET=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_SYN_COOKIES=y +CONFIG_IPV6=y +CONFIG_NETFILTER=y +CONFIG_NF_CONNTRACK=y +CONFIG_NF_CONNTRACK_IPV4=y +CONFIG_IP_NF_IPTABLES=y +CONFIG_IP_NF_FILTER=y +CONFIG_NF_NAT_IPV4=y +CONFIG_IP_NF_RAW=y +CONFIG_NF_CONNTRACK_IPV6=y +CONFIG_IP6_NF_IPTABLES=y +CONFIG_IP6_NF_FILTER=y +CONFIG_IP6_NF_RAW=y +CONFIG_NF_NAT_IPV6=y +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +CONFIG_EEPROM_AT24=y +CONFIG_BLK_DEV_SD=y +CONFIG_ATA=y +CONFIG_SATA_AHCI_PLATFORM=y +CONFIG_SATA_AHCI_ST=y +CONFIG_NETDEVICES=y +CONFIG_VETH=y +CONFIG_NET_CALXEDA_XGMAC=y +CONFIG_SMSC911X=y +CONFIG_STMMAC_ETH=y +CONFIG_ISVE_ST=m +CONFIG_ICPLUS_PHY=y +CONFIG_FIXED_PHY=y +CONFIG_RTL8366_SMI=y +CONFIG_RTL8366_SMI_DEBUG_FS=y +CONFIG_RTL8367_PHY=y +CONFIG_INPUT_MATRIXKMAP=y +CONFIG_KEYBOARD_ST_KEYSCAN=y +CONFIG_SERIAL_ST_ASC=y +CONFIG_SERIAL_ST_ASC_CONSOLE=y +CONFIG_HW_RANDOM=y +CONFIG_HW_RANDOM_ST=y +CONFIG_I2C=y +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_ST=y +CONFIG_SPI=y +CONFIG_SPI_ST=y +CONFIG_GPIO_SYSFS=y +CONFIG_POWER_SUPPLY=y +CONFIG_POWER_RESET=y +CONFIG_POWER_RESET_ST=y +# CONFIG_HWMON is not set +CONFIG_THERMAL=y +CONFIG_ST_THERMAL=y +CONFIG_ST_THERMAL_SYSCFG=y +CONFIG_ST_THERMAL_MEMMAP=y +CONFIG_WATCHDOG=y +CONFIG_ST_LPC_WATCHDOG=y +CONFIG_REGULATOR=y +CONFIG_REGULATOR_ST_FLASHSS=y +CONFIG_MEDIA_SUPPORT=y +CONFIG_MEDIA_RC_SUPPORT=y +CONFIG_LIRC=y +CONFIG_RC_DEVICES=y +CONFIG_RC_ST=y +CONFIG_DVB_TUNER_DIB0070=y +CONFIG_DVB_TUNER_DIB0090=y +CONFIG_FB=y +CONFIG_FB_MODE_HELPERS=y +CONFIG_FB_SIMPLE=y +CONFIG_USB=y +CONFIG_USB_XHCI_HCD=y +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_OHCI_HCD=y +CONFIG_USB_HCD_ST=y +CONFIG_USB_STORAGE=y +CONFIG_USB_DWC3=y +CONFIG_USB_PHY=y +CONFIG_PHY_STIH407_USB=y +CONFIG_ST_USB3_MIPHY=y +CONFIG_PHY_STI8416_USB2=y +CONFIG_MMC=y +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_PLTFM=y +CONFIG_MMC_SDHCI_ST=y +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y +CONFIG_LEDS_GPIO=y +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_HEARTBEAT=y +CONFIG_MALI400=y +CONFIG_COMMON_CLK_DEBUG=y +# CONFIG_IOMMU_SUPPORT is not set +CONFIG_ST_REMOTEPROC=m +CONFIG_PWM=y +CONFIG_PWM_ST=y +CONFIG_PHY_STIH41X_USB=y +CONFIG_PHY_MIPHY365X=y +CONFIG_PHY_STID127_USB=y +CONFIG_PHY_MIPHY28LP=y +CONFIG_PHY_STI8416_USB=y +CONFIG_EXT2_FS=y +CONFIG_EXT3_FS=y +CONFIG_EXT4_FS=y +CONFIG_FUSE_FS=y +CONFIG_VFAT_FS=y +CONFIG_NTFS_FS=y +CONFIG_TMPFS=y +CONFIG_NFS_FS=y +CONFIG_ROOT_NFS=y +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_ISO8859_1=y +CONFIG_DEBUG_SECTION_MISMATCH=y +CONFIG_DEBUG_KERNEL=y +CONFIG_DEBUG_INFO=y +# CONFIG_FTRACE is not set +CONFIG_CRYPTO_MANAGER=y +CONFIG_CRYPTO_SEQIV=y +# CONFIG_CRYPTO_ANSI_CPRNG is not set +# CONFIG_CRYPTO_HW is not set +CONFIG_XZ_DEC=y diff --git a/arch/arm/mach-sti/Kconfig b/arch/arm/mach-sti/Kconfig index 7e33e9d2c42e..7bb7eaad1a25 100644 --- a/arch/arm/mach-sti/Kconfig +++ b/arch/arm/mach-sti/Kconfig @@ -42,4 +42,15 @@ config SOC_STIH416 and other digital audio/video applications using Flattened Device Trees. +config SOC_STIH407 + bool "STiH407 STMicroelectronics Consumer Electronics family" + default y + select STIH407_RESET + select USB_ARCH_HAS_XHCI + help + This enables support for STMicroelectronics Digital Consumer + Electronics family StiH407 parts, targetted at set-top-box + and other digital audio/video applications using Flattened Device + Trees. + endif diff --git a/drivers/reset/sti/reset-stih407.c b/drivers/reset/sti/reset-stih407.c index 4a57742f4db6..214c3d87a393 100644 --- a/drivers/reset/sti/reset-stih407.c +++ b/drivers/reset/sti/reset-stih407.c @@ -104,6 +104,8 @@ static struct platform_driver stih407_reset_driver = { static int __init stih407_reset_init(void) { + + printk("\n%s:%d\n",__FUNCTION__, __LINE__); return platform_driver_register(&stih407_reset_driver); } diff --git a/drivers/reset/sti/reset-syscfg.c b/drivers/reset/sti/reset-syscfg.c index a145cc066d4a..b05af15f17db 100644 --- a/drivers/reset/sti/reset-syscfg.c +++ b/drivers/reset/sti/reset-syscfg.c @@ -109,11 +109,34 @@ static int syscfg_reset_dev(struct reset_controller_dev *rcdev, return syscfg_reset_deassert(rcdev, idx); } +#if 0 +static int syscfg_reset_is_asserted(struct reset_controller_dev *rcdev, + unsigned long idx) +{ + struct syscfg_reset_controller *rst = to_syscfg_reset_controller(rcdev); + const struct syscfg_reset_channel *ch; + u32 ret_val = 0; + int err; + if (idx >= rcdev->nr_resets) + return -EINVAL; + + ch = &rst->channels[idx]; + if (ch->ack) + err = regmap_field_read(ch->ack, &ret_val); + else + err = regmap_field_read(ch->reset, &ret_val); + if (err) + return err; + + return rst->active_low ? !ret_val : !!ret_val; +} +#endif static struct reset_control_ops syscfg_reset_ops = { .reset = syscfg_reset_dev, .assert = syscfg_reset_assert, .deassert = syscfg_reset_deassert, +// .is_asserted = syscfg_reset_is_asserted, }; static int syscfg_reset_controller_register(struct device *dev, diff --git a/drivers/reset/sti/reset-syscfg.h b/drivers/reset/sti/reset-syscfg.h index 2cc2283bac40..e98e76462cc8 100644 --- a/drivers/reset/sti/reset-syscfg.h +++ b/drivers/reset/sti/reset-syscfg.h @@ -34,6 +34,10 @@ struct syscfg_reset_channel_data { .reset = REG_FIELD(_rr, _rb, _rb), \ .ack = REG_FIELD(_ar, _ab, _ab), } +#define SYSCFG_SRST(_c, _rr, _rb) \ + { .compatible = _c, \ + .reset = REG_FIELD(_rr, _rb, _rb), } + #define _SYSCFG_RST_CH_NO_ACK(_c, _rr, _rb) \ { .compatible = _c, \ .reset = REG_FIELD(_rr, _rb, _rb), } diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index eb69eb9f06c8..03dfd19629fd 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -505,6 +505,7 @@ static int dwc3_core_get_phy(struct dwc3 *dwc) if (ret == -ENXIO || ret == -ENODEV) { dwc->usb2_phy = NULL; } else if (ret == -EPROBE_DEFER) { + printk("%s:%d()+\n",__FUNCTION__, __LINE__); return ret; } else { dev_err(dev, "no usb2 phy configured\n"); @@ -517,6 +518,7 @@ static int dwc3_core_get_phy(struct dwc3 *dwc) if (ret == -ENXIO || ret == -ENODEV) { dwc->usb3_phy = NULL; } else if (ret == -EPROBE_DEFER) { + printk("%s:%d()+\n",__FUNCTION__, __LINE__); return ret; } else { dev_err(dev, "no usb3 phy configured\n"); @@ -530,6 +532,7 @@ static int dwc3_core_get_phy(struct dwc3 *dwc) if (ret == -ENOSYS || ret == -ENODEV) { dwc->usb2_generic_phy = NULL; } else if (ret == -EPROBE_DEFER) { + printk("%s:%d()+\n",__FUNCTION__, __LINE__); return ret; } else { dev_err(dev, "no usb2 phy configured\n"); @@ -543,6 +546,7 @@ static int dwc3_core_get_phy(struct dwc3 *dwc) if (ret == -ENOSYS || ret == -ENODEV) { dwc->usb3_generic_phy = NULL; } else if (ret == -EPROBE_DEFER) { + printk("%s:%d()+\n",__FUNCTION__, __LINE__); return ret; } else { dev_err(dev, "no usb3 phy configured\n"); @@ -631,6 +635,8 @@ static int dwc3_probe(struct platform_device *pdev) void __iomem *regs; void *mem; + printk("%s:%d ()+\n",__FUNCTION__, __LINE__); + mem = devm_kzalloc(dev, sizeof(*dwc) + DWC3_ALIGN_MASK, GFP_KERNEL); if (!mem) { dev_err(dev, "not enough memory\n"); @@ -640,6 +646,8 @@ static int dwc3_probe(struct platform_device *pdev) dwc->mem = mem; dwc->dev = dev; + printk("%s:%d ()+\n",__FUNCTION__, __LINE__); + res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (!res) { dev_err(dev, "missing IRQ\n"); @@ -656,6 +664,8 @@ static int dwc3_probe(struct platform_device *pdev) return -ENODEV; } + printk("%s:%d ()+\n",__FUNCTION__, __LINE__); + if (node) { dwc->maximum_speed = of_usb_get_maximum_speed(node); @@ -672,6 +682,8 @@ static int dwc3_probe(struct platform_device *pdev) if (dwc->maximum_speed == USB_SPEED_UNKNOWN) dwc->maximum_speed = USB_SPEED_SUPER; + printk("%s:%d ()+\n",__FUNCTION__, __LINE__); + ret = dwc3_core_get_phy(dwc); if (ret) return ret; @@ -695,6 +707,8 @@ static int dwc3_probe(struct platform_device *pdev) spin_lock_init(&dwc->lock); platform_set_drvdata(pdev, dwc); + printk("%s:%d ()+\n",__FUNCTION__, __LINE__); + dwc->regs = regs; dwc->regs_size = resource_size(res); @@ -708,6 +722,8 @@ static int dwc3_probe(struct platform_device *pdev) dwc3_cache_hwparams(dwc); + printk("%s:%d ()+\n",__FUNCTION__, __LINE__); + ret = dwc3_alloc_event_buffers(dwc, DWC3_EVENT_BUFFERS_SIZE); if (ret) { dev_err(dwc->dev, "failed to allocate event buffers\n"); @@ -735,6 +751,8 @@ static int dwc3_probe(struct platform_device *pdev) if (ret < 0) goto err1; + printk("%s:%d ()+\n",__FUNCTION__, __LINE__); + ret = phy_power_on(dwc->usb3_generic_phy); if (ret < 0) goto err_usb2phy_power; @@ -749,12 +767,16 @@ static int dwc3_probe(struct platform_device *pdev) if (ret) goto err2; + printk("%s:%d ()+\n",__FUNCTION__, __LINE__); + ret = dwc3_debugfs_init(dwc); if (ret) { dev_err(dev, "failed to initialize debugfs\n"); goto err3; } + printk("%s:%d ()+\n",__FUNCTION__, __LINE__); + pm_runtime_allow(dev); return 0; @@ -780,6 +802,8 @@ err0: dwc3_free_event_buffers(dwc); return ret; + + printk("%s:%d ()-\n",__FUNCTION__, __LINE__); } static int dwc3_remove(struct platform_device *pdev) diff --git a/drivers/usb/dwc3/dwc3-st.c b/drivers/usb/dwc3/dwc3-st.c index 19ede8643c7b..14ee7bb5e7d1 100644 --- a/drivers/usb/dwc3/dwc3-st.c +++ b/drivers/usb/dwc3/dwc3-st.c @@ -92,6 +92,8 @@ static int st_dwc3_drd_init(struct st_dwc3 *dwc3_data) { u32 val; + printk("%s:%d ()+\n",__FUNCTION__, __LINE__); + regmap_read(dwc3_data->regmap, dwc3_data->syscfg_reg_off, &val); if (dwc3_data->drd_device_conf) @@ -99,6 +101,8 @@ static int st_dwc3_drd_init(struct st_dwc3 *dwc3_data) else val &= USB_HOST_DEFAULT_MASK; + printk("%s:%d ()-\n",__FUNCTION__, __LINE__); + return regmap_write(dwc3_data->regmap, dwc3_data->syscfg_reg_off, val); } @@ -108,6 +112,8 @@ static int st_dwc3_drd_init(struct st_dwc3 *dwc3_data) */ static void st_dwc3_init(struct st_dwc3 *dwc3_data) { + + printk("%s:%d ()+\n",__FUNCTION__, __LINE__); u32 reg = st_dwc3_readl(dwc3_data->glue_base, USB2_CLKRST_CTRL); reg |= aux_clk_en(1) | ext_cfg_reset_n(1) | xhci_revision(1); @@ -123,6 +129,7 @@ static void st_dwc3_init(struct st_dwc3 *dwc3_data) reg = st_dwc3_readl(dwc3_data->glue_base, USB2_CLKRST_CTRL); reg |= sw_pipew_reset_n(1); st_dwc3_writel(dwc3_data->glue_base, USB2_CLKRST_CTRL, reg); + printk("%s:%d ()-\n",__FUNCTION__, __LINE__); } static void st_dwc3_dt_get_pdata(struct platform_device *pdev, @@ -150,6 +157,8 @@ static int st_dwc3_probe(struct platform_device *pdev) struct regmap *regmap; int ret = 0; + printk("%s:%d()+\n",__FUNCTION__, __LINE__); + dwc3_data = devm_kzalloc(dev, sizeof(*dwc3_data), GFP_KERNEL); if (!dwc3_data) return -ENOMEM; @@ -206,12 +215,19 @@ static int st_dwc3_probe(struct platform_device *pdev) if (IS_ERR(dwc3_data->rstc)) dwc3_data->rstc = NULL; + printk("%s:%d\n",__FUNCTION__, __LINE__); + /* Manage PowerDown */ - reset_control_deassert(dwc3_data->rstc); + if (dwc3_data->rstc) + reset_control_deassert(dwc3_data->rstc); + + printk("%s:%d()+\n",__FUNCTION__, __LINE__); if (node) { + printk("%s:%d()+\n",__FUNCTION__, __LINE__); st_dwc3_dt_get_pdata(pdev, dwc3_data); /* Allocate and initialize the core */ + printk("%s:%d()+\n",__FUNCTION__, __LINE__); ret = of_platform_populate(node, NULL, NULL, dev); if (ret) { dev_err(dev, "failed to add dwc3 core\n"); @@ -221,7 +237,7 @@ static int st_dwc3_probe(struct platform_device *pdev) dev_err(dev, "no device node, failed to add dwc3 core\n"); return -ENODEV; } - + printk("%s:%d()+\n",__FUNCTION__, __LINE__); /* ST glue logic init */ st_dwc3_init(dwc3_data); @@ -242,6 +258,8 @@ static int st_dwc3_probe(struct platform_device *pdev) dev_info(&pdev->dev, "probe exits fine...\n"); + printk("%s:d ()-\n",__FUNCTION__, __LINE__); + return ret; } @@ -259,7 +277,8 @@ static int st_dwc3_suspend(struct device *dev) { struct st_dwc3 *dwc3_data = dev_get_drvdata(dev); - reset_control_assert(dwc3_data->rstc); + if (dwc3_data->rstc) + reset_control_assert(dwc3_data->rstc); pinctrl_pm_select_sleep_state(dev); @@ -272,7 +291,8 @@ static int st_dwc3_resume(struct device *dev) pinctrl_pm_select_default_state(dev); - reset_control_deassert(dwc3_data->rstc); + if (dwc3_data->rstc) + reset_control_deassert(dwc3_data->rstc); return 0; } diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig index a7f4a5a70438..895e72463165 100644 --- a/drivers/usb/phy/Kconfig +++ b/drivers/usb/phy/Kconfig @@ -232,6 +232,8 @@ config USB_ULPI_VIEWPORT config PHY_STIH407_USB tristate "STMicroelectronics picoPHY/MiPHY driver for STiH407 series" depends on ARCH_STI + depends on RESET_CONTROLLER + select USB_PHY help Enable this to support the USB transceiver that is part of STMicroelectronics STiH407 SoC series. This will provide the picoPHY diff --git a/drivers/usb/phy/Makefile b/drivers/usb/phy/Makefile index 4747e67656a1..7584d4894a4e 100644 --- a/drivers/usb/phy/Makefile +++ b/drivers/usb/phy/Makefile @@ -29,5 +29,5 @@ obj-$(CONFIG_USB_RCAR_GEN2_PHY) += phy-rcar-gen2-usb.o obj-$(CONFIG_USB_ULPI) += phy-ulpi.o obj-$(CONFIG_USB_ULPI_VIEWPORT) += phy-ulpi-viewport.o obj-$(CONFIG_KEYSTONE_USB_PHY) += phy-keystone.o -obj-$(CONFIG_PHY_STIH407_USB) += phy-stih407-usb2.o phy-stih407-usb3.o +obj-$(CONFIG_PHY_STIH407_USB) += phy-stih407-usb2.o phy-st-usb3.o diff --git a/drivers/usb/phy/phy-st-usb3.c b/drivers/usb/phy/phy-st-usb3.c new file mode 100644 index 000000000000..205db9f0ab9c --- /dev/null +++ b/drivers/usb/phy/phy-st-usb3.c @@ -0,0 +1,317 @@ +/* + * Copyright (C) 2013 STMicroelectronics + * + * STMicroelectronics PHY driver for MiPHY LP28 (MiPHY2 for USB3 device) + * + * Author: Giuseppe Cavallaro <peppe.cavallaro@st.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, as + * published by the Free Software Foundation. + * + */ +#include <linux/platform_device.h> +#include <linux/io.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/of_platform.h> +#include <linux/clk.h> +#include <linux/regmap.h> +#include <linux/reset.h> +#include <linux/delay.h> +#include <linux/mfd/syscon.h> +#include <linux/usb/phy.h> + +#define phy_to_priv(x) container_of((x), struct sti_usb3_miphy, phy) + +/* MiPHY_2 Control */ +#define SYSCFG5071 0x11c +#define MIPHY2_PX_TX_POLARITY 1 +#define MIPHY2_PX_RX_POLARITY 2 +#define MIPHY2_PX_SYNC_DETECT_ENABLE 3 + +/** + * struct sti_usb3_cfg - SoC specific PHY register mapping + * @syscfg: Offset in syscfg registers bank + * @cfg_mask: Bits mask for PHY configuration + * @cfg: Static configuration value for PHY + */ +struct sti_usb3_cfg { + u32 syscfg; + u32 cfg_mask; + u32 cfg; +}; + +struct sti_usb3_miphy { + struct usb_phy phy; + struct device *dev; + struct regmap *regmap; + const struct sti_usb3_cfg *cfg; + struct reset_control *rstc; + void __iomem *usb3_base; + void __iomem *pipe_base; +}; + +static struct sti_usb3_cfg sti_usb3_miphy_cfg = { + .syscfg = SYSCFG5071, + .cfg_mask = 0x7, + .cfg = MIPHY2_PX_SYNC_DETECT_ENABLE, +}; + +struct miphy_initval { + u16 reg; + u16 val; +}; + +/* That is a magic sequence of register settings provided at + * verification level to setup the MiPHY2 for USB3 DWC3 device on STiH407. + */ +static const struct miphy_initval initvals[] = { + /* Putting Macro in reset */ + {0x00, 0x01}, {0x00, 0x03}, + /* Wait for a while */ + {0x00, 0x01}, {0x04, 0x1C}, + /* PLL calibration */ + {0xEB, 0x1D}, {0x0D, 0x1E}, {0x0F, 0x00}, {0xC4, 0x70}, + {0xC9, 0x02}, {0xCA, 0x02}, {0xCB, 0x02}, {0xCC, 0x0A}, + /* Writing The PLL Ratio */ + {0xD4, 0xA6}, {0xD5, 0xAA}, {0xD6, 0xAA}, {0xD7, 0x04}, + {0xD3, 0x00}, + /* Writing The Speed Rate */ + {0x0F, 0x00}, {0x0E, 0x0A}, + /* RX Channel compensation and calibration */ + {0xC2, 0x1C}, {0x97, 0x51}, {0x98, 0x70}, {0x99, 0x5F}, + {0x9A, 0x22}, {0x9F, 0x0E}, + + {0x7A, 0x05}, {0x7F, 0x78}, {0x30, 0x1B}, + /* Enable GENSEL_SEL and SSC */ + /* TX_SEL=0 swing preemp forced by pipe registres */ + {0x0A, 0x11}, + /* MIPHY Bias boost */ + {0x63, 0x00}, {0x64, 0xA7}, + /* TX compensation offset to re-center TX impedance */ + {0x42, 0x02}, + /* SSC modulation */ + {0x0C, 0x04}, + /* MIPHY TX control */ + {0x0F, 0x00}, {0xE5, 0x5A}, {0xE6, 0xA0}, {0xE4, 0x3C}, + {0xE6, 0xA1}, {0xE3, 0x00}, {0xE3, 0x02}, {0xE3, 0x00}, + /* Rx PI controller settings */ + {0x78, 0xCA}, + /* MIPHY RX input bridge control */ + /* INPUT_BRIDGE_EN_SW=1, manual input bridge control[0]=1 */ + {0xCD, 0x21}, {0xCD, 0x29}, {0xCE, 0x1A}, + /* MIPHY Reset */ + {0x00, 0x01}, {0x00, 0x00}, {0x01, 0x04}, {0x01, 0x05}, + {0xE9, 0x00}, {0x0D, 0x1E}, {0x3A, 0x40}, {0x01, 0x01}, + {0x01, 0x00}, {0xE9, 0x40}, {0x0F, 0x00}, {0x0B, 0x00}, + {0x62, 0x00}, {0x0F, 0x00}, {0xE3, 0x02}, {0x26, 0xA5}, + {0x0F, 0x00}, +}; + +static int sti_usb3_miphy_autocalibration(struct usb_phy *phy_dev, + enum usb_device_speed speed) +{ + struct sti_usb3_miphy *miphy = phy_to_priv(phy_dev); + + writeb_relaxed(0x40, miphy->usb3_base + 0x01); + writeb_relaxed(0x00, miphy->usb3_base + 0x01); + dev_dbg(miphy->dev, "miphy autocalibration done\n"); + + /* + * Set a safe delay after calibration; we use the same range as in the + * phy-miphy28lp driver, where a delay is set after miphy reset. + * Here we are in the same case given that we are + * performing a reset to allow miphy to re-calibrate itself. + */ + usleep_range(10, 20); + + /* Check status */ + if ((readb_relaxed(miphy->usb3_base + 0x83)) || + (readb_relaxed(miphy->usb3_base + 0x84))) + dev_err(miphy->dev, "miphy autocalibration failed!\n"); + + return 0; +} + +static void sti_usb3_miphy28lp(struct sti_usb3_miphy *phy_dev) +{ + int i; + + dev_info(phy_dev->dev, "MiPHY28LP setup\n"); + + for (i = 0; i < ARRAY_SIZE(initvals); i++) { + dev_dbg(phy_dev->dev, "reg: 0x%x=0x%x\n", initvals[i].reg, + initvals[i].val); + writeb_relaxed(initvals[i].val, + phy_dev->usb3_base + initvals[i].reg); + } + + /* PIPE Wrapper Configuration */ + writeb_relaxed(0X68, phy_dev->pipe_base + 0x23); + writeb_relaxed(0X61, phy_dev->pipe_base + 0x24); + writeb_relaxed(0X68, phy_dev->pipe_base + 0x26); + writeb_relaxed(0X61, phy_dev->pipe_base + 0x27); + writeb_relaxed(0X18, phy_dev->pipe_base + 0x29); + writeb_relaxed(0X61, phy_dev->pipe_base + 0x2A); + + /*pipe Wrapper usb3 TX swing de-emph margin PREEMPH[7:4], SWING[3:0] */ + writeb_relaxed(0X67, phy_dev->pipe_base + 0x68); + writeb_relaxed(0X0D, phy_dev->pipe_base + 0x69); + writeb_relaxed(0X67, phy_dev->pipe_base + 0x6A); + writeb_relaxed(0X0D, phy_dev->pipe_base + 0x6B); + writeb_relaxed(0X67, phy_dev->pipe_base + 0x6C); + writeb_relaxed(0X0D, phy_dev->pipe_base + 0x6D); + writeb_relaxed(0X67, phy_dev->pipe_base + 0x6E); + writeb_relaxed(0X0D, phy_dev->pipe_base + 0x6F); +} + +static int sti_usb3_miphy_init(struct usb_phy *phy) +{ + struct sti_usb3_miphy *phy_dev = phy_to_priv(phy); + int ret; + + ret = regmap_update_bits(phy_dev->regmap, phy_dev->cfg->syscfg, + phy_dev->cfg->cfg_mask, phy_dev->cfg->cfg); + if (ret) + return ret; + + reset_control_deassert(phy_dev->rstc); + + /* Program the MiPHY2 internal registers */ + sti_usb3_miphy28lp(phy_dev); + + return 0; +} + +static void sti_usb3_miphy_shutdown(struct usb_phy *phy) +{ + struct sti_usb3_miphy *phy_dev = phy_to_priv(phy); + + reset_control_assert(phy_dev->rstc); +} + +static const struct of_device_id sti_usb3_miphy_of_match[]; + +static int sti_usb3_miphy_probe(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + const struct of_device_id *match; + struct sti_usb3_miphy *phy_dev; + struct device *dev = &pdev->dev; + struct usb_phy *phy; + struct resource *res; + + phy_dev = devm_kzalloc(dev, sizeof(*phy_dev), GFP_KERNEL); + if (!phy_dev) + return -ENOMEM; + + match = of_match_device(sti_usb3_miphy_of_match, &pdev->dev); + if (!match) + return -ENODEV; + + phy_dev->cfg = match->data; + phy_dev->dev = dev; + + phy_dev->rstc = devm_reset_control_get(dev, NULL); + if (IS_ERR(phy_dev->rstc)) { + dev_err(dev, "failed to ctrl MiPHY2 USB3 reset ret = %d\n",phy_dev->rstc); + return PTR_ERR(phy_dev->rstc); + } + + dev_info(dev, "reset MiPHY\n"); + reset_control_deassert(phy_dev->rstc); + + phy_dev->regmap = syscon_regmap_lookup_by_phandle(np, "st,syscfg"); + if (IS_ERR(phy_dev->regmap)) { + dev_err(dev, "No syscfg phandle specified\n"); + return PTR_ERR(phy_dev->regmap); + } + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "usb3-uport"); + if (res) { + phy_dev->usb3_base = devm_request_and_ioremap(&pdev->dev, res); + if (!phy_dev->usb3_base) { + dev_err(&pdev->dev, "Unable to map base registers\n"); + return -ENOMEM; + } + } + /* Check for PIPE registers */ + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pipew"); + if (res) { + phy_dev->pipe_base = devm_request_and_ioremap(&pdev->dev, res); + if (!phy_dev->pipe_base) { + dev_err(&pdev->dev, "Unable to map PIPE registers\n"); + return -ENOMEM; + } + } + + dev_info(dev, "usb3 ioaddr 0x%p, pipew ioaddr 0x%p\n", + phy_dev->usb3_base, phy_dev->pipe_base); + + phy = &phy_dev->phy; + phy->dev = dev; + phy->label = "USB3 MiPHY2 (LP28)"; + phy->init = sti_usb3_miphy_init; + phy->type = USB_PHY_TYPE_USB3; + phy->shutdown = sti_usb3_miphy_shutdown; + if (of_property_read_bool(np, "st,auto-calibration")) + phy->notify_disconnect = sti_usb3_miphy_autocalibration; + + usb_add_phy_dev(phy); + + platform_set_drvdata(pdev, phy_dev); + + dev_info(dev, "USB3 MiPHY2 probed\n"); + + return 0; +} + +static int sti_usb3_miphy_remove(struct platform_device *pdev) +{ + struct sti_usb3_miphy *phy_dev = platform_get_drvdata(pdev); + + reset_control_assert(phy_dev->rstc); + + usb_remove_phy(&phy_dev->phy); + + return 0; +} + +static const struct of_device_id sti_usb3_miphy_of_match[] = { + { + .compatible = "st,sti-usb3phy", + .data = &sti_usb3_miphy_cfg}, + {}, +}; + +MODULE_DEVICE_TABLE(of, sti_usb3_miphy_of_match); + +static struct platform_driver sti_usb3_miphy_driver = { + .probe = sti_usb3_miphy_probe, + .remove = sti_usb3_miphy_remove, + .driver = { + .name = "sti-usb3-phy", + .owner = THIS_MODULE, + .of_match_table = sti_usb3_miphy_of_match, + } +}; + +//module_platform_driver(sti_usb3_miphy_driver); + +static int __init sti_usb3_miphy_drive_init(void) +{ + return platform_driver_register(&sti_usb3_miphy_driver); +} + +subsys_initcall(sti_usb3_miphy_drive_init); + +static void __exit sti_usb3_miphy_drive_exit(void) +{ + return platform_driver_unregister(&sti_usb3_miphy_driver); +} + +MODULE_AUTHOR("Giuseppe Cavallaro <peppe.cavallaro@st.com>"); +MODULE_DESCRIPTION("STMicroelectronics USB3 MiPHY for STiH407/STi8416 SoC"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/usb/phy/phy-stih407-usb2.c b/drivers/usb/phy/phy-stih407-usb2.c index 2cb7751ec93e..7160f80eeff3 100644 --- a/drivers/usb/phy/phy-stih407-usb2.c +++ b/drivers/usb/phy/phy-stih407-usb2.c @@ -93,6 +93,8 @@ static int stih407_usb2_picophy_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct usb_phy *phy; + printk("%s:%d()+\n",__FUNCTION__, __LINE__); + phy_dev = devm_kzalloc(dev, sizeof(*phy_dev), GFP_KERNEL); if (!phy_dev) return -ENOMEM; @@ -129,6 +131,7 @@ static int stih407_usb2_picophy_probe(struct platform_device *pdev) platform_set_drvdata(pdev, phy_dev); dev_info(dev, "USB2 picoPHY probed\n"); + printk("%s:%d()-\n",__FUNCTION__, __LINE__); return 0; } |