From 27d068d4f7068f8118623df27b3886eda20d30b8 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 24 Jun 2015 14:32:21 +0300 Subject: [PATCH 01/26] mmc: block: don't use parameter prefix if built as module It's excessive to use prefix for the parameters when you do modprobe mmc-block mmcblk.perdev_minors=16 Make this available only for built-in case. Change-Id: I85b3ab146cca341795315fb5578fec8ceda3d30c Signed-off-by: Andy Shevchenko Signed-off-by: Ulf Hansson --- drivers/mmc/card/block.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index 8a0147dfed27d8..9abc0e7fbc6fd7 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -47,10 +47,13 @@ #include "queue.h" MODULE_ALIAS("mmc:block"); + +#ifdef KERNEL #ifdef MODULE_PARAM_PREFIX #undef MODULE_PARAM_PREFIX #endif #define MODULE_PARAM_PREFIX "mmcblk." +#endif #define INAND_CMD38_ARG_EXT_CSD 113 #define INAND_CMD38_ARG_ERASE 0x00 From a61909c7c2977217873a8f720e0ac32cb3bb5174 Mon Sep 17 00:00:00 2001 From: Anand Moon Date: Sun, 12 Jul 2015 18:41:20 +0530 Subject: [PATCH 02/26] regulator: s2mps11: Added shutdown function to poweroff Added .shutdown function to s2mps11 to help poweroff the board successfully. The device driver clears the register to turn off the PMIC. s2mps11-pmic: S2MPS11_REG_CTRL1 reg value 16:00000000000000000000000000010000 Console log. * Unmounting temporary filesystems... [ OK ] * Deactivating swap... [ OK ] * Unmounting local filesystems... [ OK ] * Will now halt [ 209.020280] reboot: Power down [ 209.122039] Power down failed, please power off system manually. Change-Id: If6ea0dec154b00ceeaaddbac393c67dc35c26279 Signed-off-by: Anand Moon --- drivers/regulator/s2mps11.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c index 6dfa3502e1f1a5..7dc82addd27454 100644 --- a/drivers/regulator/s2mps11.c +++ b/drivers/regulator/s2mps11.c @@ -1219,6 +1219,31 @@ static int s2mps11_pmic_probe(struct platform_device *pdev) return ret; } +static void s2mps11_pmic_shutdown(struct platform_device *pdev) +{ + struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent); + unsigned int reg_val, ret; + + ret = regmap_read(iodev->regmap_pmic, S2MPS11_REG_CTRL1, ®_val); + if (ret < 0) { + dev_crit(&pdev->dev, "could not read S2MPS11_REG_CTRL1 value\n"); + } else { + /* + * s2mps11-pmic: S2MPS11_REG_CTRL1 reg value + * is 00000000000000000000000000010000 + * clear the S2MPS11_REG_CTRL1 0x10 value to shutdown. + */ + if (reg_val & BIT(4)) { + ret = regmap_update_bits(iodev->regmap_pmic, + S2MPS11_REG_CTRL1, + BIT(4), BIT(0)); + if (ret) + dev_crit(&pdev->dev, + "could not write S2MPS11_REG_CTRL1 value\n"); + } + } +} + static const struct platform_device_id s2mps11_pmic_id[] = { { "s2mps11-regulator", S2MPS11X}, { "s2mps13-regulator", S2MPS13X}, @@ -1234,6 +1259,7 @@ static struct platform_driver s2mps11_pmic_driver = { .name = "s2mps11-pmic", }, .probe = s2mps11_pmic_probe, + .shutdown = s2mps11_pmic_shutdown, .id_table = s2mps11_pmic_id, }; From c57de4341baf133656cc41300b689e39cd57a82b Mon Sep 17 00:00:00 2001 From: Heikki Krogerus Date: Wed, 19 Nov 2014 17:28:22 +0200 Subject: [PATCH 03/26] base: platform: name the device already during allocation The device name is usually required when assigning resources like clocks to platform devices. The problem is that the device name is not know before platform_device_add is called and that can be too late as the drivers may have already requested the resources when the function returns. By naming the device already in platform_device_alloc, the resources can be assigned before platform_device_add is called. This change allows different kinds of probe drivers to pass forward their resources to the actual driver. The first place where we need it is dwc3 controllers host glue code (drivers/usb/dwc3/host.c) to pass the phy's to xhci. Change-Id: I1a5a6009ad053e44054b86b5a675142f301dfefc Signed-off-by: Heikki Krogerus Cc: Greg Kroah-Hartman --- drivers/base/platform.c | 69 ++++++++++++++++++++++++----------------- 1 file changed, 41 insertions(+), 28 deletions(-) diff --git a/drivers/base/platform.c b/drivers/base/platform.c index f437afa17f2b1d..e485e6646905ec 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -225,11 +225,41 @@ void platform_device_put(struct platform_device *pdev) } EXPORT_SYMBOL_GPL(platform_device_put); +static int pdev_set_name(struct platform_device *pdev) +{ + int ret; + + switch (pdev->id) { + default: + return dev_set_name(&pdev->dev, "%s.%d", pdev->name, pdev->id); + case PLATFORM_DEVID_NONE: + return dev_set_name(&pdev->dev, "%s", pdev->name); + case PLATFORM_DEVID_AUTO: + /* + * Automatically allocated device ID. We mark it as such so + * that we remember it must be freed, and we append a suffix + * to avoid namespace collision with explicit IDs. + */ + ret = ida_simple_get(&platform_devid_ida, 0, 0, GFP_KERNEL); + if (ret < 0) + return ret; + pdev->id = ret; + pdev->id_auto = true; + return dev_set_name(&pdev->dev, "%s.%d.auto", pdev->name, + pdev->id); + } + + return 0; +} + static void platform_device_release(struct device *dev) { struct platform_object *pa = container_of(dev, struct platform_object, pdev.dev); + if (pa->pdev.id_auto) + ida_simple_remove(&platform_devid_ida, pa->pdev.id); + of_device_node_put(&pa->pdev.dev); kfree(pa->pdev.dev.platform_data); kfree(pa->pdev.mfd_cell); @@ -258,6 +288,10 @@ struct platform_device *platform_device_alloc(const char *name, int id) device_initialize(&pa->pdev.dev); pa->pdev.dev.release = platform_device_release; arch_setup_pdev_archdata(&pa->pdev); + if (pdev_set_name(&pa->pdev)) { + kfree(pa); + return NULL; + } } return pa ? &pa->pdev : NULL; @@ -354,28 +388,6 @@ int platform_device_add(struct platform_device *pdev) pdev->dev.bus = &platform_bus_type; - switch (pdev->id) { - default: - dev_set_name(&pdev->dev, "%s.%d", pdev->name, pdev->id); - break; - case PLATFORM_DEVID_NONE: - dev_set_name(&pdev->dev, "%s", pdev->name); - break; - case PLATFORM_DEVID_AUTO: - /* - * Automatically allocated device ID. We mark it as such so - * that we remember it must be freed, and we append a suffix - * to avoid namespace collision with explicit IDs. - */ - ret = ida_simple_get(&platform_devid_ida, 0, 0, GFP_KERNEL); - if (ret < 0) - goto err_out; - pdev->id = ret; - pdev->id_auto = true; - dev_set_name(&pdev->dev, "%s.%d.auto", pdev->name, pdev->id); - break; - } - for (i = 0; i < pdev->num_resources; i++) { struct resource *p, *r = &pdev->resource[i]; @@ -416,7 +428,6 @@ int platform_device_add(struct platform_device *pdev) release_resource(r); } - err_out: return ret; } EXPORT_SYMBOL_GPL(platform_device_add); @@ -436,11 +447,6 @@ void platform_device_del(struct platform_device *pdev) if (pdev) { device_del(&pdev->dev); - if (pdev->id_auto) { - ida_simple_remove(&platform_devid_ida, pdev->id); - pdev->id = PLATFORM_DEVID_AUTO; - } - for (i = 0; i < pdev->num_resources; i++) { struct resource *r = &pdev->resource[i]; if (r->parent) @@ -458,8 +464,15 @@ EXPORT_SYMBOL_GPL(platform_device_del); */ int platform_device_register(struct platform_device *pdev) { + int ret; + device_initialize(&pdev->dev); arch_setup_pdev_archdata(pdev); + + ret = pdev_set_name(pdev); + if (ret) + return ret; + return platform_device_add(pdev); } EXPORT_SYMBOL_GPL(platform_device_register); From 1ad955c8380f296ae514fe64bf6fc45d1c2f73d9 Mon Sep 17 00:00:00 2001 From: Vivek Gautam Date: Fri, 31 Oct 2014 18:56:28 +0530 Subject: [PATCH 04/26] usb: host: xhci-plat: Get PHYs for xhci's hcds The host controller by itself may sometimes need to handle PHY and re-initialize it to re-configure some of the PHY parameters to get full support out of the PHY controller. Therefore, facilitate getting the two possible PHYs, viz. USB 2.0 type (UTMI+) and USB 3.0 type (PIPE3), and initialize them. Signed-off-by: Vivek Gautam Conflicts: drivers/usb/host/xhci-plat.c Change-Id: Ib92f7ea631c2f2d76271d77cf84dda4914b74668 --- drivers/usb/host/xhci-plat.c | 94 +++++++++++++++++++++++++++++------- 1 file changed, 76 insertions(+), 18 deletions(-) diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c index 474b5fa149007b..60137fe18bc77e 100644 --- a/drivers/usb/host/xhci-plat.c +++ b/drivers/usb/host/xhci-plat.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -213,6 +214,41 @@ static int xhci_plat_probe(struct platform_device *pdev) goto disable_clk; } + /* Get possile USB 2.0 type PHY (UTMI+) available with xhci */ + hcd->phy = devm_phy_get(&pdev->dev, "usb2-phy"); + if (IS_ERR(hcd->phy)) { + ret = PTR_ERR(hcd->phy); + if (ret == -EPROBE_DEFER) { + goto disable_clk; + } else if (ret != -ENOSYS && ret != -ENODEV) { + hcd->phy = NULL; + dev_warn(&pdev->dev, + "Error retrieving usb2 phy: %d\n", ret); + } + } + + ret = usb_add_hcd(hcd, irq, IRQF_SHARED); + if (ret) + goto disable_clk; + + /* + * Initialize and power-on USB 2.0 PHY + * FIXME: Isn't this a hacky way of initializing the PHY again ? + * xhci's parent would have already initialized the PHY, but we + * wanna do it again. + */ + hcd->phy->init_count = 0; + ret = phy_init(hcd->phy); + if (ret) + goto dealloc_usb2_hcd; + + hcd->phy->power_count = 0; + ret = phy_power_on(hcd->phy); + if (ret) { + phy_exit(hcd->phy); + goto dealloc_usb2_hcd; + } + device_wakeup_enable(hcd->self.controller); xhci->clk = clk; @@ -231,38 +267,47 @@ static int xhci_plat_probe(struct platform_device *pdev) if (HCC_MAX_PSA(xhci->hcc_params) >= 4) xhci->shared_hcd->can_do_streams = 1; - hcd->usb_phy = devm_usb_get_phy_by_phandle(&pdev->dev, "usb-phy", 0); - if (IS_ERR(hcd->usb_phy)) { - ret = PTR_ERR(hcd->usb_phy); - if (ret == -EPROBE_DEFER) - goto put_usb3_hcd; - hcd->usb_phy = NULL; - } else { - ret = usb_phy_init(hcd->usb_phy); - if (ret) + /* Get possile USB 3.0 type PHY (PIPE3) available with xhci */ + xhci->shared_hcd->phy = devm_phy_get(&pdev->dev, "usb3-phy"); + if (IS_ERR(xhci->shared_hcd->phy)) { + ret = PTR_ERR(xhci->shared_hcd->phy); + if (ret == -EPROBE_DEFER) { goto put_usb3_hcd; + } else if (ret != -ENOSYS && ret != -ENODEV) { + xhci->shared_hcd->phy = NULL; + dev_warn(&pdev->dev, + "Error retrieving usb3 phy: %d\n", ret); + } } - ret = usb_add_hcd(hcd, irq, IRQF_SHARED); - if (ret) - goto disable_usb_phy; - ret = usb_add_hcd(xhci->shared_hcd, irq, IRQF_SHARED); if (ret) goto dealloc_usb2_hcd; - return 0; + /* Initialize and power-on USB 3.0 PHY */ + xhci->shared_hcd->phy->init_count = 0; + ret = phy_init(xhci->shared_hcd->phy); + if (ret) + goto dealloc_usb3_hcd; + xhci->shared_hcd->phy->power_count = 0; + ret = phy_power_on(xhci->shared_hcd->phy); + if (ret) { + phy_exit(xhci->shared_hcd->phy); + goto dealloc_usb3_hcd; + } -dealloc_usb2_hcd: - usb_remove_hcd(hcd); + return 0; -disable_usb_phy: - usb_phy_shutdown(hcd->usb_phy); +dealloc_usb3_hcd: + usb_remove_hcd(xhci->shared_hcd); put_usb3_hcd: usb_put_hcd(xhci->shared_hcd); +dealloc_usb2_hcd: + usb_remove_hcd(hcd); + disable_clk: if (!IS_ERR(clk)) clk_disable_unprepare(clk); @@ -279,9 +324,15 @@ static int xhci_plat_remove(struct platform_device *dev) struct xhci_hcd *xhci = hcd_to_xhci(hcd); struct clk *clk = xhci->clk; + phy_power_off(xhci->shared_hcd->phy); + phy_exit(xhci->shared_hcd->phy); + usb_remove_hcd(xhci->shared_hcd); usb_phy_shutdown(hcd->usb_phy); + phy_power_off(hcd->phy); + phy_exit(hcd->phy); + usb_remove_hcd(hcd); usb_put_hcd(xhci->shared_hcd); @@ -298,6 +349,8 @@ static int xhci_plat_suspend(struct device *dev) struct usb_hcd *hcd = dev_get_drvdata(dev); struct xhci_hcd *xhci = hcd_to_xhci(hcd); + phy_exit(hcd->phy); + /* * xhci_suspend() needs `do_wakeup` to know whether host is allowed * to do wakeup during suspend. Since xhci_plat_suspend is currently @@ -313,6 +366,11 @@ static int xhci_plat_resume(struct device *dev) { struct usb_hcd *hcd = dev_get_drvdata(dev); struct xhci_hcd *xhci = hcd_to_xhci(hcd); + int ret; + + ret = phy_init(hcd->phy); + if (ret) + return ret; return xhci_resume(xhci, 0); } From ef35228427ee8cfbb3e4a2cc658040b349679cac Mon Sep 17 00:00:00 2001 From: Vivek Gautam Date: Fri, 31 Oct 2014 18:56:29 +0530 Subject: [PATCH 05/26] phy: exynos5-usbdrd: Calibrate LOS levels for exynos5420/5800 Adding phy calibration sequence for USB 3.0 DRD PHY present on Exynos5420/5800 systems. This calibration facilitates setting certain PHY parameters viz. the Loss-of-Signal (LOS) Detector Threshold Level, as well as Tx-Vboost-Level for Super-Speed operations. Additionally we also set proper time to wait for RxDetect measurement, for desired PHY reference clock, so as to solve issue with enumeration of few USB 3.0 devices, like Samsung SUM-TSB16S 3.0 USB drive on the controller. We are using CR_port for this purpose to send required data to override the LOS values. On testing with USB 3.0 devices on USB 3.0 port present on SMDK5420, and peach-pit boards should see following message: usb 2-1: new SuperSpeed USB device number 2 using xhci-hcd and without this patch, should see below shown message: usb 1-1: new high-speed USB device number 2 using xhci-hcd [Also removed unnecessary extra lines in the register macro definitions] Change-Id: I81dcd0dfa057b6b63e18578f2bc9dc276cc5b74a Signed-off-by: Vivek Gautam --- drivers/phy/phy-exynos5-usbdrd.c | 219 ++++++++++++++++++++++++++++--- 1 file changed, 203 insertions(+), 16 deletions(-) diff --git a/drivers/phy/phy-exynos5-usbdrd.c b/drivers/phy/phy-exynos5-usbdrd.c index 20696f53303f07..70ef7e37e02133 100644 --- a/drivers/phy/phy-exynos5-usbdrd.c +++ b/drivers/phy/phy-exynos5-usbdrd.c @@ -37,13 +37,11 @@ /* EXYNOS5: USB 3.0 DRD PHY registers */ #define EXYNOS5_DRD_LINKSYSTEM 0x04 - #define LINKSYSTEM_FLADJ_MASK (0x3f << 1) #define LINKSYSTEM_FLADJ(_x) ((_x) << 1) #define LINKSYSTEM_XHCI_VERSION_CONTROL BIT(27) #define EXYNOS5_DRD_PHYUTMI 0x08 - #define PHYUTMI_OTGDISABLE BIT(6) #define PHYUTMI_FORCESUSPEND BIT(1) #define PHYUTMI_FORCESLEEP BIT(0) @@ -51,26 +49,20 @@ #define EXYNOS5_DRD_PHYPIPE 0x0c #define EXYNOS5_DRD_PHYCLKRST 0x10 - #define PHYCLKRST_EN_UTMISUSPEND BIT(31) - #define PHYCLKRST_SSC_REFCLKSEL_MASK (0xff << 23) #define PHYCLKRST_SSC_REFCLKSEL(_x) ((_x) << 23) - #define PHYCLKRST_SSC_RANGE_MASK (0x03 << 21) #define PHYCLKRST_SSC_RANGE(_x) ((_x) << 21) - #define PHYCLKRST_SSC_EN BIT(20) #define PHYCLKRST_REF_SSP_EN BIT(19) #define PHYCLKRST_REF_CLKDIV2 BIT(18) - #define PHYCLKRST_MPLL_MULTIPLIER_MASK (0x7f << 11) #define PHYCLKRST_MPLL_MULTIPLIER_100MHZ_REF (0x19 << 11) #define PHYCLKRST_MPLL_MULTIPLIER_50M_REF (0x32 << 11) #define PHYCLKRST_MPLL_MULTIPLIER_24MHZ_REF (0x68 << 11) #define PHYCLKRST_MPLL_MULTIPLIER_20MHZ_REF (0x7d << 11) #define PHYCLKRST_MPLL_MULTIPLIER_19200KHZ_REF (0x02 << 11) - #define PHYCLKRST_FSEL_UTMI_MASK (0x7 << 5) #define PHYCLKRST_FSEL_PIPE_MASK (0x7 << 8) #define PHYCLKRST_FSEL(_x) ((_x) << 5) @@ -78,46 +70,68 @@ #define PHYCLKRST_FSEL_PAD_24MHZ (0x2a << 5) #define PHYCLKRST_FSEL_PAD_20MHZ (0x31 << 5) #define PHYCLKRST_FSEL_PAD_19_2MHZ (0x38 << 5) - #define PHYCLKRST_RETENABLEN BIT(4) - #define PHYCLKRST_REFCLKSEL_MASK (0x03 << 2) #define PHYCLKRST_REFCLKSEL_PAD_REFCLK (0x2 << 2) #define PHYCLKRST_REFCLKSEL_EXT_REFCLK (0x3 << 2) - #define PHYCLKRST_PORTRESET BIT(1) #define PHYCLKRST_COMMONONN BIT(0) #define EXYNOS5_DRD_PHYREG0 0x14 +#define PHYREG0_SSC_REF_CLK_SEL BIT(21) +#define PHYREG0_SSC_RANGE BIT(20) +#define PHYREG0_CR_WRITE BIT(19) +#define PHYREG0_CR_READ BIT(18) +#define PHYREG0_CR_DATA_IN(_x) ((_x) << 2) +#define PHYREG0_CR_CAP_DATA BIT(1) +#define PHYREG0_CR_CAP_ADDR BIT(0) + #define EXYNOS5_DRD_PHYREG1 0x18 +#define PHYREG1_CR_DATA_OUT(_x) ((_x) << 1) +#define PHYREG1_CR_ACK BIT(0) #define EXYNOS5_DRD_PHYPARAM0 0x1c - #define PHYPARAM0_REF_USE_PAD BIT(31) #define PHYPARAM0_REF_LOSLEVEL_MASK (0x1f << 26) #define PHYPARAM0_REF_LOSLEVEL (0x9 << 26) #define EXYNOS5_DRD_PHYPARAM1 0x20 - #define PHYPARAM1_PCS_TXDEEMPH_MASK (0x1f << 0) #define PHYPARAM1_PCS_TXDEEMPH (0x1c) #define EXYNOS5_DRD_PHYTERM 0x24 #define EXYNOS5_DRD_PHYTEST 0x28 - #define PHYTEST_POWERDOWN_SSP BIT(3) #define PHYTEST_POWERDOWN_HSP BIT(2) #define EXYNOS5_DRD_PHYADP 0x2c #define EXYNOS5_DRD_PHYUTMICLKSEL 0x30 - #define PHYUTMICLKSEL_UTMI_CLKSEL BIT(2) #define EXYNOS5_DRD_PHYRESUME 0x34 #define EXYNOS5_DRD_LINKPORT 0x44 +/* USB 3.0 DRD PHY SS Function Control Reg; accessed by CR_PORT */ +#define EXYNOS5_DRD_PHYSS_LOSLEVEL_OVRD_IN (0x15) +#define LOSLEVEL_OVRD_IN_LOS_BIAS_5420 (0x5 << 13) +#define LOSLEVEL_OVRD_IN_LOS_BIAS_DEFAULT (0x0 << 13) +#define LOSLEVEL_OVRD_IN_EN (0x1 << 10) +#define LOSLEVEL_OVRD_IN_LOS_LEVEL_DEFAULT (0x9 << 0) + +#define EXYNOS5_DRD_PHYSS_TX_VBOOSTLEVEL_OVRD_IN (0x12) +#define TX_VBOOSTLEVEL_OVRD_IN_VBOOST_5420 (0x5 << 13) +#define TX_VBOOSTLEVEL_OVRD_IN_VBOOST_DEFAULT (0x4 << 13) + +#define EXYNOS5_DRD_PHYSS_LANE0_TX_DEBUG (0x1010) +#define LANE0_TX_DEBUG_RXDET_MEAS_TIME_19M2_20M (0x4 << 4) +#define LANE0_TX_DEBUG_RXDET_MEAS_TIME_24M (0x8 << 4) +#define LANE0_TX_DEBUG_RXDET_MEAS_TIME_25M_26M (0x8 << 4) +#define LANE0_TX_DEBUG_RXDET_MEAS_TIME_48M_50M_52M (0x20 << 4) +#define LANE0_TX_DEBUG_RXDET_MEAS_TIME_62M5 (0x20 << 4) +#define LANE0_TX_DEBUG_RXDET_MEAS_TIME_96M_100M (0x40 << 4) + #define KHZ 1000 #define MHZ (KHZ * KHZ) @@ -135,6 +149,7 @@ struct exynos5_usbdrd_phy_config { void (*phy_isol)(struct phy_usb_instance *inst, u32 on); void (*phy_init)(struct exynos5_usbdrd_phy *phy_drd); unsigned int (*set_refclk)(struct phy_usb_instance *inst); + int (*phy_calibrate)(struct phy_usb_instance *inst); }; struct exynos5_usbdrd_phy_drvdata { @@ -142,6 +157,7 @@ struct exynos5_usbdrd_phy_drvdata { u32 pmu_offset_usbdrd0_phy; u32 pmu_offset_usbdrd1_phy; bool has_common_clk_gate; + int (*phy_exynos_calibrate)(struct exynos5_usbdrd_phy *phy_drd); }; /** @@ -408,9 +424,21 @@ static int exynos5_usbdrd_phy_init(struct phy *phy) reg &= ~PHYCLKRST_PORTRESET; writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYCLKRST); + /* + * Calibrate some of the PHY parameters, using cr_port control + * register, which are internal to PHY and are not exposed + * directly to the outside world for configuring. + */ + if (inst->phy_cfg->phy_calibrate) { + ret = inst->phy_cfg->phy_calibrate(inst); + if (ret) + dev_err(phy_drd->dev, + "Exiting init: Failed to calibrate PHY\n"); + } + clk_disable_unprepare(phy_drd->clk); - return 0; + return ret; } static int exynos5_usbdrd_phy_exit(struct phy *phy) @@ -526,6 +554,163 @@ static int exynos5_usbdrd_phy_power_off(struct phy *phy) return 0; } +static int crport_handshake(struct exynos5_usbdrd_phy *phy_drd, + u32 val, u32 cmd) +{ + u32 usec = 100; + unsigned int result; + + writel(val | cmd, phy_drd->reg_phy + EXYNOS5_DRD_PHYREG0); + + do { + result = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYREG1); + if (result & PHYREG1_CR_ACK) + break; + + udelay(1); + } while (usec-- > 0); + + if (!usec) { + dev_err(phy_drd->dev, + "CRPORT handshake timeout1 (0x%08x)\n", val); + return -ETIME; + } + + usec = 100; + + writel(val, phy_drd->reg_phy + EXYNOS5_DRD_PHYREG0); + + do { + result = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYREG1); + if (!(result & PHYREG1_CR_ACK)) + break; + + udelay(1); + } while (usec-- > 0); + + if (!usec) { + dev_err(phy_drd->dev, + "CRPORT handshake timeout2 (0x%08x)\n", val); + return -ETIME; + } + + return 0; +} + +static int crport_ctrl_write(struct exynos5_usbdrd_phy *phy_drd, + u32 addr, u32 data) +{ + int ret; + + /* Write Address */ + writel(PHYREG0_CR_DATA_IN(addr), + phy_drd->reg_phy + EXYNOS5_DRD_PHYREG0); + ret = crport_handshake(phy_drd, PHYREG0_CR_DATA_IN(addr), + PHYREG0_CR_CAP_ADDR); + if (ret) + return ret; + + /* Write Data */ + writel(PHYREG0_CR_DATA_IN(data), + phy_drd->reg_phy + EXYNOS5_DRD_PHYREG0); + ret = crport_handshake(phy_drd, PHYREG0_CR_DATA_IN(data), + PHYREG0_CR_CAP_DATA); + if (ret) + return ret; + + ret = crport_handshake(phy_drd, PHYREG0_CR_DATA_IN(data), + PHYREG0_CR_WRITE); + + return ret; +} + +/* + * Calibrate few PHY parameters using CR_PORT register to meet + * SuperSpeed requirements on Exynos5420 and Exynos5800 systems, + * which have 28nm USB 3.0 DRD PHY. + */ +static void exynos5420_usbdrd_phy_calibrate(struct exynos5_usbdrd_phy *phy_drd) +{ + unsigned int temp; + int ret = 0; + + /* + * Change los_bias to (0x5) for 28nm PHY from a + * default value (0x0); los_level is set as default + * (0x9) as also reflected in los_level[30:26] bits + * of PHYPARAM0 register. + */ + temp = LOSLEVEL_OVRD_IN_LOS_BIAS_5420 | + LOSLEVEL_OVRD_IN_EN | + LOSLEVEL_OVRD_IN_LOS_LEVEL_DEFAULT; + ret = crport_ctrl_write(phy_drd, + EXYNOS5_DRD_PHYSS_LOSLEVEL_OVRD_IN, + temp); + if (ret) { + dev_err(phy_drd->dev, + "Failed setting Loss-of-Signal level for SuperSpeed\n"); + return ret; + } + + /* + * Set tx_vboost_lvl to (0x5) for 28nm PHY Tuning, + * to raise Tx signal level from its default value of (0x4) + */ + temp = TX_VBOOSTLEVEL_OVRD_IN_VBOOST_5420; + ret = crport_ctrl_write(phy_drd, + EXYNOS5_DRD_PHYSS_TX_VBOOSTLEVEL_OVRD_IN, + temp); + if (ret) { + dev_err(phy_drd->dev, + "Failed setting Tx-Vboost-Level for SuperSpeed\n"); + return ret; + } + + /* + * Set proper time to wait for RxDetect measurement, for + * desired reference clock of PHY, by tuning the CR_PORT + * register LANE0.TX_DEBUG which is internal to PHY. + * This fixes issue with few USB 3.0 devices, which are + * not detected (not even generate interrupts on the bus + * on insertion) without this change. + * e.g. Samsung SUM-TSB16S 3.0 USB drive. + */ + switch (phy_drd->extrefclk) { + case EXYNOS5_FSEL_50MHZ: + temp = LANE0_TX_DEBUG_RXDET_MEAS_TIME_48M_50M_52M; + break; + case EXYNOS5_FSEL_20MHZ: + case EXYNOS5_FSEL_19MHZ2: + temp = LANE0_TX_DEBUG_RXDET_MEAS_TIME_19M2_20M; + break; + case EXYNOS5_FSEL_24MHZ: + default: + temp = LANE0_TX_DEBUG_RXDET_MEAS_TIME_24M; + break; + } + + ret = crport_ctrl_write(phy_drd, + EXYNOS5_DRD_PHYSS_LANE0_TX_DEBUG, + temp); + if (ret) + dev_err(phy_drd->dev, + "Failed setting RxDetect measurement time for SuperSpeed\n"); + + return ret; +} + +/* Calibrate PIPE3 PHY settings, if any */ +static int exynos5_usbdrd_pipe3_calibrate(struct phy_usb_instance *inst) +{ + struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst); + + /* Call respective phy_calibrate given by certain platform */ + if (phy_drd->drv_data->phy_exynos_calibrate) + return phy_drd->drv_data->phy_exynos_calibrate(phy_drd); + + return -ENODEV; +} + static struct phy *exynos5_usbdrd_phy_xlate(struct device *dev, struct of_phandle_args *args) { @@ -608,6 +793,7 @@ static const struct exynos5_usbdrd_phy_config phy_cfg_exynos5[] = { .phy_isol = exynos5_usbdrd_phy_isol, .phy_init = exynos5_usbdrd_pipe3_init, .set_refclk = exynos5_usbdrd_pipe3_set_refclk, + .phy_calibrate = exynos5_usbdrd_pipe3_calibrate, }, }; @@ -615,6 +801,7 @@ static const struct exynos5_usbdrd_phy_drvdata exynos5420_usbdrd_phy = { .phy_cfg = phy_cfg_exynos5, .pmu_offset_usbdrd0_phy = EXYNOS5_USBDRD_PHY_CONTROL, .pmu_offset_usbdrd1_phy = EXYNOS5420_USBDRD1_PHY_CONTROL, + .phy_exynos_calibrate = exynos5420_usbdrd_phy_calibrate, .has_common_clk_gate = true, }; From b9be8aa88bea68772d4141a4e6387cee9d144e76 Mon Sep 17 00:00:00 2001 From: Dongjin Kim Date: Sat, 1 Aug 2015 03:02:19 +0000 Subject: [PATCH 06/26] media/rc: Add new receiver to specify gpio number for IR sensor This driver helps to register the device of GPIO based IR receiver, "gpio-ir-recv", with the gpio number and pulse trigger when driver is loading. For example, # modprobe gpio-ir-recv # modprobe gpioplug-ir-recv gpio_nr=24 active_low=1 Signed-off-by: Dongjin Kim --- drivers/media/rc/Kconfig | 10 ++ drivers/media/rc/Makefile | 1 + drivers/media/rc/gpio-ir-recv.c | 3 - drivers/media/rc/gpioplug-ir-recv.c | 93 +++++++++++++++++++ .../linux/platform_data/media/gpio-ir-recv.h | 3 + 5 files changed, 107 insertions(+), 3 deletions(-) create mode 100644 drivers/media/rc/gpioplug-ir-recv.c diff --git a/drivers/media/rc/Kconfig b/drivers/media/rc/Kconfig index bd4d6850008531..10f690cd994e85 100644 --- a/drivers/media/rc/Kconfig +++ b/drivers/media/rc/Kconfig @@ -368,6 +368,16 @@ config IR_GPIO_CIR To compile this driver as a module, choose M here: the module will be called gpio-ir-recv. +config IR_GPIOPLUG_CIR + tristate "GPIOPLUG IR remote control" + depends on RC_CORE + select IR_GPIO_CIR + ---help--- + Say Y if you want to use GPIOPLUG based IR Receiver. + + To compile this driver as a module, choose M here: the module will + be called gpio-ir-recv. + config RC_ST tristate "ST remote control receiver" depends on RC_CORE diff --git a/drivers/media/rc/Makefile b/drivers/media/rc/Makefile index 379a5c0f137920..61939e44ad9912 100644 --- a/drivers/media/rc/Makefile +++ b/drivers/media/rc/Makefile @@ -31,6 +31,7 @@ obj-$(CONFIG_IR_STREAMZAP) += streamzap.o obj-$(CONFIG_IR_WINBOND_CIR) += winbond-cir.o obj-$(CONFIG_RC_LOOPBACK) += rc-loopback.o obj-$(CONFIG_IR_GPIO_CIR) += gpio-ir-recv.o +obj-$(CONFIG_IR_GPIOPLUG_CIR) += gpioplug-ir-recv.o obj-$(CONFIG_IR_IGORPLUGUSB) += igorplugusb.o obj-$(CONFIG_IR_IGUANA) += iguanair.o obj-$(CONFIG_IR_TTUSBIR) += ttusbir.o diff --git a/drivers/media/rc/gpio-ir-recv.c b/drivers/media/rc/gpio-ir-recv.c index 5b63b1f15cb18b..240e9bc1e493a5 100644 --- a/drivers/media/rc/gpio-ir-recv.c +++ b/drivers/media/rc/gpio-ir-recv.c @@ -23,9 +23,6 @@ #include #include -#define GPIO_IR_DRIVER_NAME "gpio-rc-recv" -#define GPIO_IR_DEVICE_NAME "gpio_ir_recv" - struct gpio_rc_dev { struct rc_dev *rcdev; int gpio_nr; diff --git a/drivers/media/rc/gpioplug-ir-recv.c b/drivers/media/rc/gpioplug-ir-recv.c new file mode 100644 index 00000000000000..624ed426389361 --- /dev/null +++ b/drivers/media/rc/gpioplug-ir-recv.c @@ -0,0 +1,93 @@ +/* + * Pluggable GPIO IR receiver + * + * Copyright (c) 2015 Dongjin Kim (tobetter@gmail.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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include + +static unsigned gpio_nr = -1; +module_param(gpio_nr, uint, 0); +MODULE_PARM_DESC(gpio_nr, "GPIO number to receive IR pulse"); + +static bool active_low = 0; +module_param(active_low, bool, 0); +MODULE_PARM_DESC(active_low, + "IR pulse trigger level, (1=low active, 0=high active"); + +static struct platform_device *pdev; +static struct gpio_ir_recv_platform_data *pdata; + +static int __init gpio_init(void) +{ + int rc = -ENOMEM; + + if (gpio_nr == -1) { + pr_err("gpioplug-ir-recv: missing module parameter: 'gpio_nr'\n"); + return -EINVAL; + } + + pdev = platform_device_alloc(GPIO_IR_DRIVER_NAME, -1); + if (!pdev) + return rc; + + pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); + if (!pdata) + goto err_free_platform_data; + + pdev->dev.platform_data = pdata; + + pdata->gpio_nr = gpio_nr; + pdata->active_low = active_low; + pdata->allowed_protos = 0; + pdata->map_name = NULL; + + rc = platform_device_add(pdev); + if (rc < 0) + goto err_free_device; + + dev_info (&pdev->dev, "IR driver is initialized (gpio=%d, pulse level=%s)\n", + pdata->gpio_nr, pdata->active_low ? "low" : "high"); + + return 0; + +err_free_platform_data: + kfree(pdata); + +err_free_device: + platform_device_put(pdev); + + return rc; +} + +static void __exit gpio_exit(void) +{ + dev_info(&pdev->dev, "gpioplug-ir-recv: IR driver is removed\n"); + platform_device_unregister(pdev); +} + +MODULE_DESCRIPTION("GPIO IR Receiver driver"); +MODULE_LICENSE("GPL v2"); + +module_init(gpio_init); +module_exit(gpio_exit); diff --git a/include/linux/platform_data/media/gpio-ir-recv.h b/include/linux/platform_data/media/gpio-ir-recv.h index 0c298f569d5abd..5d212e0a274e22 100644 --- a/include/linux/platform_data/media/gpio-ir-recv.h +++ b/include/linux/platform_data/media/gpio-ir-recv.h @@ -13,6 +13,9 @@ #ifndef __GPIO_IR_RECV_H__ #define __GPIO_IR_RECV_H__ +#define GPIO_IR_DRIVER_NAME "gpio-rc-recv" +#define GPIO_IR_DEVICE_NAME "gpio_ir_recv" + struct gpio_ir_recv_platform_data { int gpio_nr; bool active_low; From 332cdd66b78704d9485dc844062f0aa6e436cc2c Mon Sep 17 00:00:00 2001 From: Anand Moon Date: Sun, 7 Jun 2015 21:23:47 +0930 Subject: [PATCH 07/26] ARM: dts: odroidxu3: Enable USB3 regulators Enable regulator for usbdrd3_0 and usbdrd3_1. Looking at the schematic pin diagram for MAX77802 USB3_0 and USB3_1 is regulated by LDO9 and LD011. This removes following warnings during boot: [ 3.503539] exynos-dwc3 usb@12000000: Looking up vdd33-supply from device tree [ 3.503556] exynos-dwc3 usb@12000000: Looking up vdd33-supply property in node /usb@12000000 failed [ 3.503568] usb@12000000 supply vdd33 not found, using dummy regulator [ 3.509154] exynos-dwc3 usb@12000000: Looking up vdd10-supply from device tree [ 3.509170] exynos-dwc3 usb@12000000: Looking up vdd10-supply property in node /usb@12000000 failed [ 3.509181] usb@12000000 supply vdd10 not found, using dummy regulator [ 3.917548] exynos-dwc3 usb@12400000: Looking up vdd33-supply from device tree [ 3.917565] exynos-dwc3 usb@12400000: Looking up vdd33-supply property in node /usb@12400000 failed [ 3.917578] usb@12400000 supply vdd33 not found, using dummy regulator [ 3.922731] exynos-dwc3 usb@12400000: Looking up vdd10-supply from device tree [ 3.922747] exynos-dwc3 usb@12400000: Looking up vdd10-supply property in node /usb@12400000 failed Signed-off-by: Anand Moon Tested-by: Krzysztof Kozlowski Reviewed-by: Krzysztof Kozlowski Signed-off-by: Krzysztof Kozlowski --- arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi b/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi index 1bd507bfa75015..d6e24c09db2f8b 100644 --- a/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi +++ b/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi @@ -432,3 +432,13 @@ vdd33-supply = <&ldo9_reg>; vdd10-supply = <&ldo11_reg>; }; + +&usbdrd3_0 { + vdd33-supply = <&ldo9_reg>; + vdd10-supply = <&ldo11_reg>; +}; + +&usbdrd3_1 { + vdd33-supply = <&ldo9_reg>; + vdd10-supply = <&ldo11_reg>; +}; From 428bab9960b082e8456a7d148a8e6fa4908d5422 Mon Sep 17 00:00:00 2001 From: Anand Moon Date: Mon, 15 Jun 2015 12:23:21 +0930 Subject: [PATCH 08/26] ARM: dts: exynos5422-odroidxu3: Enable TMU at Exynos5422 base This changes enables TMU IP block on the Exynos5422 Odroid-XU3 device. Signed-off-by: Anand Moon Acked-by: Lukasz Majewski Signed-off-by: Krzysztof Kozlowski --- .../boot/dts/exynos5422-odroidxu3-common.dtsi | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi b/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi index d6e24c09db2f8b..a1d862f5bf455f 100644 --- a/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi +++ b/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi @@ -411,6 +411,31 @@ status = "okay"; }; +&tmu_cpu0 { + vtmu-supply = <&ldo7_reg>; + status = "okay"; +}; + +&tmu_cpu1 { + vtmu-supply = <&ldo7_reg>; + status = "okay"; +}; + +&tmu_cpu2 { + vtmu-supply = <&ldo7_reg>; + status = "okay"; +}; + +&tmu_cpu3 { + vtmu-supply = <&ldo7_reg>; + status = "okay"; +}; + +&tmu_gpu { + vtmu-supply = <&ldo7_reg>; + status = "okay"; +}; + &rtc { status = "okay"; clocks = <&clock CLK_RTC>, <&s2mps11_osc S2MPS11_CLK_AP>; From 50b0d0d33846b1b4552f3aefbd2b55fa4c6310ec Mon Sep 17 00:00:00 2001 From: Dongjin Kim Date: Tue, 21 Jul 2015 14:37:21 +0900 Subject: [PATCH 09/26] ARM: dts: Add to enable SPI1 on ODROID-XU4 Change-Id: I65e9f38395dddfbe14daf7300a34a955453b5cb4 Signed-off-by: Dongjin Kim --- arch/arm/boot/dts/exynos5422-odroidxu4.dts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm/boot/dts/exynos5422-odroidxu4.dts b/arch/arm/boot/dts/exynos5422-odroidxu4.dts index 2faf88627a4895..6f1c93562eff8d 100644 --- a/arch/arm/boot/dts/exynos5422-odroidxu4.dts +++ b/arch/arm/boot/dts/exynos5422-odroidxu4.dts @@ -46,3 +46,7 @@ &usbdrd_dwc3_1 { dr_mode = "host"; }; + +&spi_1 { + status = "okay"; +}; From 71bbed0b6ee00141353a9c0ec1b946a65caa60ea Mon Sep 17 00:00:00 2001 From: Anand Moon Date: Thu, 3 Sep 2015 18:48:32 +0530 Subject: [PATCH 10/26] ARM: dts: exynos5422-odroidxu4: use cd-gpio method to detect sd-card From: Jaehoon Chung To detect sd-card use the cd-gpio method. It can decrease the interrupt for detecting sd-card. Just added the vmmc regulator support for SDCards and eMMC. Change-Id: Ia24dc18ed8b8e9c1f7d36df4708b54e3918edba4 Signed-off-by: Jaehoon Chung --- arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi b/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi index a1d862f5bf455f..d6eb4f5af5a24a 100644 --- a/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi +++ b/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi @@ -188,6 +188,7 @@ regulator-min-microvolt = <2800000>; regulator-max-microvolt = <2800000>; regulator-always-on; + regulator-ramp-delay = <12000>; }; ldo15_reg: LDO15 { @@ -216,6 +217,7 @@ regulator-min-microvolt = <2800000>; regulator-max-microvolt = <2800000>; regulator-always-on; + regulator-ramp-delay = <12000>; }; ldo24_reg: LDO24 { @@ -341,6 +343,7 @@ samsung,dw-mshc-ddr-timing = <0 2>; samsung,dw-mshc-hs400-timing = <0 2>; samsung,read-strobe-delay = <90>; + vmmc-supply = <&ldo3_reg>; pinctrl-names = "default"; pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus1 &sd0_bus4 &sd0_bus8 &sd0_cd &sd0_rclk>; bus-width = <8>; @@ -355,8 +358,12 @@ samsung,dw-mshc-ciu-div = <3>; samsung,dw-mshc-sdr-timing = <0 4>; samsung,dw-mshc-ddr-timing = <0 2>; + vmmc-supply = <&ldo19_reg>; + vqmmc-supply = <&ldo13_reg>; + cd-gpios = <&gpc2 2 GPIO_ACTIVE_HIGH>; + cd-inverted; pinctrl-names = "default"; - pinctrl-0 = <&sd2_clk &sd2_cmd &sd2_cd &sd2_bus1 &sd2_bus4>; + pinctrl-0 = <&sd2_clk &sd2_cmd &sd2_bus1 &sd2_bus4>; bus-width = <4>; cap-sd-highspeed; }; From ec67814cc3b863d0eac9d9c04a50bce104c5972e Mon Sep 17 00:00:00 2001 From: Anand Moon Date: Tue, 8 Sep 2015 14:41:18 +0000 Subject: [PATCH 11/26] ARM: dts: exynos5422-odroidxu3: Added UHS-I bus speed support Added support for UHS-I bus speed 50MB/s (SDR50, DDR50) 104MB/s (SDR104) Change-Id: I235eaff5add234c19b934cabd7cc88d00165c0c0 --- arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi b/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi index d6eb4f5af5a24a..7564a8d5fbabc3 100644 --- a/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi +++ b/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi @@ -185,8 +185,8 @@ ldo13_reg: LDO13 { regulator-name = "vdd_ldo13"; - regulator-min-microvolt = <2800000>; - regulator-max-microvolt = <2800000>; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; regulator-always-on; regulator-ramp-delay = <12000>; }; @@ -366,6 +366,11 @@ pinctrl-0 = <&sd2_clk &sd2_cmd &sd2_bus1 &sd2_bus4>; bus-width = <4>; cap-sd-highspeed; + sd-uhs-sdr12; + sd-uhs-sdr25; + sd-uhs-sdr50; + sd-uhs-sdr104; + sd-uhs-ddr50; }; &pinctrl_0 { From f705357fadc77c30550575c9110006214a1b4550 Mon Sep 17 00:00:00 2001 From: Dongjin Kim Date: Tue, 21 Jul 2015 14:35:52 +0900 Subject: [PATCH 12/26] staging: fbtft: Add new fbtft lcd for ODROID board Signed-off-by: Dongjin Kim --- drivers/staging/fbtft/fbtft_device.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/drivers/staging/fbtft/fbtft_device.c b/drivers/staging/fbtft/fbtft_device.c index 241d7c6bebde82..570dbb23c7b3f1 100644 --- a/drivers/staging/fbtft/fbtft_device.c +++ b/drivers/staging/fbtft/fbtft_device.c @@ -20,6 +20,7 @@ #include #include #include