From af7e9069543aabd415d7c543f3f89b143ac1a932 Mon Sep 17 00:00:00 2001 From: Jacob Pan Date: Mon, 6 Oct 2014 21:17:14 -0700 Subject: mfd: axp20x: Extend axp20x to support axp288 pmic X-Powers AXP288 is a customized PMIC for Intel Baytrail-CR platforms. Similar to AXP202/209, AXP288 comes with USB charger, more LDO and BUCK channels, and AD converters. It also provides extended status and interrupt reporting capabilities than the devices currently supported in axp20x.c. In addition to feature extension, this patch also adds ACPI binding for enumeration. This consolidated driver should support more X-Powers' PMICs in both device tree and ACPI enumerated platforms. Signed-off-by: Jacob Pan Reviewed-by: Maxime Ripard Reviewed-by: Jonathan Cameron Signed-off-by: Lee Jones --- include/linux/mfd/axp20x.h | 59 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) (limited to 'include/linux') diff --git a/include/linux/mfd/axp20x.h b/include/linux/mfd/axp20x.h index d0e31a2287ac..81589d176ae8 100644 --- a/include/linux/mfd/axp20x.h +++ b/include/linux/mfd/axp20x.h @@ -14,6 +14,8 @@ enum { AXP202_ID = 0, AXP209_ID, + AXP288_ID, + NR_AXP20X_VARIANTS, }; #define AXP20X_DATACACHE(m) (0x04 + (m)) @@ -49,11 +51,13 @@ enum { #define AXP20X_IRQ3_EN 0x42 #define AXP20X_IRQ4_EN 0x43 #define AXP20X_IRQ5_EN 0x44 +#define AXP20X_IRQ6_EN 0x45 #define AXP20X_IRQ1_STATE 0x48 #define AXP20X_IRQ2_STATE 0x49 #define AXP20X_IRQ3_STATE 0x4a #define AXP20X_IRQ4_STATE 0x4b #define AXP20X_IRQ5_STATE 0x4c +#define AXP20X_IRQ6_STATE 0x4d /* ADC */ #define AXP20X_ACIN_V_ADC_H 0x56 @@ -116,6 +120,15 @@ enum { #define AXP20X_CC_CTRL 0xb8 #define AXP20X_FG_RES 0xb9 +/* AXP288 specific registers */ +#define AXP288_PMIC_ADC_H 0x56 +#define AXP288_PMIC_ADC_L 0x57 +#define AXP288_ADC_TS_PIN_CTRL 0x84 + +#define AXP288_PMIC_ADC_EN 0x84 +#define AXP288_FG_TUNE5 0xed + + /* Regulators IDs */ enum { AXP20X_LDO1 = 0, @@ -169,12 +182,58 @@ enum { AXP20X_IRQ_GPIO0_INPUT, }; +enum axp288_irqs { + AXP288_IRQ_VBUS_FALL = 2, + AXP288_IRQ_VBUS_RISE, + AXP288_IRQ_OV, + AXP288_IRQ_FALLING_ALT, + AXP288_IRQ_RISING_ALT, + AXP288_IRQ_OV_ALT, + AXP288_IRQ_DONE = 10, + AXP288_IRQ_CHARGING, + AXP288_IRQ_SAFE_QUIT, + AXP288_IRQ_SAFE_ENTER, + AXP288_IRQ_ABSENT, + AXP288_IRQ_APPEND, + AXP288_IRQ_QWBTU, + AXP288_IRQ_WBTU, + AXP288_IRQ_QWBTO, + AXP288_IRQ_WBTO, + AXP288_IRQ_QCBTU, + AXP288_IRQ_CBTU, + AXP288_IRQ_QCBTO, + AXP288_IRQ_CBTO, + AXP288_IRQ_WL2, + AXP288_IRQ_WL1, + AXP288_IRQ_GPADC, + AXP288_IRQ_OT = 31, + AXP288_IRQ_GPIO0, + AXP288_IRQ_GPIO1, + AXP288_IRQ_POKO, + AXP288_IRQ_POKL, + AXP288_IRQ_POKS, + AXP288_IRQ_POKN, + AXP288_IRQ_POKP, + AXP288_IRQ_TIMER, + AXP288_IRQ_MV_CHNG, + AXP288_IRQ_BC_USB_CHNG, +}; + +#define AXP288_TS_ADC_H 0x58 +#define AXP288_TS_ADC_L 0x59 +#define AXP288_GP_ADC_H 0x5a +#define AXP288_GP_ADC_L 0x5b + struct axp20x_dev { struct device *dev; struct i2c_client *i2c_client; struct regmap *regmap; struct regmap_irq_chip_data *regmap_irqc; long variant; + int nr_cells; + struct mfd_cell *cells; + const struct regmap_config *regmap_cfg; + const struct regmap_irq_chip *regmap_irq_chip; }; #endif /* __LINUX_MFD_AXP20X_H */ -- cgit v1.2.3 From 729de41baf63e2172b9d61de61bbd53f231095ca Mon Sep 17 00:00:00 2001 From: Dinh Nguyen Date: Fri, 10 Oct 2014 10:21:14 -0500 Subject: reset: add reset_control_status helper function There are cases where a system will want to read a reset status bit before doing any other toggling. Add a reset_control_status helper function to the reset controller API. Signed-off-by: Dinh Nguyen Signed-off-by: Philipp Zabel --- drivers/reset/core.c | 15 +++++++++++++++ include/linux/reset-controller.h | 2 ++ include/linux/reset.h | 7 +++++++ 3 files changed, 24 insertions(+) (limited to 'include/linux') diff --git a/drivers/reset/core.c b/drivers/reset/core.c index baeaf82d40d9..7955e00d04d4 100644 --- a/drivers/reset/core.c +++ b/drivers/reset/core.c @@ -125,6 +125,21 @@ int reset_control_deassert(struct reset_control *rstc) } EXPORT_SYMBOL_GPL(reset_control_deassert); +/** + * reset_control_status - returns a negative errno if not supported, a + * positive value if the reset line is asserted, or zero if the reset + * line is not asserted. + * @rstc: reset controller + */ +int reset_control_status(struct reset_control *rstc) +{ + if (rstc->rcdev->ops->status) + return rstc->rcdev->ops->status(rstc->rcdev, rstc->id); + + return -ENOSYS; +} +EXPORT_SYMBOL_GPL(reset_control_status); + /** * of_reset_control_get - Lookup and obtain a reference to a reset controller. * @node: device to be reset by the controller diff --git a/include/linux/reset-controller.h b/include/linux/reset-controller.h index 41a4695fde08..ce6b962ffed4 100644 --- a/include/linux/reset-controller.h +++ b/include/linux/reset-controller.h @@ -12,11 +12,13 @@ struct reset_controller_dev; * things to reset the device * @assert: manually assert the reset line, if supported * @deassert: manually deassert the reset line, if supported + * @status: return the status of the reset line, if supported */ struct reset_control_ops { int (*reset)(struct reset_controller_dev *rcdev, unsigned long id); int (*assert)(struct reset_controller_dev *rcdev, unsigned long id); int (*deassert)(struct reset_controller_dev *rcdev, unsigned long id); + int (*status)(struct reset_controller_dev *rcdev, unsigned long id); }; struct module; diff --git a/include/linux/reset.h b/include/linux/reset.h index 349f150ae12c..da5602bd77d7 100644 --- a/include/linux/reset.h +++ b/include/linux/reset.h @@ -10,6 +10,7 @@ struct reset_control; int reset_control_reset(struct reset_control *rstc); int reset_control_assert(struct reset_control *rstc); int reset_control_deassert(struct reset_control *rstc); +int reset_control_status(struct reset_control *rstc); struct reset_control *reset_control_get(struct device *dev, const char *id); void reset_control_put(struct reset_control *rstc); @@ -57,6 +58,12 @@ static inline int reset_control_deassert(struct reset_control *rstc) return 0; } +static inline int reset_control_status(struct reset_control *rstc) +{ + WARN_ON(1); + return 0; +} + static inline void reset_control_put(struct reset_control *rstc) { WARN_ON(1); -- cgit v1.2.3 From 76f439df50aba1838e06dd01e5f20dada7473f57 Mon Sep 17 00:00:00 2001 From: Markus Pargmann Date: Wed, 8 Oct 2014 15:47:05 +0200 Subject: regulator: Add ena_gpio_initialized to regulator_config Most drivers do not set the ena_gpio field of struct regulator_config before passing it to the regulator core. This is fine as long as the gpio identifier that is passed is a positive integer. But the gpio identifier 0 is also valid. So we are not able to decide wether we got a real gpio identifier or not based on a 0 in ena_gpio. To be able to decide if it is a valid gpio that got passed, this patch adds a ena_gpio_initialized field that should be set if was initialized with a correct value, either a gpio >= 0 or a negative error number. The core then checks if ena_gpio or ena_gpio_initialized before handling it as a gpio. This way we maintain backwards compatibility and fix the behaviour for gpio number 0. Signed-off-by: Markus Pargmann Signed-off-by: Mark Brown --- drivers/regulator/core.c | 3 ++- include/linux/regulator/driver.h | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'include/linux') diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index cd87c0c37034..55a87a2722d8 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -3650,7 +3650,8 @@ regulator_register(const struct regulator_desc *regulator_desc, dev_set_drvdata(&rdev->dev, rdev); - if (config->ena_gpio && gpio_is_valid(config->ena_gpio)) { + if ((config->ena_gpio || config->ena_gpio_initialized) && + gpio_is_valid(config->ena_gpio)) { ret = regulator_ena_gpio_request(rdev, config); if (ret != 0) { rdev_err(rdev, "Failed to request enable GPIO%d: %d\n", diff --git a/include/linux/regulator/driver.h b/include/linux/regulator/driver.h index fc0ee0ce8325..28da08e4671f 100644 --- a/include/linux/regulator/driver.h +++ b/include/linux/regulator/driver.h @@ -301,6 +301,9 @@ struct regulator_desc { * NULL). * @regmap: regmap to use for core regmap helpers if dev_get_regulator() is * insufficient. + * @ena_gpio_initialized: GPIO controlling regulator enable was properly + * initialized, meaning that >= 0 is a valid gpio + * identifier and < 0 is a non existent gpio. * @ena_gpio: GPIO controlling regulator enable. * @ena_gpio_invert: Sense for GPIO enable control. * @ena_gpio_flags: Flags to use when calling gpio_request_one() @@ -312,6 +315,7 @@ struct regulator_config { struct device_node *of_node; struct regmap *regmap; + bool ena_gpio_initialized; int ena_gpio; unsigned int ena_gpio_invert:1; unsigned int ena_gpio_flags; -- cgit v1.2.3 From 5356e0da49e61e0de29a5f61996be66e97425217 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Thu, 16 Oct 2014 18:48:50 +0200 Subject: regulator: max77802: Add header for operating modes Add a header file for the max77802 constants that could be shared between the regulator driver and Device Tree source files. Also, remove standby and off opmodes since only normal and low power are valid operating modes. Signed-off-by: Javier Martinez Canillas Signed-off-by: Mark Brown --- drivers/regulator/max77802.c | 1 + include/dt-bindings/regulator/maxim,max77802.h | 18 ++++++++++++++++++ include/linux/mfd/max77686.h | 7 ------- 3 files changed, 19 insertions(+), 7 deletions(-) create mode 100644 include/dt-bindings/regulator/maxim,max77802.h (limited to 'include/linux') diff --git a/drivers/regulator/max77802.c b/drivers/regulator/max77802.c index 3abf99dbf953..5839c4509e1f 100644 --- a/drivers/regulator/max77802.c +++ b/drivers/regulator/max77802.c @@ -33,6 +33,7 @@ #include #include #include +#include /* Default ramp delay in case it is not manually set */ #define MAX77802_RAMP_DELAY 100000 /* uV/us */ diff --git a/include/dt-bindings/regulator/maxim,max77802.h b/include/dt-bindings/regulator/maxim,max77802.h new file mode 100644 index 000000000000..cf28631d7109 --- /dev/null +++ b/include/dt-bindings/regulator/maxim,max77802.h @@ -0,0 +1,18 @@ +/* + * Copyright (C) 2014 Google, Inc + * + * 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. + * + * Device Tree binding constants for the Maxim 77802 PMIC regulators + */ + +#ifndef _DT_BINDINGS_REGULATOR_MAXIM_MAX77802_H +#define _DT_BINDINGS_REGULATOR_MAXIM_MAX77802_H + +/* Regulator operating modes */ +#define MAX77802_OPMODE_LP 1 +#define MAX77802_OPMODE_NORMAL 3 + +#endif /* _DT_BINDINGS_REGULATOR_MAXIM_MAX77802_H */ diff --git a/include/linux/mfd/max77686.h b/include/linux/mfd/max77686.h index 7e6dc4b2b795..553f7d09258a 100644 --- a/include/linux/mfd/max77686.h +++ b/include/linux/mfd/max77686.h @@ -131,13 +131,6 @@ enum max77686_opmode { MAX77686_OPMODE_STANDBY, }; -enum max77802_opmode { - MAX77802_OPMODE_OFF, - MAX77802_OPMODE_STANDBY, - MAX77802_OPMODE_LP, - MAX77802_OPMODE_NORMAL, -}; - struct max77686_opmode_data { int id; int mode; -- cgit v1.2.3 From 4cbbdb51cc921f95978360fd7a0652d493dadc3e Mon Sep 17 00:00:00 2001 From: Aravind Gopalakrishnan Date: Thu, 18 Sep 2014 14:56:35 -0500 Subject: pci_ids: Add PCI device IDs for F15h M60h Add F3, F4 device IDs to be used in amd_nb.c and amd64_edac.c Signed-off-by: Aravind Gopalakrishnan Acked-by: Bjorn Helgaas Link: http://lkml.kernel.org/r/1411070195-10177-1-git-send-email-Aravind.Gopalakrishnan@amd.com Signed-off-by: Borislav Petkov --- include/linux/pci_ids.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include/linux') diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 1fa99a301817..97fb9f69aaed 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -522,6 +522,8 @@ #define PCI_DEVICE_ID_AMD_15H_M10H_F3 0x1403 #define PCI_DEVICE_ID_AMD_15H_M30H_NB_F3 0x141d #define PCI_DEVICE_ID_AMD_15H_M30H_NB_F4 0x141e +#define PCI_DEVICE_ID_AMD_15H_M60H_NB_F3 0x1573 +#define PCI_DEVICE_ID_AMD_15H_M60H_NB_F4 0x1574 #define PCI_DEVICE_ID_AMD_15H_NB_F0 0x1600 #define PCI_DEVICE_ID_AMD_15H_NB_F1 0x1601 #define PCI_DEVICE_ID_AMD_15H_NB_F2 0x1602 -- cgit v1.2.3 From 348fec70213835df18a587353b3bdc0481b37c6b Mon Sep 17 00:00:00 2001 From: Aravind Gopalakrishnan Date: Thu, 18 Sep 2014 14:56:58 -0500 Subject: EDAC: Add DDR3 LRDIMM entries to edac_mem_types F15hM60h adds support for DDR4 and DDR3 LRDIMMs. Add them here. Signed-off-by: Aravind Gopalakrishnan Link: http://lkml.kernel.org/r/1411070218-10258-1-git-send-email-Aravind.Gopalakrishnan@amd.com [ Boris: improve comments. ] Signed-off-by: Borislav Petkov --- drivers/edac/edac_mc.c | 3 +++ include/linux/edac.h | 4 +++- 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'include/linux') diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c index c3893b0ddb18..129ff9c36a78 100644 --- a/drivers/edac/edac_mc.c +++ b/drivers/edac/edac_mc.c @@ -146,6 +146,9 @@ const char * const edac_mem_types[] = { "Rambus XDR", "Unbuffered DDR3 RAM", "Registered DDR3 RAM", + "Load-Reduced DDR3 RAM", + "Unbuffered DDR4 RAM", + "Registered DDR4 RAM", }; EXPORT_SYMBOL_GPL(edac_mem_types); diff --git a/include/linux/edac.h b/include/linux/edac.h index e1e68da6f35c..da3b72e95db3 100644 --- a/include/linux/edac.h +++ b/include/linux/edac.h @@ -194,7 +194,8 @@ static inline char *mc_event_error_type(const unsigned int err_type) * @MEM_DDR3: DDR3 RAM * @MEM_RDDR3: Registered DDR3 RAM * This is a variant of the DDR3 memories. - * @MEM_DDR4: DDR4 RAM + * @MEM_LRDDR3 Load-Reduced DDR3 memory. + * @MEM_DDR4: Unbuffered DDR4 RAM * @MEM_RDDR4: Registered DDR4 RAM * This is a variant of the DDR4 memories. */ @@ -216,6 +217,7 @@ enum mem_type { MEM_XDR, MEM_DDR3, MEM_RDDR3, + MEM_LRDDR3, MEM_DDR4, MEM_RDDR4, }; -- cgit v1.2.3 From a4b4e0461ec5532ad498f0dd0e68993ad79bec2b Mon Sep 17 00:00:00 2001 From: Romain Perier Date: Tue, 14 Oct 2014 06:31:09 +0000 Subject: of: Add standard property for poweroff capability Several drivers create their own devicetree property when they register poweroff capabilities. This is for example the case for mfd, regulator or power drivers which define "vendor,system-power-controller" property. This patch adds support for a standard property "poweroff-source" which marks the device as able to shutdown the system. Signed-off-by: Romain Perier Acked-by: Grant Likely Signed-off-by: Mark Brown --- include/linux/of.h | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'include/linux') diff --git a/include/linux/of.h b/include/linux/of.h index 6545e7aec7bb..27b3ba1e9e59 100644 --- a/include/linux/of.h +++ b/include/linux/of.h @@ -866,4 +866,15 @@ static inline int of_changeset_update_property(struct of_changeset *ocs, /* CONFIG_OF_RESOLVE api */ extern int of_resolve_phandles(struct device_node *tree); +/** + * of_system_has_poweroff_source - Tells if poweroff-source is found for device_node + * @np: Pointer to the given device_node + * + * return true if present false otherwise + */ +static inline bool of_system_has_poweroff_source(const struct device_node *np) +{ + return of_property_read_bool(np, "poweroff-source"); +} + #endif /* _LINUX_OF_H */ -- cgit v1.2.3 From 70b946f9acf4e805361bd877a7e25cc05e497c52 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 24 Oct 2014 21:56:58 +0100 Subject: regulator: Return an error from stubbed regulator_get_exclusive() The user hasn't got a regulator and shouldn't be mislead into thinking they have one; really we should probably remove this stub entirely (and may well before the next merge window). Signed-off-by: Mark Brown --- include/linux/regulator/consumer.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include/linux') diff --git a/include/linux/regulator/consumer.h b/include/linux/regulator/consumer.h index d347c805f923..c0c0a437ec75 100644 --- a/include/linux/regulator/consumer.h +++ b/include/linux/regulator/consumer.h @@ -282,7 +282,7 @@ devm_regulator_get(struct device *dev, const char *id) static inline struct regulator *__must_check regulator_get_exclusive(struct device *dev, const char *id) { - return NULL; + return ERR_PTR(-ENODEV); } static inline struct regulator *__must_check -- cgit v1.2.3 From 315786ebbf4ad6552b6fd8e0e7b2ea220fcbfdbd Mon Sep 17 00:00:00 2001 From: Olav Haugan Date: Sat, 25 Oct 2014 09:55:16 -0700 Subject: iommu: Add iommu_map_sg() function Mapping and unmapping are more often than not in the critical path. map_sg allows IOMMU driver implementations to optimize the process of mapping buffers into the IOMMU page tables. Instead of mapping a buffer one page at a time and requiring potentially expensive TLB operations for each page, this function allows the driver to map all pages in one go and defer TLB maintenance until after all pages have been mapped. Additionally, the mapping operation would be faster in general since clients does not have to keep calling map API over and over again for each physically contiguous chunk of memory that needs to be mapped to a virtually contiguous region. Signed-off-by: Olav Haugan Signed-off-by: Joerg Roedel --- drivers/iommu/amd_iommu.c | 1 + drivers/iommu/arm-smmu.c | 1 + drivers/iommu/exynos-iommu.c | 1 + drivers/iommu/intel-iommu.c | 1 + drivers/iommu/iommu.c | 25 +++++++++++++++++++++++++ drivers/iommu/ipmmu-vmsa.c | 1 + drivers/iommu/msm_iommu.c | 1 + drivers/iommu/omap-iommu.c | 1 + drivers/iommu/shmobile-iommu.c | 1 + drivers/iommu/tegra-smmu.c | 1 + include/linux/iommu.h | 22 ++++++++++++++++++++++ 11 files changed, 56 insertions(+) (limited to 'include/linux') diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c index 505a9adac2d5..2d84c9edf3b8 100644 --- a/drivers/iommu/amd_iommu.c +++ b/drivers/iommu/amd_iommu.c @@ -3424,6 +3424,7 @@ static const struct iommu_ops amd_iommu_ops = { .detach_dev = amd_iommu_detach_device, .map = amd_iommu_map, .unmap = amd_iommu_unmap, + .map_sg = default_iommu_map_sg, .iova_to_phys = amd_iommu_iova_to_phys, .pgsize_bitmap = AMD_IOMMU_PGSIZES, }; diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index 60558f794922..e393ae01b5d2 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -1652,6 +1652,7 @@ static const struct iommu_ops arm_smmu_ops = { .detach_dev = arm_smmu_detach_dev, .map = arm_smmu_map, .unmap = arm_smmu_unmap, + .map_sg = default_iommu_map_sg, .iova_to_phys = arm_smmu_iova_to_phys, .add_device = arm_smmu_add_device, .remove_device = arm_smmu_remove_device, diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c index 74233186f6f7..28372b85d8da 100644 --- a/drivers/iommu/exynos-iommu.c +++ b/drivers/iommu/exynos-iommu.c @@ -1178,6 +1178,7 @@ static const struct iommu_ops exynos_iommu_ops = { .detach_dev = exynos_iommu_detach_device, .map = exynos_iommu_map, .unmap = exynos_iommu_unmap, + .map_sg = default_iommu_map_sg, .iova_to_phys = exynos_iommu_iova_to_phys, .add_device = exynos_iommu_add_device, .remove_device = exynos_iommu_remove_device, diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index a27d6cb1a793..02cd26a17fe0 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -4467,6 +4467,7 @@ static const struct iommu_ops intel_iommu_ops = { .detach_dev = intel_iommu_detach_device, .map = intel_iommu_map, .unmap = intel_iommu_unmap, + .map_sg = default_iommu_map_sg, .iova_to_phys = intel_iommu_iova_to_phys, .add_device = intel_iommu_add_device, .remove_device = intel_iommu_remove_device, diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index ed8b04867b1f..46727ce9280d 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -1124,6 +1124,31 @@ size_t iommu_unmap(struct iommu_domain *domain, unsigned long iova, size_t size) } EXPORT_SYMBOL_GPL(iommu_unmap); +size_t default_iommu_map_sg(struct iommu_domain *domain, unsigned long iova, + struct scatterlist *sg, unsigned int nents, int prot) +{ + int ret; + size_t mapped = 0; + unsigned int i; + struct scatterlist *s; + + for_each_sg(sg, s, nents, i) { + phys_addr_t phys = page_to_phys(sg_page(s)); + size_t page_len = s->offset + s->length; + + ret = iommu_map(domain, iova + mapped, phys, page_len, prot); + if (ret) { + /* undo mappings already done */ + iommu_unmap(domain, iova, mapped); + mapped = 0; + break; + } + mapped += page_len; + } + + return mapped; +} +EXPORT_SYMBOL_GPL(default_iommu_map_sg); int iommu_domain_window_enable(struct iommu_domain *domain, u32 wnd_nr, phys_addr_t paddr, u64 size, int prot) diff --git a/drivers/iommu/ipmmu-vmsa.c b/drivers/iommu/ipmmu-vmsa.c index 7dab5cbcc775..e509c58eee92 100644 --- a/drivers/iommu/ipmmu-vmsa.c +++ b/drivers/iommu/ipmmu-vmsa.c @@ -1127,6 +1127,7 @@ static const struct iommu_ops ipmmu_ops = { .detach_dev = ipmmu_detach_device, .map = ipmmu_map, .unmap = ipmmu_unmap, + .map_sg = default_iommu_map_sg, .iova_to_phys = ipmmu_iova_to_phys, .add_device = ipmmu_add_device, .remove_device = ipmmu_remove_device, diff --git a/drivers/iommu/msm_iommu.c b/drivers/iommu/msm_iommu.c index 6e3dcc289d59..1c7b78ecf3e3 100644 --- a/drivers/iommu/msm_iommu.c +++ b/drivers/iommu/msm_iommu.c @@ -681,6 +681,7 @@ static const struct iommu_ops msm_iommu_ops = { .detach_dev = msm_iommu_detach_dev, .map = msm_iommu_map, .unmap = msm_iommu_unmap, + .map_sg = default_iommu_map_sg, .iova_to_phys = msm_iommu_iova_to_phys, .pgsize_bitmap = MSM_IOMMU_PGSIZES, }; diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c index 36278870e84a..18003c044454 100644 --- a/drivers/iommu/omap-iommu.c +++ b/drivers/iommu/omap-iommu.c @@ -1288,6 +1288,7 @@ static const struct iommu_ops omap_iommu_ops = { .detach_dev = omap_iommu_detach_dev, .map = omap_iommu_map, .unmap = omap_iommu_unmap, + .map_sg = default_iommu_map_sg, .iova_to_phys = omap_iommu_iova_to_phys, .add_device = omap_iommu_add_device, .remove_device = omap_iommu_remove_device, diff --git a/drivers/iommu/shmobile-iommu.c b/drivers/iommu/shmobile-iommu.c index 1333e6fb3405..f1b00774e4de 100644 --- a/drivers/iommu/shmobile-iommu.c +++ b/drivers/iommu/shmobile-iommu.c @@ -361,6 +361,7 @@ static const struct iommu_ops shmobile_iommu_ops = { .detach_dev = shmobile_iommu_detach_device, .map = shmobile_iommu_map, .unmap = shmobile_iommu_unmap, + .map_sg = default_iommu_map_sg, .iova_to_phys = shmobile_iommu_iova_to_phys, .add_device = shmobile_iommu_add_device, .pgsize_bitmap = SZ_1M | SZ_64K | SZ_4K, diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c index 3afdf43f732a..73e845a66925 100644 --- a/drivers/iommu/tegra-smmu.c +++ b/drivers/iommu/tegra-smmu.c @@ -955,6 +955,7 @@ static const struct iommu_ops smmu_iommu_ops = { .detach_dev = smmu_iommu_detach_dev, .map = smmu_iommu_map, .unmap = smmu_iommu_unmap, + .map_sg = default_iommu_map_sg, .iova_to_phys = smmu_iommu_iova_to_phys, .pgsize_bitmap = SMMU_IOMMU_PGSIZES, }; diff --git a/include/linux/iommu.h b/include/linux/iommu.h index e6a7c9ff72f2..b29a5982e1c3 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -22,6 +22,7 @@ #include #include #include +#include #include #define IOMMU_READ (1 << 0) @@ -97,6 +98,8 @@ enum iommu_attr { * @detach_dev: detach device from an iommu domain * @map: map a physically contiguous memory region to an iommu domain * @unmap: unmap a physically contiguous memory region from an iommu domain + * @map_sg: map a scatter-gather list of physically contiguous memory chunks + * to an iommu domain * @iova_to_phys: translate iova to physical address * @add_device: add device to iommu grouping * @remove_device: remove device from iommu grouping @@ -114,6 +117,8 @@ struct iommu_ops { phys_addr_t paddr, size_t size, int prot); size_t (*unmap)(struct iommu_domain *domain, unsigned long iova, size_t size); + size_t (*map_sg)(struct iommu_domain *domain, unsigned long iova, + struct scatterlist *sg, unsigned int nents, int prot); phys_addr_t (*iova_to_phys)(struct iommu_domain *domain, dma_addr_t iova); int (*add_device)(struct device *dev); void (*remove_device)(struct device *dev); @@ -156,6 +161,9 @@ extern int iommu_map(struct iommu_domain *domain, unsigned long iova, phys_addr_t paddr, size_t size, int prot); extern size_t iommu_unmap(struct iommu_domain *domain, unsigned long iova, size_t size); +extern size_t default_iommu_map_sg(struct iommu_domain *domain, unsigned long iova, + struct scatterlist *sg,unsigned int nents, + int prot); extern phys_addr_t iommu_iova_to_phys(struct iommu_domain *domain, dma_addr_t iova); extern void iommu_set_fault_handler(struct iommu_domain *domain, iommu_fault_handler_t handler, void *token); @@ -241,6 +249,13 @@ static inline int report_iommu_fault(struct iommu_domain *domain, return ret; } +static inline size_t iommu_map_sg(struct iommu_domain *domain, + unsigned long iova, struct scatterlist *sg, + unsigned int nents, int prot) +{ + return domain->ops->map_sg(domain, iova, sg, nents, prot); +} + #else /* CONFIG_IOMMU_API */ struct iommu_ops {}; @@ -293,6 +308,13 @@ static inline int iommu_unmap(struct iommu_domain *domain, unsigned long iova, return -ENODEV; } +static inline size_t iommu_map_sg(struct iommu_domain *domain, + unsigned long iova, struct scatterlist *sg, + unsigned int nents, int prot) +{ + return -ENODEV; +} + static inline int iommu_domain_window_enable(struct iommu_domain *domain, u32 wnd_nr, phys_addr_t paddr, u64 size, int prot) -- cgit v1.2.3 From e1ccbbc9d5aa01a6c1c9c78acea6515db4f1be71 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Tue, 14 Oct 2014 16:34:47 +0200 Subject: efi: dmi: add support for SMBIOS 3.0 UEFI configuration table This adds support to the UEFI side for detecting the presence of a SMBIOS 3.0 64-bit entry point. This allows the actual SMBIOS structure table to reside at a physical offset over 4 GB, which cannot be supported by the legacy SMBIOS 32-bit entry point. Since the firmware can legally provide both entry points, store the SMBIOS 3.0 entry point in a separate variable, and let the DMI decoding layer decide which one will be used. Tested-by: Suravee Suthikulpanit Acked-by: Leif Lindholm Acked-by: Matt Fleming Signed-off-by: Ard Biesheuvel --- drivers/firmware/efi/efi.c | 4 ++++ drivers/xen/efi.c | 1 + include/linux/efi.h | 6 +++++- 3 files changed, 10 insertions(+), 1 deletion(-) (limited to 'include/linux') diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c index 8590099ac148..9035c1b74d58 100644 --- a/drivers/firmware/efi/efi.c +++ b/drivers/firmware/efi/efi.c @@ -30,6 +30,7 @@ struct efi __read_mostly efi = { .acpi = EFI_INVALID_TABLE_ADDR, .acpi20 = EFI_INVALID_TABLE_ADDR, .smbios = EFI_INVALID_TABLE_ADDR, + .smbios3 = EFI_INVALID_TABLE_ADDR, .sal_systab = EFI_INVALID_TABLE_ADDR, .boot_info = EFI_INVALID_TABLE_ADDR, .hcdp = EFI_INVALID_TABLE_ADDR, @@ -86,6 +87,8 @@ static ssize_t systab_show(struct kobject *kobj, str += sprintf(str, "ACPI=0x%lx\n", efi.acpi); if (efi.smbios != EFI_INVALID_TABLE_ADDR) str += sprintf(str, "SMBIOS=0x%lx\n", efi.smbios); + if (efi.smbios3 != EFI_INVALID_TABLE_ADDR) + str += sprintf(str, "SMBIOS3=0x%lx\n", efi.smbios3); if (efi.hcdp != EFI_INVALID_TABLE_ADDR) str += sprintf(str, "HCDP=0x%lx\n", efi.hcdp); if (efi.boot_info != EFI_INVALID_TABLE_ADDR) @@ -260,6 +263,7 @@ static __initdata efi_config_table_type_t common_tables[] = { {MPS_TABLE_GUID, "MPS", &efi.mps}, {SAL_SYSTEM_TABLE_GUID, "SALsystab", &efi.sal_systab}, {SMBIOS_TABLE_GUID, "SMBIOS", &efi.smbios}, + {SMBIOS3_TABLE_GUID, "SMBIOS 3.0", &efi.smbios3}, {UGA_IO_PROTOCOL_GUID, "UGA", &efi.uga}, {NULL_GUID, NULL, NULL}, }; diff --git a/drivers/xen/efi.c b/drivers/xen/efi.c index 1f850c97482f..f745db270171 100644 --- a/drivers/xen/efi.c +++ b/drivers/xen/efi.c @@ -294,6 +294,7 @@ static const struct efi efi_xen __initconst = { .acpi = EFI_INVALID_TABLE_ADDR, .acpi20 = EFI_INVALID_TABLE_ADDR, .smbios = EFI_INVALID_TABLE_ADDR, + .smbios3 = EFI_INVALID_TABLE_ADDR, .sal_systab = EFI_INVALID_TABLE_ADDR, .boot_info = EFI_INVALID_TABLE_ADDR, .hcdp = EFI_INVALID_TABLE_ADDR, diff --git a/include/linux/efi.h b/include/linux/efi.h index 0949f9c7e872..0238d612750e 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -547,6 +547,9 @@ void efi_native_runtime_setup(void); #define SMBIOS_TABLE_GUID \ EFI_GUID( 0xeb9d2d31, 0x2d88, 0x11d3, 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d ) +#define SMBIOS3_TABLE_GUID \ + EFI_GUID( 0xf2fd1544, 0x9794, 0x4a2c, 0x99, 0x2e, 0xe5, 0xbb, 0xcf, 0x20, 0xe3, 0x94 ) + #define SAL_SYSTEM_TABLE_GUID \ EFI_GUID( 0xeb9d2d32, 0x2d88, 0x11d3, 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d ) @@ -810,7 +813,8 @@ extern struct efi { unsigned long mps; /* MPS table */ unsigned long acpi; /* ACPI table (IA64 ext 0.71) */ unsigned long acpi20; /* ACPI table (ACPI 2.0) */ - unsigned long smbios; /* SM BIOS table */ + unsigned long smbios; /* SMBIOS table (32 bit entry point) */ + unsigned long smbios3; /* SMBIOS table (64 bit entry point) */ unsigned long sal_systab; /* SAL system table */ unsigned long boot_info; /* boot info table */ unsigned long hcdp; /* HCDP table */ -- cgit v1.2.3 From cc9571e85808dfc121e4fda5c75c9a3c3c75e514 Mon Sep 17 00:00:00 2001 From: Sebastian Hesselbarth Date: Tue, 21 Oct 2014 11:22:35 +0200 Subject: mmc: sdhci-pxav3: Move private driver data to driver source struct sdhci_pxa is only used in sdhci_pxa driver itself, so move it there. Signed-off-by: Sebastian Hesselbarth Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-pxav3.c | 5 +++++ include/linux/platform_data/pxa_sdhci.h | 5 ----- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'include/linux') diff --git a/drivers/mmc/host/sdhci-pxav3.c b/drivers/mmc/host/sdhci-pxav3.c index b55c807982fe..48bc8179c8fc 100644 --- a/drivers/mmc/host/sdhci-pxav3.c +++ b/drivers/mmc/host/sdhci-pxav3.c @@ -58,6 +58,11 @@ #define SDCE_MISC_INT (1<<2) #define SDCE_MISC_INT_EN (1<<1) +struct sdhci_pxa { + u8 clk_enable; + u8 power_mode; +}; + /* * These registers are relative to the second register region, for the * MBus bridge. diff --git a/include/linux/platform_data/pxa_sdhci.h b/include/linux/platform_data/pxa_sdhci.h index 27d3156d093a..9e20c2fb4ffd 100644 --- a/include/linux/platform_data/pxa_sdhci.h +++ b/include/linux/platform_data/pxa_sdhci.h @@ -55,9 +55,4 @@ struct sdhci_pxa_platdata { unsigned int quirks2; unsigned int pm_caps; }; - -struct sdhci_pxa { - u8 clk_enable; - u8 power_mode; -}; #endif /* _PXA_SDHCI_H_ */ -- cgit v1.2.3 From 433b7b1210a4ece4f2b4f1b04f31a2f0928c8aa8 Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Mon, 6 Oct 2014 11:00:15 +0200 Subject: mmc: core: Don't export the to_sdio_driver macro The macro is only used by the mmc core, so let's move it in there. Signed-off-by: Ulf Hansson --- drivers/mmc/core/sdio_bus.c | 2 ++ include/linux/mmc/sdio_func.h | 2 -- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'include/linux') diff --git a/drivers/mmc/core/sdio_bus.c b/drivers/mmc/core/sdio_bus.c index f09040bf5484..51e23f502108 100644 --- a/drivers/mmc/core/sdio_bus.c +++ b/drivers/mmc/core/sdio_bus.c @@ -26,6 +26,8 @@ #include "sdio_cis.h" #include "sdio_bus.h" +#define to_sdio_driver(d) container_of(d, struct sdio_driver, drv) + /* show configuration fields */ #define sdio_config_attr(field, format_string) \ static ssize_t \ diff --git a/include/linux/mmc/sdio_func.h b/include/linux/mmc/sdio_func.h index 50f0bc952328..aab032a6ae61 100644 --- a/include/linux/mmc/sdio_func.h +++ b/include/linux/mmc/sdio_func.h @@ -84,8 +84,6 @@ struct sdio_driver { struct device_driver drv; }; -#define to_sdio_driver(d) container_of(d, struct sdio_driver, drv) - /** * SDIO_DEVICE - macro used to describe a specific SDIO device * @vend: the 16 bit manufacturer code -- cgit v1.2.3 From 6685ac62b2f08fcff77dc35c6b8bff1b74aaa408 Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Mon, 6 Oct 2014 13:51:40 +0200 Subject: mmc: core: Convert mmc_driver to device_driver The struct mmc_driver adds an extra layer on top of the struct device_driver. That would be fine, if there were a good reason, but that's not the case. Let's simplify code by converting to the common struct device_driver instead and thus also removing superfluous overhead. Signed-off-by: Ulf Hansson --- drivers/mmc/card/block.c | 26 ++++++++++++++------------ drivers/mmc/card/mmc_test.c | 18 +++++++++++------- drivers/mmc/core/bus.c | 41 ++++++++--------------------------------- include/linux/mmc/card.h | 16 ++-------------- 4 files changed, 35 insertions(+), 66 deletions(-) (limited to 'include/linux') diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index dfbdfb995dd3..70569d9b5c74 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -2425,8 +2425,9 @@ static const struct mmc_fixup blk_fixups[] = END_FIXUP }; -static int mmc_blk_probe(struct mmc_card *card) +static int mmc_blk_probe(struct device *dev) { + struct mmc_card *card = mmc_dev_to_card(dev); struct mmc_blk_data *md, *part_md; char cap_str[10]; @@ -2481,8 +2482,9 @@ static int mmc_blk_probe(struct mmc_card *card) return 0; } -static void mmc_blk_remove(struct mmc_card *card) +static int mmc_blk_remove(struct device *dev) { + struct mmc_card *card = mmc_dev_to_card(dev); struct mmc_blk_data *md = mmc_get_drvdata(card); mmc_blk_remove_parts(card, md); @@ -2495,11 +2497,14 @@ static void mmc_blk_remove(struct mmc_card *card) pm_runtime_put_noidle(&card->dev); mmc_blk_remove_req(md); mmc_set_drvdata(card, NULL); + + return 0; } -static int _mmc_blk_suspend(struct mmc_card *card) +static int _mmc_blk_suspend(struct device *dev) { struct mmc_blk_data *part_md; + struct mmc_card *card = mmc_dev_to_card(dev); struct mmc_blk_data *md = mmc_get_drvdata(card); if (md) { @@ -2511,16 +2516,15 @@ static int _mmc_blk_suspend(struct mmc_card *card) return 0; } -static void mmc_blk_shutdown(struct mmc_card *card) +static void mmc_blk_shutdown(struct device *dev) { - _mmc_blk_suspend(card); + _mmc_blk_suspend(dev); } #ifdef CONFIG_PM_SLEEP static int mmc_blk_suspend(struct device *dev) { - struct mmc_card *card = mmc_dev_to_card(dev); - return _mmc_blk_suspend(card); + return _mmc_blk_suspend(dev); } static int mmc_blk_resume(struct device *dev) @@ -2546,11 +2550,9 @@ static int mmc_blk_resume(struct device *dev) static SIMPLE_DEV_PM_OPS(mmc_blk_pm_ops, mmc_blk_suspend, mmc_blk_resume); -static struct mmc_driver mmc_driver = { - .drv = { - .name = "mmcblk", - .pm = &mmc_blk_pm_ops, - }, +static struct device_driver mmc_driver = { + .name = "mmcblk", + .pm = &mmc_blk_pm_ops, .probe = mmc_blk_probe, .remove = mmc_blk_remove, .shutdown = mmc_blk_shutdown, diff --git a/drivers/mmc/card/mmc_test.c b/drivers/mmc/card/mmc_test.c index 0c0fc52d42c5..b0643432d6d9 100644 --- a/drivers/mmc/card/mmc_test.c +++ b/drivers/mmc/card/mmc_test.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include /* For nr_free_buffer_pages() */ @@ -2997,8 +2998,9 @@ err: return ret; } -static int mmc_test_probe(struct mmc_card *card) +static int mmc_test_probe(struct device *dev) { + struct mmc_card *card = mmc_dev_to_card(dev); int ret; if (!mmc_card_mmc(card) && !mmc_card_sd(card)) @@ -3013,20 +3015,22 @@ static int mmc_test_probe(struct mmc_card *card) return 0; } -static void mmc_test_remove(struct mmc_card *card) +static int mmc_test_remove(struct device *dev) { + struct mmc_card *card = mmc_dev_to_card(dev); + mmc_test_free_result(card); mmc_test_free_dbgfs_file(card); + + return 0; } -static void mmc_test_shutdown(struct mmc_card *card) +static void mmc_test_shutdown(struct device *dev) { } -static struct mmc_driver mmc_driver = { - .drv = { - .name = "mmc_test", - }, +static struct device_driver mmc_driver = { + .name = "mmc_test", .probe = mmc_test_probe, .remove = mmc_test_remove, .shutdown = mmc_test_shutdown, diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c index 2f375283c423..5ca562ccfcf3 100644 --- a/drivers/mmc/core/bus.c +++ b/drivers/mmc/core/bus.c @@ -25,8 +25,6 @@ #include "sdio_cis.h" #include "bus.h" -#define to_mmc_driver(d) container_of(d, struct mmc_driver, drv) - static ssize_t type_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -106,33 +104,14 @@ mmc_bus_uevent(struct device *dev, struct kobj_uevent_env *env) return retval; } -static int mmc_bus_probe(struct device *dev) -{ - struct mmc_driver *drv = to_mmc_driver(dev->driver); - struct mmc_card *card = mmc_dev_to_card(dev); - - return drv->probe(card); -} - -static int mmc_bus_remove(struct device *dev) -{ - struct mmc_driver *drv = to_mmc_driver(dev->driver); - struct mmc_card *card = mmc_dev_to_card(dev); - - drv->remove(card); - - return 0; -} - static void mmc_bus_shutdown(struct device *dev) { - struct mmc_driver *drv = to_mmc_driver(dev->driver); struct mmc_card *card = mmc_dev_to_card(dev); struct mmc_host *host = card->host; int ret; - if (dev->driver && drv->shutdown) - drv->shutdown(card); + if (dev->driver && dev->driver->shutdown) + dev->driver->shutdown(dev); if (host->bus_ops->shutdown) { ret = host->bus_ops->shutdown(host); @@ -201,8 +180,6 @@ static struct bus_type mmc_bus_type = { .dev_groups = mmc_dev_groups, .match = mmc_bus_match, .uevent = mmc_bus_uevent, - .probe = mmc_bus_probe, - .remove = mmc_bus_remove, .shutdown = mmc_bus_shutdown, .pm = &mmc_bus_pm_ops, }; @@ -221,24 +198,22 @@ void mmc_unregister_bus(void) * mmc_register_driver - register a media driver * @drv: MMC media driver */ -int mmc_register_driver(struct mmc_driver *drv) +int mmc_register_driver(struct device_driver *drv) { - drv->drv.bus = &mmc_bus_type; - return driver_register(&drv->drv); + drv->bus = &mmc_bus_type; + return driver_register(drv); } - EXPORT_SYMBOL(mmc_register_driver); /** * mmc_unregister_driver - unregister a media driver * @drv: MMC media driver */ -void mmc_unregister_driver(struct mmc_driver *drv) +void mmc_unregister_driver(struct device_driver *drv) { - drv->drv.bus = &mmc_bus_type; - driver_unregister(&drv->drv); + drv->bus = &mmc_bus_type; + driver_unregister(drv); } - EXPORT_SYMBOL(mmc_unregister_driver); static void mmc_release_card(struct device *dev) diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h index b0692d28f8e6..cf54afe5d863 100644 --- a/include/linux/mmc/card.h +++ b/include/linux/mmc/card.h @@ -513,20 +513,8 @@ static inline int mmc_card_broken_irq_polling(const struct mmc_card *c) #define mmc_get_drvdata(c) dev_get_drvdata(&(c)->dev) #define mmc_set_drvdata(c,d) dev_set_drvdata(&(c)->dev, d) -/* - * MMC device driver (e.g., Flash card, I/O card...) - */ -struct mmc_driver { - struct device_driver drv; - int (*probe)(struct mmc_card *); - void (*remove)(struct mmc_card *); - int (*suspend)(struct mmc_card *); - int (*resume)(struct mmc_card *); - void (*shutdown)(struct mmc_card *); -}; - -extern int mmc_register_driver(struct mmc_driver *); -extern void mmc_unregister_driver(struct mmc_driver *); +extern int mmc_register_driver(struct device_driver *); +extern void mmc_unregister_driver(struct device_driver *); extern void mmc_fixup_device(struct mmc_card *card, const struct mmc_fixup *table); -- cgit v1.2.3 From fc95e30ba33b9f4faa8630d0762af2548031dc00 Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Mon, 6 Oct 2014 14:34:09 +0200 Subject: mmc: block: Use dev_set|get_drvdata() In most of the cases mmc_get|set_drvdata() didn't simplify code, which should be the primary reason for such macros. Let's remove them and convert to the common device_driver macros, dev_set|get_drvdata() instead. Signed-off-by: Ulf Hansson --- drivers/mmc/card/block.c | 21 ++++++++++----------- include/linux/mmc/card.h | 2 -- 2 files changed, 10 insertions(+), 13 deletions(-) (limited to 'include/linux') diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index 70569d9b5c74..f45f7e3870be 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -112,7 +112,7 @@ struct mmc_blk_data { /* * Only set in main mmc_blk_data associated - * with mmc_card with mmc_set_drvdata, and keeps + * with mmc_card with dev_set_drvdata, and keeps * track of the current selected device partition. */ unsigned int part_curr; @@ -642,7 +642,7 @@ static inline int mmc_blk_part_switch(struct mmc_card *card, struct mmc_blk_data *md) { int ret; - struct mmc_blk_data *main_md = mmc_get_drvdata(card); + struct mmc_blk_data *main_md = dev_get_drvdata(&card->dev); if (main_md->part_curr == md->part_type) return 0; @@ -1004,7 +1004,8 @@ static int mmc_blk_reset(struct mmc_blk_data *md, struct mmc_host *host, err = mmc_hw_reset(host); /* Ensure we switch back to the correct partition */ if (err != -EOPNOTSUPP) { - struct mmc_blk_data *main_md = mmc_get_drvdata(host->card); + struct mmc_blk_data *main_md = + dev_get_drvdata(&host->card->dev); int part_err; main_md->part_curr = main_md->part_type; @@ -2093,7 +2094,7 @@ static struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card, /* * !subname implies we are creating main mmc_blk_data that will be - * associated with mmc_card with mmc_set_drvdata. Due to device + * associated with mmc_card with dev_set_drvdata. Due to device * partitions, devidx will not coincide with a per-physical card * index anymore so we keep track of a name index. */ @@ -2452,7 +2453,7 @@ static int mmc_blk_probe(struct device *dev) if (mmc_blk_alloc_parts(card, md)) goto out; - mmc_set_drvdata(card, md); + dev_set_drvdata(dev, md); if (mmc_add_disk(md)) goto out; @@ -2485,7 +2486,7 @@ static int mmc_blk_probe(struct device *dev) static int mmc_blk_remove(struct device *dev) { struct mmc_card *card = mmc_dev_to_card(dev); - struct mmc_blk_data *md = mmc_get_drvdata(card); + struct mmc_blk_data *md = dev_get_drvdata(dev); mmc_blk_remove_parts(card, md); pm_runtime_get_sync(&card->dev); @@ -2496,7 +2497,7 @@ static int mmc_blk_remove(struct device *dev) pm_runtime_disable(&card->dev); pm_runtime_put_noidle(&card->dev); mmc_blk_remove_req(md); - mmc_set_drvdata(card, NULL); + dev_set_drvdata(dev, NULL); return 0; } @@ -2504,8 +2505,7 @@ static int mmc_blk_remove(struct device *dev) static int _mmc_blk_suspend(struct device *dev) { struct mmc_blk_data *part_md; - struct mmc_card *card = mmc_dev_to_card(dev); - struct mmc_blk_data *md = mmc_get_drvdata(card); + struct mmc_blk_data *md = dev_get_drvdata(dev); if (md) { mmc_queue_suspend(&md->queue); @@ -2530,8 +2530,7 @@ static int mmc_blk_suspend(struct device *dev) static int mmc_blk_resume(struct device *dev) { struct mmc_blk_data *part_md; - struct mmc_card *card = mmc_dev_to_card(dev); - struct mmc_blk_data *md = mmc_get_drvdata(card); + struct mmc_blk_data *md = dev_get_drvdata(dev); if (md) { /* diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h index cf54afe5d863..64f413676410 100644 --- a/include/linux/mmc/card.h +++ b/include/linux/mmc/card.h @@ -510,8 +510,6 @@ static inline int mmc_card_broken_irq_polling(const struct mmc_card *c) #define mmc_dev_to_card(d) container_of(d, struct mmc_card, dev) #define mmc_list_to_card(l) container_of(l, struct mmc_card, node) -#define mmc_get_drvdata(c) dev_get_drvdata(&(c)->dev) -#define mmc_set_drvdata(c,d) dev_set_drvdata(&(c)->dev, d) extern int mmc_register_driver(struct device_driver *); extern void mmc_unregister_driver(struct device_driver *); -- cgit v1.2.3 From 390e316c606de2f839389698f4531004cfe1bafd Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Mon, 6 Oct 2014 14:39:03 +0200 Subject: mmc: core: Remove unused mmc_list_to_card() macro Signed-off-by: Ulf Hansson --- include/linux/mmc/card.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'include/linux') diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h index 64f413676410..0ba8f251f8ef 100644 --- a/include/linux/mmc/card.h +++ b/include/linux/mmc/card.h @@ -509,8 +509,6 @@ static inline int mmc_card_broken_irq_polling(const struct mmc_card *c) #define mmc_dev_to_card(d) container_of(d, struct mmc_card, dev) -#define mmc_list_to_card(l) container_of(l, struct mmc_card, node) - extern int mmc_register_driver(struct device_driver *); extern void mmc_unregister_driver(struct device_driver *); -- cgit v1.2.3 From 0f762426769a517d5b278e4e5d579fcea6801734 Mon Sep 17 00:00:00 2001 From: Gwendal Grignou Date: Thu, 16 Oct 2014 11:27:16 -0700 Subject: mmc: core: Report firmware version for eMMC 5.0 devices. For eMMC 5.0 compliant device, firmware version is stored in ext_csd. Report firmware as a 64bit hexa decimal. Vendor can use hexa or ascii string to report firmware version. Also add FFU related EXT_CSD register and note if the device is FFU capable. Signed-off-by: Gwendal Grignou Signed-off-by: Ulf Hansson --- drivers/mmc/core/mmc.c | 27 ++++++++++++++++++++++++++- include/linux/mmc/card.h | 3 +++ include/linux/mmc/mmc.h | 3 +++ 3 files changed, 32 insertions(+), 1 deletion(-) (limited to 'include/linux') diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index bcde451f6d91..a5e05ceb554c 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -628,6 +628,14 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd) card->ext_csd.data_sector_size = 512; } + /* eMMC v5 or later */ + if (card->ext_csd.rev >= 7) { + memcpy(card->ext_csd.fwrev, &ext_csd[EXT_CSD_FIRMWARE_VERSION], + MMC_FIRMWARE_LEN); + card->ext_csd.ffu_capable = + (ext_csd[EXT_CSD_SUPPORTED_MODE] & 0x1) && + !(ext_csd[EXT_CSD_FW_CONFIG] & 0x1); + } out: return err; } @@ -722,7 +730,7 @@ MMC_DEV_ATTR(csd, "%08x%08x%08x%08x\n", card->raw_csd[0], card->raw_csd[1], MMC_DEV_ATTR(date, "%02d/%04d\n", card->cid.month, card->cid.year); MMC_DEV_ATTR(erase_size, "%u\n", card->erase_size << 9); MMC_DEV_ATTR(preferred_erase_size, "%u\n", card->pref_erase << 9); -MMC_DEV_ATTR(fwrev, "0x%x\n", card->cid.fwrev); +MMC_DEV_ATTR(ffu_capable, "%d\n", card->ext_csd.ffu_capable); MMC_DEV_ATTR(hwrev, "0x%x\n", card->cid.hwrev); MMC_DEV_ATTR(manfid, "0x%06x\n", card->cid.manfid); MMC_DEV_ATTR(name, "%s\n", card->cid.prod_name); @@ -735,6 +743,22 @@ MMC_DEV_ATTR(enhanced_area_size, "%u\n", card->ext_csd.enhanced_area_size); MMC_DEV_ATTR(raw_rpmb_size_mult, "%#x\n", card->ext_csd.raw_rpmb_size_mult); MMC_DEV_ATTR(rel_sectors, "%#x\n", card->ext_csd.rel_sectors); +static ssize_t mmc_fwrev_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct mmc_card *card = mmc_dev_to_card(dev); + + if (card->ext_csd.rev < 7) { + return sprintf(buf, "0x%x\n", card->cid.fwrev); + } else { + return sprintf(buf, "0x%*phN\n", MMC_FIRMWARE_LEN, + card->ext_csd.fwrev); + } +} + +static DEVICE_ATTR(fwrev, S_IRUGO, mmc_fwrev_show, NULL); + static struct attribute *mmc_std_attrs[] = { &dev_attr_cid.attr, &dev_attr_csd.attr, @@ -742,6 +766,7 @@ static struct attribute *mmc_std_attrs[] = { &dev_attr_erase_size.attr, &dev_attr_preferred_erase_size.attr, &dev_attr_fwrev.attr, + &dev_attr_ffu_capable.attr, &dev_attr_hwrev.attr, &dev_attr_manfid.attr, &dev_attr_name.attr, diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h index 0ba8f251f8ef..4d69c00497bd 100644 --- a/include/linux/mmc/card.h +++ b/include/linux/mmc/card.h @@ -88,6 +88,9 @@ struct mmc_ext_csd { unsigned int data_tag_unit_size; /* DATA TAG UNIT size */ unsigned int boot_ro_lock; /* ro lock support */ bool boot_ro_lockable; + bool ffu_capable; /* Firmware upgrade support */ +#define MMC_FIRMWARE_LEN 8 + u8 fwrev[MMC_FIRMWARE_LEN]; /* FW version */ u8 raw_exception_status; /* 54 */ u8 raw_partition_support; /* 160 */ u8 raw_rpmb_size_mult; /* 168 */ diff --git a/include/linux/mmc/mmc.h b/include/linux/mmc/mmc.h index 1cd00b3a75b9..49ad7a943638 100644 --- a/include/linux/mmc/mmc.h +++ b/include/linux/mmc/mmc.h @@ -296,6 +296,7 @@ struct _mmc_csd { #define EXT_CSD_SANITIZE_START 165 /* W */ #define EXT_CSD_WR_REL_PARAM 166 /* RO */ #define EXT_CSD_RPMB_MULT 168 /* RO */ +#define EXT_CSD_FW_CONFIG 169 /* R/W */ #define EXT_CSD_BOOT_WP 173 /* R/W */ #define EXT_CSD_ERASE_GROUP_DEF 175 /* R/W */ #define EXT_CSD_PART_CONFIG 179 /* R/W */ @@ -332,6 +333,8 @@ struct _mmc_csd { #define EXT_CSD_GENERIC_CMD6_TIME 248 /* RO */ #define EXT_CSD_CACHE_SIZE 249 /* RO, 4 bytes */ #define EXT_CSD_PWR_CL_DDR_200_360 253 /* RO */ +#define EXT_CSD_FIRMWARE_VERSION 254 /* RO, 8 bytes */ +#define EXT_CSD_SUPPORTED_MODE 493 /* RO */ #define EXT_CSD_TAG_UNIT_SIZE 498 /* RO */ #define EXT_CSD_DATA_TAG_SUPPORT 499 /* RO */ #define EXT_CSD_MAX_PACKED_WRITES 500 /* RO */ -- cgit v1.2.3 From 9cbef73cb657ff795c130cccfed251f0ae923abb Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Fri, 17 Oct 2014 10:26:36 +0200 Subject: mmc: atmel-mci: move mach header to platform_data Move the mach header that can come either from arm/mach-at91 or avr32 to platform_data to be able to switch the AT91 platforms to multiplatform. Signed-off-by: Alexandre Belloni Acked-by: Arnd Bergmann Acked-by: Ludovic Desroches Signed-off-by: Ulf Hansson [Ulf: Fixed compile error] --- drivers/mmc/host/atmel-mci.c | 2 +- include/linux/platform_data/mmc-atmel-mci.h | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 include/linux/platform_data/mmc-atmel-mci.h (limited to 'include/linux') diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index 77250d4b1979..0b9ddf8aed04 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c @@ -30,11 +30,11 @@ #include #include #include +#include #include #include -#include #include #include diff --git a/include/linux/platform_data/mmc-atmel-mci.h b/include/linux/platform_data/mmc-atmel-mci.h new file mode 100644 index 000000000000..399a2d5a14bd --- /dev/null +++ b/include/linux/platform_data/mmc-atmel-mci.h @@ -0,0 +1,22 @@ +#ifndef __MMC_ATMEL_MCI_H +#define __MMC_ATMEL_MCI_H + +#include +#include + +/** + * struct mci_dma_data - DMA data for MCI interface + */ +struct mci_dma_data { +#ifdef CONFIG_ARM + struct at_dma_slave sdata; +#else + struct dw_dma_slave sdata; +#endif +}; + +/* accessor macros */ +#define slave_data_ptr(s) (&(s)->sdata) +#define find_slave_dev(s) ((s)->sdata.dma_dev) + +#endif /* __MMC_ATMEL_MCI_H */ -- cgit v1.2.3 From 6130e7a9c34d01afbd4e7e215846d1f2d70333bb Mon Sep 17 00:00:00 2001 From: Doug Anderson Date: Tue, 14 Oct 2014 09:33:09 -0700 Subject: mmc: dw_mmc: Remove old card detect infrastructure The dw_mmc driver had a bunch of code that ran whenever a card was ejected and inserted. However, this code was old and crufty and should be removed. Some evidence that it's really not needed: 1. Is is supposed to be legal to use 'cd-gpio' on dw_mmc instead of using the built-in card detect mechanism. The 'cd-gpio' code doesn't run any of the crufty old code but yet still works. 2. While looking at this, I realized that my old change (369ac86 mmc: dw_mmc: don't queue up a card detect at slot startup) actually castrated the old code a little bit already and nobody noticed. Specifically "last_detect_state" was left as 0 at bootup. That means that on the first card removal none of the crufty code ran. 3. I can run "while true; do dd if=/dev/mmcblk1 of=/dev/null; done" while ejecting and inserting an SD Card and the world doesn't explode. If some of the crufty old code is actually needed, we should justify it and also put it in some place where it will be run even with "cd-gpio". Note that in my case I'm using the "cd-gpio" mechanism but for various reasons the hardware triggers a dw_mmc "card detect" at bootup. That was actually causing a real bug. The card detect workqueue was running while the system was trying to enumerate the card. The "present != slot->last_detect_state" triggered and we were doing all kinds of crazy stuff and messing up enumeration. The new mechanism of just asking the core to check the card is much safer and then the bogus interrupt doesn't hurt. Signed-off-by: Doug Anderson Tested-by: Jaehoon Chung Acked-by: Jaehoon Chung Tested-by: alim.akhtar Signed-off-by: Ulf Hansson --- drivers/mmc/host/dw_mmc.c | 121 ++++++++------------------------------------- drivers/mmc/host/dw_mmc.h | 2 - include/linux/mmc/dw_mmc.h | 2 - 3 files changed, 20 insertions(+), 105 deletions(-) (limited to 'include/linux') diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index 545f62191afd..bb46b1b8d16b 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -34,7 +34,6 @@ #include #include #include -#include #include #include #include @@ -1959,6 +1958,23 @@ static void dw_mci_cmd_interrupt(struct dw_mci *host, u32 status) tasklet_schedule(&host->tasklet); } +static void dw_mci_handle_cd(struct dw_mci *host) +{ + int i; + + for (i = 0; i < host->num_slots; i++) { + struct dw_mci_slot *slot = host->slot[i]; + + if (!slot) + continue; + + if (slot->mmc->ops->card_event) + slot->mmc->ops->card_event(slot->mmc); + mmc_detect_change(slot->mmc, + msecs_to_jiffies(host->pdata->detect_delay_ms)); + } +} + static irqreturn_t dw_mci_interrupt(int irq, void *dev_id) { struct dw_mci *host = dev_id; @@ -2034,7 +2050,7 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id) if (pending & SDMMC_INT_CD) { mci_writel(host, RINTSTS, SDMMC_INT_CD); - queue_work(host->card_workqueue, &host->card_work); + dw_mci_handle_cd(host); } /* Handle SDIO Interrupts */ @@ -2061,88 +2077,6 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id) return IRQ_HANDLED; } -static void dw_mci_work_routine_card(struct work_struct *work) -{ - struct dw_mci *host = container_of(work, struct dw_mci, card_work); - int i; - - for (i = 0; i < host->num_slots; i++) { - struct dw_mci_slot *slot = host->slot[i]; - struct mmc_host *mmc = slot->mmc; - struct mmc_request *mrq; - int present; - - present = dw_mci_get_cd(mmc); - while (present != slot->last_detect_state) { - dev_dbg(&slot->mmc->class_dev, "card %s\n", - present ? "inserted" : "removed"); - - spin_lock_bh(&host->lock); - - /* Card change detected */ - slot->last_detect_state = present; - - /* Clean up queue if present */ - mrq = slot->mrq; - if (mrq) { - if (mrq == host->mrq) { - host->data = NULL; - host->cmd = NULL; - - switch (host->state) { - case STATE_IDLE: - case STATE_WAITING_CMD11_DONE: - break; - case STATE_SENDING_CMD11: - case STATE_SENDING_CMD: - mrq->cmd->error = -ENOMEDIUM; - if (!mrq->data) - break; - /* fall through */ - case STATE_SENDING_DATA: - mrq->data->error = -ENOMEDIUM; - dw_mci_stop_dma(host); - break; - case STATE_DATA_BUSY: - case STATE_DATA_ERROR: - if (mrq->data->error == -EINPROGRESS) - mrq->data->error = -ENOMEDIUM; - /* fall through */ - case STATE_SENDING_STOP: - if (mrq->stop) - mrq->stop->error = -ENOMEDIUM; - break; - } - - dw_mci_request_end(host, mrq); - } else { - list_del(&slot->queue_node); - mrq->cmd->error = -ENOMEDIUM; - if (mrq->data) - mrq->data->error = -ENOMEDIUM; - if (mrq->stop) - mrq->stop->error = -ENOMEDIUM; - - spin_unlock(&host->lock); - mmc_request_done(slot->mmc, mrq); - spin_lock(&host->lock); - } - } - - /* Power down slot */ - if (present == 0) - dw_mci_reset(host); - - spin_unlock_bh(&host->lock); - - present = dw_mci_get_cd(mmc); - } - - mmc_detect_change(slot->mmc, - msecs_to_jiffies(host->pdata->detect_delay_ms)); - } -} - #ifdef CONFIG_OF /* given a slot id, find out the device node representing that slot */ static struct device_node *dw_mci_of_find_slot_node(struct device *dev, u8 slot) @@ -2294,9 +2228,6 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id) dw_mci_init_debugfs(slot); #endif - /* Card initially undetected */ - slot->last_detect_state = 0; - return 0; err_host_allocated: @@ -2677,17 +2608,10 @@ int dw_mci_probe(struct dw_mci *host) host->data_offset = DATA_240A_OFFSET; tasklet_init(&host->tasklet, dw_mci_tasklet_func, (unsigned long)host); - host->card_workqueue = alloc_workqueue("dw-mci-card", - WQ_MEM_RECLAIM, 1); - if (!host->card_workqueue) { - ret = -ENOMEM; - goto err_dmaunmap; - } - INIT_WORK(&host->card_work, dw_mci_work_routine_card); ret = devm_request_irq(host->dev, host->irq, dw_mci_interrupt, host->irq_flags, "dw-mci", host); if (ret) - goto err_workqueue; + goto err_dmaunmap; if (host->pdata->num_slots) host->num_slots = host->pdata->num_slots; @@ -2723,7 +2647,7 @@ int dw_mci_probe(struct dw_mci *host) } else { dev_dbg(host->dev, "attempted to initialize %d slots, " "but failed on all\n", host->num_slots); - goto err_workqueue; + goto err_dmaunmap; } if (host->quirks & DW_MCI_QUIRK_IDMAC_DTO) @@ -2731,9 +2655,6 @@ int dw_mci_probe(struct dw_mci *host) return 0; -err_workqueue: - destroy_workqueue(host->card_workqueue); - err_dmaunmap: if (host->use_dma && host->dma_ops->exit) host->dma_ops->exit(host); @@ -2767,8 +2688,6 @@ void dw_mci_remove(struct dw_mci *host) mci_writel(host, CLKENA, 0); mci_writel(host, CLKSRC, 0); - destroy_workqueue(host->card_workqueue); - if (host->use_dma && host->dma_ops->exit) host->dma_ops->exit(host); diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h index 01b99e8a9190..71d499557edc 100644 --- a/drivers/mmc/host/dw_mmc.h +++ b/drivers/mmc/host/dw_mmc.h @@ -214,7 +214,6 @@ extern int dw_mci_resume(struct dw_mci *host); * with CONFIG_MMC_CLKGATE. * @flags: Random state bits associated with the slot. * @id: Number of this slot. - * @last_detect_state: Most recently observed card detect state. */ struct dw_mci_slot { struct mmc_host *mmc; @@ -234,7 +233,6 @@ struct dw_mci_slot { #define DW_MMC_CARD_PRESENT 0 #define DW_MMC_CARD_NEED_INIT 1 int id; - int last_detect_state; }; struct dw_mci_tuning_data { diff --git a/include/linux/mmc/dw_mmc.h b/include/linux/mmc/dw_mmc.h index 001366927cf4..69d08144cfad 100644 --- a/include/linux/mmc/dw_mmc.h +++ b/include/linux/mmc/dw_mmc.h @@ -135,7 +135,6 @@ struct dw_mci { struct mmc_command stop_abort; unsigned int prev_blksz; unsigned char timing; - struct workqueue_struct *card_workqueue; /* DMA interface members*/ int use_dma; @@ -154,7 +153,6 @@ struct dw_mci { u32 stop_cmdr; u32 dir_status; struct tasklet_struct tasklet; - struct work_struct card_work; unsigned long pending_events; unsigned long completed_events; enum dw_mci_state state; -- cgit v1.2.3 From e21aa519ee3667d0fabda5d806cc68826e9899e0 Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Fri, 17 Oct 2014 11:32:32 +0200 Subject: mmc: core: Export mmc_get_ext_csd() Callers of mmc_send_ext_csd() will be able to decrease code duplication by using mmc_get_ext_csd() instead. Let's make it available. Signed-off-by: Ulf Hansson --- drivers/mmc/core/mmc.c | 31 ------------------------------- drivers/mmc/core/mmc_ops.c | 29 +++++++++++++++++++++++++++++ include/linux/mmc/core.h | 1 + 3 files changed, 30 insertions(+), 31 deletions(-) (limited to 'include/linux') diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index efaa9f8f07b0..02ad79229f65 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -177,37 +177,6 @@ static int mmc_decode_csd(struct mmc_card *card) return 0; } -/* - * Read extended CSD. - */ -static int mmc_get_ext_csd(struct mmc_card *card, u8 **new_ext_csd) -{ - int err; - u8 *ext_csd; - - if (!card || !new_ext_csd) - return -EINVAL; - - if (!mmc_can_ext_csd(card)) - return -EOPNOTSUPP; - - /* - * As the ext_csd is so large and mostly unused, we don't store the - * raw block in mmc_card. - */ - ext_csd = kmalloc(512, GFP_KERNEL); - if (!ext_csd) - return -ENOMEM; - - err = mmc_send_ext_csd(card, ext_csd); - if (err) - kfree(ext_csd); - else - *new_ext_csd = ext_csd; - - return err; -} - static void mmc_select_card_type(struct mmc_card *card) { struct mmc_host *host = card->host; diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c index 1db60be43c37..72e1f9b3ed0d 100644 --- a/drivers/mmc/core/mmc_ops.c +++ b/drivers/mmc/core/mmc_ops.c @@ -385,6 +385,35 @@ int mmc_send_ext_csd(struct mmc_card *card, u8 *ext_csd) } EXPORT_SYMBOL_GPL(mmc_send_ext_csd); +int mmc_get_ext_csd(struct mmc_card *card, u8 **new_ext_csd) +{ + int err; + u8 *ext_csd; + + if (!card || !new_ext_csd) + return -EINVAL; + + if (!mmc_can_ext_csd(card)) + return -EOPNOTSUPP; + + /* + * As the ext_csd is so large and mostly unused, we don't store the + * raw block in mmc_card. + */ + ext_csd = kmalloc(512, GFP_KERNEL); + if (!ext_csd) + return -ENOMEM; + + err = mmc_send_ext_csd(card, ext_csd); + if (err) + kfree(ext_csd); + else + *new_ext_csd = ext_csd; + + return err; +} +EXPORT_SYMBOL_GPL(mmc_get_ext_csd); + int mmc_spi_read_ocr(struct mmc_host *host, int highcap, u32 *ocrp) { struct mmc_command cmd = {0}; diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h index f206e29f94d7..0a77d3567c27 100644 --- a/include/linux/mmc/core.h +++ b/include/linux/mmc/core.h @@ -155,6 +155,7 @@ extern int __mmc_switch(struct mmc_card *, u8, u8, u8, unsigned int, bool, bool, bool); extern int mmc_switch(struct mmc_card *, u8, u8, u8, unsigned int); extern int mmc_send_ext_csd(struct mmc_card *card, u8 *ext_csd); +extern int mmc_get_ext_csd(struct mmc_card *card, u8 **new_ext_csd); #define MMC_ERASE_ARG 0x00000000 #define MMC_SECURE_ERASE_ARG 0x80000000 -- cgit v1.2.3 From 2fc91e8b0e1cd89094677d1c9dfba1b26979e48b Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Fri, 17 Oct 2014 11:54:22 +0200 Subject: mmc: core: Remove the redundant mmc_send_ext_csd() API Previous patches has replaced the calls to mmc_send_ext_csd() into mmc_get_ext_csd(), thus mmc_send_ext_csd() has become redundant. Let's remove it. Signed-off-by: Ulf Hansson --- drivers/mmc/core/mmc_ops.c | 10 ++-------- include/linux/mmc/core.h | 1 - 2 files changed, 2 insertions(+), 9 deletions(-) (limited to 'include/linux') diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c index 72e1f9b3ed0d..9a6181bf0c06 100644 --- a/drivers/mmc/core/mmc_ops.c +++ b/drivers/mmc/core/mmc_ops.c @@ -378,13 +378,6 @@ err: return ret; } -int mmc_send_ext_csd(struct mmc_card *card, u8 *ext_csd) -{ - return mmc_send_cxd_data(card, card->host, MMC_SEND_EXT_CSD, - ext_csd, 512); -} -EXPORT_SYMBOL_GPL(mmc_send_ext_csd); - int mmc_get_ext_csd(struct mmc_card *card, u8 **new_ext_csd) { int err; @@ -404,7 +397,8 @@ int mmc_get_ext_csd(struct mmc_card *card, u8 **new_ext_csd) if (!ext_csd) return -ENOMEM; - err = mmc_send_ext_csd(card, ext_csd); + err = mmc_send_cxd_data(card, card->host, MMC_SEND_EXT_CSD, ext_csd, + 512); if (err) kfree(ext_csd); else diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h index 0a77d3567c27..b11e43c10631 100644 --- a/include/linux/mmc/core.h +++ b/include/linux/mmc/core.h @@ -154,7 +154,6 @@ extern void mmc_start_bkops(struct mmc_card *card, bool from_exception); extern int __mmc_switch(struct mmc_card *, u8, u8, u8, unsigned int, bool, bool, bool); extern int mmc_switch(struct mmc_card *, u8, u8, u8, unsigned int); -extern int mmc_send_ext_csd(struct mmc_card *card, u8 *ext_csd); extern int mmc_get_ext_csd(struct mmc_card *card, u8 **new_ext_csd); #define MMC_ERASE_ARG 0x00000000 -- cgit v1.2.3 From 76d5556428fbbdf411504895b516272cad27127d Mon Sep 17 00:00:00 2001 From: Timo Kokkonen Date: Mon, 3 Nov 2014 13:12:59 +0200 Subject: mmc: host: atmel-mci: Add support for non-removable slots Add support for non-removable slots which have no card detection GPIO and which should not be polled for a card change. Signed-off-by: Timo Kokkonen Acked-by: Ludovic Desroches Signed-off-by: Ulf Hansson --- drivers/mmc/host/atmel-mci.c | 11 +++++++++-- include/linux/atmel-mci.h | 2 ++ 2 files changed, 11 insertions(+), 2 deletions(-) (limited to 'include/linux') diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index 0b9ddf8aed04..d9646e5ae2c8 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c @@ -560,6 +560,9 @@ atmci_of_init(struct platform_device *pdev) pdata->slot[slot_id].detect_is_active_high = of_property_read_bool(cnp, "cd-inverted"); + pdata->slot[slot_id].non_removable = + of_property_read_bool(cnp, "non-removable"); + pdata->slot[slot_id].wp_pin = of_get_named_gpio(cnp, "wp-gpios", 0); } @@ -2206,8 +2209,12 @@ static int __init atmci_init_slot(struct atmel_mci *host, } } - if (!gpio_is_valid(slot->detect_pin)) - mmc->caps |= MMC_CAP_NEEDS_POLL; + if (!gpio_is_valid(slot->detect_pin)) { + if (slot_data->non_removable) + mmc->caps |= MMC_CAP_NONREMOVABLE; + else + mmc->caps |= MMC_CAP_NEEDS_POLL; + } if (gpio_is_valid(slot->wp_pin)) { if (devm_gpio_request(&host->pdev->dev, slot->wp_pin, diff --git a/include/linux/atmel-mci.h b/include/linux/atmel-mci.h index 91b77f8d495d..9177947bf032 100644 --- a/include/linux/atmel-mci.h +++ b/include/linux/atmel-mci.h @@ -11,6 +11,7 @@ * @detect_pin: GPIO pin wired to the card detect switch * @wp_pin: GPIO pin wired to the write protect sensor * @detect_is_active_high: The state of the detect pin when it is active + * @non_removable: The slot is not removable, only detect once * * If a given slot is not present on the board, @bus_width should be * set to 0. The other fields are ignored in this case. @@ -26,6 +27,7 @@ struct mci_slot_pdata { int detect_pin; int wp_pin; bool detect_is_active_high; + bool non_removable; }; /** -- cgit v1.2.3 From 4efaa6fbe1fd5e86ab2fee4cdcfc6873dab60716 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Tue, 4 Nov 2014 12:42:39 +0200 Subject: mmc: sdhci: Rename adma_desc to adma_table In preparation for 64-bit ADMA, rename adma_desc to adma_table. That is because members will be added for descriptor size and table size, so using adma_desc (which is the table) is confusing. Signed-off-by: Adrian Hunter Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci.c | 31 ++++++++++++++++--------------- include/linux/mmc/sdhci.h | 2 +- 2 files changed, 17 insertions(+), 16 deletions(-) (limited to 'include/linux') diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index e40414ab7ef8..f2062b073e00 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -505,7 +505,7 @@ static int sdhci_adma_table_pre(struct sdhci_host *host, if (host->sg_count == 0) goto unmap_align; - desc = host->adma_desc; + desc = host->adma_table; align = host->align_buffer; align_addr = host->align_addr; @@ -555,14 +555,14 @@ static int sdhci_adma_table_pre(struct sdhci_host *host, * If this triggers then we have a calculation bug * somewhere. :/ */ - WARN_ON((desc - host->adma_desc) >= ADMA_SIZE); + WARN_ON((desc - host->adma_table) >= ADMA_SIZE); } if (host->quirks & SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC) { /* * Mark the last descriptor as the terminating descriptor */ - if (desc != host->adma_desc) { + if (desc != host->adma_table) { desc -= 8; desc[0] |= 0x2; /* end */ } @@ -2294,7 +2294,7 @@ static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask, u32 *mask) static void sdhci_adma_show_error(struct sdhci_host *host) { const char *name = mmc_hostname(host->mmc); - u8 *desc = host->adma_desc; + u8 *desc = host->adma_table; __le32 *dma; __le16 *len; u8 attr; @@ -2875,27 +2875,28 @@ int sdhci_add_host(struct sdhci_host *host) * (128) and potentially one alignment transfer for * each of those entries. */ - host->adma_desc = dma_alloc_coherent(mmc_dev(mmc), - ADMA_SIZE, &host->adma_addr, - GFP_KERNEL); + host->adma_table = dma_alloc_coherent(mmc_dev(mmc), + ADMA_SIZE, + &host->adma_addr, + GFP_KERNEL); host->align_buffer = kmalloc(128 * 4, GFP_KERNEL); - if (!host->adma_desc || !host->align_buffer) { + if (!host->adma_table || !host->align_buffer) { dma_free_coherent(mmc_dev(mmc), ADMA_SIZE, - host->adma_desc, host->adma_addr); + host->adma_table, host->adma_addr); kfree(host->align_buffer); pr_warn("%s: Unable to allocate ADMA buffers - falling back to standard DMA\n", mmc_hostname(mmc)); host->flags &= ~SDHCI_USE_ADMA; - host->adma_desc = NULL; + host->adma_table = NULL; host->align_buffer = NULL; } else if (host->adma_addr & 3) { pr_warn("%s: unable to allocate aligned ADMA descriptor\n", mmc_hostname(mmc)); host->flags &= ~SDHCI_USE_ADMA; dma_free_coherent(mmc_dev(mmc), ADMA_SIZE, - host->adma_desc, host->adma_addr); + host->adma_table, host->adma_addr); kfree(host->align_buffer); - host->adma_desc = NULL; + host->adma_table = NULL; host->align_buffer = NULL; } } @@ -3351,12 +3352,12 @@ void sdhci_remove_host(struct sdhci_host *host, int dead) if (!IS_ERR(mmc->supply.vqmmc)) regulator_disable(mmc->supply.vqmmc); - if (host->adma_desc) + if (host->adma_table) dma_free_coherent(mmc_dev(mmc), ADMA_SIZE, - host->adma_desc, host->adma_addr); + host->adma_table, host->adma_addr); kfree(host->align_buffer); - host->adma_desc = NULL; + host->adma_table = NULL; host->align_buffer = NULL; } diff --git a/include/linux/mmc/sdhci.h b/include/linux/mmc/sdhci.h index dba793e3a331..76e04324cc33 100644 --- a/include/linux/mmc/sdhci.h +++ b/include/linux/mmc/sdhci.h @@ -155,7 +155,7 @@ struct sdhci_host { int sg_count; /* Mapped sg entries */ - u8 *adma_desc; /* ADMA descriptor table */ + u8 *adma_table; /* ADMA descriptor table */ u8 *align_buffer; /* Bounce buffer */ dma_addr_t adma_addr; /* Mapped ADMA descr. table */ -- cgit v1.2.3 From 1c3d5f6ddcb915c0e702cf513bad4a3b1583f48f Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Tue, 4 Nov 2014 12:42:41 +0200 Subject: mmc: sdhci: Use 'void *' for not 'u8 *' for ADMA data It is kernel-style to use 'void *' for anonymous data. This is being applied to the ADMA bounce buffer which contains unaligned bytes, and to the ADMA descriptor table which will contain 32-bit ADMA descriptors or 64-bit ADMA descriptors when support is added. Signed-off-by: Adrian Hunter Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci.c | 12 ++++++------ include/linux/mmc/sdhci.h | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) (limited to 'include/linux') diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 19f31ea99738..20e8a2d0d51a 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -454,7 +454,7 @@ static void sdhci_kunmap_atomic(void *buffer, unsigned long *flags) local_irq_restore(*flags); } -static void sdhci_adma_write_desc(u8 *desc, u32 addr, int len, unsigned cmd) +static void sdhci_adma_write_desc(void *desc, u32 addr, int len, unsigned cmd) { __le32 *dataddr = (__le32 __force *)(desc + 4); __le16 *cmdlen = (__le16 __force *)desc; @@ -480,8 +480,8 @@ static int sdhci_adma_table_pre(struct sdhci_host *host, { int direction; - u8 *desc; - u8 *align; + void *desc; + void *align; dma_addr_t addr; dma_addr_t align_addr; int len, offset; @@ -606,7 +606,7 @@ static void sdhci_adma_table_post(struct sdhci_host *host, struct scatterlist *sg; int i, size; - u8 *align; + void *align; char *buffer; unsigned long flags; bool has_unaligned; @@ -2301,7 +2301,7 @@ static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask, u32 *mask) static void sdhci_adma_show_error(struct sdhci_host *host) { const char *name = mmc_hostname(host->mmc); - u8 *desc = host->adma_table; + void *desc = host->adma_table; __le32 *dma; __le16 *len; u8 attr; @@ -2311,7 +2311,7 @@ static void sdhci_adma_show_error(struct sdhci_host *host) while (true) { dma = (__le32 *)(desc + 4); len = (__le16 *)(desc + 2); - attr = *desc; + attr = *(u8 *)desc; DBG("%s: %p: DMA 0x%08x, LEN 0x%04x, Attr=0x%02x\n", name, desc, le32_to_cpu(*dma), le16_to_cpu(*len), attr); diff --git a/include/linux/mmc/sdhci.h b/include/linux/mmc/sdhci.h index 76e04324cc33..933dbbb50742 100644 --- a/include/linux/mmc/sdhci.h +++ b/include/linux/mmc/sdhci.h @@ -155,8 +155,8 @@ struct sdhci_host { int sg_count; /* Mapped sg entries */ - u8 *adma_table; /* ADMA descriptor table */ - u8 *align_buffer; /* Bounce buffer */ + void *adma_table; /* ADMA descriptor table */ + void *align_buffer; /* Bounce buffer */ dma_addr_t adma_addr; /* Mapped ADMA descr. table */ dma_addr_t align_addr; /* Mapped bounce buffer */ -- cgit v1.2.3 From 76fe379acaeb857f91705f3bd5c6f69ec13872a9 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Tue, 4 Nov 2014 12:42:42 +0200 Subject: mmc: sdhci: Parameterize ADMA sizes and alignment In preparation for 64-bit ADMA, parameterize ADMA sizes and alignment. 64-bit ADMA has a larger descriptor because it contains a 64-bit address instead of a 32-bit address. Also data must be 8-byte aligned instead of 4-byte aligned. Consequently, sdhci_host members are added for descriptor, table, and buffer sizes and alignment. Signed-off-by: Adrian Hunter Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci.c | 68 +++++++++++++++++++++++------------------------ include/linux/mmc/sdhci.h | 7 +++++ 2 files changed, 41 insertions(+), 34 deletions(-) (limited to 'include/linux') diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 20e8a2d0d51a..053b55df9df1 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -44,14 +44,6 @@ #define MAX_TUNING_LOOP 40 -/* - * The ADMA2 descriptor table size is calculated as the maximum number of - * segments (128), times 2 to allow for an alignment descriptor for each - * segment, plus 1 for a nop end descriptor, all multipled by the 32-bit - * descriptor size (8). - */ -#define ADMA_SIZE ((128 * 2 + 1) * 8) - static unsigned int debug_quirks = 0; static unsigned int debug_quirks2; @@ -502,10 +494,10 @@ static int sdhci_adma_table_pre(struct sdhci_host *host, direction = DMA_TO_DEVICE; host->align_addr = dma_map_single(mmc_dev(host->mmc), - host->align_buffer, 128 * 4, direction); + host->align_buffer, host->align_buffer_sz, direction); if (dma_mapping_error(mmc_dev(host->mmc), host->align_addr)) goto fail; - BUG_ON(host->align_addr & 0x3); + BUG_ON(host->align_addr & host->align_mask); host->sg_count = dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len, direction); @@ -528,7 +520,8 @@ static int sdhci_adma_table_pre(struct sdhci_host *host, * the (up to three) bytes that screw up the * alignment. */ - offset = (4 - (addr & 0x3)) & 0x3; + offset = (host->align_sz - (addr & host->align_mask)) & + host->align_mask; if (offset) { if (data->flags & MMC_DATA_WRITE) { buffer = sdhci_kmap_atomic(sg, &flags); @@ -543,10 +536,10 @@ static int sdhci_adma_table_pre(struct sdhci_host *host, BUG_ON(offset > 65536); - align += 4; - align_addr += 4; + align += host->align_sz; + align_addr += host->align_sz; - desc += 8; + desc += host->desc_sz; addr += offset; len -= offset; @@ -556,13 +549,13 @@ static int sdhci_adma_table_pre(struct sdhci_host *host, /* tran, valid */ sdhci_adma_write_desc(desc, addr, len, 0x21); - desc += 8; + desc += host->desc_sz; /* * If this triggers then we have a calculation bug * somewhere. :/ */ - WARN_ON((desc - host->adma_table) >= ADMA_SIZE); + WARN_ON((desc - host->adma_table) >= host->adma_table_sz); } if (host->quirks & SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC) { @@ -570,7 +563,7 @@ static int sdhci_adma_table_pre(struct sdhci_host *host, * Mark the last descriptor as the terminating descriptor */ if (desc != host->adma_table) { - desc -= 8; + desc -= host->desc_sz; sdhci_adma_mark_end(desc); } } else { @@ -587,14 +580,14 @@ static int sdhci_adma_table_pre(struct sdhci_host *host, */ if (data->flags & MMC_DATA_WRITE) { dma_sync_single_for_device(mmc_dev(host->mmc), - host->align_addr, 128 * 4, direction); + host->align_addr, host->align_buffer_sz, direction); } return 0; unmap_align: dma_unmap_single(mmc_dev(host->mmc), host->align_addr, - 128 * 4, direction); + host->align_buffer_sz, direction); fail: return -EINVAL; } @@ -617,12 +610,12 @@ static void sdhci_adma_table_post(struct sdhci_host *host, direction = DMA_TO_DEVICE; dma_unmap_single(mmc_dev(host->mmc), host->align_addr, - 128 * 4, direction); + host->align_buffer_sz, direction); /* Do a quick scan of the SG list for any unaligned mappings */ has_unaligned = false; for_each_sg(data->sg, sg, host->sg_count, i) - if (sg_dma_address(sg) & 3) { + if (sg_dma_address(sg) & host->align_mask) { has_unaligned = true; break; } @@ -634,8 +627,9 @@ static void sdhci_adma_table_post(struct sdhci_host *host, align = host->align_buffer; for_each_sg(data->sg, sg, host->sg_count, i) { - if (sg_dma_address(sg) & 0x3) { - size = 4 - (sg_dma_address(sg) & 0x3); + if (sg_dma_address(sg) & host->align_mask) { + size = host->align_sz - + (sg_dma_address(sg) & host->align_mask); buffer = sdhci_kmap_atomic(sg, &flags); WARN_ON(((long)buffer & (PAGE_SIZE - 1)) > @@ -643,7 +637,7 @@ static void sdhci_adma_table_post(struct sdhci_host *host, memcpy(buffer, align, size); sdhci_kunmap_atomic(buffer, &flags); - align += 4; + align += host->align_sz; } } } @@ -2316,7 +2310,7 @@ static void sdhci_adma_show_error(struct sdhci_host *host) DBG("%s: %p: DMA 0x%08x, LEN 0x%04x, Attr=0x%02x\n", name, desc, le32_to_cpu(*dma), le16_to_cpu(*len), attr); - desc += 8; + desc += host->desc_sz; if (attr & 2) break; @@ -2878,17 +2872,23 @@ int sdhci_add_host(struct sdhci_host *host) if (host->flags & SDHCI_USE_ADMA) { /* - * We need to allocate descriptors for all sg entries - * (128) and potentially one alignment transfer for - * each of those entries. + * The DMA descriptor table size is calculated as the maximum + * number of segments times 2, to allow for an alignment + * descriptor for each segment, plus 1 for a nop end descriptor, + * all multipled by the descriptor size. */ + host->adma_table_sz = (128 * 2 + 1) * 8; + host->align_buffer_sz = 128 * 4; + host->desc_sz = 8; + host->align_sz = 4; + host->align_mask = 3; host->adma_table = dma_alloc_coherent(mmc_dev(mmc), - ADMA_SIZE, + host->adma_table_sz, &host->adma_addr, GFP_KERNEL); - host->align_buffer = kmalloc(128 * 4, GFP_KERNEL); + host->align_buffer = kmalloc(host->align_buffer_sz, GFP_KERNEL); if (!host->adma_table || !host->align_buffer) { - dma_free_coherent(mmc_dev(mmc), ADMA_SIZE, + dma_free_coherent(mmc_dev(mmc), host->adma_table_sz, host->adma_table, host->adma_addr); kfree(host->align_buffer); pr_warn("%s: Unable to allocate ADMA buffers - falling back to standard DMA\n", @@ -2896,11 +2896,11 @@ int sdhci_add_host(struct sdhci_host *host) host->flags &= ~SDHCI_USE_ADMA; host->adma_table = NULL; host->align_buffer = NULL; - } else if (host->adma_addr & 3) { + } else if (host->adma_addr & host->align_mask) { pr_warn("%s: unable to allocate aligned ADMA descriptor\n", mmc_hostname(mmc)); host->flags &= ~SDHCI_USE_ADMA; - dma_free_coherent(mmc_dev(mmc), ADMA_SIZE, + dma_free_coherent(mmc_dev(mmc), host->adma_table_sz, host->adma_table, host->adma_addr); kfree(host->align_buffer); host->adma_table = NULL; @@ -3360,7 +3360,7 @@ void sdhci_remove_host(struct sdhci_host *host, int dead) regulator_disable(mmc->supply.vqmmc); if (host->adma_table) - dma_free_coherent(mmc_dev(mmc), ADMA_SIZE, + dma_free_coherent(mmc_dev(mmc), host->adma_table_sz, host->adma_table, host->adma_addr); kfree(host->align_buffer); diff --git a/include/linux/mmc/sdhci.h b/include/linux/mmc/sdhci.h index 933dbbb50742..2a72e9510833 100644 --- a/include/linux/mmc/sdhci.h +++ b/include/linux/mmc/sdhci.h @@ -158,9 +158,16 @@ struct sdhci_host { void *adma_table; /* ADMA descriptor table */ void *align_buffer; /* Bounce buffer */ + size_t adma_table_sz; /* ADMA descriptor table size */ + size_t align_buffer_sz; /* Bounce buffer size */ + dma_addr_t adma_addr; /* Mapped ADMA descr. table */ dma_addr_t align_addr; /* Mapped bounce buffer */ + unsigned int desc_sz; /* ADMA descriptor size */ + unsigned int align_sz; /* ADMA alignment */ + unsigned int align_mask; /* ADMA alignment mask */ + struct tasklet_struct finish_tasklet; /* Tasklet structures */ struct timer_list timer; /* Timer for timeouts */ -- cgit v1.2.3 From e57a5f61eae7e145aeeda18ccb22576822f534bf Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Tue, 4 Nov 2014 12:42:46 +0200 Subject: mmc: sdhci: Add 64-bit ADMA support Add 64-bit ADMA support including: - add 64-bit ADMA descriptor - add SDHCI_USE_64_BIT_DMA flag - set upper 32-bits of DMA addresses - ability to select 64-bit ADMA - ability to use 64-bit ADMA sizes and alignment - display "ADMA 64-bit" when host is added It is assumed that a 64-bit capable device has set a 64-bit DMA mask and *must* do 64-bit DMA. A driver has the opportunity to change that during the first call to ->enable_dma(). Similarly SDHCI_QUIRK2_BROKEN_64_BIT_DMA must be left to the drivers to implement. Signed-off-by: Adrian Hunter Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci.c | 109 ++++++++++++++++++++++++++++++++++------------ drivers/mmc/host/sdhci.h | 18 ++++++++ include/linux/mmc/sdhci.h | 3 ++ 3 files changed, 102 insertions(+), 28 deletions(-) (limited to 'include/linux') diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index ec093490a24f..f895ab07fcc2 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -117,10 +117,17 @@ static void sdhci_dumpregs(struct sdhci_host *host) pr_debug(DRIVER_NAME ": Host ctl2: 0x%08x\n", sdhci_readw(host, SDHCI_HOST_CONTROL2)); - if (host->flags & SDHCI_USE_ADMA) - pr_debug(DRIVER_NAME ": ADMA Err: 0x%08x | ADMA Ptr: 0x%08x\n", - readl(host->ioaddr + SDHCI_ADMA_ERROR), - readl(host->ioaddr + SDHCI_ADMA_ADDRESS)); + if (host->flags & SDHCI_USE_ADMA) { + if (host->flags & SDHCI_USE_64_BIT_DMA) + pr_debug(DRIVER_NAME ": ADMA Err: 0x%08x | ADMA Ptr: 0x%08x%08x\n", + readl(host->ioaddr + SDHCI_ADMA_ERROR), + readl(host->ioaddr + SDHCI_ADMA_ADDRESS_HI), + readl(host->ioaddr + SDHCI_ADMA_ADDRESS)); + else + pr_debug(DRIVER_NAME ": ADMA Err: 0x%08x | ADMA Ptr: 0x%08x\n", + readl(host->ioaddr + SDHCI_ADMA_ERROR), + readl(host->ioaddr + SDHCI_ADMA_ADDRESS)); + } pr_debug(DRIVER_NAME ": ===========================================\n"); } @@ -446,19 +453,25 @@ static void sdhci_kunmap_atomic(void *buffer, unsigned long *flags) local_irq_restore(*flags); } -static void sdhci_adma_write_desc(void *desc, u32 addr, int len, unsigned cmd) +static void sdhci_adma_write_desc(struct sdhci_host *host, void *desc, + dma_addr_t addr, int len, unsigned cmd) { - struct sdhci_adma2_32_desc *dma_desc = desc; + struct sdhci_adma2_64_desc *dma_desc = desc; + /* 32-bit and 64-bit descriptors have these members in same position */ dma_desc->cmd = cpu_to_le16(cmd); dma_desc->len = cpu_to_le16(len); - dma_desc->addr = cpu_to_le32(addr); + dma_desc->addr_lo = cpu_to_le32((u32)addr); + + if (host->flags & SDHCI_USE_64_BIT_DMA) + dma_desc->addr_hi = cpu_to_le32((u64)addr >> 32); } static void sdhci_adma_mark_end(void *desc) { - struct sdhci_adma2_32_desc *dma_desc = desc; + struct sdhci_adma2_64_desc *dma_desc = desc; + /* 32-bit and 64-bit descriptors have 'cmd' in same position */ dma_desc->cmd |= cpu_to_le16(ADMA2_END); } @@ -527,7 +540,7 @@ static int sdhci_adma_table_pre(struct sdhci_host *host, } /* tran, valid */ - sdhci_adma_write_desc(desc, align_addr, offset, + sdhci_adma_write_desc(host, desc, align_addr, offset, ADMA2_TRAN_VALID); BUG_ON(offset > 65536); @@ -544,7 +557,7 @@ static int sdhci_adma_table_pre(struct sdhci_host *host, BUG_ON(len > 65536); /* tran, valid */ - sdhci_adma_write_desc(desc, addr, len, ADMA2_TRAN_VALID); + sdhci_adma_write_desc(host, desc, addr, len, ADMA2_TRAN_VALID); desc += host->desc_sz; /* @@ -568,7 +581,7 @@ static int sdhci_adma_table_pre(struct sdhci_host *host, */ /* nop, end, valid */ - sdhci_adma_write_desc(desc, 0, 0, ADMA2_NOP_END_VALID); + sdhci_adma_write_desc(host, desc, 0, 0, ADMA2_NOP_END_VALID); } /* @@ -827,6 +840,10 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd) } else { sdhci_writel(host, host->adma_addr, SDHCI_ADMA_ADDRESS); + if (host->flags & SDHCI_USE_64_BIT_DMA) + sdhci_writel(host, + (u64)host->adma_addr >> 32, + SDHCI_ADMA_ADDRESS_HI); } } else { int sg_cnt; @@ -860,10 +877,14 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd) ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); ctrl &= ~SDHCI_CTRL_DMA_MASK; if ((host->flags & SDHCI_REQ_USE_DMA) && - (host->flags & SDHCI_USE_ADMA)) - ctrl |= SDHCI_CTRL_ADMA32; - else + (host->flags & SDHCI_USE_ADMA)) { + if (host->flags & SDHCI_USE_64_BIT_DMA) + ctrl |= SDHCI_CTRL_ADMA64; + else + ctrl |= SDHCI_CTRL_ADMA32; + } else { ctrl |= SDHCI_CTRL_SDMA; + } sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); } @@ -2296,12 +2317,19 @@ static void sdhci_adma_show_error(struct sdhci_host *host) sdhci_dumpregs(host); while (true) { - struct sdhci_adma2_32_desc *dma_desc = desc; - - DBG("%s: %p: DMA 0x%08x, LEN 0x%04x, Attr=0x%02x\n", - name, desc, le32_to_cpu(dma_desc->addr), - le16_to_cpu(dma_desc->len), - le16_to_cpu(dma_desc->cmd)); + struct sdhci_adma2_64_desc *dma_desc = desc; + + if (host->flags & SDHCI_USE_64_BIT_DMA) + DBG("%s: %p: DMA 0x%08x%08x, LEN 0x%04x, Attr=0x%02x\n", + name, desc, le32_to_cpu(dma_desc->addr_hi), + le32_to_cpu(dma_desc->addr_lo), + le16_to_cpu(dma_desc->len), + le16_to_cpu(dma_desc->cmd)); + else + DBG("%s: %p: DMA 0x%08x, LEN 0x%04x, Attr=0x%02x\n", + name, desc, le32_to_cpu(dma_desc->addr_lo), + le16_to_cpu(dma_desc->len), + le16_to_cpu(dma_desc->cmd)); desc += host->desc_sz; @@ -2852,6 +2880,16 @@ int sdhci_add_host(struct sdhci_host *host) host->flags &= ~SDHCI_USE_ADMA; } + /* + * It is assumed that a 64-bit capable device has set a 64-bit DMA mask + * and *must* do 64-bit DMA. A driver has the opportunity to change + * that during the first call to ->enable_dma(). Similarly + * SDHCI_QUIRK2_BROKEN_64_BIT_DMA must be left to the drivers to + * implement. + */ + if (sdhci_readl(host, SDHCI_CAPABILITIES) & SDHCI_CAN_64BIT) + host->flags |= SDHCI_USE_64_BIT_DMA; + if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) { if (host->ops->enable_dma) { if (host->ops->enable_dma(host)) { @@ -2863,6 +2901,10 @@ int sdhci_add_host(struct sdhci_host *host) } } + /* SDMA does not support 64-bit DMA */ + if (host->flags & SDHCI_USE_64_BIT_DMA) + host->flags &= ~SDHCI_USE_SDMA; + if (host->flags & SDHCI_USE_ADMA) { /* * The DMA descriptor table size is calculated as the maximum @@ -2870,13 +2912,23 @@ int sdhci_add_host(struct sdhci_host *host) * descriptor for each segment, plus 1 for a nop end descriptor, * all multipled by the descriptor size. */ - host->adma_table_sz = (SDHCI_MAX_SEGS * 2 + 1) * - SDHCI_ADMA2_32_DESC_SZ; - host->align_buffer_sz = SDHCI_MAX_SEGS * - SDHCI_ADMA2_32_ALIGN; - host->desc_sz = SDHCI_ADMA2_32_DESC_SZ; - host->align_sz = SDHCI_ADMA2_32_ALIGN; - host->align_mask = SDHCI_ADMA2_32_ALIGN - 1; + if (host->flags & SDHCI_USE_64_BIT_DMA) { + host->adma_table_sz = (SDHCI_MAX_SEGS * 2 + 1) * + SDHCI_ADMA2_64_DESC_SZ; + host->align_buffer_sz = SDHCI_MAX_SEGS * + SDHCI_ADMA2_64_ALIGN; + host->desc_sz = SDHCI_ADMA2_64_DESC_SZ; + host->align_sz = SDHCI_ADMA2_64_ALIGN; + host->align_mask = SDHCI_ADMA2_64_ALIGN - 1; + } else { + host->adma_table_sz = (SDHCI_MAX_SEGS * 2 + 1) * + SDHCI_ADMA2_32_DESC_SZ; + host->align_buffer_sz = SDHCI_MAX_SEGS * + SDHCI_ADMA2_32_ALIGN; + host->desc_sz = SDHCI_ADMA2_32_DESC_SZ; + host->align_sz = SDHCI_ADMA2_32_ALIGN; + host->align_mask = SDHCI_ADMA2_32_ALIGN - 1; + } host->adma_table = dma_alloc_coherent(mmc_dev(mmc), host->adma_table_sz, &host->adma_addr, @@ -3289,7 +3341,8 @@ int sdhci_add_host(struct sdhci_host *host) pr_info("%s: SDHCI controller on %s [%s] using %s\n", mmc_hostname(mmc), host->hw_name, dev_name(mmc_dev(mmc)), - (host->flags & SDHCI_USE_ADMA) ? "ADMA" : + (host->flags & SDHCI_USE_ADMA) ? + (host->flags & SDHCI_USE_64_BIT_DMA) ? "ADMA 64-bit" : "ADMA" : (host->flags & SDHCI_USE_SDMA) ? "DMA" : "PIO"); sdhci_enable_card_detection(host); diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index 14c8b6773dbb..c2ec7fcd8a1f 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h @@ -227,6 +227,7 @@ /* 55-57 reserved */ #define SDHCI_ADMA_ADDRESS 0x58 +#define SDHCI_ADMA_ADDRESS_HI 0x5C /* 60-FB reserved */ @@ -279,6 +280,23 @@ struct sdhci_adma2_32_desc { __le32 addr; } __packed __aligned(SDHCI_ADMA2_32_ALIGN); +/* ADMA2 64-bit DMA descriptor size */ +#define SDHCI_ADMA2_64_DESC_SZ 12 + +/* ADMA2 64-bit DMA alignment */ +#define SDHCI_ADMA2_64_ALIGN 8 + +/* + * ADMA2 64-bit descriptor. Note 12-byte descriptor can't always be 8-byte + * aligned. + */ +struct sdhci_adma2_64_desc { + __le16 cmd; + __le16 len; + __le32 addr_lo; + __le32 addr_hi; +} __packed __aligned(4); + #define ADMA2_TRAN_VALID 0x21 #define ADMA2_NOP_END_VALID 0x3 #define ADMA2_END 0x2 diff --git a/include/linux/mmc/sdhci.h b/include/linux/mmc/sdhci.h index 2a72e9510833..931ac5e05453 100644 --- a/include/linux/mmc/sdhci.h +++ b/include/linux/mmc/sdhci.h @@ -100,6 +100,8 @@ struct sdhci_host { #define SDHCI_QUIRK2_BROKEN_DDR50 (1<<7) /* Stop command (CMD12) can set Transfer Complete when not using MMC_RSP_BUSY */ #define SDHCI_QUIRK2_STOP_WITH_TC (1<<8) +/* Controller does not support 64-bit DMA */ +#define SDHCI_QUIRK2_BROKEN_64_BIT_DMA (1<<9) int irq; /* Device IRQ */ void __iomem *ioaddr; /* Mapped address */ @@ -130,6 +132,7 @@ struct sdhci_host { #define SDHCI_SDIO_IRQ_ENABLED (1<<9) /* SDIO irq enabled */ #define SDHCI_SDR104_NEEDS_TUNING (1<<10) /* SDR104/HS200 needs tuning */ #define SDHCI_USING_RETUNING_TIMER (1<<11) /* Host is using a retuning timer for the card */ +#define SDHCI_USE_64_BIT_DMA (1<<12) /* Use 64-bit DMA */ unsigned int version; /* SDHCI spec. version */ -- cgit v1.2.3 From a7975473cc41773d9f6d8ea72b48c7656e6cd0f6 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Fri, 26 Sep 2014 12:55:30 +0200 Subject: mfd: core: Add helper function to register hotplug devices Hot-pluggable multi-function devices should always be registered with PLATFORM_DEVID_AUTO to avoid name collisions on the platform bus. This helper also hides the memory map and irq parameters, which aren't used by hot-pluggable (e.g. USB-based) devices. Signed-off-by: Johan Hovold Signed-off-by: Lee Jones --- include/linux/mfd/core.h | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'include/linux') diff --git a/include/linux/mfd/core.h b/include/linux/mfd/core.h index 73e1709d4c09..a76bc100bf97 100644 --- a/include/linux/mfd/core.h +++ b/include/linux/mfd/core.h @@ -111,6 +111,13 @@ extern int mfd_add_devices(struct device *parent, int id, struct resource *mem_base, int irq_base, struct irq_domain *irq_domain); +static inline int mfd_add_hotplug_devices(struct device *parent, + const struct mfd_cell *cells, int n_devs) +{ + return mfd_add_devices(parent, PLATFORM_DEVID_AUTO, cells, n_devs, + NULL, 0, NULL); +} + extern void mfd_remove_devices(struct device *parent); #endif -- cgit v1.2.3 From 338a128142975439a19ab3c91480bc9d5a71f033 Mon Sep 17 00:00:00 2001 From: Octavian Purdila Date: Thu, 6 Nov 2014 15:48:03 +0200 Subject: mfd: Add support for Diolan DLN-2 devices This patch implements the USB part of the Diolan USB-I2C/SPI/GPIO Master Adapter DLN-2. Details about the device can be found here: https://www.diolan.com/i2c/i2c_interface.html. Information about the USB protocol can be found in the Programmer's Reference Manual [1], see section 1.7. Because the hardware has a single transmit endpoint and a single receive endpoint the communication between the various DLN2 drivers and the hardware will be muxed/demuxed by this driver. Each DLN2 module will be identified by the handle field within the DLN2 message header. If a DLN2 module issues multiple commands in parallel they will be identified by the echo counter field in the message header. The DLN2 modules can use the dln2_transfer() function to issue a command and wait for its response. They can also register a callback that is going to be called when a specific event id is generated by the device (e.g. GPIO interrupts). The device uses handle 0 for sending events. [1] https://www.diolan.com/downloads/dln-api-manual.pdf Signed-off-by: Octavian Purdila Reviewed-by: Johan Hovold Signed-off-by: Lee Jones --- drivers/mfd/Kconfig | 10 + drivers/mfd/Makefile | 1 + drivers/mfd/dln2.c | 763 +++++++++++++++++++++++++++++++++++++++++++++++ include/linux/mfd/dln2.h | 103 +++++++ 4 files changed, 877 insertions(+) create mode 100644 drivers/mfd/dln2.c create mode 100644 include/linux/mfd/dln2.h (limited to 'include/linux') diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 1456ea70bbc7..c1acc76a519f 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -183,6 +183,16 @@ config MFD_DA9063 Additional drivers must be enabled in order to use the functionality of the device. +config MFD_DLN2 + tristate "Diolan DLN2 support" + select MFD_CORE + depends on USB + help + This adds support for Diolan USB-I2C/SPI/GPIO Master Adapter + DLN-2. Additional drivers such as I2C_DLN2, GPIO_DLN2, + etc. must be enabled in order to use the functionality of + the device. + config MFD_MC13XXX tristate depends on (SPI_MASTER || I2C) diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 8bd54b1253af..10bbd0b9096b 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -174,6 +174,7 @@ obj-$(CONFIG_MFD_STW481X) += stw481x.o obj-$(CONFIG_MFD_IPAQ_MICRO) += ipaq-micro.o obj-$(CONFIG_MFD_MENF21BMC) += menf21bmc.o obj-$(CONFIG_MFD_HI6421_PMIC) += hi6421-pmic-core.o +obj-$(CONFIG_MFD_DLN2) += dln2.o intel-soc-pmic-objs := intel_soc_pmic_core.o intel_soc_pmic_crc.o obj-$(CONFIG_INTEL_SOC_PMIC) += intel-soc-pmic.o diff --git a/drivers/mfd/dln2.c b/drivers/mfd/dln2.c new file mode 100644 index 000000000000..9765a174d2c5 --- /dev/null +++ b/drivers/mfd/dln2.c @@ -0,0 +1,763 @@ +/* + * Driver for the Diolan DLN-2 USB adapter + * + * Copyright (c) 2014 Intel Corporation + * + * Derived from: + * i2c-diolan-u2c.c + * Copyright (c) 2010-2011 Ericsson AB + * + * 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, version 2. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct dln2_header { + __le16 size; + __le16 id; + __le16 echo; + __le16 handle; +}; + +struct dln2_response { + struct dln2_header hdr; + __le16 result; +}; + +#define DLN2_GENERIC_MODULE_ID 0x00 +#define DLN2_GENERIC_CMD(cmd) DLN2_CMD(cmd, DLN2_GENERIC_MODULE_ID) +#define CMD_GET_DEVICE_VER DLN2_GENERIC_CMD(0x30) +#define CMD_GET_DEVICE_SN DLN2_GENERIC_CMD(0x31) + +#define DLN2_HW_ID 0x200 +#define DLN2_USB_TIMEOUT 200 /* in ms */ +#define DLN2_MAX_RX_SLOTS 16 +#define DLN2_MAX_URBS 16 +#define DLN2_RX_BUF_SIZE 512 + +enum dln2_handle { + DLN2_HANDLE_EVENT = 0, /* don't change, hardware defined */ + DLN2_HANDLE_CTRL, + DLN2_HANDLE_GPIO, + DLN2_HANDLE_I2C, + DLN2_HANDLES +}; + +/* + * Receive context used between the receive demultiplexer and the transfer + * routine. While sending a request the transfer routine will look for a free + * receive context and use it to wait for a response and to receive the URB and + * thus the response data. + */ +struct dln2_rx_context { + /* completion used to wait for a response */ + struct completion done; + + /* if non-NULL the URB contains the response */ + struct urb *urb; + + /* if true then this context is used to wait for a response */ + bool in_use; +}; + +/* + * Receive contexts for a particular DLN2 module (i2c, gpio, etc.). We use the + * handle header field to identify the module in dln2_dev.mod_rx_slots and then + * the echo header field to index the slots field and find the receive context + * for a particular request. + */ +struct dln2_mod_rx_slots { + /* RX slots bitmap */ + DECLARE_BITMAP(bmap, DLN2_MAX_RX_SLOTS); + + /* used to wait for a free RX slot */ + wait_queue_head_t wq; + + /* used to wait for an RX operation to complete */ + struct dln2_rx_context slots[DLN2_MAX_RX_SLOTS]; + + /* avoid races between alloc/free_rx_slot and dln2_rx_transfer */ + spinlock_t lock; +}; + +struct dln2_dev { + struct usb_device *usb_dev; + struct usb_interface *interface; + u8 ep_in; + u8 ep_out; + + struct urb *rx_urb[DLN2_MAX_URBS]; + void *rx_buf[DLN2_MAX_URBS]; + + struct dln2_mod_rx_slots mod_rx_slots[DLN2_HANDLES]; + + struct list_head event_cb_list; + spinlock_t event_cb_lock; + + bool disconnect; + int active_transfers; + wait_queue_head_t disconnect_wq; + spinlock_t disconnect_lock; +}; + +struct dln2_event_cb_entry { + struct list_head list; + u16 id; + struct platform_device *pdev; + dln2_event_cb_t callback; +}; + +int dln2_register_event_cb(struct platform_device *pdev, u16 id, + dln2_event_cb_t event_cb) +{ + struct dln2_dev *dln2 = dev_get_drvdata(pdev->dev.parent); + struct dln2_event_cb_entry *i, *entry; + unsigned long flags; + int ret = 0; + + entry = kzalloc(sizeof(*entry), GFP_KERNEL); + if (!entry) + return -ENOMEM; + + entry->id = id; + entry->callback = event_cb; + entry->pdev = pdev; + + spin_lock_irqsave(&dln2->event_cb_lock, flags); + + list_for_each_entry(i, &dln2->event_cb_list, list) { + if (i->id == id) { + ret = -EBUSY; + break; + } + } + + if (!ret) + list_add_rcu(&entry->list, &dln2->event_cb_list); + + spin_unlock_irqrestore(&dln2->event_cb_lock, flags); + + if (ret) + kfree(entry); + + return ret; +} +EXPORT_SYMBOL(dln2_register_event_cb); + +void dln2_unregister_event_cb(struct platform_device *pdev, u16 id) +{ + struct dln2_dev *dln2 = dev_get_drvdata(pdev->dev.parent); + struct dln2_event_cb_entry *i; + unsigned long flags; + bool found = false; + + spin_lock_irqsave(&dln2->event_cb_lock, flags); + + list_for_each_entry(i, &dln2->event_cb_list, list) { + if (i->id == id) { + list_del_rcu(&i->list); + found = true; + break; + } + } + + spin_unlock_irqrestore(&dln2->event_cb_lock, flags); + + if (found) { + synchronize_rcu(); + kfree(i); + } +} +EXPORT_SYMBOL(dln2_unregister_event_cb); + +/* + * Returns true if a valid transfer slot is found. In this case the URB must not + * be resubmitted immediately in dln2_rx as we need the data when dln2_transfer + * is woke up. It will be resubmitted there. + */ +static bool dln2_transfer_complete(struct dln2_dev *dln2, struct urb *urb, + u16 handle, u16 rx_slot) +{ + struct device *dev = &dln2->interface->dev; + struct dln2_mod_rx_slots *rxs = &dln2->mod_rx_slots[handle]; + struct dln2_rx_context *rxc; + bool valid_slot = false; + + rxc = &rxs->slots[rx_slot]; + + /* + * No need to disable interrupts as this lock is not taken in interrupt + * context elsewhere in this driver. This function (or its callers) are + * also not exported to other modules. + */ + spin_lock(&rxs->lock); + if (rxc->in_use && !rxc->urb) { + rxc->urb = urb; + complete(&rxc->done); + valid_slot = true; + } + spin_unlock(&rxs->lock); + + if (!valid_slot) + dev_warn(dev, "bad/late response %d/%d\n", handle, rx_slot); + + return valid_slot; +} + +static void dln2_run_event_callbacks(struct dln2_dev *dln2, u16 id, u16 echo, + void *data, int len) +{ + struct dln2_event_cb_entry *i; + + rcu_read_lock(); + + list_for_each_entry_rcu(i, &dln2->event_cb_list, list) { + if (i->id == id) { + i->callback(i->pdev, echo, data, len); + break; + } + } + + rcu_read_unlock(); +} + +static void dln2_rx(struct urb *urb) +{ + struct dln2_dev *dln2 = urb->context; + struct dln2_header *hdr = urb->transfer_buffer; + struct device *dev = &dln2->interface->dev; + u16 id, echo, handle, size; + u8 *data; + int len; + int err; + + switch (urb->status) { + case 0: + /* success */ + break; + case -ECONNRESET: + case -ENOENT: + case -ESHUTDOWN: + case -EPIPE: + /* this urb is terminated, clean up */ + dev_dbg(dev, "urb shutting down with status %d\n", urb->status); + return; + default: + dev_dbg(dev, "nonzero urb status received %d\n", urb->status); + goto out; + } + + if (urb->actual_length < sizeof(struct dln2_header)) { + dev_err(dev, "short response: %d\n", urb->actual_length); + goto out; + } + + handle = le16_to_cpu(hdr->handle); + id = le16_to_cpu(hdr->id); + echo = le16_to_cpu(hdr->echo); + size = le16_to_cpu(hdr->size); + + if (size != urb->actual_length) { + dev_err(dev, "size mismatch: handle %x cmd %x echo %x size %d actual %d\n", + handle, id, echo, size, urb->actual_length); + goto out; + } + + if (handle >= DLN2_HANDLES) { + dev_warn(dev, "invalid handle %d\n", handle); + goto out; + } + + data = urb->transfer_buffer + sizeof(struct dln2_header); + len = urb->actual_length - sizeof(struct dln2_header); + + if (handle == DLN2_HANDLE_EVENT) { + dln2_run_event_callbacks(dln2, id, echo, data, len); + } else { + /* URB will be re-submitted in _dln2_transfer (free_rx_slot) */ + if (dln2_transfer_complete(dln2, urb, handle, echo)) + return; + } + +out: + err = usb_submit_urb(urb, GFP_ATOMIC); + if (err < 0) + dev_err(dev, "failed to resubmit RX URB: %d\n", err); +} + +static void *dln2_prep_buf(u16 handle, u16 cmd, u16 echo, const void *obuf, + int *obuf_len, gfp_t gfp) +{ + int len; + void *buf; + struct dln2_header *hdr; + + len = *obuf_len + sizeof(*hdr); + buf = kmalloc(len, gfp); + if (!buf) + return NULL; + + hdr = (struct dln2_header *)buf; + hdr->id = cpu_to_le16(cmd); + hdr->size = cpu_to_le16(len); + hdr->echo = cpu_to_le16(echo); + hdr->handle = cpu_to_le16(handle); + + memcpy(buf + sizeof(*hdr), obuf, *obuf_len); + + *obuf_len = len; + + return buf; +} + +static int dln2_send_wait(struct dln2_dev *dln2, u16 handle, u16 cmd, u16 echo, + const void *obuf, int obuf_len) +{ + int ret = 0; + int len = obuf_len; + void *buf; + int actual; + + buf = dln2_prep_buf(handle, cmd, echo, obuf, &len, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + ret = usb_bulk_msg(dln2->usb_dev, + usb_sndbulkpipe(dln2->usb_dev, dln2->ep_out), + buf, len, &actual, DLN2_USB_TIMEOUT); + + kfree(buf); + + return ret; +} + +static bool find_free_slot(struct dln2_dev *dln2, u16 handle, int *slot) +{ + struct dln2_mod_rx_slots *rxs; + unsigned long flags; + + if (dln2->disconnect) { + *slot = -ENODEV; + return true; + } + + rxs = &dln2->mod_rx_slots[handle]; + + spin_lock_irqsave(&rxs->lock, flags); + + *slot = find_first_zero_bit(rxs->bmap, DLN2_MAX_RX_SLOTS); + + if (*slot < DLN2_MAX_RX_SLOTS) { + struct dln2_rx_context *rxc = &rxs->slots[*slot]; + + set_bit(*slot, rxs->bmap); + rxc->in_use = true; + } + + spin_unlock_irqrestore(&rxs->lock, flags); + + return *slot < DLN2_MAX_RX_SLOTS; +} + +static int alloc_rx_slot(struct dln2_dev *dln2, u16 handle) +{ + int ret; + int slot; + + /* + * No need to timeout here, the wait is bounded by the timeout in + * _dln2_transfer. + */ + ret = wait_event_interruptible(dln2->mod_rx_slots[handle].wq, + find_free_slot(dln2, handle, &slot)); + if (ret < 0) + return ret; + + return slot; +} + +static void free_rx_slot(struct dln2_dev *dln2, u16 handle, int slot) +{ + struct dln2_mod_rx_slots *rxs; + struct urb *urb = NULL; + unsigned long flags; + struct dln2_rx_context *rxc; + + rxs = &dln2->mod_rx_slots[handle]; + + spin_lock_irqsave(&rxs->lock, flags); + + clear_bit(slot, rxs->bmap); + + rxc = &rxs->slots[slot]; + rxc->in_use = false; + urb = rxc->urb; + rxc->urb = NULL; + reinit_completion(&rxc->done); + + spin_unlock_irqrestore(&rxs->lock, flags); + + if (urb) { + int err; + struct device *dev = &dln2->interface->dev; + + err = usb_submit_urb(urb, GFP_KERNEL); + if (err < 0) + dev_err(dev, "failed to resubmit RX URB: %d\n", err); + } + + wake_up_interruptible(&rxs->wq); +} + +static int _dln2_transfer(struct dln2_dev *dln2, u16 handle, u16 cmd, + const void *obuf, unsigned obuf_len, + void *ibuf, unsigned *ibuf_len) +{ + int ret = 0; + int rx_slot; + struct dln2_response *rsp; + struct dln2_rx_context *rxc; + struct device *dev = &dln2->interface->dev; + const unsigned long timeout = DLN2_USB_TIMEOUT * HZ / 1000; + struct dln2_mod_rx_slots *rxs = &dln2->mod_rx_slots[handle]; + + spin_lock(&dln2->disconnect_lock); + if (!dln2->disconnect) + dln2->active_transfers++; + else + ret = -ENODEV; + spin_unlock(&dln2->disconnect_lock); + + if (ret) + return ret; + + rx_slot = alloc_rx_slot(dln2, handle); + if (rx_slot < 0) { + ret = rx_slot; + goto out_decr; + } + + ret = dln2_send_wait(dln2, handle, cmd, rx_slot, obuf, obuf_len); + if (ret < 0) { + dev_err(dev, "USB write failed: %d\n", ret); + goto out_free_rx_slot; + } + + rxc = &rxs->slots[rx_slot]; + + ret = wait_for_completion_interruptible_timeout(&rxc->done, timeout); + if (ret <= 0) { + if (!ret) + ret = -ETIMEDOUT; + goto out_free_rx_slot; + } + + if (dln2->disconnect) { + ret = -ENODEV; + goto out_free_rx_slot; + } + + /* if we got here we know that the response header has been checked */ + rsp = rxc->urb->transfer_buffer; + + if (rsp->hdr.size < sizeof(*rsp)) { + ret = -EPROTO; + goto out_free_rx_slot; + } + + if (le16_to_cpu(rsp->result) > 0x80) { + dev_dbg(dev, "%d received response with error %d\n", + handle, le16_to_cpu(rsp->result)); + ret = -EREMOTEIO; + goto out_free_rx_slot; + } + + if (!ibuf) { + ret = 0; + goto out_free_rx_slot; + } + + if (*ibuf_len > rsp->hdr.size - sizeof(*rsp)) + *ibuf_len = rsp->hdr.size - sizeof(*rsp); + + memcpy(ibuf, rsp + 1, *ibuf_len); + +out_free_rx_slot: + free_rx_slot(dln2, handle, rx_slot); +out_decr: + spin_lock(&dln2->disconnect_lock); + dln2->active_transfers--; + spin_unlock(&dln2->disconnect_lock); + if (dln2->disconnect) + wake_up(&dln2->disconnect_wq); + + return ret; +} + +int dln2_transfer(struct platform_device *pdev, u16 cmd, + const void *obuf, unsigned obuf_len, + void *ibuf, unsigned *ibuf_len) +{ + struct dln2_platform_data *dln2_pdata; + struct dln2_dev *dln2; + u16 handle; + + dln2 = dev_get_drvdata(pdev->dev.parent); + dln2_pdata = dev_get_platdata(&pdev->dev); + handle = dln2_pdata->handle; + + return _dln2_transfer(dln2, handle, cmd, obuf, obuf_len, ibuf, + ibuf_len); +} +EXPORT_SYMBOL(dln2_transfer); + +static int dln2_check_hw(struct dln2_dev *dln2) +{ + int ret; + __le32 hw_type; + int len = sizeof(hw_type); + + ret = _dln2_transfer(dln2, DLN2_HANDLE_CTRL, CMD_GET_DEVICE_VER, + NULL, 0, &hw_type, &len); + if (ret < 0) + return ret; + if (len < sizeof(hw_type)) + return -EREMOTEIO; + + if (le32_to_cpu(hw_type) != DLN2_HW_ID) { + dev_err(&dln2->interface->dev, "Device ID 0x%x not supported\n", + le32_to_cpu(hw_type)); + return -ENODEV; + } + + return 0; +} + +static int dln2_print_serialno(struct dln2_dev *dln2) +{ + int ret; + __le32 serial_no; + int len = sizeof(serial_no); + struct device *dev = &dln2->interface->dev; + + ret = _dln2_transfer(dln2, DLN2_HANDLE_CTRL, CMD_GET_DEVICE_SN, NULL, 0, + &serial_no, &len); + if (ret < 0) + return ret; + if (len < sizeof(serial_no)) + return -EREMOTEIO; + + dev_info(dev, "Diolan DLN2 serial %u\n", le32_to_cpu(serial_no)); + + return 0; +} + +static int dln2_hw_init(struct dln2_dev *dln2) +{ + int ret; + + ret = dln2_check_hw(dln2); + if (ret < 0) + return ret; + + return dln2_print_serialno(dln2); +} + +static void dln2_free_rx_urbs(struct dln2_dev *dln2) +{ + int i; + + for (i = 0; i < DLN2_MAX_URBS; i++) { + usb_kill_urb(dln2->rx_urb[i]); + usb_free_urb(dln2->rx_urb[i]); + kfree(dln2->rx_buf[i]); + } +} + +static void dln2_free(struct dln2_dev *dln2) +{ + dln2_free_rx_urbs(dln2); + usb_put_dev(dln2->usb_dev); + kfree(dln2); +} + +static int dln2_setup_rx_urbs(struct dln2_dev *dln2, + struct usb_host_interface *hostif) +{ + int i; + int ret; + const int rx_max_size = DLN2_RX_BUF_SIZE; + struct device *dev = &dln2->interface->dev; + + for (i = 0; i < DLN2_MAX_URBS; i++) { + dln2->rx_buf[i] = kmalloc(rx_max_size, GFP_KERNEL); + if (!dln2->rx_buf[i]) + return -ENOMEM; + + dln2->rx_urb[i] = usb_alloc_urb(0, GFP_KERNEL); + if (!dln2->rx_urb[i]) + return -ENOMEM; + + usb_fill_bulk_urb(dln2->rx_urb[i], dln2->usb_dev, + usb_rcvbulkpipe(dln2->usb_dev, dln2->ep_in), + dln2->rx_buf[i], rx_max_size, dln2_rx, dln2); + + ret = usb_submit_urb(dln2->rx_urb[i], GFP_KERNEL); + if (ret < 0) { + dev_err(dev, "failed to submit RX URB: %d\n", ret); + return ret; + } + } + + return 0; +} + +static struct dln2_platform_data dln2_pdata_gpio = { + .handle = DLN2_HANDLE_GPIO, +}; + +/* Only one I2C port seems to be supported on current hardware */ +static struct dln2_platform_data dln2_pdata_i2c = { + .handle = DLN2_HANDLE_I2C, + .port = 0, +}; + +static const struct mfd_cell dln2_devs[] = { + { + .name = "dln2-gpio", + .platform_data = &dln2_pdata_gpio, + .pdata_size = sizeof(struct dln2_platform_data), + }, + { + .name = "dln2-i2c", + .platform_data = &dln2_pdata_i2c, + .pdata_size = sizeof(struct dln2_platform_data), + }, +}; + +static void dln2_disconnect(struct usb_interface *interface) +{ + struct dln2_dev *dln2 = usb_get_intfdata(interface); + int i, j; + + /* don't allow starting new transfers */ + spin_lock(&dln2->disconnect_lock); + dln2->disconnect = true; + spin_unlock(&dln2->disconnect_lock); + + /* cancel in progress transfers */ + for (i = 0; i < DLN2_HANDLES; i++) { + struct dln2_mod_rx_slots *rxs = &dln2->mod_rx_slots[i]; + unsigned long flags; + + spin_lock_irqsave(&rxs->lock, flags); + + /* cancel all response waiters */ + for (j = 0; j < DLN2_MAX_RX_SLOTS; j++) { + struct dln2_rx_context *rxc = &rxs->slots[j]; + + if (rxc->in_use) + complete(&rxc->done); + } + + spin_unlock_irqrestore(&rxs->lock, flags); + } + + /* wait for transfers to end */ + wait_event(dln2->disconnect_wq, !dln2->active_transfers); + + mfd_remove_devices(&interface->dev); + + dln2_free(dln2); +} + +static int dln2_probe(struct usb_interface *interface, + const struct usb_device_id *usb_id) +{ + struct usb_host_interface *hostif = interface->cur_altsetting; + struct device *dev = &interface->dev; + struct dln2_dev *dln2; + int ret; + int i, j; + + if (hostif->desc.bInterfaceNumber != 0 || + hostif->desc.bNumEndpoints < 2) + return -ENODEV; + + dln2 = kzalloc(sizeof(*dln2), GFP_KERNEL); + if (!dln2) + return -ENOMEM; + + dln2->ep_out = hostif->endpoint[0].desc.bEndpointAddress; + dln2->ep_in = hostif->endpoint[1].desc.bEndpointAddress; + dln2->usb_dev = usb_get_dev(interface_to_usbdev(interface)); + dln2->interface = interface; + usb_set_intfdata(interface, dln2); + init_waitqueue_head(&dln2->disconnect_wq); + + for (i = 0; i < DLN2_HANDLES; i++) { + init_waitqueue_head(&dln2->mod_rx_slots[i].wq); + spin_lock_init(&dln2->mod_rx_slots[i].lock); + for (j = 0; j < DLN2_MAX_RX_SLOTS; j++) + init_completion(&dln2->mod_rx_slots[i].slots[j].done); + } + + spin_lock_init(&dln2->event_cb_lock); + spin_lock_init(&dln2->disconnect_lock); + INIT_LIST_HEAD(&dln2->event_cb_list); + + ret = dln2_setup_rx_urbs(dln2, hostif); + if (ret) + goto out_cleanup; + + ret = dln2_hw_init(dln2); + if (ret < 0) { + dev_err(dev, "failed to initialize hardware\n"); + goto out_cleanup; + } + + ret = mfd_add_hotplug_devices(dev, dln2_devs, ARRAY_SIZE(dln2_devs)); + if (ret != 0) { + dev_err(dev, "failed to add mfd devices to core\n"); + goto out_cleanup; + } + + return 0; + +out_cleanup: + dln2_free(dln2); + + return ret; +} + +static const struct usb_device_id dln2_table[] = { + { USB_DEVICE(0xa257, 0x2013) }, + { } +}; + +MODULE_DEVICE_TABLE(usb, dln2_table); + +static struct usb_driver dln2_driver = { + .name = "dln2", + .probe = dln2_probe, + .disconnect = dln2_disconnect, + .id_table = dln2_table, +}; + +module_usb_driver(dln2_driver); + +MODULE_AUTHOR("Octavian Purdila "); +MODULE_DESCRIPTION("Core driver for the Diolan DLN2 interface adapter"); +MODULE_LICENSE("GPL v2"); diff --git a/include/linux/mfd/dln2.h b/include/linux/mfd/dln2.h new file mode 100644 index 000000000000..004b24576da8 --- /dev/null +++ b/include/linux/mfd/dln2.h @@ -0,0 +1,103 @@ +#ifndef __LINUX_USB_DLN2_H +#define __LINUX_USB_DLN2_H + +#define DLN2_CMD(cmd, id) ((cmd) | ((id) << 8)) + +struct dln2_platform_data { + u16 handle; /* sub-driver handle (internally used only) */ + u8 port; /* I2C/SPI port */ +}; + +/** + * dln2_event_cb_t - event callback function signature + * + * @pdev - the sub-device that registered this callback + * @echo - the echo header field received in the message + * @data - the data payload + * @len - the data payload length + * + * The callback function is called in interrupt context and the data payload is + * only valid during the call. If the user needs later access of the data, it + * must copy it. + */ + +typedef void (*dln2_event_cb_t)(struct platform_device *pdev, u16 echo, + const void *data, int len); + +/** + * dl2n_register_event_cb - register a callback function for an event + * + * @pdev - the sub-device that registers the callback + * @event - the event for which to register a callback + * @event_cb - the callback function + * + * @return 0 in case of success, negative value in case of error + */ +int dln2_register_event_cb(struct platform_device *pdev, u16 event, + dln2_event_cb_t event_cb); + +/** + * dln2_unregister_event_cb - unregister the callback function for an event + * + * @pdev - the sub-device that registered the callback + * @event - the event for which to register a callback + */ +void dln2_unregister_event_cb(struct platform_device *pdev, u16 event); + +/** + * dln2_transfer - issue a DLN2 command and wait for a response and the + * associated data + * + * @pdev - the sub-device which is issuing this transfer + * @cmd - the command to be sent to the device + * @obuf - the buffer to be sent to the device; it can be NULL if the user + * doesn't need to transmit data with this command + * @obuf_len - the size of the buffer to be sent to the device + * @ibuf - any data associated with the response will be copied here; it can be + * NULL if the user doesn't need the response data + * @ibuf_len - must be initialized to the input buffer size; it will be modified + * to indicate the actual data transferred; + * + * @return 0 for success, negative value for errors + */ +int dln2_transfer(struct platform_device *pdev, u16 cmd, + const void *obuf, unsigned obuf_len, + void *ibuf, unsigned *ibuf_len); + +/** + * dln2_transfer_rx - variant of @dln2_transfer() where TX buffer is not needed + * + * @pdev - the sub-device which is issuing this transfer + * @cmd - the command to be sent to the device + * @ibuf - any data associated with the response will be copied here; it can be + * NULL if the user doesn't need the response data + * @ibuf_len - must be initialized to the input buffer size; it will be modified + * to indicate the actual data transferred; + * + * @return 0 for success, negative value for errors + */ + +static inline int dln2_transfer_rx(struct platform_device *pdev, u16 cmd, + void *ibuf, unsigned *ibuf_len) +{ + return dln2_transfer(pdev, cmd, NULL, 0, ibuf, ibuf_len); +} + +/** + * dln2_transfer_tx - variant of @dln2_transfer() where RX buffer is not needed + * + * @pdev - the sub-device which is issuing this transfer + * @cmd - the command to be sent to the device + * @obuf - the buffer to be sent to the device; it can be NULL if the + * user doesn't need to transmit data with this command + * @obuf_len - the size of the buffer to be sent to the device + * + * @return 0 for success, negative value for errors + */ +static inline int dln2_transfer_tx(struct platform_device *pdev, u16 cmd, + const void *obuf, unsigned obuf_len) +{ + return dln2_transfer(pdev, cmd, obuf, obuf_len, NULL, NULL); +} + +#endif -- cgit v1.2.3 From 7aff221c5dbe4f88930a64531df2236f303e1851 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Sat, 8 Nov 2014 10:42:46 +1100 Subject: ARM: OMAP: serial: remove last vestige of DTR_gpio support. These fields were added by: commit 9574f36fb801035f6ab0fbb1b53ce2c12c17d100 OMAP/serial: Add support for driving a GPIO as DTR. but not removed by commit 985bfd54c826c0ba873ca0adfd5589263e0c6ee2 tty: serial: omap: remove some dead code which reverted most of that commit. Time to revert the rest. Signed-off-by: NeilBrown Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/serial.c | 3 --- include/linux/platform_data/serial-omap.h | 3 --- 2 files changed, 6 deletions(-) (limited to 'include/linux') diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c index a388f8c1bcb3..57dee0c7cd2b 100644 --- a/arch/arm/mach-omap2/serial.c +++ b/arch/arm/mach-omap2/serial.c @@ -263,9 +263,6 @@ void __init omap_serial_init_port(struct omap_board_data *bdata, omap_up.dma_rx_timeout = info->dma_rx_timeout; omap_up.dma_rx_poll_rate = info->dma_rx_poll_rate; omap_up.autosuspend_timeout = info->autosuspend_timeout; - omap_up.DTR_gpio = info->DTR_gpio; - omap_up.DTR_inverted = info->DTR_inverted; - omap_up.DTR_present = info->DTR_present; pdata = &omap_up; pdata_size = sizeof(struct omap_uart_port_info); diff --git a/include/linux/platform_data/serial-omap.h b/include/linux/platform_data/serial-omap.h index c860c1b314c0..d09275f3cde3 100644 --- a/include/linux/platform_data/serial-omap.h +++ b/include/linux/platform_data/serial-omap.h @@ -38,9 +38,6 @@ struct omap_uart_port_info { unsigned int dma_rx_timeout; unsigned int autosuspend_timeout; unsigned int dma_rx_poll_rate; - int DTR_gpio; - int DTR_inverted; - int DTR_present; int (*get_context_loss_count)(struct device *); void (*enable_wakeup)(struct device *, bool); -- cgit v1.2.3 From 205fb5f5ba1d8edcf18009998ed05b80b7d186af Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 30 Oct 2014 14:45:11 +0100 Subject: blk-mq: add blk_mq_unique_tag() The queuecommand() callback functions in SCSI low-level drivers need to know which hardware context has been selected by the block layer. Since this information is not available in the request structure, and since passing the hctx pointer directly to the queuecommand callback function would require modification of all SCSI LLDs, add a function to the block layer that allows to query the hardware context index. Signed-off-by: Bart Van Assche Acked-by: Jens Axboe Reviewed-by: Sagi Grimberg Reviewed-by: Martin K. Petersen Signed-off-by: Christoph Hellwig --- block/blk-mq-tag.c | 28 ++++++++++++++++++++++++++++ block/blk-mq.c | 2 ++ include/linux/blk-mq.h | 17 +++++++++++++++++ 3 files changed, 47 insertions(+) (limited to 'include/linux') diff --git a/block/blk-mq-tag.c b/block/blk-mq-tag.c index 8317175a3009..728b9a4d5f56 100644 --- a/block/blk-mq-tag.c +++ b/block/blk-mq-tag.c @@ -584,6 +584,34 @@ int blk_mq_tag_update_depth(struct blk_mq_tags *tags, unsigned int tdepth) return 0; } +/** + * blk_mq_unique_tag() - return a tag that is unique queue-wide + * @rq: request for which to compute a unique tag + * + * The tag field in struct request is unique per hardware queue but not over + * all hardware queues. Hence this function that returns a tag with the + * hardware context index in the upper bits and the per hardware queue tag in + * the lower bits. + * + * Note: When called for a request that is queued on a non-multiqueue request + * queue, the hardware context index is set to zero. + */ +u32 blk_mq_unique_tag(struct request *rq) +{ + struct request_queue *q = rq->q; + struct blk_mq_hw_ctx *hctx; + int hwq = 0; + + if (q->mq_ops) { + hctx = q->mq_ops->map_queue(q, rq->mq_ctx->cpu); + hwq = hctx->queue_num; + } + + return (hwq << BLK_MQ_UNIQUE_TAG_BITS) | + (rq->tag & BLK_MQ_UNIQUE_TAG_MASK); +} +EXPORT_SYMBOL(blk_mq_unique_tag); + ssize_t blk_mq_tag_sysfs_show(struct blk_mq_tags *tags, char *page) { char *orig_page = page; diff --git a/block/blk-mq.c b/block/blk-mq.c index 68929bad9a6a..b5896d436fc9 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c @@ -2024,6 +2024,8 @@ static int blk_mq_alloc_rq_maps(struct blk_mq_tag_set *set) */ int blk_mq_alloc_tag_set(struct blk_mq_tag_set *set) { + BUILD_BUG_ON(BLK_MQ_MAX_DEPTH > 1 << BLK_MQ_UNIQUE_TAG_BITS); + if (!set->nr_hw_queues) return -EINVAL; if (!set->queue_depth) diff --git a/include/linux/blk-mq.h b/include/linux/blk-mq.h index c9be1589415a..15f7034aa377 100644 --- a/include/linux/blk-mq.h +++ b/include/linux/blk-mq.h @@ -167,6 +167,23 @@ struct request *blk_mq_alloc_request(struct request_queue *q, int rw, gfp_t gfp, bool reserved); struct request *blk_mq_tag_to_rq(struct blk_mq_tags *tags, unsigned int tag); +enum { + BLK_MQ_UNIQUE_TAG_BITS = 16, + BLK_MQ_UNIQUE_TAG_MASK = (1 << BLK_MQ_UNIQUE_TAG_BITS) - 1, +}; + +u32 blk_mq_unique_tag(struct request *rq); + +static inline u16 blk_mq_unique_tag_to_hwq(u32 unique_tag) +{ + return unique_tag >> BLK_MQ_UNIQUE_TAG_BITS; +} + +static inline u16 blk_mq_unique_tag_to_tag(u32 unique_tag) +{ + return unique_tag & BLK_MQ_UNIQUE_TAG_MASK; +} + struct blk_mq_hw_ctx *blk_mq_map_queue(struct request_queue *, const int ctx_index); struct blk_mq_hw_ctx *blk_mq_alloc_single_hw_queue(struct blk_mq_tag_set *, unsigned int, int); -- cgit v1.2.3 From 125c99bc8b6b108d251169a86324a7ed3c6f3cce Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 3 Nov 2014 12:47:47 +0100 Subject: scsi: add new scsi-command flag for tagged commands Currently scsi piggy backs on the block layer to define the concept of a tagged command. But we want to be able to have block-level host-wide tags assigned even for untagged commands like the initial INQUIRY, so add a new SCSI-level flag for commands that are tagged at the scsi level, so that even commands without that set can have tags assigned to them. Note that this alredy is the case for the blk-mq code path, and this just lets the old path catch up with it. We also set this flag based upon sdev->simple_tags instead of the block queue flag, so that it is entirely independent of the block layer tagging, and thus always correct even if a driver doesn't use block level tagging yet. Also remove the old blk_rq_tagged; it was only used by SCSI drivers, and removing it forces them to look for the proper replacement. Signed-off-by: Christoph Hellwig Reviewed-by: Mike Christie Reviewed-by: Martin K. Petersen Reviewed-by: Hannes Reinecke --- Documentation/block/biodoc.txt | 4 ---- block/blk-core.c | 4 ++-- drivers/scsi/53c700.c | 6 +++--- drivers/scsi/aic7xxx/aic7xxx_osm.c | 2 +- drivers/scsi/scsi_lib.c | 13 +++++++++---- drivers/usb/storage/uas.c | 2 +- include/linux/blkdev.h | 1 - include/scsi/scsi_cmnd.h | 4 ++++ include/scsi/scsi_tcq.h | 6 ++---- 9 files changed, 22 insertions(+), 20 deletions(-) (limited to 'include/linux') diff --git a/Documentation/block/biodoc.txt b/Documentation/block/biodoc.txt index 2101e718670d..6b972b287795 100644 --- a/Documentation/block/biodoc.txt +++ b/Documentation/block/biodoc.txt @@ -827,10 +827,6 @@ but in the event of any barrier requests in the tag queue we need to ensure that requests are restarted in the order they were queue. This may happen if the driver needs to use blk_queue_invalidate_tags(). -Tagging also defines a new request flag, REQ_QUEUED. This is set whenever -a request is currently tagged. You should not use this flag directly, -blk_rq_tagged(rq) is the portable way to do so. - 3.3 I/O Submission The routine submit_bio() is used to submit a single io. Higher level i/o diff --git a/block/blk-core.c b/block/blk-core.c index 0421b53e6431..2e7424b42947 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -1266,7 +1266,7 @@ void blk_requeue_request(struct request_queue *q, struct request *rq) blk_clear_rq_complete(rq); trace_block_rq_requeue(q, rq); - if (blk_rq_tagged(rq)) + if (rq->cmd_flags & REQ_QUEUED) blk_queue_end_tag(q, rq); BUG_ON(blk_queued_rq(rq)); @@ -2554,7 +2554,7 @@ EXPORT_SYMBOL_GPL(blk_unprep_request); */ void blk_finish_request(struct request *req, int error) { - if (blk_rq_tagged(req)) + if (req->cmd_flags & REQ_QUEUED) blk_queue_end_tag(req->q, req); BUG_ON(blk_queued_rq(req)); diff --git a/drivers/scsi/53c700.c b/drivers/scsi/53c700.c index 474cc6dc98e2..5143d3213e86 100644 --- a/drivers/scsi/53c700.c +++ b/drivers/scsi/53c700.c @@ -1767,7 +1767,7 @@ NCR_700_queuecommand_lck(struct scsi_cmnd *SCp, void (*done)(struct scsi_cmnd *) */ if(NCR_700_get_depth(SCp->device) != 0 && (!(hostdata->tag_negotiated & (1<request))) { + || !(SCp->flags & SCMD_TAGGED))) { CDEBUG(KERN_ERR, SCp, "has non zero depth %d\n", NCR_700_get_depth(SCp->device)); return SCSI_MLQUEUE_DEVICE_BUSY; @@ -1795,7 +1795,7 @@ NCR_700_queuecommand_lck(struct scsi_cmnd *SCp, void (*done)(struct scsi_cmnd *) printk("53c700: scsi%d, command ", SCp->device->host->host_no); scsi_print_command(SCp); #endif - if(blk_rq_tagged(SCp->request) + if ((SCp->flags & SCMD_TAGGED) && (hostdata->tag_negotiated &(1<device) == NCR_700_START_TAG_NEGOTIATION) { scmd_printk(KERN_ERR, SCp, "Enabling Tag Command Queuing\n"); @@ -1809,7 +1809,7 @@ NCR_700_queuecommand_lck(struct scsi_cmnd *SCp, void (*done)(struct scsi_cmnd *) * * FIXME: This will royally screw up on multiple LUN devices * */ - if(!blk_rq_tagged(SCp->request) + if (!(SCp->flags & SCMD_TAGGED) && (hostdata->tag_negotiated &(1<tag_negotiated &= ~(1<request) + if (!(cmd->flags & SCMD_TAGGED) && (ahc->features & AHC_SCB_BTT) == 0) { int target_offset; diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 38f8c85957b6..994eb083fff9 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -1740,7 +1740,7 @@ static void scsi_request_fn(struct request_queue *q) * we add the dev to the starved list so it eventually gets * a run when a tag is freed. */ - if (blk_queue_tagged(q) && !blk_rq_tagged(req)) { + if (blk_queue_tagged(q) && !(req->cmd_flags & REQ_QUEUED)) { spin_lock_irq(shost->host_lock); if (list_empty(&sdev->starved_entry)) list_add_tail(&sdev->starved_entry, @@ -1754,6 +1754,11 @@ static void scsi_request_fn(struct request_queue *q) if (!scsi_host_queue_ready(q, shost, sdev)) goto host_not_ready; + + if (sdev->simple_tags) + cmd->flags |= SCMD_TAGGED; + else + cmd->flags &= ~SCMD_TAGGED; /* * Finally, initialize any error handling parameters, and set up @@ -1908,10 +1913,10 @@ static int scsi_queue_rq(struct blk_mq_hw_ctx *hctx, struct request *req, blk_mq_start_request(req); } - if (blk_queue_tagged(q)) - req->cmd_flags |= REQ_QUEUED; + if (sdev->simple_tags) + cmd->flags |= SCMD_TAGGED; else - req->cmd_flags &= ~REQ_QUEUED; + cmd->flags &= ~SCMD_TAGGED; scsi_init_cmd_errh(cmd); cmd->scsi_done = scsi_mq_done; diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c index 89b24349269e..b38bc1318a60 100644 --- a/drivers/usb/storage/uas.c +++ b/drivers/usb/storage/uas.c @@ -181,7 +181,7 @@ static int uas_get_tag(struct scsi_cmnd *cmnd) { int tag; - if (blk_rq_tagged(cmnd->request)) + if (cmnd->flags & SCMD_TAGGED) tag = cmnd->request->tag + 2; else tag = 1; diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index aac0f9ea952a..6d76b8b4aa2b 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -1136,7 +1136,6 @@ static inline bool blk_needs_flush_plug(struct task_struct *tsk) /* * tag stuff */ -#define blk_rq_tagged(rq) ((rq)->cmd_flags & REQ_QUEUED) extern int blk_queue_start_tag(struct request_queue *, struct request *); extern struct request *blk_queue_find_tag(struct request_queue *, int); extern void blk_queue_end_tag(struct request_queue *, struct request *); diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h index 522a5f27f553..e119142e565e 100644 --- a/include/scsi/scsi_cmnd.h +++ b/include/scsi/scsi_cmnd.h @@ -53,6 +53,9 @@ struct scsi_pointer { volatile int phase; }; +/* for scmd->flags */ +#define SCMD_TAGGED (1 << 0) + struct scsi_cmnd { struct scsi_device *device; struct list_head list; /* scsi_cmnd participates in queue lists */ @@ -132,6 +135,7 @@ struct scsi_cmnd { * to be at an address < 16Mb). */ int result; /* Status code from lower level driver */ + int flags; /* Command flags */ unsigned char tag; /* SCSI-II queued command tag */ }; diff --git a/include/scsi/scsi_tcq.h b/include/scsi/scsi_tcq.h index 1712dab6e00e..032df74b66d7 100644 --- a/include/scsi/scsi_tcq.h +++ b/include/scsi/scsi_tcq.h @@ -101,11 +101,9 @@ static inline void scsi_deactivate_tcq(struct scsi_device *sdev, int depth) **/ static inline int scsi_populate_tag_msg(struct scsi_cmnd *cmd, char *msg) { - struct request *req = cmd->request; - - if (blk_rq_tagged(req)) { + if (cmd->flags & SCMD_TAGGED) { *msg++ = MSG_SIMPLE_TAG; - *msg++ = req->tag; + *msg++ = cmd->request->tag; return 2; } -- cgit v1.2.3 From d539efa37f1f789339699c941e72e320d12d5f28 Mon Sep 17 00:00:00 2001 From: Tero Kristo Date: Fri, 3 Oct 2014 16:57:11 +0300 Subject: ARM: OMAP3: clock: add new rate changing logic support for noncore DPLLs Currently, DPLL code hides the re-parenting within its internals, which is wrong. This needs to be exposed to the common clock code via determine_rate and set_rate_and_parent APIs. This patch adds support for these, which will be taken into use in the following patches. Signed-off-by: Tero Kristo Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/dpll3xxx.c | 147 +++++++++++++++++++++++++++++++++++++++++ include/linux/clk/ti.h | 9 +++ 2 files changed, 156 insertions(+) (limited to 'include/linux') diff --git a/arch/arm/mach-omap2/dpll3xxx.c b/arch/arm/mach-omap2/dpll3xxx.c index ac3d789ac3cd..cfe7c30235d1 100644 --- a/arch/arm/mach-omap2/dpll3xxx.c +++ b/arch/arm/mach-omap2/dpll3xxx.c @@ -546,6 +546,153 @@ int omap3_noncore_dpll_set_rate(struct clk_hw *hw, unsigned long rate, return 0; } +/** + * omap3_noncore_dpll_determine_rate - determine rate for a DPLL + * @hw: pointer to the clock to determine rate for + * @rate: target rate for the DPLL + * @best_parent_rate: pointer for returning best parent rate + * @best_parent_clk: pointer for returning best parent clock + * + * Determines which DPLL mode to use for reaching a desired target rate. + * Checks whether the DPLL shall be in bypass or locked mode, and if + * locked, calculates the M,N values for the DPLL via round-rate. + * Returns a positive clock rate with success, negative error value + * in failure. + */ +long omap3_noncore_dpll_determine_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *best_parent_rate, + struct clk **best_parent_clk) +{ + struct clk_hw_omap *clk = to_clk_hw_omap(hw); + struct dpll_data *dd; + + if (!hw || !rate) + return -EINVAL; + + dd = clk->dpll_data; + if (!dd) + return -EINVAL; + + if (__clk_get_rate(dd->clk_bypass) == rate && + (dd->modes & (1 << DPLL_LOW_POWER_BYPASS))) { + *best_parent_clk = dd->clk_bypass; + } else { + rate = omap2_dpll_round_rate(hw, rate, best_parent_rate); + *best_parent_clk = dd->clk_ref; + } + + *best_parent_rate = rate; + + return rate; +} + +/** + * omap3_noncore_dpll_set_parent - set parent for a DPLL clock + * @hw: pointer to the clock to set parent for + * @index: parent index to select + * + * Sets parent for a DPLL clock. This sets the DPLL into bypass or + * locked mode. Returns 0 with success, negative error value otherwise. + */ +int omap3_noncore_dpll_set_parent(struct clk_hw *hw, u8 index) +{ + struct clk_hw_omap *clk = to_clk_hw_omap(hw); + int ret; + + if (!hw) + return -EINVAL; + + if (index) + ret = _omap3_noncore_dpll_bypass(clk); + else + ret = _omap3_noncore_dpll_lock(clk); + + return ret; +} + +/** + * omap3_noncore_dpll_set_rate_new - set rate for a DPLL clock + * @hw: pointer to the clock to set parent for + * @rate: target rate for the clock + * @parent_rate: rate of the parent clock + * + * Sets rate for a DPLL clock. First checks if the clock parent is + * reference clock (in bypass mode, the rate of the clock can't be + * changed) and proceeds with the rate change operation. Returns 0 + * with success, negative error value otherwise. + */ +static int omap3_noncore_dpll_set_rate_new(struct clk_hw *hw, + unsigned long rate, + unsigned long parent_rate) +{ + struct clk_hw_omap *clk = to_clk_hw_omap(hw); + struct dpll_data *dd; + u16 freqsel = 0; + int ret; + + if (!hw || !rate) + return -EINVAL; + + dd = clk->dpll_data; + if (!dd) + return -EINVAL; + + if (__clk_get_parent(hw->clk) != dd->clk_ref) + return -EINVAL; + + if (dd->last_rounded_rate == 0) + return -EINVAL; + + /* Freqsel is available only on OMAP343X devices */ + if (ti_clk_features.flags & TI_CLK_DPLL_HAS_FREQSEL) { + freqsel = _omap3_dpll_compute_freqsel(clk, dd->last_rounded_n); + WARN_ON(!freqsel); + } + + pr_debug("%s: %s: set rate: locking rate to %lu.\n", __func__, + __clk_get_name(hw->clk), rate); + + ret = omap3_noncore_dpll_program(clk, freqsel); + + return ret; +} + +/** + * omap3_noncore_dpll_set_rate_and_parent - set rate and parent for a DPLL clock + * @hw: pointer to the clock to set rate and parent for + * @rate: target rate for the DPLL + * @parent_rate: clock rate of the DPLL parent + * @index: new parent index for the DPLL, 0 - reference, 1 - bypass + * + * Sets rate and parent for a DPLL clock. If new parent is the bypass + * clock, only selects the parent. Otherwise proceeds with a rate + * change, as this will effectively also change the parent as the + * DPLL is put into locked mode. Returns 0 with success, negative error + * value otherwise. + */ +int omap3_noncore_dpll_set_rate_and_parent(struct clk_hw *hw, + unsigned long rate, + unsigned long parent_rate, + u8 index) +{ + int ret; + + if (!hw || !rate) + return -EINVAL; + + /* + * clk-ref at index[0], in which case we only need to set rate, + * the parent will be changed automatically with the lock sequence. + * With clk-bypass case we only need to change parent. + */ + if (index) + ret = omap3_noncore_dpll_set_parent(hw, index); + else + ret = omap3_noncore_dpll_set_rate_new(hw, rate, parent_rate); + + return ret; +} + /* DPLL autoidle read/set code */ /** diff --git a/include/linux/clk/ti.h b/include/linux/clk/ti.h index f75acbf70e96..6f9fb77ffdd5 100644 --- a/include/linux/clk/ti.h +++ b/include/linux/clk/ti.h @@ -254,8 +254,17 @@ extern const struct clk_ops ti_clk_mux_ops; void omap2_init_clk_hw_omap_clocks(struct clk *clk); int omap3_noncore_dpll_enable(struct clk_hw *hw); void omap3_noncore_dpll_disable(struct clk_hw *hw); +int omap3_noncore_dpll_set_parent(struct clk_hw *hw, u8 index); int omap3_noncore_dpll_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate); +int omap3_noncore_dpll_set_rate_and_parent(struct clk_hw *hw, + unsigned long rate, + unsigned long parent_rate, + u8 index); +long omap3_noncore_dpll_determine_rate(struct clk_hw *hw, + unsigned long rate, + unsigned long *best_parent_rate, + struct clk **best_parent_clk); unsigned long omap4_dpll_regm4xen_recalc(struct clk_hw *hw, unsigned long parent_rate); long omap4_dpll_regm4xen_round_rate(struct clk_hw *hw, -- cgit v1.2.3 From 83501ff0a5032dfbd63ab1ca9d9d25b97ec49fb9 Mon Sep 17 00:00:00 2001 From: Tero Kristo Date: Fri, 3 Oct 2014 16:57:12 +0300 Subject: ARM: OMAP4: clock: add support for determine_rate for omap4 regm4xen DPLL Similarly to OMAP3 noncore DPLL, the implementation of this DPLL clock type is wrong. This patch adds basic functionality for determine_rate for this clock type which will be taken into use in the patches following later. Signed-off-by: Tero Kristo Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/dpll44xx.c | 41 +++++++++++++++++++++++++++++++++++++++++ include/linux/clk/ti.h | 4 ++++ 2 files changed, 45 insertions(+) (limited to 'include/linux') diff --git a/arch/arm/mach-omap2/dpll44xx.c b/arch/arm/mach-omap2/dpll44xx.c index 4613f1e86988..535822fcf4bb 100644 --- a/arch/arm/mach-omap2/dpll44xx.c +++ b/arch/arm/mach-omap2/dpll44xx.c @@ -207,3 +207,44 @@ out: return dd->last_rounded_rate; } + +/** + * omap4_dpll_regm4xen_determine_rate - determine rate for a DPLL + * @hw: pointer to the clock to determine rate for + * @rate: target rate for the DPLL + * @best_parent_rate: pointer for returning best parent rate + * @best_parent_clk: pointer for returning best parent clock + * + * Determines which DPLL mode to use for reaching a desired rate. + * Checks whether the DPLL shall be in bypass or locked mode, and if + * locked, calculates the M,N values for the DPLL via round-rate. + * Returns a positive clock rate with success, negative error value + * in failure. + */ +long omap4_dpll_regm4xen_determine_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *best_parent_rate, + struct clk **best_parent_clk) +{ + struct clk_hw_omap *clk = to_clk_hw_omap(hw); + struct dpll_data *dd; + + if (!hw || !rate) + return -EINVAL; + + dd = clk->dpll_data; + if (!dd) + return -EINVAL; + + if (__clk_get_rate(dd->clk_bypass) == rate && + (dd->modes & (1 << DPLL_LOW_POWER_BYPASS))) { + *best_parent_clk = dd->clk_bypass; + } else { + rate = omap4_dpll_regm4xen_round_rate(hw, rate, + best_parent_rate); + *best_parent_clk = dd->clk_ref; + } + + *best_parent_rate = rate; + + return rate; +} diff --git a/include/linux/clk/ti.h b/include/linux/clk/ti.h index 6f9fb77ffdd5..abc702a73aca 100644 --- a/include/linux/clk/ti.h +++ b/include/linux/clk/ti.h @@ -270,6 +270,10 @@ unsigned long omap4_dpll_regm4xen_recalc(struct clk_hw *hw, long omap4_dpll_regm4xen_round_rate(struct clk_hw *hw, unsigned long target_rate, unsigned long *parent_rate); +long omap4_dpll_regm4xen_determine_rate(struct clk_hw *hw, + unsigned long rate, + unsigned long *best_parent_rate, + struct clk **best_parent_clk); u8 omap2_init_dpll_parent(struct clk_hw *hw); unsigned long omap3_dpll_recalc(struct clk_hw *hw, unsigned long parent_rate); long omap2_dpll_round_rate(struct clk_hw *hw, unsigned long target_rate, -- cgit v1.2.3 From e3ab6013ab06d3a861ed00c1f8d32aa4e6b66ddd Mon Sep 17 00:00:00 2001 From: Tero Kristo Date: Fri, 3 Oct 2014 16:57:13 +0300 Subject: ARM: OMAP3: clock: add support for dpll4_set_rate_and_parent Expand the support of omap4 per-dpll to provide set_rate_and_parent. This is required for proper behavior of clk_change_rate with determine_rate support. Signed-off-by: Tero Kristo Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/clock3xxx.c | 36 ++++++++++++++++++++++++++++++++++++ include/linux/clk/ti.h | 2 ++ 2 files changed, 38 insertions(+) (limited to 'include/linux') diff --git a/arch/arm/mach-omap2/clock3xxx.c b/arch/arm/mach-omap2/clock3xxx.c index 9a2560181909..a9e86db5daf9 100644 --- a/arch/arm/mach-omap2/clock3xxx.c +++ b/arch/arm/mach-omap2/clock3xxx.c @@ -38,6 +38,18 @@ /* needed by omap3_core_dpll_m2_set_rate() */ struct clk *sdrc_ick_p, *arm_fck_p; + +/** + * omap3_dpll4_set_rate - set rate for omap3 per-dpll + * @hw: clock to change + * @rate: target rate for clock + * @parent_rate: rate of the parent clock + * + * Check if the current SoC supports the per-dpll reprogram operation + * or not, and then do the rate change if supported. Returns -EINVAL + * if not supported, 0 for success, and potential error codes from the + * clock rate change. + */ int omap3_dpll4_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { @@ -54,6 +66,30 @@ int omap3_dpll4_set_rate(struct clk_hw *hw, unsigned long rate, return omap3_noncore_dpll_set_rate(hw, rate, parent_rate); } +/** + * omap3_dpll4_set_rate_and_parent - set rate and parent for omap3 per-dpll + * @hw: clock to change + * @rate: target rate for clock + * @parent_rate: rate of the parent clock + * @index: parent index, 0 - reference clock, 1 - bypass clock + * + * Check if the current SoC support the per-dpll reprogram operation + * or not, and then do the rate + parent change if supported. Returns + * -EINVAL if not supported, 0 for success, and potential error codes + * from the clock rate change. + */ +int omap3_dpll4_set_rate_and_parent(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate, u8 index) +{ + if (ti_clk_features.flags & TI_CLK_DPLL4_DENY_REPROGRAM) { + pr_err("clock: DPLL4 cannot change rate due to silicon 'Limitation 2.5' on 3430ES1.\n"); + return -EINVAL; + } + + return omap3_noncore_dpll_set_rate_and_parent(hw, rate, parent_rate, + index); +} + void __init omap3_clk_lock_dpll5(void) { struct clk *dpll5_clk; diff --git a/include/linux/clk/ti.h b/include/linux/clk/ti.h index abc702a73aca..74e5341463c9 100644 --- a/include/linux/clk/ti.h +++ b/include/linux/clk/ti.h @@ -291,6 +291,8 @@ int omap2_clk_disable_autoidle_all(void); void omap2_clk_enable_init_clocks(const char **clk_names, u8 num_clocks); int omap3_dpll4_set_rate(struct clk_hw *clk, unsigned long rate, unsigned long parent_rate); +int omap3_dpll4_set_rate_and_parent(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate, u8 index); int omap2_dflt_clk_enable(struct clk_hw *hw); void omap2_dflt_clk_disable(struct clk_hw *hw); int omap2_dflt_clk_is_enabled(struct clk_hw *hw); -- cgit v1.2.3 From 22853223d15b3a626de62cf9e40ce2d3881bc0a8 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 18 Nov 2014 19:45:51 +0100 Subject: regmap: ac97: Add generic AC'97 callbacks Use the recently added support for bus operations to provide a standard mapping for AC'97 register I/O. Signed-off-by: Mark Brown Signed-off-by: Lars-Peter Clausen --- drivers/base/regmap/Kconfig | 5 +- drivers/base/regmap/Makefile | 1 + drivers/base/regmap/regmap-ac97.c | 114 ++++++++++++++++++++++++++++++++++++++ include/linux/regmap.h | 7 +++ 4 files changed, 126 insertions(+), 1 deletion(-) create mode 100644 drivers/base/regmap/regmap-ac97.c (limited to 'include/linux') diff --git a/drivers/base/regmap/Kconfig b/drivers/base/regmap/Kconfig index 8a3f51f7b1b9..db9d00c36a3e 100644 --- a/drivers/base/regmap/Kconfig +++ b/drivers/base/regmap/Kconfig @@ -3,12 +3,15 @@ # subsystems should select the appropriate symbols. config REGMAP - default y if (REGMAP_I2C || REGMAP_SPI || REGMAP_SPMI || REGMAP_MMIO || REGMAP_IRQ) + default y if (REGMAP_I2C || REGMAP_SPI || REGMAP_SPMI || REGMAP_AC97 || REGMAP_MMIO || REGMAP_IRQ) select LZO_COMPRESS select LZO_DECOMPRESS select IRQ_DOMAIN if REGMAP_IRQ bool +config REGMAP_AC97 + tristate + config REGMAP_I2C tristate depends on I2C diff --git a/drivers/base/regmap/Makefile b/drivers/base/regmap/Makefile index a7c670b4123a..0a533653ef3b 100644 --- a/drivers/base/regmap/Makefile +++ b/drivers/base/regmap/Makefile @@ -1,6 +1,7 @@ obj-$(CONFIG_REGMAP) += regmap.o regcache.o obj-$(CONFIG_REGMAP) += regcache-rbtree.o regcache-lzo.o regcache-flat.o obj-$(CONFIG_DEBUG_FS) += regmap-debugfs.o +obj-$(CONFIG_REGMAP_AC97) += regmap-ac97.o obj-$(CONFIG_REGMAP_I2C) += regmap-i2c.o obj-$(CONFIG_REGMAP_SPI) += regmap-spi.o obj-$(CONFIG_REGMAP_SPMI) += regmap-spmi.o diff --git a/drivers/base/regmap/regmap-ac97.c b/drivers/base/regmap/regmap-ac97.c new file mode 100644 index 000000000000..e4c45d2299c1 --- /dev/null +++ b/drivers/base/regmap/regmap-ac97.c @@ -0,0 +1,114 @@ +/* + * Register map access API - AC'97 support + * + * Copyright 2013 Linaro Ltd. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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, see . + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +bool regmap_ac97_default_volatile(struct device *dev, unsigned int reg) +{ + switch (reg) { + case AC97_RESET: + case AC97_POWERDOWN: + case AC97_INT_PAGING: + case AC97_EXTENDED_ID: + case AC97_EXTENDED_STATUS: + case AC97_EXTENDED_MID: + case AC97_EXTENDED_MSTATUS: + case AC97_GPIO_STATUS: + case AC97_MISC_AFE: + case AC97_VENDOR_ID1: + case AC97_VENDOR_ID2: + case AC97_CODEC_CLASS_REV: + case AC97_PCI_SVID: + case AC97_PCI_SID: + case AC97_FUNC_SELECT: + case AC97_FUNC_INFO: + case AC97_SENSE_INFO: + return true; + default: + return false; + } +} +EXPORT_SYMBOL_GPL(regmap_ac97_default_volatile); + +static int regmap_ac97_reg_read(void *context, unsigned int reg, + unsigned int *val) +{ + struct snd_ac97 *ac97 = context; + + *val = ac97->bus->ops->read(ac97, reg); + + return 0; +} + +static int regmap_ac97_reg_write(void *context, unsigned int reg, + unsigned int val) +{ + struct snd_ac97 *ac97 = context; + + ac97->bus->ops->write(ac97, reg, val); + + return 0; +} + +static const struct regmap_bus ac97_regmap_bus = { + .reg_write = regmap_ac97_reg_write, + .reg_read = regmap_ac97_reg_read, +}; + +/** + * regmap_init_ac97(): Initialise AC'97 register map + * + * @ac97: Device that will be interacted with + * @config: Configuration for register map + * + * The return value will be an ERR_PTR() on error or a valid pointer to + * a struct regmap. + */ +struct regmap *regmap_init_ac97(struct snd_ac97 *ac97, + const struct regmap_config *config) +{ + return regmap_init(&ac97->dev, &ac97_regmap_bus, ac97, config); +} +EXPORT_SYMBOL_GPL(regmap_init_ac97); + +/** + * devm_regmap_init_ac97(): Initialise AC'97 register map + * + * @ac97: Device that will be interacted with + * @config: Configuration for register map + * + * The return value will be an ERR_PTR() on error or a valid pointer + * to a struct regmap. The regmap will be automatically freed by the + * device management code. + */ +struct regmap *devm_regmap_init_ac97(struct snd_ac97 *ac97, + const struct regmap_config *config) +{ + return devm_regmap_init(&ac97->dev, &ac97_regmap_bus, ac97, config); +} +EXPORT_SYMBOL_GPL(devm_regmap_init_ac97); + +MODULE_LICENSE("GPL v2"); diff --git a/include/linux/regmap.h b/include/linux/regmap.h index c5ed83f49c4e..4419b99d8d6e 100644 --- a/include/linux/regmap.h +++ b/include/linux/regmap.h @@ -27,6 +27,7 @@ struct spmi_device; struct regmap; struct regmap_range_cfg; struct regmap_field; +struct snd_ac97; /* An enum of all the supported cache types */ enum regcache_type { @@ -340,6 +341,8 @@ struct regmap *regmap_init_spmi_ext(struct spmi_device *dev, struct regmap *regmap_init_mmio_clk(struct device *dev, const char *clk_id, void __iomem *regs, const struct regmap_config *config); +struct regmap *regmap_init_ac97(struct snd_ac97 *ac97, + const struct regmap_config *config); struct regmap *devm_regmap_init(struct device *dev, const struct regmap_bus *bus, @@ -356,6 +359,10 @@ struct regmap *devm_regmap_init_spmi_ext(struct spmi_device *dev, struct regmap *devm_regmap_init_mmio_clk(struct device *dev, const char *clk_id, void __iomem *regs, const struct regmap_config *config); +struct regmap *devm_regmap_init_ac97(struct snd_ac97 *ac97, + const struct regmap_config *config); + +bool regmap_ac97_default_volatile(struct device *dev, unsigned int reg); /** * regmap_init_mmio(): Initialise register map -- cgit v1.2.3 From d67ee213fa5700c7da526fe5bcccd485cfa63d8b Mon Sep 17 00:00:00 2001 From: Mike Snitzer Date: Tue, 28 Oct 2014 20:13:31 -0400 Subject: dm: add presuspend_undo hook to target_type The DM thin-pool target now must undo the changes performed during pool_presuspend() so introduce presuspend_undo hook in target_type. Signed-off-by: Mike Snitzer Acked-by: Joe Thornber --- drivers/md/dm-table.c | 36 +++++++++++++++++++++++++++++------- drivers/md/dm.c | 10 ++++++++-- drivers/md/dm.h | 1 + include/linux/device-mapper.h | 2 ++ include/uapi/linux/dm-ioctl.h | 4 ++-- 5 files changed, 42 insertions(+), 11 deletions(-) (limited to 'include/linux') diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c index b2bd1ebf4562..3afae9e062f8 100644 --- a/drivers/md/dm-table.c +++ b/drivers/md/dm-table.c @@ -1521,18 +1521,32 @@ fmode_t dm_table_get_mode(struct dm_table *t) } EXPORT_SYMBOL(dm_table_get_mode); -static void suspend_targets(struct dm_table *t, unsigned postsuspend) +enum suspend_mode { + PRESUSPEND, + PRESUSPEND_UNDO, + POSTSUSPEND, +}; + +static void suspend_targets(struct dm_table *t, enum suspend_mode mode) { int i = t->num_targets; struct dm_target *ti = t->targets; while (i--) { - if (postsuspend) { + switch (mode) { + case PRESUSPEND: + if (ti->type->presuspend) + ti->type->presuspend(ti); + break; + case PRESUSPEND_UNDO: + if (ti->type->presuspend_undo) + ti->type->presuspend_undo(ti); + break; + case POSTSUSPEND: if (ti->type->postsuspend) ti->type->postsuspend(ti); - } else if (ti->type->presuspend) - ti->type->presuspend(ti); - + break; + } ti++; } } @@ -1542,7 +1556,15 @@ void dm_table_presuspend_targets(struct dm_table *t) if (!t) return; - suspend_targets(t, 0); + suspend_targets(t, PRESUSPEND); +} + +void dm_table_presuspend_undo_targets(struct dm_table *t) +{ + if (!t) + return; + + suspend_targets(t, PRESUSPEND_UNDO); } void dm_table_postsuspend_targets(struct dm_table *t) @@ -1550,7 +1572,7 @@ void dm_table_postsuspend_targets(struct dm_table *t) if (!t) return; - suspend_targets(t, 1); + suspend_targets(t, POSTSUSPEND); } int dm_table_resume_targets(struct dm_table *t) diff --git a/drivers/md/dm.c b/drivers/md/dm.c index f8cdd97c28a7..f84de3215982 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -2756,7 +2756,10 @@ int dm_suspend(struct mapped_device *md, unsigned suspend_flags) if (noflush) set_bit(DMF_NOFLUSH_SUSPENDING, &md->flags); - /* This does not get reverted if there's an error later. */ + /* + * This gets reverted if there's an error later and the targets + * provide the .presuspend_undo hook. + */ dm_table_presuspend_targets(map); /* @@ -2767,8 +2770,10 @@ int dm_suspend(struct mapped_device *md, unsigned suspend_flags) */ if (!noflush && do_lockfs) { r = lock_fs(md); - if (r) + if (r) { + dm_table_presuspend_undo_targets(map); goto out_unlock; + } } /* @@ -2816,6 +2821,7 @@ int dm_suspend(struct mapped_device *md, unsigned suspend_flags) start_queue(md->queue); unlock_fs(md); + dm_table_presuspend_undo_targets(map); goto out_unlock; /* pushback list is already flushed, so skip flush */ } diff --git a/drivers/md/dm.h b/drivers/md/dm.h index 988c7fb7b145..781994093bf5 100644 --- a/drivers/md/dm.h +++ b/drivers/md/dm.h @@ -65,6 +65,7 @@ void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q, struct queue_limits *limits); struct list_head *dm_table_get_devices(struct dm_table *t); void dm_table_presuspend_targets(struct dm_table *t); +void dm_table_presuspend_undo_targets(struct dm_table *t); void dm_table_postsuspend_targets(struct dm_table *t); int dm_table_resume_targets(struct dm_table *t); int dm_table_any_congested(struct dm_table *t, int bdi_bits); diff --git a/include/linux/device-mapper.h b/include/linux/device-mapper.h index e1707de043ae..ca6d2acc5eb7 100644 --- a/include/linux/device-mapper.h +++ b/include/linux/device-mapper.h @@ -64,6 +64,7 @@ typedef int (*dm_request_endio_fn) (struct dm_target *ti, union map_info *map_context); typedef void (*dm_presuspend_fn) (struct dm_target *ti); +typedef void (*dm_presuspend_undo_fn) (struct dm_target *ti); typedef void (*dm_postsuspend_fn) (struct dm_target *ti); typedef int (*dm_preresume_fn) (struct dm_target *ti); typedef void (*dm_resume_fn) (struct dm_target *ti); @@ -145,6 +146,7 @@ struct target_type { dm_endio_fn end_io; dm_request_endio_fn rq_end_io; dm_presuspend_fn presuspend; + dm_presuspend_undo_fn presuspend_undo; dm_postsuspend_fn postsuspend; dm_preresume_fn preresume; dm_resume_fn resume; diff --git a/include/uapi/linux/dm-ioctl.h b/include/uapi/linux/dm-ioctl.h index 3315ab21f728..2be66f4be2f9 100644 --- a/include/uapi/linux/dm-ioctl.h +++ b/include/uapi/linux/dm-ioctl.h @@ -267,9 +267,9 @@ enum { #define DM_DEV_SET_GEOMETRY _IOWR(DM_IOCTL, DM_DEV_SET_GEOMETRY_CMD, struct dm_ioctl) #define DM_VERSION_MAJOR 4 -#define DM_VERSION_MINOR 28 +#define DM_VERSION_MINOR 29 #define DM_VERSION_PATCHLEVEL 0 -#define DM_VERSION_EXTRA "-ioctl (2014-09-17)" +#define DM_VERSION_EXTRA "-ioctl (2014-10-28)" /* Status bits */ #define DM_READONLY_FLAG (1 << 0) /* In/Out */ -- cgit v1.2.3 From e639cd5bfc03de7ba642d7e8570b9e533f10e54b Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Thu, 20 Nov 2014 12:11:25 -0800 Subject: ARM: OMAP2+: Prepare to move GPMC to drivers by platform data header We still need to support platform data for omap3 until it's booting in device tree only mode. So let's add platform_data/omap-gpmc.h for that, and a minimal linux/omap-gpmc.h for the save and restore used by the PM code. Let's also keep a minimal mach-omap2/gpmc.h still around to avoid churn on the board-*.c files. Once omap3 boots in device tree only mode, we can drop mach-omap2/gpmc.h and we can make the data structures in platform_data/omap-gpmc.h private to the GPMC driver. Note that we can now also remove gpmc-nand.h and gpmc-onenand.h. Cc: Arnd Bergmann Acked-by: Roger Quadros Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/board-am3517crane.c | 1 + arch/arm/mach-omap2/board-cm-t35.c | 3 +- arch/arm/mach-omap2/board-cm-t3517.c | 3 +- arch/arm/mach-omap2/board-flash.c | 3 +- arch/arm/mach-omap2/board-flash.h | 1 - arch/arm/mach-omap2/board-n8x0.c | 2 - arch/arm/mach-omap2/board-omap3pandora.c | 2 +- arch/arm/mach-omap2/board-rx51-peripherals.c | 3 +- arch/arm/mach-omap2/gpmc-nand.c | 3 +- arch/arm/mach-omap2/gpmc-nand.h | 27 ---- arch/arm/mach-omap2/gpmc-onenand.c | 3 +- arch/arm/mach-omap2/gpmc-onenand.h | 24 --- arch/arm/mach-omap2/gpmc.c | 63 +++++++- arch/arm/mach-omap2/gpmc.h | 227 +-------------------------- arch/arm/mach-omap2/pm34xx.c | 2 +- include/linux/omap-gpmc.h | 199 +++++++++++++++++++++++ 16 files changed, 271 insertions(+), 295 deletions(-) delete mode 100644 arch/arm/mach-omap2/gpmc-nand.h delete mode 100644 arch/arm/mach-omap2/gpmc-onenand.h create mode 100644 include/linux/omap-gpmc.h (limited to 'include/linux') diff --git a/arch/arm/mach-omap2/board-am3517crane.c b/arch/arm/mach-omap2/board-am3517crane.c index 212c3160de18..8168ddabaeda 100644 --- a/arch/arm/mach-omap2/board-am3517crane.c +++ b/arch/arm/mach-omap2/board-am3517crane.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include diff --git a/arch/arm/mach-omap2/board-cm-t35.c b/arch/arm/mach-omap2/board-cm-t35.c index c6df8eec4553..91738a14ecbe 100644 --- a/arch/arm/mach-omap2/board-cm-t35.c +++ b/arch/arm/mach-omap2/board-cm-t35.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -51,8 +52,6 @@ #include "sdram-micron-mt46h32m32lf-6.h" #include "hsmmc.h" #include "common-board-devices.h" -#include "gpmc.h" -#include "gpmc-nand.h" #define CM_T35_GPIO_PENDOWN 57 #define SB_T35_USB_HUB_RESET_GPIO 167 diff --git a/arch/arm/mach-omap2/board-cm-t3517.c b/arch/arm/mach-omap2/board-cm-t3517.c index 8a2c1677964c..794756df8529 100644 --- a/arch/arm/mach-omap2/board-cm-t3517.c +++ b/arch/arm/mach-omap2/board-cm-t3517.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -41,7 +42,6 @@ #include "common.h" #include -#include "gpmc.h" #include "am35xx.h" @@ -50,7 +50,6 @@ #include "hsmmc.h" #include "common-board-devices.h" #include "am35xx-emac.h" -#include "gpmc-nand.h" #if defined(CONFIG_LEDS_GPIO) || defined(CONFIG_LEDS_GPIO_MODULE) static struct gpio_led cm_t3517_leds[] = { diff --git a/arch/arm/mach-omap2/board-flash.c b/arch/arm/mach-omap2/board-flash.c index 2d245c2e641c..70b21cc279ba 100644 --- a/arch/arm/mach-omap2/board-flash.c +++ b/arch/arm/mach-omap2/board-flash.c @@ -13,6 +13,7 @@ */ #include +#include #include #include #include @@ -23,8 +24,6 @@ #include "soc.h" #include "common.h" #include "board-flash.h" -#include "gpmc-onenand.h" -#include "gpmc-nand.h" #define REG_FPGA_REV 0x10 #define REG_FPGA_DIP_SWITCH_INPUT2 0x60 diff --git a/arch/arm/mach-omap2/board-flash.h b/arch/arm/mach-omap2/board-flash.h index 2fb5d41a9fae..ea9aaebe11e7 100644 --- a/arch/arm/mach-omap2/board-flash.h +++ b/arch/arm/mach-omap2/board-flash.h @@ -12,7 +12,6 @@ */ #include #include -#include "gpmc.h" #define PDC_NOR 1 #define PDC_NAND 2 diff --git a/arch/arm/mach-omap2/board-n8x0.c b/arch/arm/mach-omap2/board-n8x0.c index 97767a27ca9d..49c3c25808e7 100644 --- a/arch/arm/mach-omap2/board-n8x0.c +++ b/arch/arm/mach-omap2/board-n8x0.c @@ -22,7 +22,6 @@ #include #include #include -#include #include #include @@ -32,7 +31,6 @@ #include "common.h" #include "mmc.h" #include "soc.h" -#include "gpmc-onenand.h" #include "common-board-devices.h" #define TUSB6010_ASYNC_CS 1 diff --git a/arch/arm/mach-omap2/board-omap3pandora.c b/arch/arm/mach-omap2/board-omap3pandora.c index f32201656cf3..7f1708738c30 100644 --- a/arch/arm/mach-omap2/board-omap3pandora.c +++ b/arch/arm/mach-omap2/board-omap3pandora.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -51,7 +52,6 @@ #include "sdram-micron-mt46h32m32lf-6.h" #include "hsmmc.h" #include "common-board-devices.h" -#include "gpmc-nand.h" #define PANDORA_WIFI_IRQ_GPIO 21 #define PANDORA_WIFI_NRESET_GPIO 23 diff --git a/arch/arm/mach-omap2/board-rx51-peripherals.c b/arch/arm/mach-omap2/board-rx51-peripherals.c index 30e7d4ce7b8d..e2ad48b5d9c0 100644 --- a/arch/arm/mach-omap2/board-rx51-peripherals.c +++ b/arch/arm/mach-omap2/board-rx51-peripherals.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -54,8 +55,6 @@ #include "omap-pm.h" #include "hsmmc.h" #include "common-board-devices.h" -#include "gpmc.h" -#include "gpmc-onenand.h" #include "soc.h" #include "omap-secure.h" diff --git a/arch/arm/mach-omap2/gpmc-nand.c b/arch/arm/mach-omap2/gpmc-nand.c index cb7764314f17..d5951b17b736 100644 --- a/arch/arm/mach-omap2/gpmc-nand.c +++ b/arch/arm/mach-omap2/gpmc-nand.c @@ -12,14 +12,13 @@ #include #include #include +#include #include #include #include -#include "gpmc.h" #include "soc.h" -#include "gpmc-nand.h" /* minimum size for IO mapping */ #define NAND_IO_SIZE 4 diff --git a/arch/arm/mach-omap2/gpmc-nand.h b/arch/arm/mach-omap2/gpmc-nand.h deleted file mode 100644 index d59e1281e851..000000000000 --- a/arch/arm/mach-omap2/gpmc-nand.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * arch/arm/mach-omap2/gpmc-nand.h - * - * 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. - */ - -#ifndef __OMAP2_GPMC_NAND_H -#define __OMAP2_GPMC_NAND_H - -#include "gpmc.h" -#include - -#if IS_ENABLED(CONFIG_MTD_NAND_OMAP2) -extern int gpmc_nand_init(struct omap_nand_platform_data *d, - struct gpmc_timings *gpmc_t); -#else -static inline int gpmc_nand_init(struct omap_nand_platform_data *d, - struct gpmc_timings *gpmc_t) -{ - return 0; -} -#endif - -#endif diff --git a/arch/arm/mach-omap2/gpmc-onenand.c b/arch/arm/mach-omap2/gpmc-onenand.c index 8b6876c98ce1..53d197e0c1f3 100644 --- a/arch/arm/mach-omap2/gpmc-onenand.c +++ b/arch/arm/mach-omap2/gpmc-onenand.c @@ -15,14 +15,13 @@ #include #include #include +#include #include #include #include -#include "gpmc.h" #include "soc.h" -#include "gpmc-onenand.h" #define ONENAND_IO_SIZE SZ_128K diff --git a/arch/arm/mach-omap2/gpmc-onenand.h b/arch/arm/mach-omap2/gpmc-onenand.h deleted file mode 100644 index 216f23a8b45c..000000000000 --- a/arch/arm/mach-omap2/gpmc-onenand.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - * arch/arm/mach-omap2/gpmc-onenand.h - * - * 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. - */ - -#ifndef __OMAP2_GPMC_ONENAND_H -#define __OMAP2_GPMC_ONENAND_H - -#include - -#if IS_ENABLED(CONFIG_MTD_ONENAND_OMAP2) -extern void gpmc_onenand_init(struct omap_onenand_platform_data *d); -#else -#define board_onenand_data NULL -static inline void gpmc_onenand_init(struct omap_onenand_platform_data *d) -{ -} -#endif - -#endif diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c index 9ea92b6f180d..0753a046fed2 100644 --- a/arch/arm/mach-omap2/gpmc.c +++ b/arch/arm/mach-omap2/gpmc.c @@ -29,18 +29,17 @@ #include #include #include +#include #include #include #include - -#include +#include #include "soc.h" #include "omap_device.h" -#include "gpmc.h" -#include "gpmc-nand.h" -#include "gpmc-onenand.h" + +#include #define DEVICE_NAME "omap-gpmc" @@ -115,6 +114,60 @@ #define GPMC_NR_WAITPINS 4 +#define GPMC_CS_CONFIG1 0x00 +#define GPMC_CS_CONFIG2 0x04 +#define GPMC_CS_CONFIG3 0x08 +#define GPMC_CS_CONFIG4 0x0c +#define GPMC_CS_CONFIG5 0x10 +#define GPMC_CS_CONFIG6 0x14 +#define GPMC_CS_CONFIG7 0x18 +#define GPMC_CS_NAND_COMMAND 0x1c +#define GPMC_CS_NAND_ADDRESS 0x20 +#define GPMC_CS_NAND_DATA 0x24 + +/* Control Commands */ +#define GPMC_CONFIG_RDY_BSY 0x00000001 +#define GPMC_CONFIG_DEV_SIZE 0x00000002 +#define GPMC_CONFIG_DEV_TYPE 0x00000003 +#define GPMC_SET_IRQ_STATUS 0x00000004 + +#define GPMC_CONFIG1_WRAPBURST_SUPP (1 << 31) +#define GPMC_CONFIG1_READMULTIPLE_SUPP (1 << 30) +#define GPMC_CONFIG1_READTYPE_ASYNC (0 << 29) +#define GPMC_CONFIG1_READTYPE_SYNC (1 << 29) +#define GPMC_CONFIG1_WRITEMULTIPLE_SUPP (1 << 28) +#define GPMC_CONFIG1_WRITETYPE_ASYNC (0 << 27) +#define GPMC_CONFIG1_WRITETYPE_SYNC (1 << 27) +#define GPMC_CONFIG1_CLKACTIVATIONTIME(val) ((val & 3) << 25) +#define GPMC_CONFIG1_PAGE_LEN(val) ((val & 3) << 23) +#define GPMC_CONFIG1_WAIT_READ_MON (1 << 22) +#define GPMC_CONFIG1_WAIT_WRITE_MON (1 << 21) +#define GPMC_CONFIG1_WAIT_MON_IIME(val) ((val & 3) << 18) +#define GPMC_CONFIG1_WAIT_PIN_SEL(val) ((val & 3) << 16) +#define GPMC_CONFIG1_DEVICESIZE(val) ((val & 3) << 12) +#define GPMC_CONFIG1_DEVICESIZE_16 GPMC_CONFIG1_DEVICESIZE(1) +#define GPMC_CONFIG1_DEVICETYPE(val) ((val & 3) << 10) +#define GPMC_CONFIG1_DEVICETYPE_NOR GPMC_CONFIG1_DEVICETYPE(0) +#define GPMC_CONFIG1_MUXTYPE(val) ((val & 3) << 8) +#define GPMC_CONFIG1_TIME_PARA_GRAN (1 << 4) +#define GPMC_CONFIG1_FCLK_DIV(val) (val & 3) +#define GPMC_CONFIG1_FCLK_DIV2 (GPMC_CONFIG1_FCLK_DIV(1)) +#define GPMC_CONFIG1_FCLK_DIV3 (GPMC_CONFIG1_FCLK_DIV(2)) +#define GPMC_CONFIG1_FCLK_DIV4 (GPMC_CONFIG1_FCLK_DIV(3)) +#define GPMC_CONFIG7_CSVALID (1 << 6) + +#define GPMC_DEVICETYPE_NOR 0 +#define GPMC_DEVICETYPE_NAND 2 +#define GPMC_CONFIG_WRITEPROTECT 0x00000010 +#define WR_RD_PIN_MONITORING 0x00600000 + +#define GPMC_ENABLE_IRQ 0x0000000d + +/* ECC commands */ +#define GPMC_ECC_READ 0 /* Reset Hardware ECC for read */ +#define GPMC_ECC_WRITE 1 /* Reset Hardware ECC for write */ +#define GPMC_ECC_READSYN 2 /* Reset before syndrom is read back */ + /* XXX: Only NAND irq has been considered,currently these are the only ones used */ #define GPMC_NR_IRQ 2 diff --git a/arch/arm/mach-omap2/gpmc.h b/arch/arm/mach-omap2/gpmc.h index 707f6d58edd5..9caa41a6cb04 100644 --- a/arch/arm/mach-omap2/gpmc.h +++ b/arch/arm/mach-omap2/gpmc.h @@ -6,226 +6,9 @@ * 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. + * + * Do not include this file in any new code, this will get removed + * once omap3 boots in device tree only mode. + * */ - -#ifndef __OMAP2_GPMC_H -#define __OMAP2_GPMC_H - -#include - -/* Maximum Number of Chip Selects */ -#define GPMC_CS_NUM 8 - -#define GPMC_CS_CONFIG1 0x00 -#define GPMC_CS_CONFIG2 0x04 -#define GPMC_CS_CONFIG3 0x08 -#define GPMC_CS_CONFIG4 0x0c -#define GPMC_CS_CONFIG5 0x10 -#define GPMC_CS_CONFIG6 0x14 -#define GPMC_CS_CONFIG7 0x18 -#define GPMC_CS_NAND_COMMAND 0x1c -#define GPMC_CS_NAND_ADDRESS 0x20 -#define GPMC_CS_NAND_DATA 0x24 - -/* Control Commands */ -#define GPMC_CONFIG_RDY_BSY 0x00000001 -#define GPMC_CONFIG_DEV_SIZE 0x00000002 -#define GPMC_CONFIG_DEV_TYPE 0x00000003 -#define GPMC_SET_IRQ_STATUS 0x00000004 -#define GPMC_CONFIG_WP 0x00000005 - -#define GPMC_ENABLE_IRQ 0x0000000d - -/* ECC commands */ -#define GPMC_ECC_READ 0 /* Reset Hardware ECC for read */ -#define GPMC_ECC_WRITE 1 /* Reset Hardware ECC for write */ -#define GPMC_ECC_READSYN 2 /* Reset before syndrom is read back */ - -#define GPMC_CONFIG1_WRAPBURST_SUPP (1 << 31) -#define GPMC_CONFIG1_READMULTIPLE_SUPP (1 << 30) -#define GPMC_CONFIG1_READTYPE_ASYNC (0 << 29) -#define GPMC_CONFIG1_READTYPE_SYNC (1 << 29) -#define GPMC_CONFIG1_WRITEMULTIPLE_SUPP (1 << 28) -#define GPMC_CONFIG1_WRITETYPE_ASYNC (0 << 27) -#define GPMC_CONFIG1_WRITETYPE_SYNC (1 << 27) -#define GPMC_CONFIG1_CLKACTIVATIONTIME(val) ((val & 3) << 25) -#define GPMC_CONFIG1_PAGE_LEN(val) ((val & 3) << 23) -#define GPMC_CONFIG1_WAIT_READ_MON (1 << 22) -#define GPMC_CONFIG1_WAIT_WRITE_MON (1 << 21) -#define GPMC_CONFIG1_WAIT_MON_IIME(val) ((val & 3) << 18) -#define GPMC_CONFIG1_WAIT_PIN_SEL(val) ((val & 3) << 16) -#define GPMC_CONFIG1_DEVICESIZE(val) ((val & 3) << 12) -#define GPMC_CONFIG1_DEVICESIZE_16 GPMC_CONFIG1_DEVICESIZE(1) -#define GPMC_CONFIG1_DEVICETYPE(val) ((val & 3) << 10) -#define GPMC_CONFIG1_DEVICETYPE_NOR GPMC_CONFIG1_DEVICETYPE(0) -#define GPMC_CONFIG1_MUXTYPE(val) ((val & 3) << 8) -#define GPMC_CONFIG1_TIME_PARA_GRAN (1 << 4) -#define GPMC_CONFIG1_FCLK_DIV(val) (val & 3) -#define GPMC_CONFIG1_FCLK_DIV2 (GPMC_CONFIG1_FCLK_DIV(1)) -#define GPMC_CONFIG1_FCLK_DIV3 (GPMC_CONFIG1_FCLK_DIV(2)) -#define GPMC_CONFIG1_FCLK_DIV4 (GPMC_CONFIG1_FCLK_DIV(3)) -#define GPMC_CONFIG7_CSVALID (1 << 6) - -#define GPMC_DEVICETYPE_NOR 0 -#define GPMC_DEVICETYPE_NAND 2 -#define GPMC_CONFIG_WRITEPROTECT 0x00000010 -#define WR_RD_PIN_MONITORING 0x00600000 -#define GPMC_IRQ_FIFOEVENTENABLE 0x01 -#define GPMC_IRQ_COUNT_EVENT 0x02 - -#define GPMC_BURST_4 4 /* 4 word burst */ -#define GPMC_BURST_8 8 /* 8 word burst */ -#define GPMC_BURST_16 16 /* 16 word burst */ -#define GPMC_DEVWIDTH_8BIT 1 /* 8-bit device width */ -#define GPMC_DEVWIDTH_16BIT 2 /* 16-bit device width */ -#define GPMC_MUX_AAD 1 /* Addr-Addr-Data multiplex */ -#define GPMC_MUX_AD 2 /* Addr-Data multiplex */ - -/* bool type time settings */ -struct gpmc_bool_timings { - bool cycle2cyclediffcsen; - bool cycle2cyclesamecsen; - bool we_extra_delay; - bool oe_extra_delay; - bool adv_extra_delay; - bool cs_extra_delay; - bool time_para_granularity; -}; - -/* - * Note that all values in this struct are in nanoseconds except sync_clk - * (which is in picoseconds), while the register values are in gpmc_fck cycles. - */ -struct gpmc_timings { - /* Minimum clock period for synchronous mode (in picoseconds) */ - u32 sync_clk; - - /* Chip-select signal timings corresponding to GPMC_CS_CONFIG2 */ - u32 cs_on; /* Assertion time */ - u32 cs_rd_off; /* Read deassertion time */ - u32 cs_wr_off; /* Write deassertion time */ - - /* ADV signal timings corresponding to GPMC_CONFIG3 */ - u32 adv_on; /* Assertion time */ - u32 adv_rd_off; /* Read deassertion time */ - u32 adv_wr_off; /* Write deassertion time */ - - /* WE signals timings corresponding to GPMC_CONFIG4 */ - u32 we_on; /* WE assertion time */ - u32 we_off; /* WE deassertion time */ - - /* OE signals timings corresponding to GPMC_CONFIG4 */ - u32 oe_on; /* OE assertion time */ - u32 oe_off; /* OE deassertion time */ - - /* Access time and cycle time timings corresponding to GPMC_CONFIG5 */ - u32 page_burst_access; /* Multiple access word delay */ - u32 access; /* Start-cycle to first data valid delay */ - u32 rd_cycle; /* Total read cycle time */ - u32 wr_cycle; /* Total write cycle time */ - - u32 bus_turnaround; - u32 cycle2cycle_delay; - - u32 wait_monitoring; - u32 clk_activation; - - /* The following are only on OMAP3430 */ - u32 wr_access; /* WRACCESSTIME */ - u32 wr_data_mux_bus; /* WRDATAONADMUXBUS */ - - struct gpmc_bool_timings bool_timings; -}; - -/* Device timings in picoseconds */ -struct gpmc_device_timings { - u32 t_ceasu; /* address setup to CS valid */ - u32 t_avdasu; /* address setup to ADV valid */ - /* XXX: try to combine t_avdp_r & t_avdp_w. Issue is - * of tusb using these timings even for sync whilst - * ideally for adv_rd/(wr)_off it should have considered - * t_avdh instead. This indirectly necessitates r/w - * variations of t_avdp as it is possible to have one - * sync & other async - */ - u32 t_avdp_r; /* ADV low time (what about t_cer ?) */ - u32 t_avdp_w; - u32 t_aavdh; /* address hold time */ - u32 t_oeasu; /* address setup to OE valid */ - u32 t_aa; /* access time from ADV assertion */ - u32 t_iaa; /* initial access time */ - u32 t_oe; /* access time from OE assertion */ - u32 t_ce; /* access time from CS asertion */ - u32 t_rd_cycle; /* read cycle time */ - u32 t_cez_r; /* read CS deassertion to high Z */ - u32 t_cez_w; /* write CS deassertion to high Z */ - u32 t_oez; /* OE deassertion to high Z */ - u32 t_weasu; /* address setup to WE valid */ - u32 t_wpl; /* write assertion time */ - u32 t_wph; /* write deassertion time */ - u32 t_wr_cycle; /* write cycle time */ - - u32 clk; - u32 t_bacc; /* burst access valid clock to output delay */ - u32 t_ces; /* CS setup time to clk */ - u32 t_avds; /* ADV setup time to clk */ - u32 t_avdh; /* ADV hold time from clk */ - u32 t_ach; /* address hold time from clk */ - u32 t_rdyo; /* clk to ready valid */ - - u32 t_ce_rdyz; /* XXX: description ?, or use t_cez instead */ - u32 t_ce_avd; /* CS on to ADV on delay */ - - /* XXX: check the possibility of combining - * cyc_aavhd_oe & cyc_aavdh_we - */ - u8 cyc_aavdh_oe;/* read address hold time in cycles */ - u8 cyc_aavdh_we;/* write address hold time in cycles */ - u8 cyc_oe; /* access time from OE assertion in cycles */ - u8 cyc_wpl; /* write deassertion time in cycles */ - u32 cyc_iaa; /* initial access time in cycles */ - - /* extra delays */ - bool ce_xdelay; - bool avd_xdelay; - bool oe_xdelay; - bool we_xdelay; -}; - -struct gpmc_settings { - bool burst_wrap; /* enables wrap bursting */ - bool burst_read; /* enables read page/burst mode */ - bool burst_write; /* enables write page/burst mode */ - bool device_nand; /* device is NAND */ - bool sync_read; /* enables synchronous reads */ - bool sync_write; /* enables synchronous writes */ - bool wait_on_read; /* monitor wait on reads */ - bool wait_on_write; /* monitor wait on writes */ - u32 burst_len; /* page/burst length */ - u32 device_width; /* device bus width (8 or 16 bit) */ - u32 mux_add_data; /* multiplex address & data */ - u32 wait_pin; /* wait-pin to be used */ -}; - -extern int gpmc_calc_timings(struct gpmc_timings *gpmc_t, - struct gpmc_settings *gpmc_s, - struct gpmc_device_timings *dev_t); - -extern void gpmc_update_nand_reg(struct gpmc_nand_regs *reg, int cs); -extern int gpmc_get_client_irq(unsigned irq_config); - -extern unsigned int gpmc_ticks_to_ns(unsigned int ticks); - -extern void gpmc_cs_write_reg(int cs, int idx, u32 val); -extern int gpmc_calc_divider(unsigned int sync_clk); -extern int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t); -extern int gpmc_cs_program_settings(int cs, struct gpmc_settings *p); -extern int gpmc_cs_request(int cs, unsigned long size, unsigned long *base); -extern void gpmc_cs_free(int cs); -extern void omap3_gpmc_save_context(void); -extern void omap3_gpmc_restore_context(void); -extern int gpmc_configure(int cmd, int wval); -extern void gpmc_read_settings_dt(struct device_node *np, - struct gpmc_settings *p); - -#endif +#include diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c index 175564c88a30..88721df6001d 100644 --- a/arch/arm/mach-omap2/pm34xx.c +++ b/arch/arm/mach-omap2/pm34xx.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -43,7 +44,6 @@ #include "common.h" #include "cm3xxx.h" #include "cm-regbits-34xx.h" -#include "gpmc.h" #include "prm-regbits-34xx.h" #include "prm3xxx.h" #include "pm.h" diff --git a/include/linux/omap-gpmc.h b/include/linux/omap-gpmc.h new file mode 100644 index 000000000000..c2080eebbb47 --- /dev/null +++ b/include/linux/omap-gpmc.h @@ -0,0 +1,199 @@ +/* + * OMAP GPMC (General Purpose Memory Controller) defines + * + * 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. + */ + +/* Maximum Number of Chip Selects */ +#define GPMC_CS_NUM 8 + +#define GPMC_CONFIG_WP 0x00000005 + +#define GPMC_IRQ_FIFOEVENTENABLE 0x01 +#define GPMC_IRQ_COUNT_EVENT 0x02 + +#define GPMC_BURST_4 4 /* 4 word burst */ +#define GPMC_BURST_8 8 /* 8 word burst */ +#define GPMC_BURST_16 16 /* 16 word burst */ +#define GPMC_DEVWIDTH_8BIT 1 /* 8-bit device width */ +#define GPMC_DEVWIDTH_16BIT 2 /* 16-bit device width */ +#define GPMC_MUX_AAD 1 /* Addr-Addr-Data multiplex */ +#define GPMC_MUX_AD 2 /* Addr-Data multiplex */ + +/* bool type time settings */ +struct gpmc_bool_timings { + bool cycle2cyclediffcsen; + bool cycle2cyclesamecsen; + bool we_extra_delay; + bool oe_extra_delay; + bool adv_extra_delay; + bool cs_extra_delay; + bool time_para_granularity; +}; + +/* + * Note that all values in this struct are in nanoseconds except sync_clk + * (which is in picoseconds), while the register values are in gpmc_fck cycles. + */ +struct gpmc_timings { + /* Minimum clock period for synchronous mode (in picoseconds) */ + u32 sync_clk; + + /* Chip-select signal timings corresponding to GPMC_CS_CONFIG2 */ + u32 cs_on; /* Assertion time */ + u32 cs_rd_off; /* Read deassertion time */ + u32 cs_wr_off; /* Write deassertion time */ + + /* ADV signal timings corresponding to GPMC_CONFIG3 */ + u32 adv_on; /* Assertion time */ + u32 adv_rd_off; /* Read deassertion time */ + u32 adv_wr_off; /* Write deassertion time */ + + /* WE signals timings corresponding to GPMC_CONFIG4 */ + u32 we_on; /* WE assertion time */ + u32 we_off; /* WE deassertion time */ + + /* OE signals timings corresponding to GPMC_CONFIG4 */ + u32 oe_on; /* OE assertion time */ + u32 oe_off; /* OE deassertion time */ + + /* Access time and cycle time timings corresponding to GPMC_CONFIG5 */ + u32 page_burst_access; /* Multiple access word delay */ + u32 access; /* Start-cycle to first data valid delay */ + u32 rd_cycle; /* Total read cycle time */ + u32 wr_cycle; /* Total write cycle time */ + + u32 bus_turnaround; + u32 cycle2cycle_delay; + + u32 wait_monitoring; + u32 clk_activation; + + /* The following are only on OMAP3430 */ + u32 wr_access; /* WRACCESSTIME */ + u32 wr_data_mux_bus; /* WRDATAONADMUXBUS */ + + struct gpmc_bool_timings bool_timings; +}; + +/* Device timings in picoseconds */ +struct gpmc_device_timings { + u32 t_ceasu; /* address setup to CS valid */ + u32 t_avdasu; /* address setup to ADV valid */ + /* XXX: try to combine t_avdp_r & t_avdp_w. Issue is + * of tusb using these timings even for sync whilst + * ideally for adv_rd/(wr)_off it should have considered + * t_avdh instead. This indirectly necessitates r/w + * variations of t_avdp as it is possible to have one + * sync & other async + */ + u32 t_avdp_r; /* ADV low time (what about t_cer ?) */ + u32 t_avdp_w; + u32 t_aavdh; /* address hold time */ + u32 t_oeasu; /* address setup to OE valid */ + u32 t_aa; /* access time from ADV assertion */ + u32 t_iaa; /* initial access time */ + u32 t_oe; /* access time from OE assertion */ + u32 t_ce; /* access time from CS asertion */ + u32 t_rd_cycle; /* read cycle time */ + u32 t_cez_r; /* read CS deassertion to high Z */ + u32 t_cez_w; /* write CS deassertion to high Z */ + u32 t_oez; /* OE deassertion to high Z */ + u32 t_weasu; /* address setup to WE valid */ + u32 t_wpl; /* write assertion time */ + u32 t_wph; /* write deassertion time */ + u32 t_wr_cycle; /* write cycle time */ + + u32 clk; + u32 t_bacc; /* burst access valid clock to output delay */ + u32 t_ces; /* CS setup time to clk */ + u32 t_avds; /* ADV setup time to clk */ + u32 t_avdh; /* ADV hold time from clk */ + u32 t_ach; /* address hold time from clk */ + u32 t_rdyo; /* clk to ready valid */ + + u32 t_ce_rdyz; /* XXX: description ?, or use t_cez instead */ + u32 t_ce_avd; /* CS on to ADV on delay */ + + /* XXX: check the possibility of combining + * cyc_aavhd_oe & cyc_aavdh_we + */ + u8 cyc_aavdh_oe;/* read address hold time in cycles */ + u8 cyc_aavdh_we;/* write address hold time in cycles */ + u8 cyc_oe; /* access time from OE assertion in cycles */ + u8 cyc_wpl; /* write deassertion time in cycles */ + u32 cyc_iaa; /* initial access time in cycles */ + + /* extra delays */ + bool ce_xdelay; + bool avd_xdelay; + bool oe_xdelay; + bool we_xdelay; +}; + +struct gpmc_settings { + bool burst_wrap; /* enables wrap bursting */ + bool burst_read; /* enables read page/burst mode */ + bool burst_write; /* enables write page/burst mode */ + bool device_nand; /* device is NAND */ + bool sync_read; /* enables synchronous reads */ + bool sync_write; /* enables synchronous writes */ + bool wait_on_read; /* monitor wait on reads */ + bool wait_on_write; /* monitor wait on writes */ + u32 burst_len; /* page/burst length */ + u32 device_width; /* device bus width (8 or 16 bit) */ + u32 mux_add_data; /* multiplex address & data */ + u32 wait_pin; /* wait-pin to be used */ +}; + +extern int gpmc_calc_timings(struct gpmc_timings *gpmc_t, + struct gpmc_settings *gpmc_s, + struct gpmc_device_timings *dev_t); + +struct gpmc_nand_regs; +struct device_node; + +extern void gpmc_update_nand_reg(struct gpmc_nand_regs *reg, int cs); +extern int gpmc_get_client_irq(unsigned irq_config); + +extern unsigned int gpmc_ticks_to_ns(unsigned int ticks); + +extern void gpmc_cs_write_reg(int cs, int idx, u32 val); +extern int gpmc_calc_divider(unsigned int sync_clk); +extern int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t); +extern int gpmc_cs_program_settings(int cs, struct gpmc_settings *p); +extern int gpmc_cs_request(int cs, unsigned long size, unsigned long *base); +extern void gpmc_cs_free(int cs); +extern int gpmc_configure(int cmd, int wval); +extern void gpmc_read_settings_dt(struct device_node *np, + struct gpmc_settings *p); + +extern void omap3_gpmc_save_context(void); +extern void omap3_gpmc_restore_context(void); + +struct gpmc_timings; +struct omap_nand_platform_data; +struct omap_onenand_platform_data; + +#if IS_ENABLED(CONFIG_MTD_NAND_OMAP2) +extern int gpmc_nand_init(struct omap_nand_platform_data *d, + struct gpmc_timings *gpmc_t); +#else +static inline int gpmc_nand_init(struct omap_nand_platform_data *d, + struct gpmc_timings *gpmc_t) +{ + return 0; +} +#endif + +#if IS_ENABLED(CONFIG_MTD_ONENAND_OMAP2) +extern void gpmc_onenand_init(struct omap_onenand_platform_data *d); +#else +#define board_onenand_data NULL +static inline void gpmc_onenand_init(struct omap_onenand_platform_data *d) +{ +} +#endif -- cgit v1.2.3 From 49c71d1c3dccff640cc082875bd8d62988d63df9 Mon Sep 17 00:00:00 2001 From: Fugang Duan Date: Wed, 24 Sep 2014 10:11:18 +0800 Subject: ARM: imx6sx: add imx6sx iomux-gpr field define Add imx6sx iomux-gpr register field define in "imx6q-iomuxc-gpr.h" header file, which is not fully define all iomux-gpr registers and fields, only align with freescale internal tree related GPR macro define. Signed-off-by: Fugang Duan Signed-off-by: Shawn Guo --- include/linux/mfd/syscon/imx6q-iomuxc-gpr.h | 39 +++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) (limited to 'include/linux') diff --git a/include/linux/mfd/syscon/imx6q-iomuxc-gpr.h b/include/linux/mfd/syscon/imx6q-iomuxc-gpr.h index ff44374a1a4e..c877cad61a13 100644 --- a/include/linux/mfd/syscon/imx6q-iomuxc-gpr.h +++ b/include/linux/mfd/syscon/imx6q-iomuxc-gpr.h @@ -395,4 +395,43 @@ #define IMX6SL_GPR1_FEC_CLOCK_MUX1_SEL_MASK (0x3 << 17) #define IMX6SL_GPR1_FEC_CLOCK_MUX2_SEL_MASK (0x1 << 14) +/* For imx6sx iomux gpr register field define */ +#define IMX6SX_GPR1_VDEC_SW_RST_MASK (0x1 << 20) +#define IMX6SX_GPR1_VDEC_SW_RST_RESET (0x1 << 20) +#define IMX6SX_GPR1_VDEC_SW_RST_RELEASE (0x0 << 20) +#define IMX6SX_GPR1_VADC_SW_RST_MASK (0x1 << 19) +#define IMX6SX_GPR1_VADC_SW_RST_RESET (0x1 << 19) +#define IMX6SX_GPR1_VADC_SW_RST_RELEASE (0x0 << 19) +#define IMX6SX_GPR1_FEC_CLOCK_MUX_SEL_MASK (0x3 << 13) +#define IMX6SX_GPR1_FEC_CLOCK_PAD_DIR_MASK (0x3 << 17) +#define IMX6SX_GPR1_FEC_CLOCK_MUX_SEL_EXT (0x3 << 13) + +#define IMX6SX_GPR4_FEC_ENET1_STOP_REQ (0x1 << 3) +#define IMX6SX_GPR4_FEC_ENET2_STOP_REQ (0x1 << 4) + +#define IMX6SX_GPR5_DISP_MUX_LDB_CTRL_MASK (0x1 << 3) +#define IMX6SX_GPR5_DISP_MUX_LDB_CTRL_LCDIF1 (0x0 << 3) +#define IMX6SX_GPR5_DISP_MUX_LDB_CTRL_LCDIF2 (0x1 << 3) + +#define IMX6SX_GPR5_CSI2_MUX_CTRL_MASK (0x3 << 27) +#define IMX6SX_GPR5_CSI2_MUX_CTRL_EXT_PIN (0x0 << 27) +#define IMX6SX_GPR5_CSI2_MUX_CTRL_CVD (0x1 << 27) +#define IMX6SX_GPR5_CSI2_MUX_CTRL_VDAC_TO_CSI (0x2 << 27) +#define IMX6SX_GPR5_CSI2_MUX_CTRL_GND (0x3 << 27) +#define IMX6SX_GPR5_VADC_TO_CSI_CAPTURE_EN_MASK (0x1 << 26) +#define IMX6SX_GPR5_VADC_TO_CSI_CAPTURE_EN_ENABLE (0x1 << 26) +#define IMX6SX_GPR5_VADC_TO_CSI_CAPTURE_EN_DISABLE (0x0 << 26) +#define IMX6SX_GPR5_CSI1_MUX_CTRL_MASK (0x3 << 4) +#define IMX6SX_GPR5_CSI1_MUX_CTRL_EXT_PIN (0x0 << 4) +#define IMX6SX_GPR5_CSI1_MUX_CTRL_CVD (0x1 << 4) +#define IMX6SX_GPR5_CSI1_MUX_CTRL_VDAC_TO_CSI (0x2 << 4) +#define IMX6SX_GPR5_CSI1_MUX_CTRL_GND (0x3 << 4) + +#define IMX6SX_GPR5_DISP_MUX_DCIC2_LCDIF2 (0x0 << 2) +#define IMX6SX_GPR5_DISP_MUX_DCIC2_LVDS (0x1 << 2) +#define IMX6SX_GPR5_DISP_MUX_DCIC2_MASK (0x1 << 2) +#define IMX6SX_GPR5_DISP_MUX_DCIC1_LCDIF1 (0x0 << 1) +#define IMX6SX_GPR5_DISP_MUX_DCIC1_LVDS (0x1 << 1) +#define IMX6SX_GPR5_DISP_MUX_DCIC1_MASK (0x1 << 1) + #endif /* __LINUX_IMX6Q_IOMUXC_GPR_H */ -- cgit v1.2.3 From db5ed4dfd5dd0142ec36ff7b335e0ec3b836b3e6 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Thu, 13 Nov 2014 15:08:42 +0100 Subject: scsi: drop reason argument from ->change_queue_depth Drop the now unused reason argument from the ->change_queue_depth method. Also add a return value to scsi_adjust_queue_depth, and rename it to scsi_change_queue_depth now that it can be used as the default ->change_queue_depth implementation. Signed-off-by: Christoph Hellwig Reviewed-by: Mike Christie Reviewed-by: Hannes Reinecke --- Documentation/scsi/scsi_mid_low_api.txt | 20 +++++++-------- drivers/ata/libata-scsi.c | 17 ++++--------- drivers/ata/sata_nv.c | 2 +- drivers/infiniband/ulp/iser/iscsi_iser.c | 2 +- drivers/infiniband/ulp/srp/ib_srp.c | 7 ++---- drivers/message/fusion/mptscsih.c | 12 +++------ drivers/message/fusion/mptscsih.h | 3 +-- drivers/s390/scsi/zfcp_scsi.c | 11 ++------- drivers/scsi/3w-9xxx.c | 13 +--------- drivers/scsi/3w-sas.c | 13 +--------- drivers/scsi/3w-xxxx.c | 13 +--------- drivers/scsi/53c700.c | 19 ++++++-------- drivers/scsi/BusLogic.c | 4 +-- drivers/scsi/aacraid/linit.c | 18 ++++++-------- drivers/scsi/advansys.c | 8 +++--- drivers/scsi/aic7xxx/aic79xx_osm.c | 4 +-- drivers/scsi/aic7xxx/aic7xxx_osm.c | 4 +-- drivers/scsi/arcmsr/arcmsr_hba.c | 9 ++----- drivers/scsi/be2iscsi/be_main.c | 2 +- drivers/scsi/bfa/bfad_im.c | 4 +-- drivers/scsi/bnx2fc/bnx2fc_fcoe.c | 2 +- drivers/scsi/bnx2i/bnx2i_iscsi.c | 2 +- drivers/scsi/csiostor/csio_scsi.c | 2 +- drivers/scsi/cxgbi/cxgb3i/cxgb3i.c | 2 +- drivers/scsi/cxgbi/cxgb4i/cxgb4i.c | 2 +- drivers/scsi/dpt_i2o.c | 2 +- drivers/scsi/eata.c | 6 ++--- drivers/scsi/esas2r/esas2r.h | 1 - drivers/scsi/esas2r/esas2r_main.c | 11 +-------- drivers/scsi/esp_scsi.c | 2 +- drivers/scsi/fcoe/fcoe.c | 2 +- drivers/scsi/fnic/fnic_main.c | 4 +-- drivers/scsi/hpsa.c | 16 +----------- drivers/scsi/hptiop.c | 8 ++---- drivers/scsi/ibmvscsi/ibmvfc.c | 9 ++----- drivers/scsi/ibmvscsi/ibmvscsi.c | 10 ++------ drivers/scsi/ipr.c | 10 +++----- drivers/scsi/ips.c | 2 +- drivers/scsi/iscsi_tcp.c | 2 +- drivers/scsi/libfc/fc_fcp.c | 15 +---------- drivers/scsi/libiscsi.c | 7 ------ drivers/scsi/libsas/sas_scsi_host.c | 12 ++++----- drivers/scsi/lpfc/lpfc_scsi.c | 26 +++----------------- drivers/scsi/megaraid/megaraid_mbox.c | 21 +--------------- drivers/scsi/megaraid/megaraid_sas_base.c | 13 +--------- drivers/scsi/mpt2sas/mpt2sas_scsih.c | 10 +++----- drivers/scsi/mpt3sas/mpt3sas_scsih.c | 10 +++----- drivers/scsi/ncr53c8xx.c | 2 +- drivers/scsi/pmcraid.c | 12 ++------- drivers/scsi/qla1280.c | 4 +-- drivers/scsi/qla2xxx/qla_os.c | 12 ++------- drivers/scsi/qla4xxx/ql4_os.c | 4 +-- drivers/scsi/scsi.c | 41 +++++++++++-------------------- drivers/scsi/scsi_debug.c | 4 +-- drivers/scsi/scsi_error.c | 2 +- drivers/scsi/scsi_scan.c | 2 +- drivers/scsi/scsi_sysfs.c | 3 +-- drivers/scsi/storvsc_drv.c | 2 +- drivers/scsi/sym53c8xx_2/sym_glue.c | 2 +- drivers/scsi/tmscsim.c | 2 +- drivers/scsi/u14-34f.c | 10 ++++---- drivers/scsi/ufs/ufshcd.c | 13 +++------- drivers/scsi/virtio_scsi.c | 8 ++---- drivers/scsi/vmw_pvscsi.c | 12 ++------- drivers/scsi/wd7000.c | 1 - drivers/target/loopback/tcm_loop.c | 15 +---------- drivers/usb/storage/uas.c | 2 +- include/linux/libata.h | 4 +-- include/scsi/libfc.h | 1 - include/scsi/libiscsi.h | 2 -- include/scsi/libsas.h | 3 +-- include/scsi/scsi_device.h | 2 +- include/scsi/scsi_host.h | 8 ++---- 73 files changed, 155 insertions(+), 412 deletions(-) (limited to 'include/linux') diff --git a/Documentation/scsi/scsi_mid_low_api.txt b/Documentation/scsi/scsi_mid_low_api.txt index bee7d86b9dcc..731bc4f4c5e6 100644 --- a/Documentation/scsi/scsi_mid_low_api.txt +++ b/Documentation/scsi/scsi_mid_low_api.txt @@ -149,7 +149,7 @@ scsi_add_host() ----> scsi_scan_host() -------+ | slave_alloc() - slave_configure() --> scsi_adjust_queue_depth() + slave_configure() --> scsi_change_queue_depth() | slave_alloc() slave_configure() @@ -159,7 +159,7 @@ scsi_scan_host() -------+ ------------------------------------------------------------ If the LLD wants to adjust the default queue settings, it can invoke -scsi_adjust_queue_depth() in its slave_configure() routine. +scsi_change_queue_depth() in its slave_configure() routine. *** For scsi devices that the mid level tries to scan but do not respond, a slave_alloc(), slave_destroy() pair is called. @@ -203,7 +203,7 @@ LLD mid level LLD scsi_add_device() ------+ | slave_alloc() - slave_configure() [--> scsi_adjust_queue_depth()] + slave_configure() [--> scsi_change_queue_depth()] ------------------------------------------------------------ In a similar fashion, an LLD may become aware that a SCSI device has been @@ -261,7 +261,7 @@ init_this_scsi_driver() ----+ | scsi_register() | slave_alloc() - slave_configure() --> scsi_adjust_queue_depth() + slave_configure() --> scsi_change_queue_depth() slave_alloc() *** slave_destroy() *** | @@ -271,7 +271,7 @@ init_this_scsi_driver() ----+ slave_destroy() *** ------------------------------------------------------------ -The mid level invokes scsi_adjust_queue_depth() with "cmd_per_lun" for that +The mid level invokes scsi_change_queue_depth() with "cmd_per_lun" for that host as the queue length. These settings can be overridden by a slave_configure() supplied by the LLD. @@ -368,7 +368,7 @@ names all start with "scsi_". Summary: scsi_add_device - creates new scsi device (lu) instance scsi_add_host - perform sysfs registration and set up transport class - scsi_adjust_queue_depth - change the queue depth on a SCSI device + scsi_change_queue_depth - change the queue depth on a SCSI device scsi_bios_ptable - return copy of block device's partition table scsi_block_requests - prevent further commands being queued to given host scsi_host_alloc - return a new scsi_host instance whose refcount==1 @@ -436,7 +436,7 @@ int scsi_add_host(struct Scsi_Host *shost, struct device * dev) /** - * scsi_adjust_queue_depth - allow LLD to change queue depth on a SCSI device + * scsi_change_queue_depth - allow LLD to change queue depth on a SCSI device * @sdev: pointer to SCSI device to change queue depth on * @tags Number of tags allowed if tagged queuing enabled, * or number of commands the LLD can queue up @@ -453,7 +453,7 @@ int scsi_add_host(struct Scsi_Host *shost, struct device * dev) * Defined in: drivers/scsi/scsi.c [see source code for more notes] * **/ -void scsi_adjust_queue_depth(struct scsi_device *sdev, int tags) +int scsi_change_queue_depth(struct scsi_device *sdev, int tags) /** @@ -1214,7 +1214,7 @@ of interest: for disk firmware uploads. cmd_per_lun - maximum number of commands that can be queued on devices controlled by the host. Overridden by LLD calls to - scsi_adjust_queue_depth(). + scsi_change_queue_depth(). unchecked_isa_dma - 1=>only use bottom 16 MB of ram (ISA DMA addressing restriction), 0=>can use full 32 bit (or better) DMA address space @@ -1254,7 +1254,7 @@ struct scsi_cmnd Instances of this structure convey SCSI commands to the LLD and responses back to the mid level. The SCSI mid level will ensure that no more SCSI commands become queued against the LLD than are indicated by -scsi_adjust_queue_depth() (or struct Scsi_Host::cmd_per_lun). There will +scsi_change_queue_depth() (or struct Scsi_Host::cmd_per_lun). There will be at least one instance of struct scsi_cmnd available for each SCSI device. Members of interest: cmnd - array containing SCSI command diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index c8bb6abbf12c..de46385dbe71 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -1164,7 +1164,7 @@ static int ata_scsi_dev_config(struct scsi_device *sdev, depth = min(sdev->host->can_queue, ata_id_queue_depth(dev->id)); depth = min(ATA_MAX_QUEUE - 1, depth); - scsi_adjust_queue_depth(sdev, depth); + scsi_change_queue_depth(sdev, depth); } blk_queue_flush_queueable(q, false); @@ -1243,21 +1243,17 @@ void ata_scsi_slave_destroy(struct scsi_device *sdev) * @ap: ATA port to which the device change the queue depth * @sdev: SCSI device to configure queue depth for * @queue_depth: new queue depth - * @reason: calling context * * libsas and libata have different approaches for associating a sdev to * its ata_port. * */ int __ata_change_queue_depth(struct ata_port *ap, struct scsi_device *sdev, - int queue_depth, int reason) + int queue_depth) { struct ata_device *dev; unsigned long flags; - if (reason != SCSI_QDEPTH_DEFAULT) - return -EOPNOTSUPP; - if (queue_depth < 1 || queue_depth == sdev->queue_depth) return sdev->queue_depth; @@ -1282,15 +1278,13 @@ int __ata_change_queue_depth(struct ata_port *ap, struct scsi_device *sdev, if (sdev->queue_depth == queue_depth) return -EINVAL; - scsi_adjust_queue_depth(sdev, queue_depth); - return queue_depth; + return scsi_change_queue_depth(sdev, queue_depth); } /** * ata_scsi_change_queue_depth - SCSI callback for queue depth config * @sdev: SCSI device to configure queue depth for * @queue_depth: new queue depth - * @reason: calling context * * This is libata standard hostt->change_queue_depth callback. * SCSI will call into this callback when user tries to set queue @@ -1302,12 +1296,11 @@ int __ata_change_queue_depth(struct ata_port *ap, struct scsi_device *sdev, * RETURNS: * Newly configured queue depth. */ -int ata_scsi_change_queue_depth(struct scsi_device *sdev, int queue_depth, - int reason) +int ata_scsi_change_queue_depth(struct scsi_device *sdev, int queue_depth) { struct ata_port *ap = ata_shost_to_port(sdev->host); - return __ata_change_queue_depth(ap, sdev, queue_depth, reason); + return __ata_change_queue_depth(ap, sdev, queue_depth); } /** diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c index cdf99fac139a..1db6f5ce5e89 100644 --- a/drivers/ata/sata_nv.c +++ b/drivers/ata/sata_nv.c @@ -1951,7 +1951,7 @@ static int nv_swncq_slave_config(struct scsi_device *sdev) ata_id_c_string(dev->id, model_num, ATA_ID_PROD, sizeof(model_num)); if (strncmp(model_num, "Maxtor", 6) == 0) { - ata_scsi_change_queue_depth(sdev, 1, SCSI_QDEPTH_DEFAULT); + ata_scsi_change_queue_depth(sdev, 1); ata_dev_notice(dev, "Disabling SWNCQ mode (depth %x)\n", sdev->queue_depth); } diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c index 812a2891de58..20ca6a619476 100644 --- a/drivers/infiniband/ulp/iser/iscsi_iser.c +++ b/drivers/infiniband/ulp/iser/iscsi_iser.c @@ -911,7 +911,7 @@ static struct scsi_host_template iscsi_iser_sht = { .module = THIS_MODULE, .name = "iSCSI Initiator over iSER", .queuecommand = iscsi_queuecommand, - .change_queue_depth = iscsi_change_queue_depth, + .change_queue_depth = scsi_change_queue_depth, .sg_tablesize = ISCSI_ISER_SG_TABLESIZE, .max_sectors = 1024, .cmd_per_lun = ISER_DEF_CMD_PER_LUN, diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c index 8d13a19e04b2..5461924c9f10 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.c +++ b/drivers/infiniband/ulp/srp/ib_srp.c @@ -2402,18 +2402,15 @@ static int srp_cm_handler(struct ib_cm_id *cm_id, struct ib_cm_event *event) * srp_change_queue_depth - setting device queue depth * @sdev: scsi device struct * @qdepth: requested queue depth - * @reason: SCSI_QDEPTH_DEFAULT - * (see include/scsi/scsi_host.h for definition) * * Returns queue depth. */ static int -srp_change_queue_depth(struct scsi_device *sdev, int qdepth, int reason) +srp_change_queue_depth(struct scsi_device *sdev, int qdepth) { if (!sdev->tagged_supported) qdepth = 1; - scsi_adjust_queue_depth(sdev, qdepth); - return sdev->queue_depth; + return scsi_change_queue_depth(sdev, qdepth); } static int srp_send_tsk_mgmt(struct srp_rdma_ch *ch, u64 req_tag, diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c index dee06d6f0b68..6c9fc11efb87 100644 --- a/drivers/message/fusion/mptscsih.c +++ b/drivers/message/fusion/mptscsih.c @@ -2311,12 +2311,11 @@ mptscsih_slave_destroy(struct scsi_device *sdev) * mptscsih_change_queue_depth - This function will set a devices queue depth * @sdev: per scsi_device pointer * @qdepth: requested queue depth - * @reason: calling context * * Adding support for new 'change_queue_depth' api. */ int -mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth, int reason) +mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth) { MPT_SCSI_HOST *hd = shost_priv(sdev->host); VirtTarget *vtarget; @@ -2327,9 +2326,6 @@ mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth, int reason) starget = scsi_target(sdev); vtarget = starget->hostdata; - if (reason != SCSI_QDEPTH_DEFAULT) - return -EOPNOTSUPP; - if (ioc->bus_type == SPI) { if (!(vtarget->tflags & MPT_TARGET_FLAGS_Q_YES)) max_depth = 1; @@ -2347,8 +2343,7 @@ mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth, int reason) if (qdepth > max_depth) qdepth = max_depth; - scsi_adjust_queue_depth(sdev, qdepth); - return sdev->queue_depth; + return scsi_change_queue_depth(sdev, qdepth); } /* @@ -2392,8 +2387,7 @@ mptscsih_slave_configure(struct scsi_device *sdev) ioc->name, vtarget->negoFlags, vtarget->maxOffset, vtarget->minSyncFactor)); - mptscsih_change_queue_depth(sdev, MPT_SCSI_CMD_PER_DEV_HIGH, - SCSI_QDEPTH_DEFAULT); + mptscsih_change_queue_depth(sdev, MPT_SCSI_CMD_PER_DEV_HIGH); dsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "tagged %d, simple %d\n", ioc->name,sdev->tagged_supported, sdev->simple_tags)); diff --git a/drivers/message/fusion/mptscsih.h b/drivers/message/fusion/mptscsih.h index e1b1a198a62a..2baeefd9be7a 100644 --- a/drivers/message/fusion/mptscsih.h +++ b/drivers/message/fusion/mptscsih.h @@ -128,8 +128,7 @@ extern int mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_F extern int mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r); extern int mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply); extern int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset); -extern int mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth, - int reason); +extern int mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth); extern u8 mptscsih_raid_id_to_num(MPT_ADAPTER *ioc, u8 channel, u8 id); extern int mptscsih_is_phys_disk(MPT_ADAPTER *ioc, u8 channel, u8 id); extern struct device_attribute *mptscsih_host_attrs[]; diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index 179bf3d8af6c..75f4bfc2b98a 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c @@ -32,13 +32,6 @@ static bool allow_lun_scan = 1; module_param(allow_lun_scan, bool, 0600); MODULE_PARM_DESC(allow_lun_scan, "For NPIV, scan and attach all storage LUNs"); -static int zfcp_scsi_change_queue_depth(struct scsi_device *sdev, int depth, - int reason) -{ - scsi_adjust_queue_depth(sdev, depth); - return sdev->queue_depth; -} - static void zfcp_scsi_slave_destroy(struct scsi_device *sdev) { struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); @@ -54,7 +47,7 @@ static void zfcp_scsi_slave_destroy(struct scsi_device *sdev) static int zfcp_scsi_slave_configure(struct scsi_device *sdp) { if (sdp->tagged_supported) - scsi_adjust_queue_depth(sdp, default_depth); + scsi_change_queue_depth(sdp, default_depth); return 0; } @@ -293,7 +286,7 @@ static struct scsi_host_template zfcp_scsi_host_template = { .slave_alloc = zfcp_scsi_slave_alloc, .slave_configure = zfcp_scsi_slave_configure, .slave_destroy = zfcp_scsi_slave_destroy, - .change_queue_depth = zfcp_scsi_change_queue_depth, + .change_queue_depth = scsi_change_queue_depth, .proc_name = "zfcp", .can_queue = 4096, .this_id = -1, diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c index 1cf37032290a..cd4129ff7ae4 100644 --- a/drivers/scsi/3w-9xxx.c +++ b/drivers/scsi/3w-9xxx.c @@ -189,17 +189,6 @@ static ssize_t twa_show_stats(struct device *dev, return len; } /* End twa_show_stats() */ -/* This function will set a devices queue depth */ -static int twa_change_queue_depth(struct scsi_device *sdev, int queue_depth, - int reason) -{ - if (reason != SCSI_QDEPTH_DEFAULT) - return -EOPNOTSUPP; - - scsi_adjust_queue_depth(sdev, queue_depth); - return queue_depth; -} /* End twa_change_queue_depth() */ - /* Create sysfs 'stats' entry */ static struct device_attribute twa_host_stats_attr = { .attr = { @@ -2014,7 +2003,7 @@ static struct scsi_host_template driver_template = { .queuecommand = twa_scsi_queue, .eh_host_reset_handler = twa_scsi_eh_reset, .bios_param = twa_scsi_biosparam, - .change_queue_depth = twa_change_queue_depth, + .change_queue_depth = scsi_change_queue_depth, .can_queue = TW_Q_LENGTH-2, .slave_configure = twa_slave_configure, .this_id = -1, diff --git a/drivers/scsi/3w-sas.c b/drivers/scsi/3w-sas.c index 547756b7d5bf..2361772d5909 100644 --- a/drivers/scsi/3w-sas.c +++ b/drivers/scsi/3w-sas.c @@ -191,17 +191,6 @@ static ssize_t twl_show_stats(struct device *dev, return len; } /* End twl_show_stats() */ -/* This function will set a devices queue depth */ -static int twl_change_queue_depth(struct scsi_device *sdev, int queue_depth, - int reason) -{ - if (reason != SCSI_QDEPTH_DEFAULT) - return -EOPNOTSUPP; - - scsi_adjust_queue_depth(sdev, queue_depth); - return queue_depth; -} /* End twl_change_queue_depth() */ - /* stats sysfs attribute initializer */ static struct device_attribute twl_host_stats_attr = { .attr = { @@ -1588,7 +1577,7 @@ static struct scsi_host_template driver_template = { .queuecommand = twl_scsi_queue, .eh_host_reset_handler = twl_scsi_eh_reset, .bios_param = twl_scsi_biosparam, - .change_queue_depth = twl_change_queue_depth, + .change_queue_depth = scsi_change_queue_depth, .can_queue = TW_Q_LENGTH-2, .slave_configure = twl_slave_configure, .this_id = -1, diff --git a/drivers/scsi/3w-xxxx.c b/drivers/scsi/3w-xxxx.c index 261a4c1da962..c75f2048319f 100644 --- a/drivers/scsi/3w-xxxx.c +++ b/drivers/scsi/3w-xxxx.c @@ -523,17 +523,6 @@ static ssize_t tw_show_stats(struct device *dev, struct device_attribute *attr, return len; } /* End tw_show_stats() */ -/* This function will set a devices queue depth */ -static int tw_change_queue_depth(struct scsi_device *sdev, int queue_depth, - int reason) -{ - if (reason != SCSI_QDEPTH_DEFAULT) - return -EOPNOTSUPP; - - scsi_adjust_queue_depth(sdev, queue_depth); - return queue_depth; -} /* End tw_change_queue_depth() */ - /* Create sysfs 'stats' entry */ static struct device_attribute tw_host_stats_attr = { .attr = { @@ -2268,7 +2257,7 @@ static struct scsi_host_template driver_template = { .queuecommand = tw_scsi_queue, .eh_host_reset_handler = tw_scsi_eh_reset, .bios_param = tw_scsi_biosparam, - .change_queue_depth = tw_change_queue_depth, + .change_queue_depth = scsi_change_queue_depth, .can_queue = TW_Q_LENGTH-2, .slave_configure = tw_slave_configure, .this_id = -1, diff --git a/drivers/scsi/53c700.c b/drivers/scsi/53c700.c index d7557b932113..aa915da2a5e5 100644 --- a/drivers/scsi/53c700.c +++ b/drivers/scsi/53c700.c @@ -175,7 +175,7 @@ STATIC void NCR_700_chip_reset(struct Scsi_Host *host); STATIC int NCR_700_slave_alloc(struct scsi_device *SDpnt); STATIC int NCR_700_slave_configure(struct scsi_device *SDpnt); STATIC void NCR_700_slave_destroy(struct scsi_device *SDpnt); -static int NCR_700_change_queue_depth(struct scsi_device *SDpnt, int depth, int reason); +static int NCR_700_change_queue_depth(struct scsi_device *SDpnt, int depth); static int NCR_700_change_queue_type(struct scsi_device *SDpnt, int depth); STATIC struct device_attribute *NCR_700_dev_attrs[]; @@ -904,7 +904,7 @@ process_message(struct Scsi_Host *host, struct NCR_700_Host_Parameters *hostdata hostdata->tag_negotiated &= ~(1<device->tagged_supported = 0; - scsi_adjust_queue_depth(SCp->device, host->cmd_per_lun); + scsi_change_queue_depth(SCp->device, host->cmd_per_lun); scsi_set_tag_type(SCp->device, 0); } else { shost_printk(KERN_WARNING, host, @@ -2052,7 +2052,7 @@ NCR_700_slave_configure(struct scsi_device *SDp) /* to do here: allocate memory; build a queue_full list */ if(SDp->tagged_supported) { - scsi_adjust_queue_depth(SDp, NCR_700_DEFAULT_TAGS); + scsi_change_queue_depth(SDp, NCR_700_DEFAULT_TAGS); NCR_700_set_tag_neg_state(SDp, NCR_700_START_TAG_NEGOTIATION); } @@ -2075,16 +2075,11 @@ NCR_700_slave_destroy(struct scsi_device *SDp) } static int -NCR_700_change_queue_depth(struct scsi_device *SDp, int depth, int reason) +NCR_700_change_queue_depth(struct scsi_device *SDp, int depth) { - if (reason != SCSI_QDEPTH_DEFAULT) - return -EOPNOTSUPP; - if (depth > NCR_700_MAX_TAGS) depth = NCR_700_MAX_TAGS; - - scsi_adjust_queue_depth(SDp, depth); - return depth; + return scsi_change_queue_depth(SDp, depth); } static int NCR_700_change_queue_type(struct scsi_device *SDp, int tag_type) @@ -2105,12 +2100,12 @@ static int NCR_700_change_queue_type(struct scsi_device *SDp, int tag_type) if (!tag_type) { /* shift back to the default unqueued number of commands * (the user can still raise this) */ - scsi_adjust_queue_depth(SDp, SDp->host->cmd_per_lun); + scsi_change_queue_depth(SDp, SDp->host->cmd_per_lun); hostdata->tag_negotiated &= ~(1 << sdev_id(SDp)); } else { /* Here, we cleared the negotiation flag above, so this * will force the driver to renegotiate */ - scsi_adjust_queue_depth(SDp, SDp->queue_depth); + scsi_change_queue_depth(SDp, SDp->queue_depth); if (change_tag) NCR_700_set_tag_neg_state(SDp, NCR_700_START_TAG_NEGOTIATION); } diff --git a/drivers/scsi/BusLogic.c b/drivers/scsi/BusLogic.c index 5aa476b6b8a8..8d66a6469e29 100644 --- a/drivers/scsi/BusLogic.c +++ b/drivers/scsi/BusLogic.c @@ -2327,12 +2327,12 @@ static int blogic_slaveconfig(struct scsi_device *dev) if (qdepth == 0) qdepth = BLOGIC_MAX_AUTO_TAG_DEPTH; adapter->qdepth[tgt_id] = qdepth; - scsi_adjust_queue_depth(dev, qdepth); + scsi_change_queue_depth(dev, qdepth); } else { adapter->tagq_ok &= ~(1 << tgt_id); qdepth = adapter->untag_qdepth; adapter->qdepth[tgt_id] = qdepth; - scsi_adjust_queue_depth(dev, qdepth); + scsi_change_queue_depth(dev, qdepth); } qdepth = 0; for (tgt_id = 0; tgt_id < adapter->maxdev; tgt_id++) diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c index 41b9c68bca67..d11c23aad046 100644 --- a/drivers/scsi/aacraid/linit.c +++ b/drivers/scsi/aacraid/linit.c @@ -462,9 +462,9 @@ static int aac_slave_configure(struct scsi_device *sdev) depth = 256; else if (depth < 2) depth = 2; - scsi_adjust_queue_depth(sdev, depth); + scsi_change_queue_depth(sdev, depth); } else - scsi_adjust_queue_depth(sdev, 1); + scsi_change_queue_depth(sdev, 1); return 0; } @@ -478,12 +478,8 @@ static int aac_slave_configure(struct scsi_device *sdev) * total capacity and the queue depth supported by the target device. */ -static int aac_change_queue_depth(struct scsi_device *sdev, int depth, - int reason) +static int aac_change_queue_depth(struct scsi_device *sdev, int depth) { - if (reason != SCSI_QDEPTH_DEFAULT) - return -EOPNOTSUPP; - if (sdev->tagged_supported && (sdev->type == TYPE_DISK) && (sdev_channel(sdev) == CONTAINER_CHANNEL)) { struct scsi_device * dev; @@ -504,10 +500,10 @@ static int aac_change_queue_depth(struct scsi_device *sdev, int depth, depth = 256; else if (depth < 2) depth = 2; - scsi_adjust_queue_depth(sdev, depth); - } else - scsi_adjust_queue_depth(sdev, 1); - return sdev->queue_depth; + return scsi_change_queue_depth(sdev, depth); + } + + return scsi_change_queue_depth(sdev, 1); } static ssize_t aac_show_raid_level(struct device *dev, struct device_attribute *attr, char *buf) diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c index ae4840e4c1c5..6719a3390ebd 100644 --- a/drivers/scsi/advansys.c +++ b/drivers/scsi/advansys.c @@ -7706,7 +7706,7 @@ advansys_narrow_slave_configure(struct scsi_device *sdev, ASC_DVC_VAR *asc_dvc) asc_dvc->cfg->can_tagged_qng |= tid_bit; asc_dvc->use_tagged_qng |= tid_bit; } - scsi_adjust_queue_depth(sdev, + scsi_change_queue_depth(sdev, asc_dvc->max_dvc_qng[sdev->id]); } } else { @@ -7847,10 +7847,8 @@ advansys_wide_slave_configure(struct scsi_device *sdev, ADV_DVC_VAR *adv_dvc) } } - if ((adv_dvc->tagqng_able & tidmask) && sdev->tagged_supported) { - scsi_adjust_queue_depth(sdev, - adv_dvc->max_dvc_qng); - } + if ((adv_dvc->tagqng_able & tidmask) && sdev->tagged_supported) + scsi_change_queue_depth(sdev, adv_dvc->max_dvc_qng); } /* diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c index 80cb4fd7caaa..d5c7b193d8d3 100644 --- a/drivers/scsi/aic7xxx/aic79xx_osm.c +++ b/drivers/scsi/aic7xxx/aic79xx_osm.c @@ -1470,7 +1470,7 @@ ahd_platform_set_tags(struct ahd_softc *ahd, struct scsi_device *sdev, switch ((dev->flags & (AHD_DEV_Q_BASIC|AHD_DEV_Q_TAGGED))) { case AHD_DEV_Q_BASIC: case AHD_DEV_Q_TAGGED: - scsi_adjust_queue_depth(sdev, + scsi_change_queue_depth(sdev, dev->openings + dev->active); break; default: @@ -1480,7 +1480,7 @@ ahd_platform_set_tags(struct ahd_softc *ahd, struct scsi_device *sdev, * serially on the controller/device. This should * remove some latency. */ - scsi_adjust_queue_depth(sdev, 1); + scsi_change_queue_depth(sdev, 1); break; } } diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c index a6a27d5398dd..88360116dbcb 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm.c +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c @@ -1336,7 +1336,7 @@ ahc_platform_set_tags(struct ahc_softc *ahc, struct scsi_device *sdev, switch ((dev->flags & (AHC_DEV_Q_BASIC|AHC_DEV_Q_TAGGED))) { case AHC_DEV_Q_BASIC: case AHC_DEV_Q_TAGGED: - scsi_adjust_queue_depth(sdev, + scsi_change_queue_depth(sdev, dev->openings + dev->active); default: /* @@ -1345,7 +1345,7 @@ ahc_platform_set_tags(struct ahc_softc *ahc, struct scsi_device *sdev, * serially on the controller/device. This should * remove some latency. */ - scsi_adjust_queue_depth(sdev, 2); + scsi_change_queue_depth(sdev, 2); break; } } diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c index 209f77162d06..914c39f9f388 100644 --- a/drivers/scsi/arcmsr/arcmsr_hba.c +++ b/drivers/scsi/arcmsr/arcmsr_hba.c @@ -114,16 +114,11 @@ static void arcmsr_hardware_reset(struct AdapterControlBlock *acb); static const char *arcmsr_info(struct Scsi_Host *); static irqreturn_t arcmsr_interrupt(struct AdapterControlBlock *acb); static void arcmsr_free_irq(struct pci_dev *, struct AdapterControlBlock *); -static int arcmsr_adjust_disk_queue_depth(struct scsi_device *sdev, - int queue_depth, int reason) +static int arcmsr_adjust_disk_queue_depth(struct scsi_device *sdev, int queue_depth) { - if (reason != SCSI_QDEPTH_DEFAULT) - return -EOPNOTSUPP; - if (queue_depth > ARCMSR_MAX_CMD_PERLUN) queue_depth = ARCMSR_MAX_CMD_PERLUN; - scsi_adjust_queue_depth(sdev, queue_depth); - return queue_depth; + return scsi_change_queue_depth(sdev, queue_depth); } static struct scsi_host_template arcmsr_scsi_host_template = { diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c index d9b999a3416f..f3193406776c 100644 --- a/drivers/scsi/be2iscsi/be_main.c +++ b/drivers/scsi/be2iscsi/be_main.c @@ -556,7 +556,7 @@ static struct scsi_host_template beiscsi_sht = { .name = "Emulex 10Gbe open-iscsi Initiator Driver", .proc_name = DRV_NAME, .queuecommand = iscsi_queuecommand, - .change_queue_depth = iscsi_change_queue_depth, + .change_queue_depth = scsi_change_queue_depth, .slave_configure = beiscsi_slave_configure, .target_alloc = iscsi_target_alloc, .eh_abort_handler = beiscsi_eh_abort, diff --git a/drivers/scsi/bfa/bfad_im.c b/drivers/scsi/bfa/bfad_im.c index 87b09cd232cc..7223b0006740 100644 --- a/drivers/scsi/bfa/bfad_im.c +++ b/drivers/scsi/bfa/bfad_im.c @@ -776,7 +776,7 @@ bfad_thread_workq(struct bfad_s *bfad) static int bfad_im_slave_configure(struct scsi_device *sdev) { - scsi_adjust_queue_depth(sdev, bfa_lun_queue_depth); + scsi_change_queue_depth(sdev, bfa_lun_queue_depth); return 0; } @@ -866,7 +866,7 @@ bfad_ramp_up_qdepth(struct bfad_itnim_s *itnim, struct scsi_device *sdev) if (bfa_lun_queue_depth > tmp_sdev->queue_depth) { if (tmp_sdev->id != sdev->id) continue; - scsi_adjust_queue_depth(tmp_sdev, + scsi_change_queue_depth(tmp_sdev, tmp_sdev->queue_depth + 1); itnim->last_ramp_up_time = jiffies; diff --git a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c index cc537972f3ea..386c2cfad306 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c +++ b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c @@ -2784,7 +2784,7 @@ static struct scsi_host_template bnx2fc_shost_template = { .eh_target_reset_handler = bnx2fc_eh_target_reset, /* tgt reset */ .eh_host_reset_handler = fc_eh_host_reset, .slave_alloc = fc_slave_alloc, - .change_queue_depth = fc_change_queue_depth, + .change_queue_depth = scsi_change_queue_depth, .change_queue_type = scsi_change_queue_type, .this_id = -1, .cmd_per_lun = 3, diff --git a/drivers/scsi/bnx2i/bnx2i_iscsi.c b/drivers/scsi/bnx2i/bnx2i_iscsi.c index 9de1c20bb0f8..e53078d03309 100644 --- a/drivers/scsi/bnx2i/bnx2i_iscsi.c +++ b/drivers/scsi/bnx2i/bnx2i_iscsi.c @@ -2259,7 +2259,7 @@ static struct scsi_host_template bnx2i_host_template = { .eh_abort_handler = iscsi_eh_abort, .eh_device_reset_handler = iscsi_eh_device_reset, .eh_target_reset_handler = iscsi_eh_recover_target, - .change_queue_depth = iscsi_change_queue_depth, + .change_queue_depth = scsi_change_queue_depth, .target_alloc = iscsi_target_alloc, .can_queue = 2048, .max_sectors = 127, diff --git a/drivers/scsi/csiostor/csio_scsi.c b/drivers/scsi/csiostor/csio_scsi.c index 44a8cc51428f..4d0b6ce55f20 100644 --- a/drivers/scsi/csiostor/csio_scsi.c +++ b/drivers/scsi/csiostor/csio_scsi.c @@ -2241,7 +2241,7 @@ csio_slave_alloc(struct scsi_device *sdev) static int csio_slave_configure(struct scsi_device *sdev) { - scsi_adjust_queue_depth(sdev, csio_lun_qdepth); + scsi_change_queue_depth(sdev, csio_lun_qdepth); return 0; } diff --git a/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c b/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c index 99ea67dcdd2a..3db4c63978c5 100644 --- a/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c +++ b/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c @@ -86,7 +86,7 @@ static struct scsi_host_template cxgb3i_host_template = { .proc_name = DRV_MODULE_NAME, .can_queue = CXGB3I_SCSI_HOST_QDEPTH, .queuecommand = iscsi_queuecommand, - .change_queue_depth = iscsi_change_queue_depth, + .change_queue_depth = scsi_change_queue_depth, .sg_tablesize = SG_ALL, .max_sectors = 0xFFFF, .cmd_per_lun = ISCSI_DEF_CMD_PER_LUN, diff --git a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c index af86e8f57b84..efe42ef7d92b 100644 --- a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c +++ b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c @@ -89,7 +89,7 @@ static struct scsi_host_template cxgb4i_host_template = { .proc_name = DRV_MODULE_NAME, .can_queue = CXGB4I_SCSI_HOST_QDEPTH, .queuecommand = iscsi_queuecommand, - .change_queue_depth = iscsi_change_queue_depth, + .change_queue_depth = scsi_change_queue_depth, .sg_tablesize = SG_ALL, .max_sectors = 0xFFFF, .cmd_per_lun = ISCSI_DEF_CMD_PER_LUN, diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c index 1af8d54bcded..0bf976936a10 100644 --- a/drivers/scsi/dpt_i2o.c +++ b/drivers/scsi/dpt_i2o.c @@ -415,7 +415,7 @@ static int adpt_slave_configure(struct scsi_device * device) pHba = (adpt_hba *) host->hostdata[0]; if (host->can_queue && device->tagged_supported) { - scsi_adjust_queue_depth(device, + scsi_change_queue_depth(device, host->can_queue - 1); } return 0; diff --git a/drivers/scsi/eata.c b/drivers/scsi/eata.c index bc0f918f1729..227dd2c2ec2f 100644 --- a/drivers/scsi/eata.c +++ b/drivers/scsi/eata.c @@ -952,12 +952,12 @@ static int eata2x_slave_configure(struct scsi_device *dev) } else { tag_suffix = ", no tags"; } - scsi_adjust_queue_depth(dev, tqd); + scsi_change_queue_depth(dev, tqd); } else if (TLDEV(dev->type) && linked_comm) { - scsi_adjust_queue_depth(dev, tqd); + scsi_change_queue_depth(dev, tqd); tag_suffix = ", untagged"; } else { - scsi_adjust_queue_depth(dev, utqd); + scsi_change_queue_depth(dev, utqd); tag_suffix = ""; } diff --git a/drivers/scsi/esas2r/esas2r.h b/drivers/scsi/esas2r/esas2r.h index 1941d837f6f2..b6030e3edd01 100644 --- a/drivers/scsi/esas2r/esas2r.h +++ b/drivers/scsi/esas2r/esas2r.h @@ -972,7 +972,6 @@ u8 handle_hba_ioctl(struct esas2r_adapter *a, struct atto_ioctl *ioctl_hba); int esas2r_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd); int esas2r_show_info(struct seq_file *m, struct Scsi_Host *sh); -int esas2r_change_queue_depth(struct scsi_device *dev, int depth, int reason); long esas2r_proc_ioctl(struct file *fp, unsigned int cmd, unsigned long arg); /* SCSI error handler (eh) functions */ diff --git a/drivers/scsi/esas2r/esas2r_main.c b/drivers/scsi/esas2r/esas2r_main.c index 30fce64faf75..593ff8a63c70 100644 --- a/drivers/scsi/esas2r/esas2r_main.c +++ b/drivers/scsi/esas2r/esas2r_main.c @@ -254,7 +254,7 @@ static struct scsi_host_template driver_template = { .use_clustering = ENABLE_CLUSTERING, .emulated = 0, .proc_name = ESAS2R_DRVR_NAME, - .change_queue_depth = esas2r_change_queue_depth, + .change_queue_depth = scsi_change_queue_depth, .change_queue_type = scsi_change_queue_type, .max_sectors = 0xFFFF, .use_blk_tags = 1, @@ -1257,15 +1257,6 @@ int esas2r_target_reset(struct scsi_cmnd *cmd) return esas2r_dev_targ_reset(cmd, true); } -int esas2r_change_queue_depth(struct scsi_device *dev, int depth, int reason) -{ - esas2r_log(ESAS2R_LOG_INFO, "change_queue_depth %p, %d", dev, depth); - - scsi_adjust_queue_depth(dev, depth); - - return dev->queue_depth; -} - void esas2r_log_request_failure(struct esas2r_adapter *a, struct esas2r_request *rq) { diff --git a/drivers/scsi/esp_scsi.c b/drivers/scsi/esp_scsi.c index 38c23e0b73af..7e7687f73deb 100644 --- a/drivers/scsi/esp_scsi.c +++ b/drivers/scsi/esp_scsi.c @@ -2407,7 +2407,7 @@ static int esp_slave_configure(struct scsi_device *dev) /* XXX make this configurable somehow XXX */ int goal_tags = min(ESP_DEFAULT_TAGS, ESP_MAX_TAG); - scsi_adjust_queue_depth(dev, goal_tags); + scsi_change_queue_depth(dev, goal_tags); } tp->flags |= ESP_TGT_DISCONNECT; diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c index 97229860398f..308a016fdaea 100644 --- a/drivers/scsi/fcoe/fcoe.c +++ b/drivers/scsi/fcoe/fcoe.c @@ -280,7 +280,7 @@ static struct scsi_host_template fcoe_shost_template = { .eh_device_reset_handler = fc_eh_device_reset, .eh_host_reset_handler = fc_eh_host_reset, .slave_alloc = fc_slave_alloc, - .change_queue_depth = fc_change_queue_depth, + .change_queue_depth = scsi_change_queue_depth, .change_queue_type = scsi_change_queue_type, .this_id = -1, .cmd_per_lun = 3, diff --git a/drivers/scsi/fnic/fnic_main.c b/drivers/scsi/fnic/fnic_main.c index 86b496c8633d..0c1f8177b5b7 100644 --- a/drivers/scsi/fnic/fnic_main.c +++ b/drivers/scsi/fnic/fnic_main.c @@ -98,7 +98,7 @@ static int fnic_slave_alloc(struct scsi_device *sdev) if (!rport || fc_remote_port_chkready(rport)) return -ENXIO; - scsi_adjust_queue_depth(sdev, fnic_max_qdepth); + scsi_change_queue_depth(sdev, fnic_max_qdepth); return 0; } @@ -110,7 +110,7 @@ static struct scsi_host_template fnic_host_template = { .eh_device_reset_handler = fnic_device_reset, .eh_host_reset_handler = fnic_host_reset, .slave_alloc = fnic_slave_alloc, - .change_queue_depth = fc_change_queue_depth, + .change_queue_depth = scsi_change_queue_depth, .change_queue_type = scsi_change_queue_type, .this_id = -1, .cmd_per_lun = 3, diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 617f218e2a16..6bb4611b238a 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -216,8 +216,6 @@ static int hpsa_scsi_queue_command(struct Scsi_Host *h, struct scsi_cmnd *cmd); static void hpsa_scan_start(struct Scsi_Host *); static int hpsa_scan_finished(struct Scsi_Host *sh, unsigned long elapsed_time); -static int hpsa_change_queue_depth(struct scsi_device *sdev, - int qdepth, int reason); static int hpsa_eh_device_reset_handler(struct scsi_cmnd *scsicmd); static int hpsa_eh_abort_handler(struct scsi_cmnd *scsicmd); @@ -673,7 +671,7 @@ static struct scsi_host_template hpsa_driver_template = { .queuecommand = hpsa_scsi_queue_command, .scan_start = hpsa_scan_start, .scan_finished = hpsa_scan_finished, - .change_queue_depth = hpsa_change_queue_depth, + .change_queue_depth = scsi_change_queue_depth, .this_id = -1, .use_clustering = ENABLE_CLUSTERING, .eh_abort_handler = hpsa_eh_abort_handler, @@ -4074,18 +4072,6 @@ static int hpsa_scan_finished(struct Scsi_Host *sh, return finished; } -static int hpsa_change_queue_depth(struct scsi_device *sdev, - int qdepth, int reason) -{ - struct ctlr_info *h = sdev_to_hba(sdev); - - if (reason != SCSI_QDEPTH_DEFAULT) - return -ENOTSUPP; - - scsi_adjust_queue_depth(sdev, qdepth); - return sdev->queue_depth; -} - static void hpsa_unregister_scsi(struct ctlr_info *h) { /* we are being forcibly unloaded, and may not refuse. */ diff --git a/drivers/scsi/hptiop.c b/drivers/scsi/hptiop.c index 151893148abd..e995218476ed 100644 --- a/drivers/scsi/hptiop.c +++ b/drivers/scsi/hptiop.c @@ -1118,17 +1118,13 @@ static int hptiop_reset(struct scsi_cmnd *scp) } static int hptiop_adjust_disk_queue_depth(struct scsi_device *sdev, - int queue_depth, int reason) + int queue_depth) { struct hptiop_hba *hba = (struct hptiop_hba *)sdev->host->hostdata; - if (reason != SCSI_QDEPTH_DEFAULT) - return -EOPNOTSUPP; - if (queue_depth > hba->max_requests) queue_depth = hba->max_requests; - scsi_adjust_queue_depth(sdev, queue_depth); - return queue_depth; + return scsi_change_queue_depth(sdev, queue_depth); } static ssize_t hptiop_show_version(struct device *dev, diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c index 381449d5be76..f58c6d8e0264 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc.c +++ b/drivers/scsi/ibmvscsi/ibmvfc.c @@ -2900,17 +2900,12 @@ static int ibmvfc_slave_configure(struct scsi_device *sdev) * Return value: * actual depth set **/ -static int ibmvfc_change_queue_depth(struct scsi_device *sdev, int qdepth, - int reason) +static int ibmvfc_change_queue_depth(struct scsi_device *sdev, int qdepth) { - if (reason != SCSI_QDEPTH_DEFAULT) - return -EOPNOTSUPP; - if (qdepth > IBMVFC_MAX_CMDS_PER_LUN) qdepth = IBMVFC_MAX_CMDS_PER_LUN; - scsi_adjust_queue_depth(sdev, qdepth); - return sdev->queue_depth; + return scsi_change_queue_depth(sdev, qdepth); } static ssize_t ibmvfc_show_host_partition_name(struct device *dev, diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c index e8c3cdf0d03b..acea5d6eebd0 100644 --- a/drivers/scsi/ibmvscsi/ibmvscsi.c +++ b/drivers/scsi/ibmvscsi/ibmvscsi.c @@ -1941,17 +1941,11 @@ static int ibmvscsi_slave_configure(struct scsi_device *sdev) * Return value: * actual depth set **/ -static int ibmvscsi_change_queue_depth(struct scsi_device *sdev, int qdepth, - int reason) +static int ibmvscsi_change_queue_depth(struct scsi_device *sdev, int qdepth) { - if (reason != SCSI_QDEPTH_DEFAULT) - return -EOPNOTSUPP; - if (qdepth > IBMVSCSI_MAX_CMDS_PER_LUN) qdepth = IBMVSCSI_MAX_CMDS_PER_LUN; - - scsi_adjust_queue_depth(sdev, qdepth); - return sdev->queue_depth; + return scsi_change_queue_depth(sdev, qdepth); } /* ------------------------------------------------------------ diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index d8d16625a876..540294389355 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -4328,16 +4328,12 @@ static int ipr_free_dump(struct ipr_ioa_cfg *ioa_cfg) { return 0; }; * Return value: * actual depth set **/ -static int ipr_change_queue_depth(struct scsi_device *sdev, int qdepth, - int reason) +static int ipr_change_queue_depth(struct scsi_device *sdev, int qdepth) { struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)sdev->host->hostdata; struct ipr_resource_entry *res; unsigned long lock_flags = 0; - if (reason != SCSI_QDEPTH_DEFAULT) - return -EOPNOTSUPP; - spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags); res = (struct ipr_resource_entry *)sdev->hostdata; @@ -4345,7 +4341,7 @@ static int ipr_change_queue_depth(struct scsi_device *sdev, int qdepth, qdepth = IPR_MAX_CMD_PER_ATA_LUN; spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); - scsi_adjust_queue_depth(sdev, qdepth); + scsi_change_queue_depth(sdev, qdepth); return sdev->queue_depth; } @@ -4752,7 +4748,7 @@ static int ipr_slave_configure(struct scsi_device *sdev) spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); if (ap) { - scsi_adjust_queue_depth(sdev, IPR_MAX_CMD_PER_ATA_LUN); + scsi_change_queue_depth(sdev, IPR_MAX_CMD_PER_ATA_LUN); ata_sas_slave_configure(sdev, ap); } diff --git a/drivers/scsi/ips.c b/drivers/scsi/ips.c index 454741a8da45..e5c28435d768 100644 --- a/drivers/scsi/ips.c +++ b/drivers/scsi/ips.c @@ -1210,7 +1210,7 @@ ips_slave_configure(struct scsi_device * SDptr) min = ha->max_cmds / 2; if (ha->enq->ucLogDriveCount <= 2) min = ha->max_cmds - 1; - scsi_adjust_queue_depth(SDptr, min); + scsi_change_queue_depth(SDptr, min); } SDptr->skip_ms_page_8 = 1; diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index a575d845b667..0b8af186e707 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c @@ -952,7 +952,7 @@ static struct scsi_host_template iscsi_sw_tcp_sht = { .module = THIS_MODULE, .name = "iSCSI Initiator over TCP/IP", .queuecommand = iscsi_queuecommand, - .change_queue_depth = iscsi_change_queue_depth, + .change_queue_depth = scsi_change_queue_depth, .can_queue = ISCSI_DEF_XMIT_CMDS_MAX - 1, .sg_tablesize = 4096, .max_sectors = 0xFFFF, diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index 0d2d024e77c5..c6795941b45d 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c @@ -2160,24 +2160,11 @@ int fc_slave_alloc(struct scsi_device *sdev) if (!rport || fc_remote_port_chkready(rport)) return -ENXIO; - scsi_adjust_queue_depth(sdev, FC_FCP_DFLT_QUEUE_DEPTH); + scsi_change_queue_depth(sdev, FC_FCP_DFLT_QUEUE_DEPTH); return 0; } EXPORT_SYMBOL(fc_slave_alloc); -/** - * fc_change_queue_depth() - Change a device's queue depth - * @sdev: The SCSI device whose queue depth is to change - * @qdepth: The new queue depth - * @reason: The resason for the change - */ -int fc_change_queue_depth(struct scsi_device *sdev, int qdepth, int reason) -{ - scsi_adjust_queue_depth(sdev, qdepth); - return sdev->queue_depth; -} -EXPORT_SYMBOL(fc_change_queue_depth); - /** * fc_fcp_destory() - Tear down the FCP layer for a given local port * @lport: The local port that no longer needs the FCP layer diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 79e977484ad5..8053f24f0349 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -1771,13 +1771,6 @@ fault: } EXPORT_SYMBOL_GPL(iscsi_queuecommand); -int iscsi_change_queue_depth(struct scsi_device *sdev, int depth, int reason) -{ - scsi_adjust_queue_depth(sdev, depth); - return sdev->queue_depth; -} -EXPORT_SYMBOL_GPL(iscsi_change_queue_depth); - int iscsi_target_alloc(struct scsi_target *starget) { struct iscsi_cls_session *cls_session = starget_to_session(starget); diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c index 914e41165137..b492293d51f2 100644 --- a/drivers/scsi/libsas/sas_scsi_host.c +++ b/drivers/scsi/libsas/sas_scsi_host.c @@ -940,12 +940,12 @@ int sas_slave_configure(struct scsi_device *scsi_dev) sas_read_port_mode_page(scsi_dev); if (scsi_dev->tagged_supported) { - scsi_adjust_queue_depth(scsi_dev, SAS_DEF_QD); + scsi_change_queue_depth(scsi_dev, SAS_DEF_QD); } else { SAS_DPRINTK("device %llx, LUN %llx doesn't support " "TCQ\n", SAS_ADDR(dev->sas_addr), scsi_dev->lun); - scsi_adjust_queue_depth(scsi_dev, 1); + scsi_change_queue_depth(scsi_dev, 1); } scsi_dev->allow_restart = 1; @@ -953,18 +953,16 @@ int sas_slave_configure(struct scsi_device *scsi_dev) return 0; } -int sas_change_queue_depth(struct scsi_device *sdev, int depth, int reason) +int sas_change_queue_depth(struct scsi_device *sdev, int depth) { struct domain_device *dev = sdev_to_domain_dev(sdev); if (dev_is_sata(dev)) - return __ata_change_queue_depth(dev->sata_dev.ap, sdev, depth, - reason); + return __ata_change_queue_depth(dev->sata_dev.ap, sdev, depth); if (!sdev->tagged_supported) depth = 1; - scsi_adjust_queue_depth(sdev, depth); - return depth; + return scsi_change_queue_depth(sdev, depth); } int sas_change_queue_type(struct scsi_device *scsi_dev, int type) diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index 522854920369..fd85952b621d 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c @@ -242,23 +242,6 @@ lpfc_update_stats(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd) spin_unlock_irqrestore(shost->host_lock, flags); } -/** - * lpfc_change_queue_depth - Alter scsi device queue depth - * @sdev: Pointer the scsi device on which to change the queue depth. - * @qdepth: New queue depth to set the sdev to. - * @reason: The reason for the queue depth change. - * - * This function is called by the midlayer and the LLD to alter the queue - * depth for a scsi device. This function sets the queue depth to the new - * value and sends an event out to log the queue depth change. - **/ -static int -lpfc_change_queue_depth(struct scsi_device *sdev, int qdepth, int reason) -{ - scsi_adjust_queue_depth(sdev, qdepth); - return sdev->queue_depth; -} - /** * lpfc_rampdown_queue_depth - Post RAMP_DOWN_QUEUE event to worker thread * @phba: The Hba for which this call is being executed. @@ -344,8 +327,7 @@ lpfc_ramp_down_queue_handler(struct lpfc_hba *phba) else new_queue_depth = sdev->queue_depth - new_queue_depth; - lpfc_change_queue_depth(sdev, new_queue_depth, - SCSI_QDEPTH_DEFAULT); + scsi_change_queue_depth(sdev, new_queue_depth); } } lpfc_destroy_vport_work_array(phba, vports); @@ -5513,7 +5495,7 @@ lpfc_slave_configure(struct scsi_device *sdev) struct lpfc_vport *vport = (struct lpfc_vport *) sdev->host->hostdata; struct lpfc_hba *phba = vport->phba; - scsi_adjust_queue_depth(sdev, vport->cfg_lun_queue_depth); + scsi_change_queue_depth(sdev, vport->cfg_lun_queue_depth); if (phba->cfg_poll & ENABLE_FCP_RING_POLLING) { lpfc_sli_handle_fast_ring_event(phba, @@ -5896,7 +5878,7 @@ struct scsi_host_template lpfc_template = { .shost_attrs = lpfc_hba_attrs, .max_sectors = 0xFFFF, .vendor_id = LPFC_NL_VENDOR_ID, - .change_queue_depth = lpfc_change_queue_depth, + .change_queue_depth = scsi_change_queue_depth, .change_queue_type = scsi_change_queue_type, .use_blk_tags = 1, .track_queue_depth = 1, @@ -5921,7 +5903,7 @@ struct scsi_host_template lpfc_vport_template = { .use_clustering = ENABLE_CLUSTERING, .shost_attrs = lpfc_vport_attrs, .max_sectors = 0xFFFF, - .change_queue_depth = lpfc_change_queue_depth, + .change_queue_depth = scsi_change_queue_depth, .change_queue_type = scsi_change_queue_type, .use_blk_tags = 1, .track_queue_depth = 1, diff --git a/drivers/scsi/megaraid/megaraid_mbox.c b/drivers/scsi/megaraid/megaraid_mbox.c index d56eb9d3d40c..f0987f22ea70 100644 --- a/drivers/scsi/megaraid/megaraid_mbox.c +++ b/drivers/scsi/megaraid/megaraid_mbox.c @@ -332,25 +332,6 @@ static struct device_attribute *megaraid_sdev_attrs[] = { NULL, }; -/** - * megaraid_change_queue_depth - Change the device's queue depth - * @sdev: scsi device struct - * @qdepth: depth to set - * @reason: calling context - * - * Return value: - * actual depth set - */ -static int megaraid_change_queue_depth(struct scsi_device *sdev, int qdepth, - int reason) -{ - if (reason != SCSI_QDEPTH_DEFAULT) - return -EOPNOTSUPP; - - scsi_adjust_queue_depth(sdev, qdepth); - return sdev->queue_depth; -} - /* * Scsi host template for megaraid unified driver */ @@ -363,7 +344,7 @@ static struct scsi_host_template megaraid_template_g = { .eh_device_reset_handler = megaraid_reset_handler, .eh_bus_reset_handler = megaraid_reset_handler, .eh_host_reset_handler = megaraid_reset_handler, - .change_queue_depth = megaraid_change_queue_depth, + .change_queue_depth = scsi_change_queue_depth, .use_clustering = ENABLE_CLUSTERING, .no_write_same = 1, .sdev_attrs = megaraid_sdev_attrs, diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index 69a9dd6ae04c..f05580e693d0 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c @@ -2591,17 +2591,6 @@ megasas_service_aen(struct megasas_instance *instance, struct megasas_cmd *cmd) } } -static int megasas_change_queue_depth(struct scsi_device *sdev, - int queue_depth, int reason) -{ - if (reason != SCSI_QDEPTH_DEFAULT) - return -EOPNOTSUPP; - - scsi_adjust_queue_depth(sdev, queue_depth); - - return queue_depth; -} - static ssize_t megasas_fw_crash_buffer_store(struct device *cdev, struct device_attribute *attr, const char *buf, size_t count) @@ -2766,7 +2755,7 @@ static struct scsi_host_template megasas_template = { .shost_attrs = megaraid_host_attrs, .bios_param = megasas_bios_param, .use_clustering = ENABLE_CLUSTERING, - .change_queue_depth = megasas_change_queue_depth, + .change_queue_depth = scsi_change_queue_depth, .no_write_same = 1, }; diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c index b006e1e9fcb8..12229de433bf 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c +++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c @@ -1222,20 +1222,18 @@ _scsih_adjust_queue_depth(struct scsi_device *sdev, int qdepth) max_depth = 1; if (qdepth > max_depth) qdepth = max_depth; - scsi_adjust_queue_depth(sdev, qdepth); + scsi_change_queue_depth(sdev, qdepth); } /** * _scsih_change_queue_depth - setting device queue depth * @sdev: scsi device struct * @qdepth: requested queue depth - * @reason: SCSI_QDEPTH_DEFAULT - * (see include/scsi/scsi_host.h for definition) * * Returns queue depth. */ static int -_scsih_change_queue_depth(struct scsi_device *sdev, int qdepth, int reason) +_scsih_change_queue_depth(struct scsi_device *sdev, int qdepth) { _scsih_adjust_queue_depth(sdev, qdepth); @@ -2077,7 +2075,7 @@ _scsih_slave_configure(struct scsi_device *sdev) r_level, raid_device->handle, (unsigned long long)raid_device->wwid, raid_device->num_pds, ds); - _scsih_change_queue_depth(sdev, qdepth, SCSI_QDEPTH_DEFAULT); + _scsih_change_queue_depth(sdev, qdepth); /* raid transport support */ if (!ioc->is_warpdrive) _scsih_set_level(sdev, raid_device->volume_type); @@ -2142,7 +2140,7 @@ _scsih_slave_configure(struct scsi_device *sdev) _scsih_display_sata_capabilities(ioc, handle, sdev); - _scsih_change_queue_depth(sdev, qdepth, SCSI_QDEPTH_DEFAULT); + _scsih_change_queue_depth(sdev, qdepth); if (ssp_target) { sas_read_port_mode_page(sdev); diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c index 568dcaed36cb..de175b9915e2 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c +++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c @@ -1090,20 +1090,18 @@ _scsih_adjust_queue_depth(struct scsi_device *sdev, int qdepth) max_depth = 1; if (qdepth > max_depth) qdepth = max_depth; - scsi_adjust_queue_depth(sdev, qdepth); + scsi_change_queue_depth(sdev, qdepth); } /** * _scsih_change_queue_depth - setting device queue depth * @sdev: scsi device struct * @qdepth: requested queue depth - * @reason: SCSI_QDEPTH_DEFAULT - * (see include/scsi/scsi_host.h for definition) * * Returns queue depth. */ static int -_scsih_change_queue_depth(struct scsi_device *sdev, int qdepth, int reason) +_scsih_change_queue_depth(struct scsi_device *sdev, int qdepth) { _scsih_adjust_queue_depth(sdev, qdepth); @@ -1734,7 +1732,7 @@ _scsih_slave_configure(struct scsi_device *sdev) raid_device->num_pds, ds); - _scsih_change_queue_depth(sdev, qdepth, SCSI_QDEPTH_DEFAULT); + _scsih_change_queue_depth(sdev, qdepth); /* raid transport support */ _scsih_set_level(sdev, raid_device->volume_type); @@ -1800,7 +1798,7 @@ _scsih_slave_configure(struct scsi_device *sdev) _scsih_display_sata_capabilities(ioc, handle, sdev); - _scsih_change_queue_depth(sdev, qdepth, SCSI_QDEPTH_DEFAULT); + _scsih_change_queue_depth(sdev, qdepth); if (ssp_target) { sas_read_port_mode_page(sdev); diff --git a/drivers/scsi/ncr53c8xx.c b/drivers/scsi/ncr53c8xx.c index 9c331b7bfdcd..5b93ed810f6e 100644 --- a/drivers/scsi/ncr53c8xx.c +++ b/drivers/scsi/ncr53c8xx.c @@ -7997,7 +7997,7 @@ static int ncr53c8xx_slave_configure(struct scsi_device *device) if (depth_to_use > MAX_TAGS) depth_to_use = MAX_TAGS; - scsi_adjust_queue_depth(device, depth_to_use); + scsi_change_queue_depth(device, depth_to_use); /* ** Since the queue depth is not tunable under Linux, diff --git a/drivers/scsi/pmcraid.c b/drivers/scsi/pmcraid.c index d8b9ba251fbd..b1b1f66b1ab7 100644 --- a/drivers/scsi/pmcraid.c +++ b/drivers/scsi/pmcraid.c @@ -285,23 +285,15 @@ static void pmcraid_slave_destroy(struct scsi_device *scsi_dev) * pmcraid_change_queue_depth - Change the device's queue depth * @scsi_dev: scsi device struct * @depth: depth to set - * @reason: calling context * * Return value * actual depth set */ -static int pmcraid_change_queue_depth(struct scsi_device *scsi_dev, int depth, - int reason) +static int pmcraid_change_queue_depth(struct scsi_device *scsi_dev, int depth) { - if (reason != SCSI_QDEPTH_DEFAULT) - return -EOPNOTSUPP; - if (depth > PMCRAID_MAX_CMD_PER_LUN) depth = PMCRAID_MAX_CMD_PER_LUN; - - scsi_adjust_queue_depth(scsi_dev, depth); - - return scsi_dev->queue_depth; + return scsi_change_queue_depth(scsi_dev, depth); } /** diff --git a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c index adedb6ef8eec..c68a66e8cfc1 100644 --- a/drivers/scsi/qla1280.c +++ b/drivers/scsi/qla1280.c @@ -1224,9 +1224,9 @@ qla1280_slave_configure(struct scsi_device *device) if (device->tagged_supported && (ha->bus_settings[bus].qtag_enables & (BIT_0 << target))) { - scsi_adjust_queue_depth(device, ha->bus_settings[bus].hiwat); + scsi_change_queue_depth(device, ha->bus_settings[bus].hiwat); } else { - scsi_adjust_queue_depth(device, default_depth); + scsi_change_queue_depth(device, default_depth); } nv->bus[bus].target[target].parameter.enable_sync = device->sdtr; diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 20049b176b64..6b4d9235368a 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -236,7 +236,6 @@ static int qla2xxx_eh_target_reset(struct scsi_cmnd *); static int qla2xxx_eh_bus_reset(struct scsi_cmnd *); static int qla2xxx_eh_host_reset(struct scsi_cmnd *); -static int qla2x00_change_queue_depth(struct scsi_device *, int, int); static void qla2x00_clear_drv_active(struct qla_hw_data *); static void qla2x00_free_device(scsi_qla_host_t *); static void qla83xx_disable_laser(scsi_qla_host_t *vha); @@ -258,7 +257,7 @@ struct scsi_host_template qla2xxx_driver_template = { .slave_destroy = qla2xxx_slave_destroy, .scan_finished = qla2xxx_scan_finished, .scan_start = qla2xxx_scan_start, - .change_queue_depth = qla2x00_change_queue_depth, + .change_queue_depth = scsi_change_queue_depth, .change_queue_type = scsi_change_queue_type, .this_id = -1, .cmd_per_lun = 3, @@ -1406,7 +1405,7 @@ qla2xxx_slave_configure(struct scsi_device *sdev) if (IS_T10_PI_CAPABLE(vha->hw)) blk_queue_update_dma_alignment(sdev->request_queue, 0x7); - scsi_adjust_queue_depth(sdev, req->max_q_depth); + scsi_change_queue_depth(sdev, req->max_q_depth); return 0; } @@ -1416,13 +1415,6 @@ qla2xxx_slave_destroy(struct scsi_device *sdev) sdev->hostdata = NULL; } -static int -qla2x00_change_queue_depth(struct scsi_device *sdev, int qdepth, int reason) -{ - scsi_adjust_queue_depth(sdev, qdepth); - return sdev->queue_depth; -} - /** * qla2x00_config_dma_addressing() - Configure OS DMA addressing method. * @ha: HA context diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index 2bfde373ea2b..6d25879d87c8 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c @@ -201,7 +201,7 @@ static struct scsi_host_template qla4xxx_driver_template = { .eh_timed_out = qla4xxx_eh_cmd_timed_out, .slave_alloc = qla4xxx_slave_alloc, - .change_queue_depth = iscsi_change_queue_depth, + .change_queue_depth = scsi_change_queue_depth, .this_id = -1, .cmd_per_lun = 3, @@ -9059,7 +9059,7 @@ static int qla4xxx_slave_alloc(struct scsi_device *sdev) if (ql4xmaxqdepth != 0 && ql4xmaxqdepth <= 0xffffU) queue_depth = ql4xmaxqdepth; - scsi_adjust_queue_depth(sdev, queue_depth); + scsi_change_queue_depth(sdev, queue_depth); return 0; } diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index 106fa2f886d2..5ea15fc7d2fb 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -742,30 +742,18 @@ void scsi_finish_command(struct scsi_cmnd *cmd) } /** - * scsi_adjust_queue_depth - Let low level drivers change a device's queue depth + * scsi_change_queue_depth - change a device's queue depth * @sdev: SCSI Device in question - * @tags: Number of tags allowed if tagged queueing enabled, - * or number of commands the low level driver can - * queue up in non-tagged mode (as per cmd_per_lun). + * @depth: number of commands allowed to be queued to the driver * - * Returns: Nothing - * - * Lock Status: None held on entry - * - * Notes: Low level drivers may call this at any time and we will do - * the right thing depending on whether or not the device is - * currently active and whether or not it even has the - * command blocks built yet. + * Sets the device queue depth and returns the new value. */ -void scsi_adjust_queue_depth(struct scsi_device *sdev, int tags) +int scsi_change_queue_depth(struct scsi_device *sdev, int depth) { unsigned long flags; - /* - * refuse to set tagged depth to an unworkable size - */ - if (tags <= 0) - return; + if (depth <= 0) + goto out; spin_lock_irqsave(sdev->request_queue->queue_lock, flags); @@ -780,15 +768,17 @@ void scsi_adjust_queue_depth(struct scsi_device *sdev, int tags) */ if (!shost_use_blk_mq(sdev->host) && !sdev->host->bqt) { if (blk_queue_tagged(sdev->request_queue) && - blk_queue_resize_tags(sdev->request_queue, tags) != 0) - goto out; + blk_queue_resize_tags(sdev->request_queue, depth) != 0) + goto out_unlock; } - sdev->queue_depth = tags; - out: + sdev->queue_depth = depth; +out_unlock: spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags); +out: + return sdev->queue_depth; } -EXPORT_SYMBOL(scsi_adjust_queue_depth); +EXPORT_SYMBOL(scsi_change_queue_depth); /** * scsi_track_queue_full - track QUEUE_FULL events to adjust queue depth @@ -833,12 +823,11 @@ int scsi_track_queue_full(struct scsi_device *sdev, int depth) if (sdev->last_queue_full_depth < 8) { /* Drop back to untagged */ scsi_set_tag_type(sdev, 0); - scsi_adjust_queue_depth(sdev, sdev->host->cmd_per_lun); + scsi_change_queue_depth(sdev, sdev->host->cmd_per_lun); return -1; } - scsi_adjust_queue_depth(sdev, depth); - return depth; + return scsi_change_queue_depth(sdev, depth); } EXPORT_SYMBOL(scsi_track_queue_full); diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index 84cf82e0782d..ce71b6d4393c 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c @@ -4469,7 +4469,7 @@ sdebug_queuecommand_lock_or_not(struct Scsi_Host *shost, struct scsi_cmnd *cmd) } static int -sdebug_change_qdepth(struct scsi_device *sdev, int qdepth, int reason) +sdebug_change_qdepth(struct scsi_device *sdev, int qdepth) { int num_in_q = 0; unsigned long iflags; @@ -4489,7 +4489,7 @@ sdebug_change_qdepth(struct scsi_device *sdev, int qdepth, int reason) /* allow to exceed max host queued_arr elements for testing */ if (qdepth > SCSI_DEBUG_CANQUEUE + 10) qdepth = SCSI_DEBUG_CANQUEUE + 10; - scsi_adjust_queue_depth(sdev, qdepth); + scsi_change_queue_depth(sdev, qdepth); if (SCSI_DEBUG_OPT_Q_NOISE & scsi_debug_opts) { sdev_printk(KERN_INFO, sdev, diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 2d0f5155ee51..1f63559184b9 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -632,7 +632,7 @@ static void scsi_handle_queue_ramp_up(struct scsi_device *sdev) tmp_sdev->queue_depth == sdev->max_queue_depth) continue; - scsi_adjust_queue_depth(tmp_sdev, tmp_sdev->queue_depth + 1); + scsi_change_queue_depth(tmp_sdev, tmp_sdev->queue_depth + 1); sdev->last_queue_ramp_up = jiffies; } } diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index d97597e6337e..0af713375db5 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -292,7 +292,7 @@ static struct scsi_device *scsi_alloc_sdev(struct scsi_target *starget, blk_queue_init_tags(sdev->request_queue, sdev->host->cmd_per_lun, shost->bqt); } - scsi_adjust_queue_depth(sdev, sdev->host->cmd_per_lun); + scsi_change_queue_depth(sdev, sdev->host->cmd_per_lun); scsi_sysfs_device_initialize(sdev); diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index bffd5abdcd1f..1cb64a8e18c9 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -880,8 +880,7 @@ sdev_store_queue_depth(struct device *dev, struct device_attribute *attr, if (depth < 1 || depth > sht->can_queue) return -EINVAL; - retval = sht->change_queue_depth(sdev, depth, - SCSI_QDEPTH_DEFAULT); + retval = sht->change_queue_depth(sdev, depth); if (retval < 0) return retval; diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index ff8befbdf17c..e3ba251fb6e7 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -1429,7 +1429,7 @@ static void storvsc_device_destroy(struct scsi_device *sdevice) static int storvsc_device_configure(struct scsi_device *sdevice) { - scsi_adjust_queue_depth(sdevice, STORVSC_MAX_IO_REQUESTS); + scsi_change_queue_depth(sdevice, STORVSC_MAX_IO_REQUESTS); blk_queue_max_segment_size(sdevice->request_queue, PAGE_SIZE); diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c index 3557b385251a..5d00e514ff28 100644 --- a/drivers/scsi/sym53c8xx_2/sym_glue.c +++ b/drivers/scsi/sym53c8xx_2/sym_glue.c @@ -820,7 +820,7 @@ static int sym53c8xx_slave_configure(struct scsi_device *sdev) if (reqtags > SYM_CONF_MAX_TAG) reqtags = SYM_CONF_MAX_TAG; depth_to_use = reqtags ? reqtags : 1; - scsi_adjust_queue_depth(sdev, depth_to_use); + scsi_change_queue_depth(sdev, depth_to_use); lp->s.scdev_depth = depth_to_use; sym_tune_dev_queuing(tp, sdev->lun, reqtags); diff --git a/drivers/scsi/tmscsim.c b/drivers/scsi/tmscsim.c index 844c9a048c00..6c3c2cef3891 100644 --- a/drivers/scsi/tmscsim.c +++ b/drivers/scsi/tmscsim.c @@ -2194,7 +2194,7 @@ static int dc390_slave_configure(struct scsi_device *sdev) if (sdev->tagged_supported && (dcb->DevMode & TAG_QUEUEING_)) { dcb->SyncMode |= EN_TAG_QUEUEING; - scsi_adjust_queue_depth(sdev, acb->TagMaxNum); + scsi_change_queue_depth(sdev, acb->TagMaxNum); } return 0; diff --git a/drivers/scsi/u14-34f.c b/drivers/scsi/u14-34f.c index aa0f4035afaf..14eb50b95a1e 100644 --- a/drivers/scsi/u14-34f.c +++ b/drivers/scsi/u14-34f.c @@ -696,25 +696,25 @@ static int u14_34f_slave_configure(struct scsi_device *dev) { if (TLDEV(dev->type) && dev->tagged_supported) if (tag_mode == TAG_SIMPLE) { - scsi_adjust_queue_depth(dev, tqd); + scsi_change_queue_depth(dev, tqd); tag_suffix = ", simple tags"; } else if (tag_mode == TAG_ORDERED) { - scsi_adjust_queue_depth(dev, tqd); + scsi_change_queue_depth(dev, tqd); tag_suffix = ", ordered tags"; } else { - scsi_adjust_queue_depth(dev, tqd); + scsi_change_queue_depth(dev, tqd); tag_suffix = ", no tags"; } else if (TLDEV(dev->type) && linked_comm) { - scsi_adjust_queue_depth(dev, tqd); + scsi_change_queue_depth(dev, tqd); tag_suffix = ", untagged"; } else { - scsi_adjust_queue_depth(dev, utqd); + scsi_change_queue_depth(dev, utqd); tag_suffix = ""; } diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index e96ab253e3e5..0c4f98ee6047 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -2695,7 +2695,7 @@ static void ufshcd_set_queue_depth(struct scsi_device *sdev) dev_dbg(hba->dev, "%s: activate tcq with queue depth %d\n", __func__, lun_qdepth); - scsi_adjust_queue_depth(sdev, lun_qdepth); + scsi_change_queue_depth(sdev, lun_qdepth); } /* @@ -2787,21 +2787,16 @@ static int ufshcd_slave_alloc(struct scsi_device *sdev) * ufshcd_change_queue_depth - change queue depth * @sdev: pointer to SCSI device * @depth: required depth to set - * @reason: reason for changing the depth * - * Change queue depth according to the reason and make sure - * the max. limits are not crossed. + * Change queue depth and make sure the max. limits are not crossed. */ -static int ufshcd_change_queue_depth(struct scsi_device *sdev, - int depth, int reason) +static int ufshcd_change_queue_depth(struct scsi_device *sdev, int depth) { struct ufs_hba *hba = shost_priv(sdev->host); if (depth > hba->nutrs) depth = hba->nutrs; - - scsi_adjust_queue_depth(sdev, depth); - return depth; + return scsi_change_queue_depth(sdev, depth); } /** diff --git a/drivers/scsi/virtio_scsi.c b/drivers/scsi/virtio_scsi.c index 0f7e4c7ff8c2..22e70126425b 100644 --- a/drivers/scsi/virtio_scsi.c +++ b/drivers/scsi/virtio_scsi.c @@ -682,17 +682,13 @@ static int virtscsi_device_reset(struct scsi_cmnd *sc) * virtscsi_change_queue_depth() - Change a virtscsi target's queue depth * @sdev: Virtscsi target whose queue depth to change * @qdepth: New queue depth - * @reason: Reason for the queue depth change. */ -static int virtscsi_change_queue_depth(struct scsi_device *sdev, - int qdepth, - int reason) +static int virtscsi_change_queue_depth(struct scsi_device *sdev, int qdepth) { struct Scsi_Host *shost = sdev->host; int max_depth = shost->cmd_per_lun; - scsi_adjust_queue_depth(sdev, min(max_depth, qdepth)); - return sdev->queue_depth; + return scsi_change_queue_depth(sdev, min(max_depth, qdepth)); } static int virtscsi_abort(struct scsi_cmnd *sc) diff --git a/drivers/scsi/vmw_pvscsi.c b/drivers/scsi/vmw_pvscsi.c index 03ad24be728e..ade1f1d013b1 100644 --- a/drivers/scsi/vmw_pvscsi.c +++ b/drivers/scsi/vmw_pvscsi.c @@ -504,19 +504,11 @@ static void pvscsi_setup_all_rings(const struct pvscsi_adapter *adapter) } } -static int pvscsi_change_queue_depth(struct scsi_device *sdev, - int qdepth, - int reason) +static int pvscsi_change_queue_depth(struct scsi_device *sdev, int qdepth) { - if (reason != SCSI_QDEPTH_DEFAULT) - /* - * We support only changing default. - */ - return -EOPNOTSUPP; - if (!sdev->tagged_supported) qdepth = 1; - scsi_adjust_queue_depth(sdev, qdepth); + scsi_change_queue_depth(sdev, qdepth); if (sdev->inquiry_len > 7) sdev_printk(KERN_INFO, sdev, diff --git a/drivers/scsi/wd7000.c b/drivers/scsi/wd7000.c index 32674236fec7..f94d73611ab4 100644 --- a/drivers/scsi/wd7000.c +++ b/drivers/scsi/wd7000.c @@ -1653,7 +1653,6 @@ static struct scsi_host_template driver_template = { .can_queue = WD7000_Q, .this_id = 7, .sg_tablesize = WD7000_SG, - .cmd_per_lun = 1, .unchecked_isa_dma = 1, .use_clustering = ENABLE_CLUSTERING, }; diff --git a/drivers/target/loopback/tcm_loop.c b/drivers/target/loopback/tcm_loop.c index 670b75a62243..4d1b7224a7f2 100644 --- a/drivers/target/loopback/tcm_loop.c +++ b/drivers/target/loopback/tcm_loop.c @@ -110,19 +110,6 @@ static struct device_driver tcm_loop_driverfs = { */ struct device *tcm_loop_primary; -/* - * Copied from drivers/scsi/libfc/fc_fcp.c:fc_change_queue_depth() and - * drivers/scsi/libiscsi.c:iscsi_change_queue_depth() - */ -static int tcm_loop_change_queue_depth( - struct scsi_device *sdev, - int depth, - int reason) -{ - scsi_adjust_queue_depth(sdev, depth); - return sdev->queue_depth; -} - static void tcm_loop_submission_work(struct work_struct *work) { struct tcm_loop_cmd *tl_cmd = @@ -397,7 +384,7 @@ static struct scsi_host_template tcm_loop_driver_template = { .proc_name = "tcm_loopback", .name = "TCM_Loopback", .queuecommand = tcm_loop_queuecommand, - .change_queue_depth = tcm_loop_change_queue_depth, + .change_queue_depth = scsi_change_queue_depth, .change_queue_type = scsi_change_queue_type, .eh_abort_handler = tcm_loop_abort_task, .eh_device_reset_handler = tcm_loop_device_reset, diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c index 33f211b56a42..4047edfb64e1 100644 --- a/drivers/usb/storage/uas.c +++ b/drivers/usb/storage/uas.c @@ -799,7 +799,7 @@ static int uas_slave_configure(struct scsi_device *sdev) if (devinfo->flags & US_FL_NO_REPORT_OPCODES) sdev->no_report_opcodes = 1; - scsi_adjust_queue_depth(sdev, devinfo->qdepth - 2); + scsi_change_queue_depth(sdev, devinfo->qdepth - 2); return 0; } diff --git a/include/linux/libata.h b/include/linux/libata.h index bd5fefeaf548..bfbc817c34ee 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -1191,9 +1191,9 @@ extern void ata_scsi_unlock_native_capacity(struct scsi_device *sdev); extern int ata_scsi_slave_config(struct scsi_device *sdev); extern void ata_scsi_slave_destroy(struct scsi_device *sdev); extern int ata_scsi_change_queue_depth(struct scsi_device *sdev, - int queue_depth, int reason); + int queue_depth); extern int __ata_change_queue_depth(struct ata_port *ap, struct scsi_device *sdev, - int queue_depth, int reason); + int queue_depth); extern struct ata_device *ata_dev_pair(struct ata_device *adev); extern int ata_do_set_mode(struct ata_link *link, struct ata_device **r_failed_dev); extern void ata_scsi_port_error_handler(struct Scsi_Host *host, struct ata_port *ap); diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h index 2e0cf568a9c1..93d14daf0994 100644 --- a/include/scsi/libfc.h +++ b/include/scsi/libfc.h @@ -1105,7 +1105,6 @@ int fc_eh_abort(struct scsi_cmnd *); int fc_eh_device_reset(struct scsi_cmnd *); int fc_eh_host_reset(struct scsi_cmnd *); int fc_slave_alloc(struct scsi_device *); -int fc_change_queue_depth(struct scsi_device *, int qdepth, int reason); /* * ELS/CT interface diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h index 728c9ad9feb0..4d1c46aac331 100644 --- a/include/scsi/libiscsi.h +++ b/include/scsi/libiscsi.h @@ -378,8 +378,6 @@ struct iscsi_host { /* * scsi host template */ -extern int iscsi_change_queue_depth(struct scsi_device *sdev, int depth, - int reason); extern int iscsi_eh_abort(struct scsi_cmnd *sc); extern int iscsi_eh_recover_target(struct scsi_cmnd *sc); extern int iscsi_eh_session_reset(struct scsi_cmnd *sc); diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h index ef7872c20da9..1f8b33ec612f 100644 --- a/include/scsi/libsas.h +++ b/include/scsi/libsas.h @@ -704,8 +704,7 @@ int sas_queue_up(struct sas_task *task); extern int sas_queuecommand(struct Scsi_Host * ,struct scsi_cmnd *); extern int sas_target_alloc(struct scsi_target *); extern int sas_slave_configure(struct scsi_device *); -extern int sas_change_queue_depth(struct scsi_device *, int new_depth, - int reason); +extern int sas_change_queue_depth(struct scsi_device *, int new_depth); extern int sas_change_queue_type(struct scsi_device *, int qt); extern int sas_bios_param(struct scsi_device *, struct block_device *, diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index 0aeaa003c3c1..6364e23454dd 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h @@ -380,7 +380,7 @@ extern struct scsi_device *__scsi_iterate_devices(struct Scsi_Host *, #define __shost_for_each_device(sdev, shost) \ list_for_each_entry((sdev), &((shost)->__devices), siblings) -extern void scsi_adjust_queue_depth(struct scsi_device *, int); +extern int scsi_change_queue_depth(struct scsi_device *, int); extern int scsi_track_queue_full(struct scsi_device *, int); extern int scsi_set_medium_removal(struct scsi_device *, char); diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h index a0b13a5cd25e..c8a462ef9a4e 100644 --- a/include/scsi/scsi_host.h +++ b/include/scsi/scsi_host.h @@ -46,10 +46,6 @@ struct blk_queue_tags; #define DISABLE_CLUSTERING 0 #define ENABLE_CLUSTERING 1 -enum { - SCSI_QDEPTH_DEFAULT, /* default requested change, e.g. from sysfs */ -}; - struct scsi_host_template { struct module *module; const char *name; @@ -193,7 +189,7 @@ struct scsi_host_template { * Things currently recommended to be handled at this time include: * * 1. Setting the device queue depth. Proper setting of this is - * described in the comments for scsi_adjust_queue_depth. + * described in the comments for scsi_change_queue_depth. * 2. Determining if the device supports the various synchronous * negotiation protocols. The device struct will already have * responded to INQUIRY and the results of the standard items @@ -279,7 +275,7 @@ struct scsi_host_template { * * Status: OPTIONAL */ - int (* change_queue_depth)(struct scsi_device *, int, int); + int (* change_queue_depth)(struct scsi_device *, int); /* * Fill in this function to allow the changing of tag types -- cgit v1.2.3 From a1c8a5512b7cddc81767172f0de37b155cea039f Mon Sep 17 00:00:00 2001 From: Richard Fitzgerald Date: Mon, 24 Nov 2014 14:10:52 +0000 Subject: regulator: core: Add PRE_DISABLE notification Add a PRE_DISABLE notification so that consumers can use a notifier to run any steps required to prepare for the regulator being switched off. Since the regulator disable can fail an abort notification is also added. Signed-off-by: Richard Fitzgerald Signed-off-by: Mark Brown --- drivers/regulator/core.c | 16 ++++++++++++++++ include/linux/regulator/consumer.h | 4 ++++ 2 files changed, 20 insertions(+) (limited to 'include/linux') diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index cd87c0c37034..53de911a0954 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -1976,9 +1976,18 @@ static int _regulator_disable(struct regulator_dev *rdev) /* we are last user */ if (_regulator_can_change_status(rdev)) { + ret = _notifier_call_chain(rdev, + REGULATOR_EVENT_PRE_DISABLE, + NULL); + if (ret & NOTIFY_STOP_MASK) + return -EINVAL; + ret = _regulator_do_disable(rdev); if (ret < 0) { rdev_err(rdev, "failed to disable\n"); + _notifier_call_chain(rdev, + REGULATOR_EVENT_ABORT_DISABLE, + NULL); return ret; } _notifier_call_chain(rdev, REGULATOR_EVENT_DISABLE, @@ -2035,9 +2044,16 @@ static int _regulator_force_disable(struct regulator_dev *rdev) { int ret = 0; + ret = _notifier_call_chain(rdev, REGULATOR_EVENT_FORCE_DISABLE | + REGULATOR_EVENT_PRE_DISABLE, NULL); + if (ret & NOTIFY_STOP_MASK) + return -EINVAL; + ret = _regulator_do_disable(rdev); if (ret < 0) { rdev_err(rdev, "failed to force disable\n"); + _notifier_call_chain(rdev, REGULATOR_EVENT_FORCE_DISABLE | + REGULATOR_EVENT_ABORT_DISABLE, NULL); return ret; } diff --git a/include/linux/regulator/consumer.h b/include/linux/regulator/consumer.h index d347c805f923..9efddd2a63ee 100644 --- a/include/linux/regulator/consumer.h +++ b/include/linux/regulator/consumer.h @@ -99,6 +99,8 @@ struct regmap; * Data passed is "struct pre_voltage_change_data" * ABORT_VOLTAGE_CHANGE Regulator voltage change failed for some reason. * Data passed is old voltage cast to (void *). + * PRE_DISABLE Regulator is about to be disabled + * ABORT_DISABLE Regulator disable failed for some reason * * NOTE: These events can be OR'ed together when passed into handler. */ @@ -113,6 +115,8 @@ struct regmap; #define REGULATOR_EVENT_DISABLE 0x80 #define REGULATOR_EVENT_PRE_VOLTAGE_CHANGE 0x100 #define REGULATOR_EVENT_ABORT_VOLTAGE_CHANGE 0x200 +#define REGULATOR_EVENT_PRE_DISABLE 0x400 +#define REGULATOR_EVENT_ABORT_DISABLE 0x800 /** * struct pre_voltage_change_data - Data sent with PRE_VOLTAGE_CHANGE event -- cgit v1.2.3 From 7ff28aee40c42676abc3baab122d45826726ea49 Mon Sep 17 00:00:00 2001 From: Ondrej Zary Date: Mon, 24 Nov 2014 23:24:40 +0100 Subject: eeprom-93cx6: Add (read-only) support for 8-bit mode Add read-only support for EEPROMs configured in 8-bit mode (ORG pin connected to GND). This will be used by wd719x driver. Signed-off-by: Ondrej Zary Reviewed-by: Hannes Reinecke Signed-off-by: Christoph Hellwig --- drivers/misc/eeprom/eeprom_93cx6.c | 62 +++++++++++++++++++++++++++++++++++++- include/linux/eeprom_93cx6.h | 4 +++ 2 files changed, 65 insertions(+), 1 deletion(-) (limited to 'include/linux') diff --git a/drivers/misc/eeprom/eeprom_93cx6.c b/drivers/misc/eeprom/eeprom_93cx6.c index 0ff4b02177be..0cf2c9d676be 100644 --- a/drivers/misc/eeprom/eeprom_93cx6.c +++ b/drivers/misc/eeprom/eeprom_93cx6.c @@ -170,7 +170,7 @@ static void eeprom_93cx6_read_bits(struct eeprom_93cx6 *eeprom, } /** - * eeprom_93cx6_read - Read multiple words from eeprom + * eeprom_93cx6_read - Read a word from eeprom * @eeprom: Pointer to eeprom structure * @word: Word index from where we should start reading * @data: target pointer where the information will have to be stored @@ -234,6 +234,66 @@ void eeprom_93cx6_multiread(struct eeprom_93cx6 *eeprom, const u8 word, } EXPORT_SYMBOL_GPL(eeprom_93cx6_multiread); +/** + * eeprom_93cx6_readb - Read a byte from eeprom + * @eeprom: Pointer to eeprom structure + * @word: Byte index from where we should start reading + * @data: target pointer where the information will have to be stored + * + * This function will read a byte of the eeprom data + * into the given data pointer. + */ +void eeprom_93cx6_readb(struct eeprom_93cx6 *eeprom, const u8 byte, + u8 *data) +{ + u16 command; + u16 tmp; + + /* + * Initialize the eeprom register + */ + eeprom_93cx6_startup(eeprom); + + /* + * Select the read opcode and the byte to be read. + */ + command = (PCI_EEPROM_READ_OPCODE << (eeprom->width + 1)) | byte; + eeprom_93cx6_write_bits(eeprom, command, + PCI_EEPROM_WIDTH_OPCODE + eeprom->width + 1); + + /* + * Read the requested 8 bits. + */ + eeprom_93cx6_read_bits(eeprom, &tmp, 8); + *data = tmp & 0xff; + + /* + * Cleanup eeprom register. + */ + eeprom_93cx6_cleanup(eeprom); +} +EXPORT_SYMBOL_GPL(eeprom_93cx6_readb); + +/** + * eeprom_93cx6_multireadb - Read multiple bytes from eeprom + * @eeprom: Pointer to eeprom structure + * @byte: Index from where we should start reading + * @data: target pointer where the information will have to be stored + * @words: Number of bytes that should be read. + * + * This function will read all requested bytes from the eeprom, + * this is done by calling eeprom_93cx6_readb() multiple times. + */ +void eeprom_93cx6_multireadb(struct eeprom_93cx6 *eeprom, const u8 byte, + u8 *data, const u16 bytes) +{ + unsigned int i; + + for (i = 0; i < bytes; i++) + eeprom_93cx6_readb(eeprom, byte + i, &data[i]); +} +EXPORT_SYMBOL_GPL(eeprom_93cx6_multireadb); + /** * eeprom_93cx6_wren - set the write enable state * @eeprom: Pointer to eeprom structure diff --git a/include/linux/eeprom_93cx6.h b/include/linux/eeprom_93cx6.h index e50f98b0297a..eb0b1988050a 100644 --- a/include/linux/eeprom_93cx6.h +++ b/include/linux/eeprom_93cx6.h @@ -75,6 +75,10 @@ extern void eeprom_93cx6_read(struct eeprom_93cx6 *eeprom, const u8 word, u16 *data); extern void eeprom_93cx6_multiread(struct eeprom_93cx6 *eeprom, const u8 word, __le16 *data, const u16 words); +extern void eeprom_93cx6_readb(struct eeprom_93cx6 *eeprom, + const u8 byte, u8 *data); +extern void eeprom_93cx6_multireadb(struct eeprom_93cx6 *eeprom, + const u8 byte, u8 *data, const u16 bytes); extern void eeprom_93cx6_wren(struct eeprom_93cx6 *eeprom, bool enable); -- cgit v1.2.3 From 3bc2ee91a470c52fb3979c23c12d43283455f10d Mon Sep 17 00:00:00 2001 From: Chanwoo Choi Date: Tue, 18 Nov 2014 17:59:39 +0900 Subject: mfd: sec-core: Add support for S2MPS13 device This patch adds the support for Samsung S2MPS13 PMIC device to the sec-core MFD driver. The S2MPS13 is very similar with existing S2MPS14 and includes PMIC/ RTC/CLOCK devices. Signed-off-by: Chanwoo Choi Acked-by: Sangbeom Kim Signed-off-by: Lee Jones --- drivers/mfd/sec-core.c | 16 ++++++++++++++++ drivers/mfd/sec-irq.c | 23 +++++++++++++++++------ include/linux/mfd/samsung/core.h | 1 + 3 files changed, 34 insertions(+), 6 deletions(-) (limited to 'include/linux') diff --git a/drivers/mfd/sec-core.c b/drivers/mfd/sec-core.c index dba7e2b6f8e9..d086e8cee1d7 100644 --- a/drivers/mfd/sec-core.c +++ b/drivers/mfd/sec-core.c @@ -74,6 +74,15 @@ static const struct mfd_cell s2mps11_devs[] = { } }; +static const struct mfd_cell s2mps13_devs[] = { + { .name = "s2mps13-pmic", }, + { .name = "s2mps13-rtc", }, + { + .name = "s2mps13-clk", + .of_compatible = "samsung,s2mps13-clk", + }, +}; + static const struct mfd_cell s2mps14_devs[] = { { .name = "s2mps14-pmic", @@ -107,6 +116,9 @@ static const struct of_device_id sec_dt_match[] = { }, { .compatible = "samsung,s2mps11-pmic", .data = (void *)S2MPS11X, + }, { + .compatible = "samsung,s2mps13-pmic", + .data = (void *)S2MPS13X, }, { .compatible = "samsung,s2mps14-pmic", .data = (void *)S2MPS14X, @@ -378,6 +390,10 @@ static int sec_pmic_probe(struct i2c_client *i2c, sec_devs = s2mps11_devs; num_sec_devs = ARRAY_SIZE(s2mps11_devs); break; + case S2MPS13X: + sec_devs = s2mps13_devs; + num_sec_devs = ARRAY_SIZE(s2mps13_devs); + break; case S2MPS14X: sec_devs = s2mps14_devs; num_sec_devs = ARRAY_SIZE(s2mps14_devs); diff --git a/drivers/mfd/sec-irq.c b/drivers/mfd/sec-irq.c index f9a57869e3ec..ba86a918c2da 100644 --- a/drivers/mfd/sec-irq.c +++ b/drivers/mfd/sec-irq.c @@ -389,14 +389,22 @@ static const struct regmap_irq_chip s2mps11_irq_chip = { .ack_base = S2MPS11_REG_INT1, }; +#define S2MPS1X_IRQ_CHIP_COMMON_DATA \ + .irqs = s2mps14_irqs, \ + .num_irqs = ARRAY_SIZE(s2mps14_irqs), \ + .num_regs = 3, \ + .status_base = S2MPS14_REG_INT1, \ + .mask_base = S2MPS14_REG_INT1M, \ + .ack_base = S2MPS14_REG_INT1 \ + +static const struct regmap_irq_chip s2mps13_irq_chip = { + .name = "s2mps13", + S2MPS1X_IRQ_CHIP_COMMON_DATA, +}; + static const struct regmap_irq_chip s2mps14_irq_chip = { .name = "s2mps14", - .irqs = s2mps14_irqs, - .num_irqs = ARRAY_SIZE(s2mps14_irqs), - .num_regs = 3, - .status_base = S2MPS14_REG_INT1, - .mask_base = S2MPS14_REG_INT1M, - .ack_base = S2MPS14_REG_INT1, + S2MPS1X_IRQ_CHIP_COMMON_DATA, }; static const struct regmap_irq_chip s2mpu02_irq_chip = { @@ -452,6 +460,9 @@ int sec_irq_init(struct sec_pmic_dev *sec_pmic) case S2MPS11X: sec_irq_chip = &s2mps11_irq_chip; break; + case S2MPS13X: + sec_irq_chip = &s2mps13_irq_chip; + break; case S2MPS14X: sec_irq_chip = &s2mps14_irq_chip; break; diff --git a/include/linux/mfd/samsung/core.h b/include/linux/mfd/samsung/core.h index 1825edacbda7..0c0343e06ba6 100644 --- a/include/linux/mfd/samsung/core.h +++ b/include/linux/mfd/samsung/core.h @@ -41,6 +41,7 @@ enum sec_device_type { S5M8767X, S2MPA01, S2MPS11X, + S2MPS13X, S2MPS14X, S2MPU02, }; -- cgit v1.2.3 From 76b9840b24ae049b39f1b3cf0e49f21b7c41748f Mon Sep 17 00:00:00 2001 From: Chanwoo Choi Date: Tue, 18 Nov 2014 17:59:40 +0900 Subject: regulator: s2mps11: Add support S2MPS13 regulator device This patch adds S2MPS13 regulator device to existing S2MPS11 device driver. The S2MPS13 has just different number of regulators from S2MPS14. The S2MPS13 regulator device includes LDO[1-40] and BUCK[1-10]. Signed-off-by: Chanwoo Choi Acked-by: Sangbeom Kim Acked-by: Mark Brown Reviewed-by: Krzysztof Kozlowski Signed-off-by: Lee Jones --- drivers/mfd/sec-core.c | 13 +++ drivers/regulator/Kconfig | 10 +- drivers/regulator/s2mps11.c | 102 +++++++++++++++++++- include/linux/mfd/samsung/core.h | 1 + include/linux/mfd/samsung/s2mps13.h | 186 ++++++++++++++++++++++++++++++++++++ 5 files changed, 304 insertions(+), 8 deletions(-) create mode 100644 include/linux/mfd/samsung/s2mps13.h (limited to 'include/linux') diff --git a/drivers/mfd/sec-core.c b/drivers/mfd/sec-core.c index d086e8cee1d7..b39960532f76 100644 --- a/drivers/mfd/sec-core.c +++ b/drivers/mfd/sec-core.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -206,6 +207,15 @@ static const struct regmap_config s2mps11_regmap_config = { .cache_type = REGCACHE_FLAT, }; +static const struct regmap_config s2mps13_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + + .max_register = S2MPS13_REG_LDODSCH5, + .volatile_reg = s2mps11_volatile, + .cache_type = REGCACHE_FLAT, +}; + static const struct regmap_config s2mps14_regmap_config = { .reg_bits = 8, .val_bits = 8, @@ -337,6 +347,9 @@ static int sec_pmic_probe(struct i2c_client *i2c, case S2MPS11X: regmap = &s2mps11_regmap_config; break; + case S2MPS13X: + regmap = &s2mps13_regmap_config; + break; case S2MPS14X: regmap = &s2mps14_regmap_config; break; diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index 55d7b7b0f2e0..5e061347be93 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -529,13 +529,13 @@ config REGULATOR_S2MPA01 via I2C bus. S2MPA01 has 10 Bucks and 26 LDO outputs. config REGULATOR_S2MPS11 - tristate "Samsung S2MPS11/S2MPS14/S2MPU02 voltage regulator" + tristate "Samsung S2MPS11/S2MPS13/S2MPS14/S2MPU02 voltage regulator" depends on MFD_SEC_CORE help - This driver supports a Samsung S2MPS11/S2MPS14/S2MPU02 voltage output - regulator via I2C bus. The chip is comprised of high efficient Buck - converters including Dual-Phase Buck converter, Buck-Boost converter, - various LDOs. + This driver supports a Samsung S2MPS11/S2MPS13/S2MPS14/S2MPU02 voltage + output regulator via I2C bus. The chip is comprised of high efficient + Buck converters including Dual-Phase Buck converter, Buck-Boost + converter, various LDOs. config REGULATOR_S5M8767 tristate "Samsung S5M8767A voltage regulator" diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c index adab82d5279f..738dc7763d47 100644 --- a/drivers/regulator/s2mps11.c +++ b/drivers/regulator/s2mps11.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -45,10 +46,10 @@ struct s2mps11_info { enum sec_device_type dev_type; /* - * One bit for each S2MPS14/S2MPU02 regulator whether the suspend mode - * was enabled. + * One bit for each S2MPS13/S2MPS14/S2MPU02 regulator whether + * the suspend mode was enabled. */ - unsigned long long s2mps14_suspend_state:35; + unsigned long long s2mps14_suspend_state:50; /* Array of size rdev_num with GPIO-s for external sleep control */ int *ext_control_gpio; @@ -369,12 +370,101 @@ static const struct regulator_desc s2mps11_regulators[] = { regulator_desc_s2mps11_buck6_10(10, MIN_750_MV, STEP_12_5_MV), }; +static struct regulator_ops s2mps14_reg_ops; + +#define regulator_desc_s2mps13_ldo(num, min, step, min_sel) { \ + .name = "LDO"#num, \ + .id = S2MPS13_LDO##num, \ + .ops = &s2mps14_reg_ops, \ + .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ + .min_uV = min, \ + .uV_step = step, \ + .linear_min_sel = min_sel, \ + .n_voltages = S2MPS14_LDO_N_VOLTAGES, \ + .vsel_reg = S2MPS13_REG_L1CTRL + num - 1, \ + .vsel_mask = S2MPS14_LDO_VSEL_MASK, \ + .enable_reg = S2MPS13_REG_L1CTRL + num - 1, \ + .enable_mask = S2MPS14_ENABLE_MASK \ +} + +#define regulator_desc_s2mps13_buck(num, min, step, min_sel) { \ + .name = "BUCK"#num, \ + .id = S2MPS13_BUCK##num, \ + .ops = &s2mps14_reg_ops, \ + .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ + .min_uV = min, \ + .uV_step = step, \ + .linear_min_sel = min_sel, \ + .n_voltages = S2MPS14_BUCK_N_VOLTAGES, \ + .ramp_delay = S2MPS13_BUCK_RAMP_DELAY, \ + .vsel_reg = S2MPS13_REG_B1OUT + (num - 1) * 2, \ + .vsel_mask = S2MPS14_BUCK_VSEL_MASK, \ + .enable_reg = S2MPS13_REG_B1CTRL + (num - 1) * 2, \ + .enable_mask = S2MPS14_ENABLE_MASK \ +} + +static const struct regulator_desc s2mps13_regulators[] = { + regulator_desc_s2mps13_ldo(1, MIN_800_MV, STEP_12_5_MV, 0x00), + regulator_desc_s2mps13_ldo(2, MIN_1400_MV, STEP_50_MV, 0x0C), + regulator_desc_s2mps13_ldo(3, MIN_1000_MV, STEP_25_MV, 0x08), + regulator_desc_s2mps13_ldo(4, MIN_800_MV, STEP_12_5_MV, 0x00), + regulator_desc_s2mps13_ldo(5, MIN_800_MV, STEP_12_5_MV, 0x00), + regulator_desc_s2mps13_ldo(6, MIN_800_MV, STEP_12_5_MV, 0x00), + regulator_desc_s2mps13_ldo(7, MIN_1000_MV, STEP_25_MV, 0x08), + regulator_desc_s2mps13_ldo(8, MIN_1000_MV, STEP_25_MV, 0x08), + regulator_desc_s2mps13_ldo(9, MIN_1000_MV, STEP_25_MV, 0x08), + regulator_desc_s2mps13_ldo(10, MIN_1400_MV, STEP_50_MV, 0x0C), + regulator_desc_s2mps13_ldo(11, MIN_800_MV, STEP_25_MV, 0x10), + regulator_desc_s2mps13_ldo(12, MIN_800_MV, STEP_25_MV, 0x10), + regulator_desc_s2mps13_ldo(13, MIN_800_MV, STEP_25_MV, 0x10), + regulator_desc_s2mps13_ldo(14, MIN_800_MV, STEP_12_5_MV, 0x00), + regulator_desc_s2mps13_ldo(15, MIN_800_MV, STEP_12_5_MV, 0x00), + regulator_desc_s2mps13_ldo(16, MIN_1400_MV, STEP_50_MV, 0x0C), + regulator_desc_s2mps13_ldo(17, MIN_1400_MV, STEP_50_MV, 0x0C), + regulator_desc_s2mps13_ldo(18, MIN_1000_MV, STEP_25_MV, 0x08), + regulator_desc_s2mps13_ldo(19, MIN_1000_MV, STEP_25_MV, 0x08), + regulator_desc_s2mps13_ldo(20, MIN_1400_MV, STEP_50_MV, 0x0C), + regulator_desc_s2mps13_ldo(21, MIN_1000_MV, STEP_25_MV, 0x08), + regulator_desc_s2mps13_ldo(22, MIN_1000_MV, STEP_25_MV, 0x08), + regulator_desc_s2mps13_ldo(23, MIN_800_MV, STEP_12_5_MV, 0x00), + regulator_desc_s2mps13_ldo(24, MIN_800_MV, STEP_12_5_MV, 0x00), + regulator_desc_s2mps13_ldo(25, MIN_1400_MV, STEP_50_MV, 0x0C), + regulator_desc_s2mps13_ldo(26, MIN_1400_MV, STEP_50_MV, 0x0C), + regulator_desc_s2mps13_ldo(27, MIN_1400_MV, STEP_50_MV, 0x0C), + regulator_desc_s2mps13_ldo(28, MIN_1000_MV, STEP_25_MV, 0x08), + regulator_desc_s2mps13_ldo(29, MIN_1400_MV, STEP_50_MV, 0x0C), + regulator_desc_s2mps13_ldo(30, MIN_1400_MV, STEP_50_MV, 0x0C), + regulator_desc_s2mps13_ldo(31, MIN_1000_MV, STEP_25_MV, 0x08), + regulator_desc_s2mps13_ldo(32, MIN_1000_MV, STEP_25_MV, 0x08), + regulator_desc_s2mps13_ldo(33, MIN_1400_MV, STEP_50_MV, 0x0C), + regulator_desc_s2mps13_ldo(34, MIN_1000_MV, STEP_25_MV, 0x08), + regulator_desc_s2mps13_ldo(35, MIN_1400_MV, STEP_50_MV, 0x0C), + regulator_desc_s2mps13_ldo(36, MIN_800_MV, STEP_12_5_MV, 0x00), + regulator_desc_s2mps13_ldo(37, MIN_1000_MV, STEP_25_MV, 0x08), + regulator_desc_s2mps13_ldo(38, MIN_1400_MV, STEP_50_MV, 0x0C), + regulator_desc_s2mps13_ldo(39, MIN_1000_MV, STEP_25_MV, 0x08), + regulator_desc_s2mps13_ldo(40, MIN_1400_MV, STEP_50_MV, 0x0C), + regulator_desc_s2mps13_buck(1, MIN_500_MV, STEP_6_25_MV, 0x10), + regulator_desc_s2mps13_buck(2, MIN_500_MV, STEP_6_25_MV, 0x10), + regulator_desc_s2mps13_buck(3, MIN_500_MV, STEP_6_25_MV, 0x10), + regulator_desc_s2mps13_buck(4, MIN_500_MV, STEP_6_25_MV, 0x10), + regulator_desc_s2mps13_buck(5, MIN_500_MV, STEP_6_25_MV, 0x10), + regulator_desc_s2mps13_buck(6, MIN_500_MV, STEP_6_25_MV, 0x10), + regulator_desc_s2mps13_buck(7, MIN_500_MV, STEP_6_25_MV, 0x10), + regulator_desc_s2mps13_buck(8, MIN_1000_MV, STEP_12_5_MV, 0x20), + regulator_desc_s2mps13_buck(9, MIN_1000_MV, STEP_12_5_MV, 0x20), + regulator_desc_s2mps13_buck(10, MIN_500_MV, STEP_6_25_MV, 0x10), +}; + static int s2mps14_regulator_enable(struct regulator_dev *rdev) { struct s2mps11_info *s2mps11 = rdev_get_drvdata(rdev); unsigned int val; switch (s2mps11->dev_type) { + case S2MPS13X: case S2MPS14X: if (s2mps11->s2mps14_suspend_state & (1 << rdev_get_id(rdev))) val = S2MPS14_ENABLE_SUSPEND; @@ -406,6 +496,7 @@ static int s2mps14_regulator_set_suspend_disable(struct regulator_dev *rdev) /* Below LDO should be always on or does not support suspend mode. */ switch (s2mps11->dev_type) { + case S2MPS13X: case S2MPS14X: switch (rdev_id) { case S2MPS14_LDO3: @@ -831,6 +922,10 @@ static int s2mps11_pmic_probe(struct platform_device *pdev) s2mps11->rdev_num = ARRAY_SIZE(s2mps11_regulators); regulators = s2mps11_regulators; break; + case S2MPS13X: + s2mps11->rdev_num = ARRAY_SIZE(s2mps13_regulators); + regulators = s2mps13_regulators; + break; case S2MPS14X: s2mps11->rdev_num = ARRAY_SIZE(s2mps14_regulators); regulators = s2mps14_regulators; @@ -927,6 +1022,7 @@ out: static const struct platform_device_id s2mps11_pmic_id[] = { { "s2mps11-pmic", S2MPS11X}, + { "s2mps13-pmic", S2MPS13X}, { "s2mps14-pmic", S2MPS14X}, { "s2mpu02-pmic", S2MPU02}, { }, diff --git a/include/linux/mfd/samsung/core.h b/include/linux/mfd/samsung/core.h index 0c0343e06ba6..3fdb7cfbffb3 100644 --- a/include/linux/mfd/samsung/core.h +++ b/include/linux/mfd/samsung/core.h @@ -28,6 +28,7 @@ #define MIN_800_MV 800000 #define MIN_750_MV 750000 #define MIN_600_MV 600000 +#define MIN_500_MV 500000 /* Macros to represent steps for LDO/BUCK */ #define STEP_50_MV 50000 diff --git a/include/linux/mfd/samsung/s2mps13.h b/include/linux/mfd/samsung/s2mps13.h new file mode 100644 index 000000000000..ce5dda8958fe --- /dev/null +++ b/include/linux/mfd/samsung/s2mps13.h @@ -0,0 +1,186 @@ +/* + * s2mps13.h + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd + * http://www.samsung.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. + * + */ + +#ifndef __LINUX_MFD_S2MPS13_H +#define __LINUX_MFD_S2MPS13_H + +/* S2MPS13 registers */ +enum s2mps13_reg { + S2MPS13_REG_ID, + S2MPS13_REG_INT1, + S2MPS13_REG_INT2, + S2MPS13_REG_INT3, + S2MPS13_REG_INT1M, + S2MPS13_REG_INT2M, + S2MPS13_REG_INT3M, + S2MPS13_REG_ST1, + S2MPS13_REG_ST2, + S2MPS13_REG_PWRONSRC, + S2MPS13_REG_OFFSRC, + S2MPS13_REG_BU_CHG, + S2MPS13_REG_RTCCTRL, + S2MPS13_REG_CTRL1, + S2MPS13_REG_CTRL2, + S2MPS13_REG_RSVD1, + S2MPS13_REG_RSVD2, + S2MPS13_REG_RSVD3, + S2MPS13_REG_RSVD4, + S2MPS13_REG_RSVD5, + S2MPS13_REG_RSVD6, + S2MPS13_REG_CTRL3, + S2MPS13_REG_RSVD7, + S2MPS13_REG_RSVD8, + S2MPS13_REG_WRSTBI, + S2MPS13_REG_B1CTRL, + S2MPS13_REG_B1OUT, + S2MPS13_REG_B2CTRL, + S2MPS13_REG_B2OUT, + S2MPS13_REG_B3CTRL, + S2MPS13_REG_B3OUT, + S2MPS13_REG_B4CTRL, + S2MPS13_REG_B4OUT, + S2MPS13_REG_B5CTRL, + S2MPS13_REG_B5OUT, + S2MPS13_REG_B6CTRL, + S2MPS13_REG_B6OUT, + S2MPS13_REG_B7CTRL, + S2MPS13_REG_B7OUT, + S2MPS13_REG_B8CTRL, + S2MPS13_REG_B8OUT, + S2MPS13_REG_B9CTRL, + S2MPS13_REG_B9OUT, + S2MPS13_REG_B10CTRL, + S2MPS13_REG_B10OUT, + S2MPS13_REG_BB1CTRL, + S2MPS13_REG_BB1OUT, + S2MPS13_REG_BUCK_RAMP1, + S2MPS13_REG_BUCK_RAMP2, + S2MPS13_REG_LDO_DVS1, + S2MPS13_REG_LDO_DVS2, + S2MPS13_REG_LDO_DVS3, + S2MPS13_REG_B6OUT2, + S2MPS13_REG_L1CTRL, + S2MPS13_REG_L2CTRL, + S2MPS13_REG_L3CTRL, + S2MPS13_REG_L4CTRL, + S2MPS13_REG_L5CTRL, + S2MPS13_REG_L6CTRL, + S2MPS13_REG_L7CTRL, + S2MPS13_REG_L8CTRL, + S2MPS13_REG_L9CTRL, + S2MPS13_REG_L10CTRL, + S2MPS13_REG_L11CTRL, + S2MPS13_REG_L12CTRL, + S2MPS13_REG_L13CTRL, + S2MPS13_REG_L14CTRL, + S2MPS13_REG_L15CTRL, + S2MPS13_REG_L16CTRL, + S2MPS13_REG_L17CTRL, + S2MPS13_REG_L18CTRL, + S2MPS13_REG_L19CTRL, + S2MPS13_REG_L20CTRL, + S2MPS13_REG_L21CTRL, + S2MPS13_REG_L22CTRL, + S2MPS13_REG_L23CTRL, + S2MPS13_REG_L24CTRL, + S2MPS13_REG_L25CTRL, + S2MPS13_REG_L26CTRL, + S2MPS13_REG_L27CTRL, + S2MPS13_REG_L28CTRL, + S2MPS13_REG_L30CTRL, + S2MPS13_REG_L31CTRL, + S2MPS13_REG_L32CTRL, + S2MPS13_REG_L33CTRL, + S2MPS13_REG_L34CTRL, + S2MPS13_REG_L35CTRL, + S2MPS13_REG_L36CTRL, + S2MPS13_REG_L37CTRL, + S2MPS13_REG_L38CTRL, + S2MPS13_REG_L39CTRL, + S2MPS13_REG_L40CTRL, + S2MPS13_REG_LDODSCH1, + S2MPS13_REG_LDODSCH2, + S2MPS13_REG_LDODSCH3, + S2MPS13_REG_LDODSCH4, + S2MPS13_REG_LDODSCH5, +}; + +/* regulator ids */ +enum s2mps13_regulators { + S2MPS13_LDO1, + S2MPS13_LDO2, + S2MPS13_LDO3, + S2MPS13_LDO4, + S2MPS13_LDO5, + S2MPS13_LDO6, + S2MPS13_LDO7, + S2MPS13_LDO8, + S2MPS13_LDO9, + S2MPS13_LDO10, + S2MPS13_LDO11, + S2MPS13_LDO12, + S2MPS13_LDO13, + S2MPS13_LDO14, + S2MPS13_LDO15, + S2MPS13_LDO16, + S2MPS13_LDO17, + S2MPS13_LDO18, + S2MPS13_LDO19, + S2MPS13_LDO20, + S2MPS13_LDO21, + S2MPS13_LDO22, + S2MPS13_LDO23, + S2MPS13_LDO24, + S2MPS13_LDO25, + S2MPS13_LDO26, + S2MPS13_LDO27, + S2MPS13_LDO28, + S2MPS13_LDO29, + S2MPS13_LDO30, + S2MPS13_LDO31, + S2MPS13_LDO32, + S2MPS13_LDO33, + S2MPS13_LDO34, + S2MPS13_LDO35, + S2MPS13_LDO36, + S2MPS13_LDO37, + S2MPS13_LDO38, + S2MPS13_LDO39, + S2MPS13_LDO40, + S2MPS13_BUCK1, + S2MPS13_BUCK2, + S2MPS13_BUCK3, + S2MPS13_BUCK4, + S2MPS13_BUCK5, + S2MPS13_BUCK6, + S2MPS13_BUCK7, + S2MPS13_BUCK8, + S2MPS13_BUCK9, + S2MPS13_BUCK10, + + S2MPS13_REGULATOR_MAX, +}; + +/* + * Default ramp delay in uv/us. Datasheet says that ramp delay can be + * controlled however it does not specify which register is used for that. + * Let's assume that default value will be set. + */ +#define S2MPS13_BUCK_RAMP_DELAY 12500 + +#endif /* __LINUX_MFD_S2MPS13_H */ -- cgit v1.2.3 From 2c86e9fb7263dbca2c21a086090d32ba90129f7b Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Mon, 6 Oct 2014 15:48:43 +0200 Subject: mfd: Add atmel-hlcdc driver The HLCDC IP available on some Atmel SoCs (i.e. at91sam9n12, at91sam9x5 family or sama5d3 family) exposes 2 subdevices: - a display controller (controlled by a DRM driver) - a PWM chip The MFD device provides a regmap and several clocks (those connected to this hardware block) to its subdevices. This way concurrent accesses to the iomem range are handled by the regmap framework, and each subdevice can safely access HLCDC registers. Signed-off-by: Boris Brezillon Tested-by: Anthony Harivel Tested-by: Ludovic Desroches Signed-off-by: Lee Jones --- drivers/mfd/Kconfig | 6 ++ drivers/mfd/Makefile | 1 + drivers/mfd/atmel-hlcdc.c | 122 ++++++++++++++++++++++++++++++++++++++++ include/linux/mfd/atmel-hlcdc.h | 85 ++++++++++++++++++++++++++++ 4 files changed, 214 insertions(+) create mode 100644 drivers/mfd/atmel-hlcdc.c create mode 100644 include/linux/mfd/atmel-hlcdc.h (limited to 'include/linux') diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index fdbb40181834..bd4a155a9564 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -59,6 +59,12 @@ config MFD_AAT2870_CORE additional drivers must be enabled in order to use the functionality of the device. +config MFD_ATMEL_HLCDC + tristate + select MFD_CORE + select REGMAP_MMIO + depends on OF + config MFD_BCM590XX tristate "Broadcom BCM590xx PMUs" select MFD_CORE diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 10bbd0b9096b..2cd7e743280c 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -157,6 +157,7 @@ obj-$(CONFIG_MFD_SPMI_PMIC) += qcom-spmi-pmic.o obj-$(CONFIG_TPS65911_COMPARATOR) += tps65911-comparator.o obj-$(CONFIG_MFD_TPS65090) += tps65090.o obj-$(CONFIG_MFD_AAT2870_CORE) += aat2870-core.o +obj-$(CONFIG_MFD_ATMEL_HLCDC) += atmel-hlcdc.o obj-$(CONFIG_MFD_INTEL_MSIC) += intel_msic.o obj-$(CONFIG_MFD_PALMAS) += palmas.o obj-$(CONFIG_MFD_VIPERBOARD) += viperboard.o diff --git a/drivers/mfd/atmel-hlcdc.c b/drivers/mfd/atmel-hlcdc.c new file mode 100644 index 000000000000..cfd58f4cc5c3 --- /dev/null +++ b/drivers/mfd/atmel-hlcdc.c @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2014 Free Electrons + * Copyright (C) 2014 Atmel + * + * Author: Boris BREZILLON + * + * 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. + * + * 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, see . + */ + +#include +#include +#include +#include +#include +#include + +#define ATMEL_HLCDC_REG_MAX (0x4000 - 0x4) + +static const struct mfd_cell atmel_hlcdc_cells[] = { + { + .name = "atmel-hlcdc-pwm", + .of_compatible = "atmel,hlcdc-pwm", + }, + { + .name = "atmel-hlcdc-dc", + .of_compatible = "atmel,hlcdc-display-controller", + }, +}; + +static const struct regmap_config atmel_hlcdc_regmap_config = { + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, + .max_register = ATMEL_HLCDC_REG_MAX, +}; + +static int atmel_hlcdc_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct atmel_hlcdc *hlcdc; + struct resource *res; + void __iomem *regs; + + hlcdc = devm_kzalloc(dev, sizeof(*hlcdc), GFP_KERNEL); + if (!hlcdc) + return -ENOMEM; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + regs = devm_ioremap_resource(dev, res); + if (IS_ERR(regs)) + return PTR_ERR(regs); + + hlcdc->irq = platform_get_irq(pdev, 0); + if (hlcdc->irq < 0) + return hlcdc->irq; + + hlcdc->periph_clk = devm_clk_get(dev, "periph_clk"); + if (IS_ERR(hlcdc->periph_clk)) { + dev_err(dev, "failed to get peripheral clock\n"); + return PTR_ERR(hlcdc->periph_clk); + } + + hlcdc->sys_clk = devm_clk_get(dev, "sys_clk"); + if (IS_ERR(hlcdc->sys_clk)) { + dev_err(dev, "failed to get system clock\n"); + return PTR_ERR(hlcdc->sys_clk); + } + + hlcdc->slow_clk = devm_clk_get(dev, "slow_clk"); + if (IS_ERR(hlcdc->slow_clk)) { + dev_err(dev, "failed to get slow clock\n"); + return PTR_ERR(hlcdc->slow_clk); + } + + hlcdc->regmap = devm_regmap_init_mmio(dev, regs, + &atmel_hlcdc_regmap_config); + if (IS_ERR(hlcdc->regmap)) + return PTR_ERR(hlcdc->regmap); + + dev_set_drvdata(dev, hlcdc); + + return mfd_add_devices(dev, -1, atmel_hlcdc_cells, + ARRAY_SIZE(atmel_hlcdc_cells), + NULL, 0, NULL); +} + +static int atmel_hlcdc_remove(struct platform_device *pdev) +{ + mfd_remove_devices(&pdev->dev); + + return 0; +} + +static const struct of_device_id atmel_hlcdc_match[] = { + { .compatible = "atmel,sama5d3-hlcdc" }, + { /* sentinel */ }, +}; + +static struct platform_driver atmel_hlcdc_driver = { + .probe = atmel_hlcdc_probe, + .remove = atmel_hlcdc_remove, + .driver = { + .name = "atmel-hlcdc", + .of_match_table = atmel_hlcdc_match, + }, +}; +module_platform_driver(atmel_hlcdc_driver); + +MODULE_ALIAS("platform:atmel-hlcdc"); +MODULE_AUTHOR("Boris Brezillon "); +MODULE_DESCRIPTION("Atmel HLCDC driver"); +MODULE_LICENSE("GPL v2"); diff --git a/include/linux/mfd/atmel-hlcdc.h b/include/linux/mfd/atmel-hlcdc.h new file mode 100644 index 000000000000..1279ab1644b5 --- /dev/null +++ b/include/linux/mfd/atmel-hlcdc.h @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2014 Free Electrons + * Copyright (C) 2014 Atmel + * + * Author: Boris BREZILLON + * + * 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. + * + * 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, see . + */ + +#ifndef __LINUX_MFD_HLCDC_H +#define __LINUX_MFD_HLCDC_H + +#include +#include + +#define ATMEL_HLCDC_CFG(i) ((i) * 0x4) +#define ATMEL_HLCDC_SIG_CFG LCDCFG(5) +#define ATMEL_HLCDC_HSPOL BIT(0) +#define ATMEL_HLCDC_VSPOL BIT(1) +#define ATMEL_HLCDC_VSPDLYS BIT(2) +#define ATMEL_HLCDC_VSPDLYE BIT(3) +#define ATMEL_HLCDC_DISPPOL BIT(4) +#define ATMEL_HLCDC_DITHER BIT(6) +#define ATMEL_HLCDC_DISPDLY BIT(7) +#define ATMEL_HLCDC_MODE_MASK GENMASK(9, 8) +#define ATMEL_HLCDC_PP BIT(10) +#define ATMEL_HLCDC_VSPSU BIT(12) +#define ATMEL_HLCDC_VSPHO BIT(13) +#define ATMEL_HLCDC_GUARDTIME_MASK GENMASK(20, 16) + +#define ATMEL_HLCDC_EN 0x20 +#define ATMEL_HLCDC_DIS 0x24 +#define ATMEL_HLCDC_SR 0x28 +#define ATMEL_HLCDC_IER 0x2c +#define ATMEL_HLCDC_IDR 0x30 +#define ATMEL_HLCDC_IMR 0x34 +#define ATMEL_HLCDC_ISR 0x38 + +#define ATMEL_HLCDC_CLKPOL BIT(0) +#define ATMEL_HLCDC_CLKSEL BIT(2) +#define ATMEL_HLCDC_CLKPWMSEL BIT(3) +#define ATMEL_HLCDC_CGDIS(i) BIT(8 + (i)) +#define ATMEL_HLCDC_CLKDIV_SHFT 16 +#define ATMEL_HLCDC_CLKDIV_MASK GENMASK(23, 16) +#define ATMEL_HLCDC_CLKDIV(div) ((div - 2) << ATMEL_HLCDC_CLKDIV_SHFT) + +#define ATMEL_HLCDC_PIXEL_CLK BIT(0) +#define ATMEL_HLCDC_SYNC BIT(1) +#define ATMEL_HLCDC_DISP BIT(2) +#define ATMEL_HLCDC_PWM BIT(3) +#define ATMEL_HLCDC_SIP BIT(4) + +#define ATMEL_HLCDC_SOF BIT(0) +#define ATMEL_HLCDC_SYNCDIS BIT(1) +#define ATMEL_HLCDC_FIFOERR BIT(4) +#define ATMEL_HLCDC_LAYER_STATUS(x) BIT((x) + 8) + +/** + * Structure shared by the MFD device and its subdevices. + * + * @regmap: register map used to access HLCDC IP registers + * @periph_clk: the hlcdc peripheral clock + * @sys_clk: the hlcdc system clock + * @slow_clk: the system slow clk + * @irq: the hlcdc irq + */ +struct atmel_hlcdc { + struct regmap *regmap; + struct clk *periph_clk; + struct clk *sys_clk; + struct clk *slow_clk; + int irq; +}; + +#endif /* __LINUX_MFD_HLCDC_H */ -- cgit v1.2.3 From 6cbac55368324ec2a0e59e192c5b596d0f4569f7 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Fri, 10 Oct 2014 10:23:53 +0200 Subject: mfd: max77693: Remove unused define Remove old MAX77693_NUM_IRQ_MUIC_REGS define. Not used anywhere. Signed-off-by: Krzysztof Kozlowski Signed-off-by: Lee Jones --- include/linux/mfd/max77693-private.h | 1 - 1 file changed, 1 deletion(-) (limited to 'include/linux') diff --git a/include/linux/mfd/max77693-private.h b/include/linux/mfd/max77693-private.h index fc17d56581b2..6392a1565452 100644 --- a/include/linux/mfd/max77693-private.h +++ b/include/linux/mfd/max77693-private.h @@ -26,7 +26,6 @@ #include -#define MAX77693_NUM_IRQ_MUIC_REGS 3 #define MAX77693_REG_INVALID (0xff) /* Slave addr = 0xCC: PMIC, Charger, Flash LED */ -- cgit v1.2.3 From 5cb5d9616a47d5383a85379afa4429382ef46b38 Mon Sep 17 00:00:00 2001 From: Micky Ching Date: Fri, 10 Oct 2014 13:58:44 +0800 Subject: mfd: rtsx: Fix PM suspend for 5227 & 5249 Fix rts5227&5249 failed send buffer cmd after suspend, PM_CTRL3 should reset before send any buffer cmd after suspend. Otherwise, buffer cmd will failed, this will lead resume fail. Signed-off-by: Micky Ching Signed-off-by: Lee Jones --- drivers/mfd/Makefile | 2 +- drivers/mfd/rts5227.c | 6 ++++++ drivers/mfd/rts5249.c | 4 ++++ drivers/mfd/rtsx_gops.c | 37 +++++++++++++++++++++++++++++++++++++ drivers/mfd/rtsx_pcr.h | 3 +++ include/linux/mfd/rtsx_pci.h | 28 ++++++++++++++++++++++++++++ 6 files changed, 79 insertions(+), 1 deletion(-) create mode 100644 drivers/mfd/rtsx_gops.c (limited to 'include/linux') diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 2cd7e743280c..53467e211381 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -13,7 +13,7 @@ obj-$(CONFIG_MFD_CROS_EC) += cros_ec.o obj-$(CONFIG_MFD_CROS_EC_I2C) += cros_ec_i2c.o obj-$(CONFIG_MFD_CROS_EC_SPI) += cros_ec_spi.o -rtsx_pci-objs := rtsx_pcr.o rts5209.o rts5229.o rtl8411.o rts5227.o rts5249.o +rtsx_pci-objs := rtsx_pcr.o rtsx_gops.o rts5209.o rts5229.o rtl8411.o rts5227.o rts5249.o obj-$(CONFIG_MFD_RTSX_PCI) += rtsx_pci.o obj-$(CONFIG_MFD_RTSX_USB) += rtsx_usb.o diff --git a/drivers/mfd/rts5227.c b/drivers/mfd/rts5227.c index 9c8eec80ceed..32407404d838 100644 --- a/drivers/mfd/rts5227.c +++ b/drivers/mfd/rts5227.c @@ -130,6 +130,12 @@ static int rts5227_extra_init_hw(struct rtsx_pcr *pcr) static int rts5227_optimize_phy(struct rtsx_pcr *pcr) { + int err; + + err = rtsx_gops_pm_reset(pcr); + if (err < 0) + return err; + /* Optimize RX sensitivity */ return rtsx_pci_write_phy_register(pcr, 0x00, 0xBA42); } diff --git a/drivers/mfd/rts5249.c b/drivers/mfd/rts5249.c index 573de7bfcced..cf425cc959d5 100644 --- a/drivers/mfd/rts5249.c +++ b/drivers/mfd/rts5249.c @@ -130,6 +130,10 @@ static int rts5249_optimize_phy(struct rtsx_pcr *pcr) { int err; + err = rtsx_gops_pm_reset(pcr); + if (err < 0) + return err; + err = rtsx_pci_write_phy_register(pcr, PHY_REG_REV, PHY_REG_REV_RESV | PHY_REG_REV_RXIDLE_LATCHED | PHY_REG_REV_P1_EN | PHY_REG_REV_RXIDLE_EN | diff --git a/drivers/mfd/rtsx_gops.c b/drivers/mfd/rtsx_gops.c new file mode 100644 index 000000000000..b1a98c678593 --- /dev/null +++ b/drivers/mfd/rtsx_gops.c @@ -0,0 +1,37 @@ +/* Driver for Realtek PCI-Express card reader + * + * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved. + * + * 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, 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, see . + * + * Author: + * Micky Ching + */ + +#include +#include "rtsx_pcr.h" + +int rtsx_gops_pm_reset(struct rtsx_pcr *pcr) +{ + int err; + + /* init aspm */ + rtsx_pci_write_register(pcr, ASPM_FORCE_CTL, 0xFF, 0x00); + err = rtsx_pci_update_cfg_byte(pcr, LCTLR, ~LCTLR_ASPM_CTL_MASK, 0x00); + if (err < 0) + return err; + + /* reset PM_CTRL3 before send buffer cmd */ + return rtsx_pci_write_register(pcr, PM_CTRL3, D3_DELINK_MODE_EN, 0x00); +} diff --git a/drivers/mfd/rtsx_pcr.h b/drivers/mfd/rtsx_pcr.h index 07e4c2ebf05a..fe2bbb67defc 100644 --- a/drivers/mfd/rtsx_pcr.h +++ b/drivers/mfd/rtsx_pcr.h @@ -72,4 +72,7 @@ do { \ pcr->ms_pull_ctl_disable_tbl = __device##_ms_pull_ctl_disable_tbl; \ } while (0) +/* generic operations */ +int rtsx_gops_pm_reset(struct rtsx_pcr *pcr); + #endif diff --git a/include/linux/mfd/rtsx_pci.h b/include/linux/mfd/rtsx_pci.h index 74346d5e7899..1604dda4edcf 100644 --- a/include/linux/mfd/rtsx_pci.h +++ b/include/linux/mfd/rtsx_pci.h @@ -707,6 +707,14 @@ #define PM_CTRL1 0xFF44 #define PM_CTRL2 0xFF45 #define PM_CTRL3 0xFF46 +#define SDIO_SEND_PME_EN 0x80 +#define FORCE_RC_MODE_ON 0x40 +#define FORCE_RX50_LINK_ON 0x20 +#define D3_DELINK_MODE_EN 0x10 +#define USE_PESRTB_CTL_DELINK 0x08 +#define DELAY_PIN_WAKE 0x04 +#define RESET_PIN_WAKE 0x02 +#define PM_WAKE_EN 0x01 #define PM_CTRL4 0xFF47 /* Memory mapping */ @@ -752,6 +760,14 @@ #define PHY_DUM_REG 0x1F #define LCTLR 0x80 +#define LCTLR_EXT_SYNC 0x80 +#define LCTLR_COMMON_CLOCK_CFG 0x40 +#define LCTLR_RETRAIN_LINK 0x20 +#define LCTLR_LINK_DISABLE 0x10 +#define LCTLR_RCB 0x08 +#define LCTLR_RESERVED 0x04 +#define LCTLR_ASPM_CTL_MASK 0x03 + #define PCR_SETTING_REG1 0x724 #define PCR_SETTING_REG2 0x814 #define PCR_SETTING_REG3 0x747 @@ -967,4 +983,16 @@ static inline u8 *rtsx_pci_get_cmd_data(struct rtsx_pcr *pcr) return (u8 *)(pcr->host_cmds_ptr); } +static inline int rtsx_pci_update_cfg_byte(struct rtsx_pcr *pcr, int addr, + u8 mask, u8 append) +{ + int err; + u8 val; + + err = pci_read_config_byte(pcr->pci, addr, &val); + if (err < 0) + return err; + return pci_write_config_byte(pcr->pci, addr, (val & mask) | append); +} + #endif -- cgit v1.2.3 From 7d082baa349e59ce3de6452abc05e5de6436aad4 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Thu, 9 Oct 2014 09:18:38 -0700 Subject: mfd: ab8500-sysctrl: Drop ab8500_restart ab8500_restart is not called from anywhere in the kernel, so drop it. Signed-off-by: Guenter Roeck Acked-by: Linus Walleij Signed-off-by: Lee Jones --- drivers/mfd/ab8500-sysctrl.c | 57 ------------------------------- include/linux/mfd/abx500/ab8500-sysctrl.h | 1 - 2 files changed, 58 deletions(-) (limited to 'include/linux') diff --git a/drivers/mfd/ab8500-sysctrl.c b/drivers/mfd/ab8500-sysctrl.c index 8e0dae59844d..94dbcdd2a1ff 100644 --- a/drivers/mfd/ab8500-sysctrl.c +++ b/drivers/mfd/ab8500-sysctrl.c @@ -85,63 +85,6 @@ shutdown: } } -/* - * Use the AB WD to reset the platform. It will perform a hard - * reset instead of a soft reset. Write the reset reason to - * the AB before reset, which can be read upon restart. - */ -void ab8500_restart(char mode, const char *cmd) -{ - struct ab8500_platform_data *plat; - struct ab8500_sysctrl_platform_data *pdata; - u16 reason = 0; - u8 val; - - if (sysctrl_dev == NULL) { - pr_err("%s: sysctrl not initialized\n", __func__); - return; - } - - plat = dev_get_platdata(sysctrl_dev->parent); - pdata = plat->sysctrl; - if (pdata && pdata->reboot_reason_code) - reason = pdata->reboot_reason_code(cmd); - else - pr_warn("[%s] No reboot reason set. Default reason %d\n", - __func__, reason); - - /* - * Disable RTC alarm, just a precaution so that no alarm - * is running when WD reset is executed. - */ - abx500_get_register_interruptible(sysctrl_dev, AB8500_RTC, - RTC_CTRL , &val); - abx500_set_register_interruptible(sysctrl_dev, AB8500_RTC, - RTC_CTRL , (val & ~RTC_ALARM_ENABLE)); - - /* - * Android is not using the RTC alarm registers during reboot - * so we borrow them for writing the reason of reset - */ - - /* reason[8 LSB] */ - val = reason & 0xFF; - abx500_set_register_interruptible(sysctrl_dev, AB8500_RTC, - AB8500_ALARM_MIN_LOW , val); - - /* reason[8 MSB] */ - val = (reason>>8) & 0xFF; - abx500_set_register_interruptible(sysctrl_dev, AB8500_RTC, - AB8500_ALARM_MIN_MID , val); - - /* Setting WD timeout to 0 */ - ab8500_sysctrl_write(AB8500_MAINWDOGTIMER, 0xFF, 0x0); - - /* Setting the parameters to AB8500 WD*/ - ab8500_sysctrl_write(AB8500_MAINWDOGCTRL, 0xFF, (AB8500_ENABLE_WD | - AB8500_WD_RESTART_ON_EXPIRE | AB8500_KICK_WD)); -} - static inline bool valid_bank(u8 bank) { return ((bank == AB8500_SYS_CTRL1_BLOCK) || diff --git a/include/linux/mfd/abx500/ab8500-sysctrl.h b/include/linux/mfd/abx500/ab8500-sysctrl.h index adba89d9c660..689312745b2f 100644 --- a/include/linux/mfd/abx500/ab8500-sysctrl.h +++ b/include/linux/mfd/abx500/ab8500-sysctrl.h @@ -12,7 +12,6 @@ int ab8500_sysctrl_read(u16 reg, u8 *value); int ab8500_sysctrl_write(u16 reg, u8 mask, u8 value); -void ab8500_restart(char mode, const char *cmd); #else -- cgit v1.2.3 From 47958c5ab4035bd91f05598f76a61cd9f7f2934c Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 4 Nov 2014 15:24:36 +0000 Subject: mfd: arizona: Document HP_CTRL_1L and HP_CTRL_1R registers These registers are documented in the datasheet and used as part of the extcon driver. Expose them properly through regmap as the datasheet notes they should be treated as volatile do so. Signed-off-by: Charles Keepax --- drivers/mfd/wm5102-tables.c | 6 +++-- drivers/mfd/wm5110-tables.c | 4 ++++ drivers/mfd/wm8997-tables.c | 4 ++++ include/linux/mfd/arizona/registers.h | 42 +++++++++++++++++++++++++++++++++++ 4 files changed, 54 insertions(+), 2 deletions(-) (limited to 'include/linux') diff --git a/drivers/mfd/wm5102-tables.c b/drivers/mfd/wm5102-tables.c index d6f35bbf795b..b326a82017ee 100644 --- a/drivers/mfd/wm5102-tables.c +++ b/drivers/mfd/wm5102-tables.c @@ -336,8 +336,6 @@ static const struct reg_default wm5102_reg_default[] = { { 0x00000218, 0x01A6 }, /* R536 - Mic Bias Ctrl 1 */ { 0x00000219, 0x01A6 }, /* R537 - Mic Bias Ctrl 2 */ { 0x0000021A, 0x01A6 }, /* R538 - Mic Bias Ctrl 3 */ - { 0x00000225, 0x0400 }, /* R549 - HP Ctrl 1L */ - { 0x00000226, 0x0400 }, /* R550 - HP Ctrl 1R */ { 0x00000293, 0x0000 }, /* R659 - Accessory Detect Mode 1 */ { 0x0000029B, 0x0020 }, /* R667 - Headphone Detect 1 */ { 0x0000029C, 0x0000 }, /* R668 - Headphone Detect 2 */ @@ -1112,6 +1110,8 @@ static bool wm5102_readable_register(struct device *dev, unsigned int reg) case ARIZONA_MIC_BIAS_CTRL_1: case ARIZONA_MIC_BIAS_CTRL_2: case ARIZONA_MIC_BIAS_CTRL_3: + case ARIZONA_HP_CTRL_1L: + case ARIZONA_HP_CTRL_1R: case ARIZONA_ACCESSORY_DETECT_MODE_1: case ARIZONA_HEADPHONE_DETECT_1: case ARIZONA_HEADPHONE_DETECT_2: @@ -1949,6 +1949,8 @@ static bool wm5102_volatile_register(struct device *dev, unsigned int reg) case ARIZONA_DSP1_SCRATCH_1: case ARIZONA_DSP1_SCRATCH_2: case ARIZONA_DSP1_SCRATCH_3: + case ARIZONA_HP_CTRL_1L: + case ARIZONA_HP_CTRL_1R: case ARIZONA_HEADPHONE_DETECT_2: case ARIZONA_HP_DACVAL: case ARIZONA_MIC_DETECT_3: diff --git a/drivers/mfd/wm5110-tables.c b/drivers/mfd/wm5110-tables.c index 4642b5b816a0..c75390ad4f45 100644 --- a/drivers/mfd/wm5110-tables.c +++ b/drivers/mfd/wm5110-tables.c @@ -1790,6 +1790,8 @@ static bool wm5110_readable_register(struct device *dev, unsigned int reg) case ARIZONA_MIC_BIAS_CTRL_1: case ARIZONA_MIC_BIAS_CTRL_2: case ARIZONA_MIC_BIAS_CTRL_3: + case ARIZONA_HP_CTRL_1L: + case ARIZONA_HP_CTRL_1R: case ARIZONA_ACCESSORY_DETECT_MODE_1: case ARIZONA_HEADPHONE_DETECT_1: case ARIZONA_HEADPHONE_DETECT_2: @@ -2825,6 +2827,8 @@ static bool wm5110_volatile_register(struct device *dev, unsigned int reg) case ARIZONA_ASYNC_SAMPLE_RATE_1_STATUS: case ARIZONA_ASYNC_SAMPLE_RATE_2_STATUS: case ARIZONA_MIC_DETECT_3: + case ARIZONA_HP_CTRL_1L: + case ARIZONA_HP_CTRL_1R: case ARIZONA_HEADPHONE_DETECT_2: case ARIZONA_INPUT_ENABLES_STATUS: case ARIZONA_OUTPUT_STATUS_1: diff --git a/drivers/mfd/wm8997-tables.c b/drivers/mfd/wm8997-tables.c index f44d195d4496..c0c25d75aacc 100644 --- a/drivers/mfd/wm8997-tables.c +++ b/drivers/mfd/wm8997-tables.c @@ -887,6 +887,8 @@ static bool wm8997_readable_register(struct device *dev, unsigned int reg) case ARIZONA_MIC_BIAS_CTRL_1: case ARIZONA_MIC_BIAS_CTRL_2: case ARIZONA_MIC_BIAS_CTRL_3: + case ARIZONA_HP_CTRL_1L: + case ARIZONA_HP_CTRL_1R: case ARIZONA_ACCESSORY_DETECT_MODE_1: case ARIZONA_HEADPHONE_DETECT_1: case ARIZONA_HEADPHONE_DETECT_2: @@ -1479,6 +1481,8 @@ static bool wm8997_volatile_register(struct device *dev, unsigned int reg) case ARIZONA_SAMPLE_RATE_3_STATUS: case ARIZONA_ASYNC_SAMPLE_RATE_1_STATUS: case ARIZONA_MIC_DETECT_3: + case ARIZONA_HP_CTRL_1L: + case ARIZONA_HP_CTRL_1R: case ARIZONA_HEADPHONE_DETECT_2: case ARIZONA_INPUT_ENABLES_STATUS: case ARIZONA_OUTPUT_STATUS_1: diff --git a/include/linux/mfd/arizona/registers.h b/include/linux/mfd/arizona/registers.h index c0b075f6bc35..d521f327b34f 100644 --- a/include/linux/mfd/arizona/registers.h +++ b/include/linux/mfd/arizona/registers.h @@ -125,6 +125,8 @@ #define ARIZONA_MIC_BIAS_CTRL_1 0x218 #define ARIZONA_MIC_BIAS_CTRL_2 0x219 #define ARIZONA_MIC_BIAS_CTRL_3 0x21A +#define ARIZONA_HP_CTRL_1L 0x225 +#define ARIZONA_HP_CTRL_1R 0x226 #define ARIZONA_ACCESSORY_DETECT_MODE_1 0x293 #define ARIZONA_HEADPHONE_DETECT_1 0x29B #define ARIZONA_HEADPHONE_DETECT_2 0x29C @@ -2244,6 +2246,46 @@ #define ARIZONA_MICB3_ENA_SHIFT 0 /* MICB3_ENA */ #define ARIZONA_MICB3_ENA_WIDTH 1 /* MICB3_ENA */ +/* + * R549 (0x225) - HP Ctrl 1L + */ +#define ARIZONA_RMV_SHRT_HP1L 0x4000 /* RMV_SHRT_HP1L */ +#define ARIZONA_RMV_SHRT_HP1L_MASK 0x4000 /* RMV_SHRT_HP1L */ +#define ARIZONA_RMV_SHRT_HP1L_SHIFT 14 /* RMV_SHRT_HP1L */ +#define ARIZONA_RMV_SHRT_HP1L_WIDTH 1 /* RMV_SHRT_HP1L */ +#define ARIZONA_HP1L_FLWR 0x0004 /* HP1L_FLWR */ +#define ARIZONA_HP1L_FLWR_MASK 0x0004 /* HP1L_FLWR */ +#define ARIZONA_HP1L_FLWR_SHIFT 2 /* HP1L_FLWR */ +#define ARIZONA_HP1L_FLWR_WIDTH 1 /* HP1L_FLWR */ +#define ARIZONA_HP1L_SHRTI 0x0002 /* HP1L_SHRTI */ +#define ARIZONA_HP1L_SHRTI_MASK 0x0002 /* HP1L_SHRTI */ +#define ARIZONA_HP1L_SHRTI_SHIFT 1 /* HP1L_SHRTI */ +#define ARIZONA_HP1L_SHRTI_WIDTH 1 /* HP1L_SHRTI */ +#define ARIZONA_HP1L_SHRTO 0x0001 /* HP1L_SHRTO */ +#define ARIZONA_HP1L_SHRTO_MASK 0x0001 /* HP1L_SHRTO */ +#define ARIZONA_HP1L_SHRTO_SHIFT 0 /* HP1L_SHRTO */ +#define ARIZONA_HP1L_SHRTO_WIDTH 1 /* HP1L_SHRTO */ + +/* + * R550 (0x226) - HP Ctrl 1R + */ +#define ARIZONA_RMV_SHRT_HP1R 0x4000 /* RMV_SHRT_HP1R */ +#define ARIZONA_RMV_SHRT_HP1R_MASK 0x4000 /* RMV_SHRT_HP1R */ +#define ARIZONA_RMV_SHRT_HP1R_SHIFT 14 /* RMV_SHRT_HP1R */ +#define ARIZONA_RMV_SHRT_HP1R_WIDTH 1 /* RMV_SHRT_HP1R */ +#define ARIZONA_HP1R_FLWR 0x0004 /* HP1R_FLWR */ +#define ARIZONA_HP1R_FLWR_MASK 0x0004 /* HP1R_FLWR */ +#define ARIZONA_HP1R_FLWR_SHIFT 2 /* HP1R_FLWR */ +#define ARIZONA_HP1R_FLWR_WIDTH 1 /* HP1R_FLWR */ +#define ARIZONA_HP1R_SHRTI 0x0002 /* HP1R_SHRTI */ +#define ARIZONA_HP1R_SHRTI_MASK 0x0002 /* HP1R_SHRTI */ +#define ARIZONA_HP1R_SHRTI_SHIFT 1 /* HP1R_SHRTI */ +#define ARIZONA_HP1R_SHRTI_WIDTH 1 /* HP1R_SHRTI */ +#define ARIZONA_HP1R_SHRTO 0x0001 /* HP1R_SHRTO */ +#define ARIZONA_HP1R_SHRTO_MASK 0x0001 /* HP1R_SHRTO */ +#define ARIZONA_HP1R_SHRTO_SHIFT 0 /* HP1R_SHRTO */ +#define ARIZONA_HP1R_SHRTO_WIDTH 1 /* HP1R_SHRTO */ + /* * R659 (0x293) - Accessory Detect Mode 1 */ -- cgit v1.2.3 From 90f2d0f7bf069b1a2798156b7dcc8e7d1e874406 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 28 Oct 2014 11:06:56 +0100 Subject: mfd: tc3589x: get rid of static base The TC3589x driver is now a device tree-only driver, so we want only dynamic IRQs and GPIO numbers from the tc3589x, no static assignments. Signed-off-by: Linus Walleij --- drivers/gpio/gpio-tc3589x.c | 2 +- drivers/mfd/tc3589x.c | 9 +++------ include/linux/mfd/tc3589x.h | 8 -------- 3 files changed, 4 insertions(+), 15 deletions(-) (limited to 'include/linux') diff --git a/drivers/gpio/gpio-tc3589x.c b/drivers/gpio/gpio-tc3589x.c index ae0f6466eb09..abdcf58935f5 100644 --- a/drivers/gpio/gpio-tc3589x.c +++ b/drivers/gpio/gpio-tc3589x.c @@ -262,7 +262,7 @@ static int tc3589x_gpio_probe(struct platform_device *pdev) tc3589x_gpio->chip = template_chip; tc3589x_gpio->chip.ngpio = tc3589x->num_gpio; tc3589x_gpio->chip.dev = &pdev->dev; - tc3589x_gpio->chip.base = (pdata) ? pdata->gpio_base : -1; + tc3589x_gpio->chip.base = -1; #ifdef CONFIG_OF_GPIO tc3589x_gpio->chip.of_node = np; diff --git a/drivers/mfd/tc3589x.c b/drivers/mfd/tc3589x.c index 0072e668c208..aacb3720065c 100644 --- a/drivers/mfd/tc3589x.c +++ b/drivers/mfd/tc3589x.c @@ -241,10 +241,8 @@ static struct irq_domain_ops tc3589x_irq_ops = { static int tc3589x_irq_init(struct tc3589x *tc3589x, struct device_node *np) { - int base = tc3589x->irq_base; - tc3589x->domain = irq_domain_add_simple( - np, TC3589x_NR_INTERNAL_IRQS, base, + np, TC3589x_NR_INTERNAL_IRQS, 0, &tc3589x_irq_ops, tc3589x); if (!tc3589x->domain) { @@ -298,7 +296,7 @@ static int tc3589x_device_init(struct tc3589x *tc3589x) if (blocks & TC3589x_BLOCK_GPIO) { ret = mfd_add_devices(tc3589x->dev, -1, tc3589x_dev_gpio, ARRAY_SIZE(tc3589x_dev_gpio), NULL, - tc3589x->irq_base, tc3589x->domain); + 0, tc3589x->domain); if (ret) { dev_err(tc3589x->dev, "failed to add gpio child\n"); return ret; @@ -309,7 +307,7 @@ static int tc3589x_device_init(struct tc3589x *tc3589x) if (blocks & TC3589x_BLOCK_KEYPAD) { ret = mfd_add_devices(tc3589x->dev, -1, tc3589x_dev_keypad, ARRAY_SIZE(tc3589x_dev_keypad), NULL, - tc3589x->irq_base, tc3589x->domain); + 0, tc3589x->domain); if (ret) { dev_err(tc3589x->dev, "failed to keypad child\n"); return ret; @@ -404,7 +402,6 @@ static int tc3589x_probe(struct i2c_client *i2c, tc3589x->dev = &i2c->dev; tc3589x->i2c = i2c; tc3589x->pdata = pdata; - tc3589x->irq_base = pdata->irq_base; switch (version) { case TC3589X_TC35893: diff --git a/include/linux/mfd/tc3589x.h b/include/linux/mfd/tc3589x.h index e6088c2e2092..e1c12d84c26a 100644 --- a/include/linux/mfd/tc3589x.h +++ b/include/linux/mfd/tc3589x.h @@ -164,13 +164,10 @@ struct tc3589x_keypad_platform_data { /** * struct tc3589x_gpio_platform_data - TC3589x GPIO platform data - * @gpio_base: first gpio number assigned to TC3589x. A maximum of - * %TC3589x_NR_GPIOS GPIOs will be allocated. * @setup: callback for board-specific initialization * @remove: callback for board-specific teardown */ struct tc3589x_gpio_platform_data { - int gpio_base; void (*setup)(struct tc3589x *tc3589x, unsigned gpio_base); void (*remove)(struct tc3589x *tc3589x, unsigned gpio_base); }; @@ -178,18 +175,13 @@ struct tc3589x_gpio_platform_data { /** * struct tc3589x_platform_data - TC3589x platform data * @block: bitmask of blocks to enable (use TC3589x_BLOCK_*) - * @irq_base: base IRQ number. %TC3589x_NR_IRQS irqs will be used. * @gpio: GPIO-specific platform data * @keypad: keypad-specific platform data */ struct tc3589x_platform_data { unsigned int block; - int irq_base; struct tc3589x_gpio_platform_data *gpio; const struct tc3589x_keypad_platform_data *keypad; }; -#define TC3589x_NR_GPIOS 24 -#define TC3589x_NR_IRQS TC3589x_INT_GPIO(TC3589x_NR_GPIOS) - #endif -- cgit v1.2.3 From 783f6fc4cecd770dfdb1418c7c890dbeb3bf3c91 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 4 Nov 2014 13:04:07 +0000 Subject: mfd: wm5110: Add missing registers for AIF2 channels 3-6 When the extra 4 channels were added to AIF2 the necessary frame control registers were not given defaults and marked readable. This patch fixes this. Signed-off-by: Charles Keepax --- drivers/mfd/wm5110-tables.c | 16 ++++++++++++++++ include/linux/mfd/arizona/registers.h | 8 ++++++++ 2 files changed, 24 insertions(+) (limited to 'include/linux') diff --git a/drivers/mfd/wm5110-tables.c b/drivers/mfd/wm5110-tables.c index c75390ad4f45..12cad94b4035 100644 --- a/drivers/mfd/wm5110-tables.c +++ b/drivers/mfd/wm5110-tables.c @@ -895,8 +895,16 @@ static const struct reg_default wm5110_reg_default[] = { { 0x00000548, 0x1818 }, /* R1352 - AIF2 Frame Ctrl 2 */ { 0x00000549, 0x0000 }, /* R1353 - AIF2 Frame Ctrl 3 */ { 0x0000054A, 0x0001 }, /* R1354 - AIF2 Frame Ctrl 4 */ + { 0x0000054B, 0x0002 }, /* R1355 - AIF2 Frame Ctrl 5 */ + { 0x0000054C, 0x0003 }, /* R1356 - AIF2 Frame Ctrl 6 */ + { 0x0000054D, 0x0004 }, /* R1357 - AIF2 Frame Ctrl 7 */ + { 0x0000054E, 0x0005 }, /* R1358 - AIF2 Frame Ctrl 8 */ { 0x00000551, 0x0000 }, /* R1361 - AIF2 Frame Ctrl 11 */ { 0x00000552, 0x0001 }, /* R1362 - AIF2 Frame Ctrl 12 */ + { 0x00000553, 0x0002 }, /* R1363 - AIF2 Frame Ctrl 13 */ + { 0x00000554, 0x0003 }, /* R1364 - AIF2 Frame Ctrl 14 */ + { 0x00000555, 0x0004 }, /* R1365 - AIF2 Frame Ctrl 15 */ + { 0x00000556, 0x0005 }, /* R1366 - AIF2 Frame Ctrl 16 */ { 0x00000559, 0x0000 }, /* R1369 - AIF2 Tx Enables */ { 0x0000055A, 0x0000 }, /* R1370 - AIF2 Rx Enables */ { 0x00000580, 0x000C }, /* R1408 - AIF3 BCLK Ctrl */ @@ -1936,8 +1944,16 @@ static bool wm5110_readable_register(struct device *dev, unsigned int reg) case ARIZONA_AIF2_FRAME_CTRL_2: case ARIZONA_AIF2_FRAME_CTRL_3: case ARIZONA_AIF2_FRAME_CTRL_4: + case ARIZONA_AIF2_FRAME_CTRL_5: + case ARIZONA_AIF2_FRAME_CTRL_6: + case ARIZONA_AIF2_FRAME_CTRL_7: + case ARIZONA_AIF2_FRAME_CTRL_8: case ARIZONA_AIF2_FRAME_CTRL_11: case ARIZONA_AIF2_FRAME_CTRL_12: + case ARIZONA_AIF2_FRAME_CTRL_13: + case ARIZONA_AIF2_FRAME_CTRL_14: + case ARIZONA_AIF2_FRAME_CTRL_15: + case ARIZONA_AIF2_FRAME_CTRL_16: case ARIZONA_AIF2_TX_ENABLES: case ARIZONA_AIF2_RX_ENABLES: case ARIZONA_AIF3_BCLK_CTRL: diff --git a/include/linux/mfd/arizona/registers.h b/include/linux/mfd/arizona/registers.h index d521f327b34f..aacc10d7789c 100644 --- a/include/linux/mfd/arizona/registers.h +++ b/include/linux/mfd/arizona/registers.h @@ -281,8 +281,16 @@ #define ARIZONA_AIF2_FRAME_CTRL_2 0x548 #define ARIZONA_AIF2_FRAME_CTRL_3 0x549 #define ARIZONA_AIF2_FRAME_CTRL_4 0x54A +#define ARIZONA_AIF2_FRAME_CTRL_5 0x54B +#define ARIZONA_AIF2_FRAME_CTRL_6 0x54C +#define ARIZONA_AIF2_FRAME_CTRL_7 0x54D +#define ARIZONA_AIF2_FRAME_CTRL_8 0x54E #define ARIZONA_AIF2_FRAME_CTRL_11 0x551 #define ARIZONA_AIF2_FRAME_CTRL_12 0x552 +#define ARIZONA_AIF2_FRAME_CTRL_13 0x553 +#define ARIZONA_AIF2_FRAME_CTRL_14 0x554 +#define ARIZONA_AIF2_FRAME_CTRL_15 0x555 +#define ARIZONA_AIF2_FRAME_CTRL_16 0x556 #define ARIZONA_AIF2_TX_ENABLES 0x559 #define ARIZONA_AIF2_RX_ENABLES 0x55A #define ARIZONA_AIF2_FORCE_WRITE 0x55B -- cgit v1.2.3 From 9b8ffea6efb0d0edcac265a1ca422188fc1b6dfb Mon Sep 17 00:00:00 2001 From: Vincent Wan Date: Wed, 5 Nov 2014 14:09:00 +0800 Subject: mmc: sdhci: Add a quirk for AMD SDHC transfer mode register need to be cleared for cmd without data SDHC controller in AMD chipsets require SDHC transfer mode register to be cleared for commands without data. The issue was uncovered during testing eMMC cards on KB/ML based platforms Signed-off-by: Vincent Wan Signed-off-by: Wan Zongshun Signed-off-by: Arindam Nath Tested-by: Vikram B Tested-by: Raghavendra Swamy Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci.c | 9 +++++++-- include/linux/mmc/sdhci.h | 2 ++ 2 files changed, 9 insertions(+), 2 deletions(-) (limited to 'include/linux') diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index f895ab07fcc2..a743d5227eda 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -915,10 +915,15 @@ static void sdhci_set_transfer_mode(struct sdhci_host *host, struct mmc_data *data = cmd->data; if (data == NULL) { + if (host->quirks2 & + SDHCI_QUIRK2_CLEAR_TRANSFERMODE_REG_BEFORE_CMD) { + sdhci_writew(host, 0x0, SDHCI_TRANSFER_MODE); + } else { /* clear Auto CMD settings for no data CMDs */ - mode = sdhci_readw(host, SDHCI_TRANSFER_MODE); - sdhci_writew(host, mode & ~(SDHCI_TRNS_AUTO_CMD12 | + mode = sdhci_readw(host, SDHCI_TRANSFER_MODE); + sdhci_writew(host, mode & ~(SDHCI_TRNS_AUTO_CMD12 | SDHCI_TRNS_AUTO_CMD23), SDHCI_TRANSFER_MODE); + } return; } diff --git a/include/linux/mmc/sdhci.h b/include/linux/mmc/sdhci.h index 931ac5e05453..ae7f357b78c9 100644 --- a/include/linux/mmc/sdhci.h +++ b/include/linux/mmc/sdhci.h @@ -102,6 +102,8 @@ struct sdhci_host { #define SDHCI_QUIRK2_STOP_WITH_TC (1<<8) /* Controller does not support 64-bit DMA */ #define SDHCI_QUIRK2_BROKEN_64_BIT_DMA (1<<9) +/* need clear transfer mode register before send cmd */ +#define SDHCI_QUIRK2_CLEAR_TRANSFERMODE_REG_BEFORE_CMD (1<<10) int irq; /* Device IRQ */ void __iomem *ioaddr; /* Mapped address */ -- cgit v1.2.3 From 69d99fdcfd7815dfb2318f0777a46181d5bf42dc Mon Sep 17 00:00:00 2001 From: Prabu Thangamuthu Date: Mon, 20 Oct 2014 07:12:33 +0000 Subject: mmc: dw_mmc: Add IDMAC 64-bit address mode support Synopsys DW_MMC IP core supports Internal DMA Controller with 64-bit address mode from IP version 2.70a onwards. Updated the driver to support IDMAC 64-bit addressing mode. Signed-off-by: Prabu Thangamuthu Reviewed-by: Alim Akhtar Acked-by: Jaehoon Chung Signed-off-by: Ulf Hansson --- drivers/mmc/host/dw_mmc.c | 199 ++++++++++++++++++++++++++++++++++++--------- drivers/mmc/host/dw_mmc.h | 11 +++ include/linux/mmc/dw_mmc.h | 2 + 3 files changed, 174 insertions(+), 38 deletions(-) (limited to 'include/linux') diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index bb46b1b8d16b..5a37c33879a1 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -61,6 +61,24 @@ SDMMC_IDMAC_INT_FBE | SDMMC_IDMAC_INT_RI | \ SDMMC_IDMAC_INT_TI) +struct idmac_desc_64addr { + u32 des0; /* Control Descriptor */ + + u32 des1; /* Reserved */ + + u32 des2; /*Buffer sizes */ +#define IDMAC_64ADDR_SET_BUFFER1_SIZE(d, s) \ + ((d)->des2 = ((d)->des2 & 0x03ffe000) | ((s) & 0x1fff)) + + u32 des3; /* Reserved */ + + u32 des4; /* Lower 32-bits of Buffer Address Pointer 1*/ + u32 des5; /* Upper 32-bits of Buffer Address Pointer 1*/ + + u32 des6; /* Lower 32-bits of Next Descriptor Address */ + u32 des7; /* Upper 32-bits of Next Descriptor Address */ +}; + struct idmac_desc { u32 des0; /* Control Descriptor */ #define IDMAC_DES0_DIC BIT(1) @@ -414,30 +432,66 @@ static void dw_mci_translate_sglist(struct dw_mci *host, struct mmc_data *data, unsigned int sg_len) { int i; - struct idmac_desc *desc = host->sg_cpu; + if (host->dma_64bit_address == 1) { + struct idmac_desc_64addr *desc = host->sg_cpu; - for (i = 0; i < sg_len; i++, desc++) { - unsigned int length = sg_dma_len(&data->sg[i]); - u32 mem_addr = sg_dma_address(&data->sg[i]); + for (i = 0; i < sg_len; i++, desc++) { + unsigned int length = sg_dma_len(&data->sg[i]); + u64 mem_addr = sg_dma_address(&data->sg[i]); - /* Set the OWN bit and disable interrupts for this descriptor */ - desc->des0 = IDMAC_DES0_OWN | IDMAC_DES0_DIC | IDMAC_DES0_CH; + /* + * Set the OWN bit and disable interrupts for this + * descriptor + */ + desc->des0 = IDMAC_DES0_OWN | IDMAC_DES0_DIC | + IDMAC_DES0_CH; + /* Buffer length */ + IDMAC_64ADDR_SET_BUFFER1_SIZE(desc, length); + + /* Physical address to DMA to/from */ + desc->des4 = mem_addr & 0xffffffff; + desc->des5 = mem_addr >> 32; + } - /* Buffer length */ - IDMAC_SET_BUFFER1_SIZE(desc, length); + /* Set first descriptor */ + desc = host->sg_cpu; + desc->des0 |= IDMAC_DES0_FD; - /* Physical address to DMA to/from */ - desc->des2 = mem_addr; - } + /* Set last descriptor */ + desc = host->sg_cpu + (i - 1) * + sizeof(struct idmac_desc_64addr); + desc->des0 &= ~(IDMAC_DES0_CH | IDMAC_DES0_DIC); + desc->des0 |= IDMAC_DES0_LD; + + } else { + struct idmac_desc *desc = host->sg_cpu; + + for (i = 0; i < sg_len; i++, desc++) { + unsigned int length = sg_dma_len(&data->sg[i]); + u32 mem_addr = sg_dma_address(&data->sg[i]); + + /* + * Set the OWN bit and disable interrupts for this + * descriptor + */ + desc->des0 = IDMAC_DES0_OWN | IDMAC_DES0_DIC | + IDMAC_DES0_CH; + /* Buffer length */ + IDMAC_SET_BUFFER1_SIZE(desc, length); + + /* Physical address to DMA to/from */ + desc->des2 = mem_addr; + } - /* Set first descriptor */ - desc = host->sg_cpu; - desc->des0 |= IDMAC_DES0_FD; + /* Set first descriptor */ + desc = host->sg_cpu; + desc->des0 |= IDMAC_DES0_FD; - /* Set last descriptor */ - desc = host->sg_cpu + (i - 1) * sizeof(struct idmac_desc); - desc->des0 &= ~(IDMAC_DES0_CH | IDMAC_DES0_DIC); - desc->des0 |= IDMAC_DES0_LD; + /* Set last descriptor */ + desc = host->sg_cpu + (i - 1) * sizeof(struct idmac_desc); + desc->des0 &= ~(IDMAC_DES0_CH | IDMAC_DES0_DIC); + desc->des0 |= IDMAC_DES0_LD; + } wmb(); } @@ -470,29 +524,71 @@ static void dw_mci_idmac_start_dma(struct dw_mci *host, unsigned int sg_len) static int dw_mci_idmac_init(struct dw_mci *host) { - struct idmac_desc *p; int i; - /* Number of descriptors in the ring buffer */ - host->ring_size = PAGE_SIZE / sizeof(struct idmac_desc); + if (host->dma_64bit_address == 1) { + struct idmac_desc_64addr *p; + /* Number of descriptors in the ring buffer */ + host->ring_size = PAGE_SIZE / sizeof(struct idmac_desc_64addr); + + /* Forward link the descriptor list */ + for (i = 0, p = host->sg_cpu; i < host->ring_size - 1; + i++, p++) { + p->des6 = (host->sg_dma + + (sizeof(struct idmac_desc_64addr) * + (i + 1))) & 0xffffffff; + + p->des7 = (u64)(host->sg_dma + + (sizeof(struct idmac_desc_64addr) * + (i + 1))) >> 32; + /* Initialize reserved and buffer size fields to "0" */ + p->des1 = 0; + p->des2 = 0; + p->des3 = 0; + } + + /* Set the last descriptor as the end-of-ring descriptor */ + p->des6 = host->sg_dma & 0xffffffff; + p->des7 = (u64)host->sg_dma >> 32; + p->des0 = IDMAC_DES0_ER; + + } else { + struct idmac_desc *p; + /* Number of descriptors in the ring buffer */ + host->ring_size = PAGE_SIZE / sizeof(struct idmac_desc); - /* Forward link the descriptor list */ - for (i = 0, p = host->sg_cpu; i < host->ring_size - 1; i++, p++) - p->des3 = host->sg_dma + (sizeof(struct idmac_desc) * (i + 1)); + /* Forward link the descriptor list */ + for (i = 0, p = host->sg_cpu; i < host->ring_size - 1; i++, p++) + p->des3 = host->sg_dma + (sizeof(struct idmac_desc) * + (i + 1)); - /* Set the last descriptor as the end-of-ring descriptor */ - p->des3 = host->sg_dma; - p->des0 = IDMAC_DES0_ER; + /* Set the last descriptor as the end-of-ring descriptor */ + p->des3 = host->sg_dma; + p->des0 = IDMAC_DES0_ER; + } dw_mci_idmac_reset(host); - /* Mask out interrupts - get Tx & Rx complete only */ - mci_writel(host, IDSTS, IDMAC_INT_CLR); - mci_writel(host, IDINTEN, SDMMC_IDMAC_INT_NI | SDMMC_IDMAC_INT_RI | - SDMMC_IDMAC_INT_TI); + if (host->dma_64bit_address == 1) { + /* Mask out interrupts - get Tx & Rx complete only */ + mci_writel(host, IDSTS64, IDMAC_INT_CLR); + mci_writel(host, IDINTEN64, SDMMC_IDMAC_INT_NI | + SDMMC_IDMAC_INT_RI | SDMMC_IDMAC_INT_TI); + + /* Set the descriptor base address */ + mci_writel(host, DBADDRL, host->sg_dma & 0xffffffff); + mci_writel(host, DBADDRU, (u64)host->sg_dma >> 32); + + } else { + /* Mask out interrupts - get Tx & Rx complete only */ + mci_writel(host, IDSTS, IDMAC_INT_CLR); + mci_writel(host, IDINTEN, SDMMC_IDMAC_INT_NI | + SDMMC_IDMAC_INT_RI | SDMMC_IDMAC_INT_TI); + + /* Set the descriptor base address */ + mci_writel(host, DBADDR, host->sg_dma); + } - /* Set the descriptor base address */ - mci_writel(host, DBADDR, host->sg_dma); return 0; } @@ -2066,11 +2162,22 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id) #ifdef CONFIG_MMC_DW_IDMAC /* Handle DMA interrupts */ - pending = mci_readl(host, IDSTS); - if (pending & (SDMMC_IDMAC_INT_TI | SDMMC_IDMAC_INT_RI)) { - mci_writel(host, IDSTS, SDMMC_IDMAC_INT_TI | SDMMC_IDMAC_INT_RI); - mci_writel(host, IDSTS, SDMMC_IDMAC_INT_NI); - host->dma_ops->complete(host); + if (host->dma_64bit_address == 1) { + pending = mci_readl(host, IDSTS64); + if (pending & (SDMMC_IDMAC_INT_TI | SDMMC_IDMAC_INT_RI)) { + mci_writel(host, IDSTS64, SDMMC_IDMAC_INT_TI | + SDMMC_IDMAC_INT_RI); + mci_writel(host, IDSTS64, SDMMC_IDMAC_INT_NI); + host->dma_ops->complete(host); + } + } else { + pending = mci_readl(host, IDSTS); + if (pending & (SDMMC_IDMAC_INT_TI | SDMMC_IDMAC_INT_RI)) { + mci_writel(host, IDSTS, SDMMC_IDMAC_INT_TI | + SDMMC_IDMAC_INT_RI); + mci_writel(host, IDSTS, SDMMC_IDMAC_INT_NI); + host->dma_ops->complete(host); + } } #endif @@ -2245,6 +2352,22 @@ static void dw_mci_cleanup_slot(struct dw_mci_slot *slot, unsigned int id) static void dw_mci_init_dma(struct dw_mci *host) { + int addr_config; + /* Check ADDR_CONFIG bit in HCON to find IDMAC address bus width */ + addr_config = (mci_readl(host, HCON) >> 27) & 0x01; + + if (addr_config == 1) { + /* host supports IDMAC in 64-bit address mode */ + host->dma_64bit_address = 1; + dev_info(host->dev, "IDMAC supports 64-bit address mode.\n"); + if (!dma_set_mask(host->dev, DMA_BIT_MASK(64))) + dma_set_coherent_mask(host->dev, DMA_BIT_MASK(64)); + } else { + /* host supports IDMAC in 32-bit address mode */ + host->dma_64bit_address = 0; + dev_info(host->dev, "IDMAC supports 32-bit address mode.\n"); + } + /* Alloc memory for sg translation */ host->sg_cpu = dmam_alloc_coherent(host->dev, PAGE_SIZE, &host->sg_dma, GFP_KERNEL); diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h index 71d499557edc..58d8a54d644b 100644 --- a/drivers/mmc/host/dw_mmc.h +++ b/drivers/mmc/host/dw_mmc.h @@ -55,6 +55,17 @@ #define SDMMC_BUFADDR 0x098 #define SDMMC_CDTHRCTL 0x100 #define SDMMC_DATA(x) (x) +/* +* Registers to support idmac 64-bit address mode +*/ +#define SDMMC_DBADDRL 0x088 +#define SDMMC_DBADDRU 0x08c +#define SDMMC_IDSTS64 0x090 +#define SDMMC_IDINTEN64 0x094 +#define SDMMC_DSCADDRL 0x098 +#define SDMMC_DSCADDRU 0x09c +#define SDMMC_BUFADDRL 0x0A0 +#define SDMMC_BUFADDRU 0x0A4 /* * Data offset is difference according to Version diff --git a/include/linux/mmc/dw_mmc.h b/include/linux/mmc/dw_mmc.h index 69d08144cfad..0a551152d600 100644 --- a/include/linux/mmc/dw_mmc.h +++ b/include/linux/mmc/dw_mmc.h @@ -54,6 +54,7 @@ struct mmc_data; * transfer is in progress. * @use_dma: Whether DMA channel is initialized or not. * @using_dma: Whether DMA is in use for the current transfer. + * @dma_64bit_address: Whether DMA supports 64-bit address mode or not. * @sg_dma: Bus address of DMA buffer. * @sg_cpu: Virtual address of DMA buffer. * @dma_ops: Pointer to platform-specific DMA callbacks. @@ -139,6 +140,7 @@ struct dw_mci { /* DMA interface members*/ int use_dma; int using_dma; + int dma_64bit_address; dma_addr_t sg_dma; void *sg_cpu; -- cgit v1.2.3 From 549c0b18485d10bb419a81b24efe719df75089bd Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Thu, 6 Nov 2014 15:19:05 +0200 Subject: mmc: sdhci: Clear also HS400 1.2V capability if 1.2V is not supported 1.2V HS200 mode capability is cleared if there is not a voltage regulator that supports 1.2V. Do the same for 1.2V HS400 mode. Signed-off-by: Adrian Hunter Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci.c | 13 +++++++------ include/linux/mmc/host.h | 1 + 2 files changed, 8 insertions(+), 6 deletions(-) (limited to 'include/linux') diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index c2f4754a28b6..5589563761f8 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -3115,16 +3115,17 @@ int sdhci_add_host(struct sdhci_host *host) /* SD3.0: SDR104 is supported so (for eMMC) the caps2 * field can be promoted to support HS200. */ - if (!(host->quirks2 & SDHCI_QUIRK2_BROKEN_HS200)) { + if (!(host->quirks2 & SDHCI_QUIRK2_BROKEN_HS200)) mmc->caps2 |= MMC_CAP2_HS200; - if (IS_ERR(mmc->supply.vqmmc) || - !regulator_is_supported_voltage - (mmc->supply.vqmmc, 1100000, 1300000)) - mmc->caps2 &= ~MMC_CAP2_HS200_1_2V_SDR; - } } else if (caps[1] & SDHCI_SUPPORT_SDR50) mmc->caps |= MMC_CAP_UHS_SDR50; + if ((mmc->caps2 & MMC_CAP2_HSX00_1_2V) && + (IS_ERR(mmc->supply.vqmmc) || + !regulator_is_supported_voltage(mmc->supply.vqmmc, 1100000, + 1300000))) + mmc->caps2 &= ~MMC_CAP2_HSX00_1_2V; + if ((caps[1] & SDHCI_SUPPORT_DDR50) && !(host->quirks2 & SDHCI_QUIRK2_BROKEN_DDR50)) mmc->caps |= MMC_CAP_UHS_DDR50; diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index df0c15396bbf..9f322706f7cb 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h @@ -289,6 +289,7 @@ struct mmc_host { #define MMC_CAP2_HS400_1_2V (1 << 16) /* Can support HS400 1.2V */ #define MMC_CAP2_HS400 (MMC_CAP2_HS400_1_8V | \ MMC_CAP2_HS400_1_2V) +#define MMC_CAP2_HSX00_1_2V (MMC_CAP2_HS200_1_2V_SDR | MMC_CAP2_HS400_1_2V) #define MMC_CAP2_SDIO_IRQ_NOTHREAD (1 << 17) mmc_pm_flag_t pm_caps; /* supported pm features */ -- cgit v1.2.3 From e9fb05d5bca7428f2749d059559e9657c710fe53 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Thu, 6 Nov 2014 15:19:06 +0200 Subject: mmc: sdhci: Add HS400 support to SDHCI driver MMC core already has support for HS400. Add HS400 support to SDHCI driver. The SDHC Standard specification does not define HS400 so consequently HS400 support is non-standard. However HS400 is not selected without the host controller setting the corresponding capability flags so host controllers not yet supporting HS400 will not be affected. To support that, a quirk SDHCI_QUIRK2_CAPS_BIT63_FOR_HS400 is introduced to enable the use of capabilities register reserved bit-63 to indicate HS400 support. Because HS400 is non-standard for SDHCI, it is possible that different vendors will do things in different ways. However HS200 support faced the same issue but currently there is only one solution. As such, no attempt has been made to provide for alternate HS400 solutions except for SDHCI_QUIRK2_CAPS_BIT63_FOR_HS400. Signed-off-by: Adrian Hunter Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci.c | 13 ++++++++++++- drivers/mmc/host/sdhci.h | 3 +++ include/linux/mmc/sdhci.h | 2 ++ 3 files changed, 17 insertions(+), 1 deletion(-) (limited to 'include/linux') diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 5589563761f8..73de62a58d70 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -1148,6 +1148,9 @@ static u16 sdhci_get_preset_value(struct sdhci_host *host) case MMC_TIMING_UHS_DDR50: preset = sdhci_readw(host, SDHCI_PRESET_FOR_DDR50); break; + case MMC_TIMING_MMC_HS400: + preset = sdhci_readw(host, SDHCI_PRESET_FOR_HS400); + break; default: pr_warn("%s: Invalid UHS-I mode selected\n", mmc_hostname(host->mmc)); @@ -1475,6 +1478,8 @@ void sdhci_set_uhs_signaling(struct sdhci_host *host, unsigned timing) else if ((timing == MMC_TIMING_UHS_DDR50) || (timing == MMC_TIMING_MMC_DDR52)) ctrl_2 |= SDHCI_CTRL_UHS_DDR50; + else if (timing == MMC_TIMING_MMC_HS400) + ctrl_2 |= SDHCI_CTRL_HS400; /* Non-standard */ sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2); } EXPORT_SYMBOL_GPL(sdhci_set_uhs_signaling); @@ -1546,7 +1551,8 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios) u16 clk, ctrl_2; /* In case of UHS-I modes, set High Speed Enable */ - if ((ios->timing == MMC_TIMING_MMC_HS200) || + if ((ios->timing == MMC_TIMING_MMC_HS400) || + (ios->timing == MMC_TIMING_MMC_HS200) || (ios->timing == MMC_TIMING_MMC_DDR52) || (ios->timing == MMC_TIMING_UHS_SDR50) || (ios->timing == MMC_TIMING_UHS_SDR104) || @@ -1893,6 +1899,7 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode) * tuning function has to be executed. */ switch (host->timing) { + case MMC_TIMING_MMC_HS400: case MMC_TIMING_MMC_HS200: case MMC_TIMING_UHS_SDR104: break; @@ -3120,6 +3127,10 @@ int sdhci_add_host(struct sdhci_host *host) } else if (caps[1] & SDHCI_SUPPORT_SDR50) mmc->caps |= MMC_CAP_UHS_SDR50; + if (host->quirks2 & SDHCI_QUIRK2_CAPS_BIT63_FOR_HS400 && + (caps[1] & SDHCI_SUPPORT_HS400)) + mmc->caps2 |= MMC_CAP2_HS400; + if ((mmc->caps2 & MMC_CAP2_HSX00_1_2V) && (IS_ERR(mmc->supply.vqmmc) || !regulator_is_supported_voltage(mmc->supply.vqmmc, 1100000, diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index 79937cfff4ca..ddd31cda2370 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h @@ -161,6 +161,7 @@ #define SDHCI_CTRL_UHS_SDR50 0x0002 #define SDHCI_CTRL_UHS_SDR104 0x0003 #define SDHCI_CTRL_UHS_DDR50 0x0004 +#define SDHCI_CTRL_HS400 0x0005 /* Non-standard */ #define SDHCI_CTRL_VDD_180 0x0008 #define SDHCI_CTRL_DRV_TYPE_MASK 0x0030 #define SDHCI_CTRL_DRV_TYPE_B 0x0000 @@ -203,6 +204,7 @@ #define SDHCI_RETUNING_MODE_SHIFT 14 #define SDHCI_CLOCK_MUL_MASK 0x00FF0000 #define SDHCI_CLOCK_MUL_SHIFT 16 +#define SDHCI_SUPPORT_HS400 0x80000000 /* Non-standard */ #define SDHCI_CAPABILITIES_1 0x44 @@ -235,6 +237,7 @@ #define SDHCI_PRESET_FOR_SDR50 0x6A #define SDHCI_PRESET_FOR_SDR104 0x6C #define SDHCI_PRESET_FOR_DDR50 0x6E +#define SDHCI_PRESET_FOR_HS400 0x74 /* Non-standard */ #define SDHCI_PRESET_DRV_MASK 0xC000 #define SDHCI_PRESET_DRV_SHIFT 14 #define SDHCI_PRESET_CLKGEN_SEL_MASK 0x400 diff --git a/include/linux/mmc/sdhci.h b/include/linux/mmc/sdhci.h index ae7f357b78c9..375af80bde7d 100644 --- a/include/linux/mmc/sdhci.h +++ b/include/linux/mmc/sdhci.h @@ -104,6 +104,8 @@ struct sdhci_host { #define SDHCI_QUIRK2_BROKEN_64_BIT_DMA (1<<9) /* need clear transfer mode register before send cmd */ #define SDHCI_QUIRK2_CLEAR_TRANSFERMODE_REG_BEFORE_CMD (1<<10) +/* Capability register bit-63 indicates HS400 support */ +#define SDHCI_QUIRK2_CAPS_BIT63_FOR_HS400 (1<<11) int irq; /* Device IRQ */ void __iomem *ioaddr; /* Mapped address */ -- cgit v1.2.3 From 551434389074791da30b7afbf44c4bbe9b8b0116 Mon Sep 17 00:00:00 2001 From: Andreas Fenkart Date: Sat, 8 Nov 2014 15:33:09 +0100 Subject: ARM: OMAP1/2+: MMC: separate platform data for mmc and mmc hs driver - omap mmc driver supports multiplexing, omap_mmc_hs doesn't this leads to one of the major confusions in the omap_hsmmc driver - platform data should be read-only for the driver most callbacks are not set by the omap3 platform init code while still required. So they are set from the driver probe function, which is against the paradigm that platform-data should not be modified by the driver typical examples are card_detect, read_only callbacks un-bundling by searching for driver name \"omap_hsmmc in the arch/arm folder. omap_hsmmc_platform_data is not initialized directly, but from omap2_hsmmc_info, which is defined in a separate header file not touched by this patch hwmod includes platform headers to declare features of the platform. All the declared features are prefixed OMAP_HSMMC. There is no need to include platform header from hwmod other except for feature defines Acked-by: Tony Lindgren Signed-off-by: Andreas Fenkart Signed-off-by: Ulf Hansson --- arch/arm/mach-omap2/hsmmc.c | 26 ++-- arch/arm/mach-omap2/omap_hwmod_2430_data.c | 4 +- .../mach-omap2/omap_hwmod_33xx_43xx_ipblock_data.c | 8 +- arch/arm/mach-omap2/omap_hwmod_3xxx_data.c | 8 +- arch/arm/mach-omap2/omap_hwmod_44xx_data.c | 4 +- arch/arm/mach-omap2/omap_hwmod_54xx_data.c | 4 +- arch/arm/mach-omap2/omap_hwmod_7xx_data.c | 4 +- drivers/mmc/host/omap_hsmmc.c | 28 ++-- include/linux/platform_data/hsmmc-omap.h | 149 +++++++++++++++++++++ include/linux/platform_data/mmc-omap.h | 27 ---- 10 files changed, 192 insertions(+), 70 deletions(-) create mode 100644 include/linux/platform_data/hsmmc-omap.h (limited to 'include/linux') diff --git a/arch/arm/mach-omap2/hsmmc.c b/arch/arm/mach-omap2/hsmmc.c index 73e28ac45d99..9edd7596d1e7 100644 --- a/arch/arm/mach-omap2/hsmmc.c +++ b/arch/arm/mach-omap2/hsmmc.c @@ -16,7 +16,7 @@ #include #include #include -#include +#include #include "soc.h" #include "omap_device.h" @@ -48,7 +48,7 @@ static void omap_hsmmc1_before_set_reg(struct device *dev, int slot, int power_on, int vdd) { u32 reg, prog_io; - struct omap_mmc_platform_data *mmc = dev->platform_data; + struct omap_hsmmc_platform_data *mmc = dev->platform_data; if (mmc->slots[0].remux) mmc->slots[0].remux(dev, slot, power_on); @@ -121,7 +121,7 @@ static void omap_hsmmc1_after_set_reg(struct device *dev, int slot, } } -static void hsmmc2_select_input_clk_src(struct omap_mmc_platform_data *mmc) +static void hsmmc2_select_input_clk_src(struct omap_hsmmc_platform_data *mmc) { u32 reg; @@ -136,7 +136,7 @@ static void hsmmc2_select_input_clk_src(struct omap_mmc_platform_data *mmc) static void hsmmc2_before_set_reg(struct device *dev, int slot, int power_on, int vdd) { - struct omap_mmc_platform_data *mmc = dev->platform_data; + struct omap_hsmmc_platform_data *mmc = dev->platform_data; if (mmc->slots[0].remux) mmc->slots[0].remux(dev, slot, power_on); @@ -148,7 +148,7 @@ static void hsmmc2_before_set_reg(struct device *dev, int slot, static int am35x_hsmmc2_set_power(struct device *dev, int slot, int power_on, int vdd) { - struct omap_mmc_platform_data *mmc = dev->platform_data; + struct omap_hsmmc_platform_data *mmc = dev->platform_data; if (power_on) hsmmc2_select_input_clk_src(mmc); @@ -162,8 +162,8 @@ static int nop_mmc_set_power(struct device *dev, int slot, int power_on, return 0; } -static inline void omap_hsmmc_mux(struct omap_mmc_platform_data *mmc_controller, - int controller_nr) +static inline void omap_hsmmc_mux(struct omap_hsmmc_platform_data + *mmc_controller, int controller_nr) { if (gpio_is_valid(mmc_controller->slots[0].switch_pin) && (mmc_controller->slots[0].switch_pin < OMAP_MAX_GPIO_LINES)) @@ -244,7 +244,7 @@ static inline void omap_hsmmc_mux(struct omap_mmc_platform_data *mmc_controller, } static int __init omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c, - struct omap_mmc_platform_data *mmc) + struct omap_hsmmc_platform_data *mmc) { char *hc_name; @@ -369,7 +369,7 @@ static int omap_hsmmc_done; void omap_hsmmc_late_init(struct omap2_hsmmc_info *c) { struct platform_device *pdev; - struct omap_mmc_platform_data *mmc_pdata; + struct omap_hsmmc_platform_data *mmc_pdata; int res; if (omap_hsmmc_done != 1) @@ -409,12 +409,12 @@ static void __init omap_hsmmc_init_one(struct omap2_hsmmc_info *hsmmcinfo, struct omap_device *od; struct platform_device *pdev; char oh_name[MAX_OMAP_MMC_HWMOD_NAME_LEN]; - struct omap_mmc_platform_data *mmc_data; - struct omap_mmc_dev_attr *mmc_dev_attr; + struct omap_hsmmc_platform_data *mmc_data; + struct omap_hsmmc_dev_attr *mmc_dev_attr; char *name; int res; - mmc_data = kzalloc(sizeof(struct omap_mmc_platform_data), GFP_KERNEL); + mmc_data = kzalloc(sizeof(*mmc_data), GFP_KERNEL); if (!mmc_data) { pr_err("Cannot allocate memory for mmc device!\n"); return; @@ -464,7 +464,7 @@ static void __init omap_hsmmc_init_one(struct omap2_hsmmc_info *hsmmcinfo, } res = platform_device_add_data(pdev, mmc_data, - sizeof(struct omap_mmc_platform_data)); + sizeof(struct omap_hsmmc_platform_data)); if (res) { pr_err("Could not add pdata for %s\n", name); goto put_pdev; diff --git a/arch/arm/mach-omap2/omap_hwmod_2430_data.c b/arch/arm/mach-omap2/omap_hwmod_2430_data.c index cd95e820c6d4..79127b35fe60 100644 --- a/arch/arm/mach-omap2/omap_hwmod_2430_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_2430_data.c @@ -15,7 +15,7 @@ #include #include -#include +#include #include #include #include @@ -372,7 +372,7 @@ static struct omap_hwmod_opt_clk omap2430_mmc1_opt_clks[] = { { .role = "dbck", .clk = "mmchsdb1_fck" }, }; -static struct omap_mmc_dev_attr mmc1_dev_attr = { +static struct omap_hsmmc_dev_attr mmc1_dev_attr = { .flags = OMAP_HSMMC_SUPPORTS_DUAL_VOLT, }; diff --git a/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_ipblock_data.c b/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_ipblock_data.c index bf8c12d595bf..cabc5695b504 100644 --- a/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_ipblock_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_ipblock_data.c @@ -15,7 +15,7 @@ */ #include -#include +#include #include #include "omap_hwmod.h" #include "i2c.h" @@ -836,7 +836,7 @@ static struct omap_hwmod_class am33xx_mmc_hwmod_class = { }; /* mmc0 */ -static struct omap_mmc_dev_attr am33xx_mmc0_dev_attr = { +static struct omap_hsmmc_dev_attr am33xx_mmc0_dev_attr = { .flags = OMAP_HSMMC_SUPPORTS_DUAL_VOLT, }; @@ -854,7 +854,7 @@ struct omap_hwmod am33xx_mmc0_hwmod = { }; /* mmc1 */ -static struct omap_mmc_dev_attr am33xx_mmc1_dev_attr = { +static struct omap_hsmmc_dev_attr am33xx_mmc1_dev_attr = { .flags = OMAP_HSMMC_SUPPORTS_DUAL_VOLT, }; @@ -872,7 +872,7 @@ struct omap_hwmod am33xx_mmc1_hwmod = { }; /* mmc2 */ -static struct omap_mmc_dev_attr am33xx_mmc2_dev_attr = { +static struct omap_hsmmc_dev_attr am33xx_mmc2_dev_attr = { .flags = OMAP_HSMMC_SUPPORTS_DUAL_VOLT, }; struct omap_hwmod am33xx_mmc2_hwmod = { diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c index 5f244a90eee5..11468eea3871 100644 --- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c @@ -18,7 +18,7 @@ #include #include #include -#include +#include #include #include "l3_3xxx.h" @@ -1786,12 +1786,12 @@ static struct omap_hwmod_opt_clk omap34xx_mmc1_opt_clks[] = { { .role = "dbck", .clk = "omap_32k_fck", }, }; -static struct omap_mmc_dev_attr mmc1_dev_attr = { +static struct omap_hsmmc_dev_attr mmc1_dev_attr = { .flags = OMAP_HSMMC_SUPPORTS_DUAL_VOLT, }; /* See 35xx errata 2.1.1.128 in SPRZ278F */ -static struct omap_mmc_dev_attr mmc1_pre_es3_dev_attr = { +static struct omap_hsmmc_dev_attr mmc1_pre_es3_dev_attr = { .flags = (OMAP_HSMMC_SUPPORTS_DUAL_VOLT | OMAP_HSMMC_BROKEN_MULTIBLOCK_READ), }; @@ -1854,7 +1854,7 @@ static struct omap_hwmod_opt_clk omap34xx_mmc2_opt_clks[] = { }; /* See 35xx errata 2.1.1.128 in SPRZ278F */ -static struct omap_mmc_dev_attr mmc2_pre_es3_dev_attr = { +static struct omap_hsmmc_dev_attr mmc2_pre_es3_dev_attr = { .flags = OMAP_HSMMC_BROKEN_MULTIBLOCK_READ, }; diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c index c385185c755d..d8a3cf1c1787 100644 --- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c @@ -22,7 +22,7 @@ #include #include -#include +#include #include #include @@ -1952,7 +1952,7 @@ static struct omap_hwmod_dma_info omap44xx_mmc1_sdma_reqs[] = { }; /* mmc1 dev_attr */ -static struct omap_mmc_dev_attr mmc1_dev_attr = { +static struct omap_hsmmc_dev_attr mmc1_dev_attr = { .flags = OMAP_HSMMC_SUPPORTS_DUAL_VOLT, }; diff --git a/arch/arm/mach-omap2/omap_hwmod_54xx_data.c b/arch/arm/mach-omap2/omap_hwmod_54xx_data.c index 13bf6a72c5ee..5ec786a76d3c 100644 --- a/arch/arm/mach-omap2/omap_hwmod_54xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_54xx_data.c @@ -19,7 +19,7 @@ #include #include -#include +#include #include #include @@ -1269,7 +1269,7 @@ static struct omap_hwmod_opt_clk mmc1_opt_clks[] = { }; /* mmc1 dev_attr */ -static struct omap_mmc_dev_attr mmc1_dev_attr = { +static struct omap_hsmmc_dev_attr mmc1_dev_attr = { .flags = OMAP_HSMMC_SUPPORTS_DUAL_VOLT, }; diff --git a/arch/arm/mach-omap2/omap_hwmod_7xx_data.c b/arch/arm/mach-omap2/omap_hwmod_7xx_data.c index 8523821fe78f..711c97e90990 100644 --- a/arch/arm/mach-omap2/omap_hwmod_7xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_7xx_data.c @@ -19,7 +19,7 @@ #include #include -#include +#include #include #include @@ -1301,7 +1301,7 @@ static struct omap_hwmod_opt_clk mmc1_opt_clks[] = { }; /* mmc1 dev_attr */ -static struct omap_mmc_dev_attr mmc1_dev_attr = { +static struct omap_hsmmc_dev_attr mmc1_dev_attr = { .flags = OMAP_HSMMC_SUPPORTS_DUAL_VOLT, }; diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index df27bb4fc098..4957c5fe555b 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -42,7 +42,7 @@ #include #include #include -#include +#include /* OMAP HSMMC Host Controller Registers */ #define OMAP_HSMMC_SYSSTATUS 0x0014 @@ -220,7 +220,7 @@ struct omap_hsmmc_host { #define HSMMC_SDIO_IRQ_ENABLED (1 << 1) /* SDIO irq enabled */ #define HSMMC_WAKE_IRQ_ENABLED (1 << 2) struct omap_hsmmc_next next_data; - struct omap_mmc_platform_data *pdata; + struct omap_hsmmc_platform_data *pdata; }; struct omap_mmc_of_data { @@ -233,7 +233,7 @@ static void omap_hsmmc_start_dma_transfer(struct omap_hsmmc_host *host); static int omap_hsmmc_card_detect(struct device *dev, int slot) { struct omap_hsmmc_host *host = dev_get_drvdata(dev); - struct omap_mmc_platform_data *mmc = host->pdata; + struct omap_hsmmc_platform_data *mmc = host->pdata; /* NOTE: assumes card detect signal is active-low */ return !gpio_get_value_cansleep(mmc->slots[0].switch_pin); @@ -242,7 +242,7 @@ static int omap_hsmmc_card_detect(struct device *dev, int slot) static int omap_hsmmc_get_wp(struct device *dev, int slot) { struct omap_hsmmc_host *host = dev_get_drvdata(dev); - struct omap_mmc_platform_data *mmc = host->pdata; + struct omap_hsmmc_platform_data *mmc = host->pdata; /* NOTE: assumes write protect signal is active-high */ return gpio_get_value_cansleep(mmc->slots[0].gpio_wp); @@ -251,7 +251,7 @@ static int omap_hsmmc_get_wp(struct device *dev, int slot) static int omap_hsmmc_get_cover_state(struct device *dev, int slot) { struct omap_hsmmc_host *host = dev_get_drvdata(dev); - struct omap_mmc_platform_data *mmc = host->pdata; + struct omap_hsmmc_platform_data *mmc = host->pdata; /* NOTE: assumes card detect signal is active-low */ return !gpio_get_value_cansleep(mmc->slots[0].switch_pin); @@ -262,7 +262,7 @@ static int omap_hsmmc_get_cover_state(struct device *dev, int slot) static int omap_hsmmc_suspend_cdirq(struct device *dev, int slot) { struct omap_hsmmc_host *host = dev_get_drvdata(dev); - struct omap_mmc_platform_data *mmc = host->pdata; + struct omap_hsmmc_platform_data *mmc = host->pdata; disable_irq(mmc->slots[0].card_detect_irq); return 0; @@ -271,7 +271,7 @@ static int omap_hsmmc_suspend_cdirq(struct device *dev, int slot) static int omap_hsmmc_resume_cdirq(struct device *dev, int slot) { struct omap_hsmmc_host *host = dev_get_drvdata(dev); - struct omap_mmc_platform_data *mmc = host->pdata; + struct omap_hsmmc_platform_data *mmc = host->pdata; enable_irq(mmc->slots[0].card_detect_irq); return 0; @@ -449,7 +449,7 @@ static inline int omap_hsmmc_have_reg(void) #endif -static int omap_hsmmc_gpio_init(struct omap_mmc_platform_data *pdata) +static int omap_hsmmc_gpio_init(struct omap_hsmmc_platform_data *pdata) { int ret; @@ -492,7 +492,7 @@ err_free_sp: return ret; } -static void omap_hsmmc_gpio_free(struct omap_mmc_platform_data *pdata) +static void omap_hsmmc_gpio_free(struct omap_hsmmc_platform_data *pdata) { if (gpio_is_valid(pdata->slots[0].gpio_wp)) gpio_free(pdata->slots[0].gpio_wp); @@ -1286,7 +1286,7 @@ static void omap_hsmmc_protect_card(struct omap_hsmmc_host *host) static irqreturn_t omap_hsmmc_detect(int irq, void *dev_id) { struct omap_hsmmc_host *host = dev_id; - struct omap_mmc_slot_data *slot = &mmc_slot(host); + struct omap_hsmmc_slot_data *slot = &mmc_slot(host); int carddetect; sysfs_notify(&host->mmc->class_dev.kobj, NULL, "cover_switch"); @@ -1957,9 +1957,9 @@ static const struct of_device_id omap_mmc_of_match[] = { }; MODULE_DEVICE_TABLE(of, omap_mmc_of_match); -static struct omap_mmc_platform_data *of_get_hsmmc_pdata(struct device *dev) +static struct omap_hsmmc_platform_data *of_get_hsmmc_pdata(struct device *dev) { - struct omap_mmc_platform_data *pdata; + struct omap_hsmmc_platform_data *pdata; struct device_node *np = dev->of_node; u32 bus_width, max_freq; int cd_gpio, wp_gpio; @@ -2009,7 +2009,7 @@ static struct omap_mmc_platform_data *of_get_hsmmc_pdata(struct device *dev) return pdata; } #else -static inline struct omap_mmc_platform_data +static inline struct omap_hsmmc_platform_data *of_get_hsmmc_pdata(struct device *dev) { return ERR_PTR(-EINVAL); @@ -2018,7 +2018,7 @@ static inline struct omap_mmc_platform_data static int omap_hsmmc_probe(struct platform_device *pdev) { - struct omap_mmc_platform_data *pdata = pdev->dev.platform_data; + struct omap_hsmmc_platform_data *pdata = pdev->dev.platform_data; struct mmc_host *mmc; struct omap_hsmmc_host *host = NULL; struct resource *res; diff --git a/include/linux/platform_data/hsmmc-omap.h b/include/linux/platform_data/hsmmc-omap.h new file mode 100644 index 000000000000..7dd42e54a587 --- /dev/null +++ b/include/linux/platform_data/hsmmc-omap.h @@ -0,0 +1,149 @@ +/* + * MMC definitions for OMAP2 + * + * Copyright (C) 2006 Nokia Corporation + * + * 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. + */ + +#define OMAP_HSMMC_MAX_SLOTS 1 + +/* + * struct omap_hsmmc_dev_attr.flags possibilities + * + * OMAP_HSMMC_SUPPORTS_DUAL_VOLT: Some HSMMC controller instances can + * operate with either 1.8Vdc or 3.0Vdc card voltages; this flag + * should be set if this is the case. See for example Section 22.5.3 + * "MMC/SD/SDIO1 Bus Voltage Selection" of the OMAP34xx Multimedia + * Device Silicon Revision 3.1.x Revision ZR (July 2011) (SWPU223R). + * + * OMAP_HSMMC_BROKEN_MULTIBLOCK_READ: Multiple-block read transfers + * don't work correctly on some MMC controller instances on some + * OMAP3 SoCs; this flag should be set if this is the case. See + * for example Advisory 2.1.1.128 "MMC: Multiple Block Read + * Operation Issue" in _OMAP3530/3525/3515/3503 Silicon Errata_ + * Revision F (October 2010) (SPRZ278F). + */ +#define OMAP_HSMMC_SUPPORTS_DUAL_VOLT BIT(0) +#define OMAP_HSMMC_BROKEN_MULTIBLOCK_READ BIT(1) +#define OMAP_HSMMC_SWAKEUP_MISSING BIT(2) + +struct omap_hsmmc_dev_attr { + u8 flags; +}; + +struct mmc_card; + +struct omap_hsmmc_platform_data { + /* back-link to device */ + struct device *dev; + + /* number of slots per controller */ + unsigned nr_slots:2; + + /* set if your board has components or wiring that limits the + * maximum frequency on the MMC bus */ + unsigned int max_freq; + + /* switch the bus to a new slot */ + int (*switch_slot)(struct device *dev, int slot); + /* initialize board-specific MMC functionality, can be NULL if + * not supported */ + int (*init)(struct device *dev); + void (*cleanup)(struct device *dev); + void (*shutdown)(struct device *dev); + + /* To handle board related suspend/resume functionality for MMC */ + int (*suspend)(struct device *dev, int slot); + int (*resume)(struct device *dev, int slot); + + /* Return context loss count due to PM states changing */ + int (*get_context_loss_count)(struct device *dev); + + /* Integrating attributes from the omap_hwmod layer */ + u8 controller_flags; + + /* Register offset deviation */ + u16 reg_offset; + + struct omap_hsmmc_slot_data { + /* + * 4/8 wires and any additional host capabilities + * need to OR'd all capabilities (ref. linux/mmc/host.h) + */ + u8 wires; /* Used for the MMC driver on omap1 and 2420 */ + u32 caps; /* Used for the MMC driver on 2430 and later */ + u32 pm_caps; /* PM capabilities of the mmc */ + + /* + * nomux means "standard" muxing is wrong on this board, and + * that board-specific code handled it before common init logic. + */ + unsigned nomux:1; + + /* switch pin can be for card detect (default) or card cover */ + unsigned cover:1; + + /* use the internal clock */ + unsigned internal_clock:1; + + /* nonremovable e.g. eMMC */ + unsigned nonremovable:1; + + /* Try to sleep or power off when possible */ + unsigned power_saving:1; + + /* If using power_saving and the MMC power is not to go off */ + unsigned no_off:1; + + /* eMMC does not handle power off when not in sleep state */ + unsigned no_regulator_off_init:1; + + /* Regulator off remapped to sleep */ + unsigned vcc_aux_disable_is_sleep:1; + + /* we can put the features above into this variable */ +#define HSMMC_HAS_PBIAS (1 << 0) +#define HSMMC_HAS_UPDATED_RESET (1 << 1) +#define HSMMC_HAS_HSPE_SUPPORT (1 << 2) + unsigned features; + + int switch_pin; /* gpio (card detect) */ + int gpio_wp; /* gpio (write protect) */ + + int (*set_bus_mode)(struct device *dev, int slot, int bus_mode); + int (*set_power)(struct device *dev, int slot, + int power_on, int vdd); + int (*get_ro)(struct device *dev, int slot); + void (*remux)(struct device *dev, int slot, int power_on); + /* Call back before enabling / disabling regulators */ + void (*before_set_reg)(struct device *dev, int slot, + int power_on, int vdd); + /* Call back after enabling / disabling regulators */ + void (*after_set_reg)(struct device *dev, int slot, + int power_on, int vdd); + /* if we have special card, init it using this callback */ + void (*init_card)(struct mmc_card *card); + + /* return MMC cover switch state, can be NULL if not supported. + * + * possible return values: + * 0 - closed + * 1 - open + */ + int (*get_cover_state)(struct device *dev, int slot); + + const char *name; + u32 ocr_mask; + + /* Card detection IRQs */ + int card_detect_irq; + + int (*card_detect)(struct device *dev, int slot); + + unsigned int ban_openended:1; + + } slots[OMAP_HSMMC_MAX_SLOTS]; +}; diff --git a/include/linux/platform_data/mmc-omap.h b/include/linux/platform_data/mmc-omap.h index 51e70cf25cbc..5c188f4e9bec 100644 --- a/include/linux/platform_data/mmc-omap.h +++ b/include/linux/platform_data/mmc-omap.h @@ -10,32 +10,8 @@ #define OMAP_MMC_MAX_SLOTS 2 -/* - * struct omap_mmc_dev_attr.flags possibilities - * - * OMAP_HSMMC_SUPPORTS_DUAL_VOLT: Some HSMMC controller instances can - * operate with either 1.8Vdc or 3.0Vdc card voltages; this flag - * should be set if this is the case. See for example Section 22.5.3 - * "MMC/SD/SDIO1 Bus Voltage Selection" of the OMAP34xx Multimedia - * Device Silicon Revision 3.1.x Revision ZR (July 2011) (SWPU223R). - * - * OMAP_HSMMC_BROKEN_MULTIBLOCK_READ: Multiple-block read transfers - * don't work correctly on some MMC controller instances on some - * OMAP3 SoCs; this flag should be set if this is the case. See - * for example Advisory 2.1.1.128 "MMC: Multiple Block Read - * Operation Issue" in _OMAP3530/3525/3515/3503 Silicon Errata_ - * Revision F (October 2010) (SPRZ278F). - */ -#define OMAP_HSMMC_SUPPORTS_DUAL_VOLT BIT(0) -#define OMAP_HSMMC_BROKEN_MULTIBLOCK_READ BIT(1) -#define OMAP_HSMMC_SWAKEUP_MISSING BIT(2) - struct mmc_card; -struct omap_mmc_dev_attr { - u8 flags; -}; - struct omap_mmc_platform_data { /* back-link to device */ struct device *dev; @@ -106,9 +82,6 @@ struct omap_mmc_platform_data { unsigned vcc_aux_disable_is_sleep:1; /* we can put the features above into this variable */ -#define HSMMC_HAS_PBIAS (1 << 0) -#define HSMMC_HAS_UPDATED_RESET (1 << 1) -#define HSMMC_HAS_HSPE_SUPPORT (1 << 2) #define MMC_OMAP7XX (1 << 3) #define MMC_OMAP15XX (1 << 4) #define MMC_OMAP16XX (1 << 5) -- cgit v1.2.3 From a74fecdf795e1d219fcdb6470b6a0709ff7e3e76 Mon Sep 17 00:00:00 2001 From: Andreas Fenkart Date: Sat, 8 Nov 2014 15:33:10 +0100 Subject: mmc: omap_hsmmc: remove unused fields in platform_data platform data is built from omap2_hsmmc_info, remove all fields that are never set in omap_hsmmc_info, hence never copied to platform data. Note that the omap_hsmmc driver is not affected by this patch those fields were completely unused. Acked-by: Tony Lindgren Signed-off-by: Andreas Fenkart Signed-off-by: Ulf Hansson --- arch/arm/mach-omap2/hsmmc.c | 14 -------------- arch/arm/mach-omap2/hsmmc.h | 6 ------ include/linux/platform_data/hsmmc-omap.h | 19 ------------------- 3 files changed, 39 deletions(-) (limited to 'include/linux') diff --git a/arch/arm/mach-omap2/hsmmc.c b/arch/arm/mach-omap2/hsmmc.c index 9edd7596d1e7..75b75b96040f 100644 --- a/arch/arm/mach-omap2/hsmmc.c +++ b/arch/arm/mach-omap2/hsmmc.c @@ -263,9 +263,7 @@ static int __init omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c, mmc->slots[0].name = hc_name; mmc->nr_slots = 1; mmc->slots[0].caps = c->caps; - mmc->slots[0].pm_caps = c->pm_caps; mmc->slots[0].internal_clock = !c->ext_clock; - mmc->max_freq = c->max_freq; mmc->reg_offset = 0; mmc->get_context_loss_count = hsmmc_get_context_loss; @@ -281,18 +279,6 @@ static int __init omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c, if (c->nonremovable) mmc->slots[0].nonremovable = 1; - if (c->power_saving) - mmc->slots[0].power_saving = 1; - - if (c->no_off) - mmc->slots[0].no_off = 1; - - if (c->no_off_init) - mmc->slots[0].no_regulator_off_init = c->no_off_init; - - if (c->vcc_aux_disable_is_sleep) - mmc->slots[0].vcc_aux_disable_is_sleep = 1; - /* * NOTE: MMC slots should have a Vcc regulator set up. * This may be from a TWL4030-family chip, another diff --git a/arch/arm/mach-omap2/hsmmc.h b/arch/arm/mach-omap2/hsmmc.h index 7f2e790e0929..bdc8870dde7e 100644 --- a/arch/arm/mach-omap2/hsmmc.h +++ b/arch/arm/mach-omap2/hsmmc.h @@ -12,23 +12,17 @@ struct omap2_hsmmc_info { u8 mmc; /* controller 1/2/3 */ u32 caps; /* 4/8 wires and any additional host * capabilities OR'd (ref. linux/mmc/host.h) */ - u32 pm_caps; /* PM capabilities */ bool transceiver; /* MMC-2 option */ bool ext_clock; /* use external pin for input clock */ bool cover_only; /* No card detect - just cover switch */ bool nonremovable; /* Nonremovable e.g. eMMC */ bool power_saving; /* Try to sleep or power off when possible */ - bool no_off; /* power_saving and power is not to go off */ - bool no_off_init; /* no power off when not in MMC sleep state */ - bool vcc_aux_disable_is_sleep; /* Regulator off remapped to sleep */ bool deferred; /* mmc needs a deferred probe */ int gpio_cd; /* or -EINVAL */ int gpio_wp; /* or -EINVAL */ char *name; /* or NULL for default */ struct platform_device *pdev; /* mmc controller instance */ int ocr_mask; /* temporary HACK */ - int max_freq; /* maximum clock, if constrained by external - * circuitry, or 0 for default */ /* Remux (pad configuration) when powering on/off */ void (*remux)(struct device *dev, int slot, int power_on); /* init some special card */ diff --git a/include/linux/platform_data/hsmmc-omap.h b/include/linux/platform_data/hsmmc-omap.h index 7dd42e54a587..11d7ed99603f 100644 --- a/include/linux/platform_data/hsmmc-omap.h +++ b/include/linux/platform_data/hsmmc-omap.h @@ -73,16 +73,9 @@ struct omap_hsmmc_platform_data { * 4/8 wires and any additional host capabilities * need to OR'd all capabilities (ref. linux/mmc/host.h) */ - u8 wires; /* Used for the MMC driver on omap1 and 2420 */ u32 caps; /* Used for the MMC driver on 2430 and later */ u32 pm_caps; /* PM capabilities of the mmc */ - /* - * nomux means "standard" muxing is wrong on this board, and - * that board-specific code handled it before common init logic. - */ - unsigned nomux:1; - /* switch pin can be for card detect (default) or card cover */ unsigned cover:1; @@ -92,18 +85,9 @@ struct omap_hsmmc_platform_data { /* nonremovable e.g. eMMC */ unsigned nonremovable:1; - /* Try to sleep or power off when possible */ - unsigned power_saving:1; - - /* If using power_saving and the MMC power is not to go off */ - unsigned no_off:1; - /* eMMC does not handle power off when not in sleep state */ unsigned no_regulator_off_init:1; - /* Regulator off remapped to sleep */ - unsigned vcc_aux_disable_is_sleep:1; - /* we can put the features above into this variable */ #define HSMMC_HAS_PBIAS (1 << 0) #define HSMMC_HAS_UPDATED_RESET (1 << 1) @@ -142,8 +126,5 @@ struct omap_hsmmc_platform_data { int card_detect_irq; int (*card_detect)(struct device *dev, int slot); - - unsigned int ban_openended:1; - } slots[OMAP_HSMMC_MAX_SLOTS]; }; -- cgit v1.2.3 From bb09d15114a55ae050f5315f2dfd6d1c989ecacd Mon Sep 17 00:00:00 2001 From: Andreas Fenkart Date: Sat, 8 Nov 2014 15:33:11 +0100 Subject: mmc: omap_hsmmc: remove un-initialized callbacks from platform data these callbacks are not set, probably legacy omap 1/2 features Acked-by: Tony Lindgren Signed-off-by: Andreas Fenkart Signed-off-by: Ulf Hansson --- drivers/mmc/host/omap_hsmmc.c | 15 +-------------- include/linux/platform_data/hsmmc-omap.h | 9 --------- 2 files changed, 1 insertion(+), 23 deletions(-) (limited to 'include/linux') diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 4957c5fe555b..03e8e9aa3756 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -2204,18 +2204,10 @@ static int omap_hsmmc_probe(struct platform_device *pdev) goto err_irq; } - if (pdata->init != NULL) { - if (pdata->init(&pdev->dev) != 0) { - dev_err(mmc_dev(host->mmc), - "Unable to configure MMC IRQs\n"); - goto err_irq; - } - } - if (omap_hsmmc_have_reg() && !mmc_slot(host).set_power) { ret = omap_hsmmc_reg_get(host); if (ret) - goto err_reg; + goto err_irq; host->use_reg = 1; } @@ -2278,9 +2270,6 @@ err_slot_name: err_irq_cd: if (host->use_reg) omap_hsmmc_reg_put(host); -err_reg: - if (host->pdata->cleanup) - host->pdata->cleanup(&pdev->dev); err_irq: if (host->tx_chan) dma_release_channel(host->tx_chan); @@ -2306,8 +2295,6 @@ static int omap_hsmmc_remove(struct platform_device *pdev) mmc_remove_host(host->mmc); if (host->use_reg) omap_hsmmc_reg_put(host); - if (host->pdata->cleanup) - host->pdata->cleanup(&pdev->dev); if (host->tx_chan) dma_release_channel(host->tx_chan); diff --git a/include/linux/platform_data/hsmmc-omap.h b/include/linux/platform_data/hsmmc-omap.h index 11d7ed99603f..7e70e15154e4 100644 --- a/include/linux/platform_data/hsmmc-omap.h +++ b/include/linux/platform_data/hsmmc-omap.h @@ -47,14 +47,6 @@ struct omap_hsmmc_platform_data { * maximum frequency on the MMC bus */ unsigned int max_freq; - /* switch the bus to a new slot */ - int (*switch_slot)(struct device *dev, int slot); - /* initialize board-specific MMC functionality, can be NULL if - * not supported */ - int (*init)(struct device *dev); - void (*cleanup)(struct device *dev); - void (*shutdown)(struct device *dev); - /* To handle board related suspend/resume functionality for MMC */ int (*suspend)(struct device *dev, int slot); int (*resume)(struct device *dev, int slot); @@ -97,7 +89,6 @@ struct omap_hsmmc_platform_data { int switch_pin; /* gpio (card detect) */ int gpio_wp; /* gpio (write protect) */ - int (*set_bus_mode)(struct device *dev, int slot, int bus_mode); int (*set_power)(struct device *dev, int slot, int power_on, int vdd); int (*get_ro)(struct device *dev, int slot); -- cgit v1.2.3 From df206c313987bff595d2199f3bbf9b160e666b32 Mon Sep 17 00:00:00 2001 From: Andreas Fenkart Date: Sat, 8 Nov 2014 15:33:13 +0100 Subject: mmc: omap_hsmmc: remove unused get_context_loss_count callback trigger of this callback has been removed in 0a82e06e6183 Acked-by: Tony Lindgren Signed-off-by: Andreas Fenkart Signed-off-by: Ulf Hansson --- arch/arm/mach-omap2/hsmmc.c | 12 ------------ include/linux/platform_data/hsmmc-omap.h | 3 --- 2 files changed, 15 deletions(-) (limited to 'include/linux') diff --git a/arch/arm/mach-omap2/hsmmc.c b/arch/arm/mach-omap2/hsmmc.c index 75b75b96040f..c65efc3cf81f 100644 --- a/arch/arm/mach-omap2/hsmmc.c +++ b/arch/arm/mach-omap2/hsmmc.c @@ -33,17 +33,6 @@ static u16 control_devconf1_offset; #define HSMMC_NAME_LEN 9 -#if defined(CONFIG_ARCH_OMAP3) && defined(CONFIG_PM) - -static int hsmmc_get_context_loss(struct device *dev) -{ - return omap_pm_get_dev_context_loss_count(dev); -} - -#else -#define hsmmc_get_context_loss NULL -#endif - static void omap_hsmmc1_before_set_reg(struct device *dev, int slot, int power_on, int vdd) { @@ -265,7 +254,6 @@ static int __init omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c, mmc->slots[0].caps = c->caps; mmc->slots[0].internal_clock = !c->ext_clock; mmc->reg_offset = 0; - mmc->get_context_loss_count = hsmmc_get_context_loss; mmc->slots[0].switch_pin = c->gpio_cd; mmc->slots[0].gpio_wp = c->gpio_wp; diff --git a/include/linux/platform_data/hsmmc-omap.h b/include/linux/platform_data/hsmmc-omap.h index 7e70e15154e4..35d494f7d62f 100644 --- a/include/linux/platform_data/hsmmc-omap.h +++ b/include/linux/platform_data/hsmmc-omap.h @@ -51,9 +51,6 @@ struct omap_hsmmc_platform_data { int (*suspend)(struct device *dev, int slot); int (*resume)(struct device *dev, int slot); - /* Return context loss count due to PM states changing */ - int (*get_context_loss_count)(struct device *dev); - /* Integrating attributes from the omap_hwmod layer */ u8 controller_flags; -- cgit v1.2.3 From 326119c9923711d782e71e197429b1bab16125e1 Mon Sep 17 00:00:00 2001 From: Andreas Fenkart Date: Sat, 8 Nov 2014 15:33:14 +0100 Subject: mmc: omap_hsmmc: remove unnecessary omap_hsmmc_slot_data indirection omap_hsmmc supports only one slot per controller, see OMAP_MMC_MAX_SLOTS. This unnecessary indirection leads to confusion in the omap_hsmmc driver. For example the card_detect callback is not installed by platform code but from the driver probe function. So it should be a field of omap_hsmmc_host. But since it is declared under the platform slot while the drivers struct omap_hsmmc_host has no slot abstraction, this looks like a bug, especially when not familiar that this driver only supports 1 slot anyway. Either we should add a slot abstraction to omap_hsmmc_host or remove it from the platform data struct. Removed since slot multiplexing is an un-implemented feature Acked-by: Tony Lindgren Signed-off-by: Andreas Fenkart Signed-off-by: Ulf Hansson --- arch/arm/mach-omap2/hsmmc.c | 88 ++++++++-------- drivers/mmc/host/omap_hsmmc.c | 175 ++++++++++++++++--------------- include/linux/platform_data/hsmmc-omap.h | 100 +++++++++--------- 3 files changed, 181 insertions(+), 182 deletions(-) (limited to 'include/linux') diff --git a/arch/arm/mach-omap2/hsmmc.c b/arch/arm/mach-omap2/hsmmc.c index c65efc3cf81f..4e2896ad0119 100644 --- a/arch/arm/mach-omap2/hsmmc.c +++ b/arch/arm/mach-omap2/hsmmc.c @@ -39,8 +39,8 @@ static void omap_hsmmc1_before_set_reg(struct device *dev, int slot, u32 reg, prog_io; struct omap_hsmmc_platform_data *mmc = dev->platform_data; - if (mmc->slots[0].remux) - mmc->slots[0].remux(dev, slot, power_on); + if (mmc->remux) + mmc->remux(dev, slot, power_on); /* * Assume we power both OMAP VMMC1 (for CMD, CLK, DAT0..3) and the @@ -62,7 +62,7 @@ static void omap_hsmmc1_before_set_reg(struct device *dev, int slot, omap_ctrl_writel(reg, OMAP243X_CONTROL_DEVCONF1); } - if (mmc->slots[0].internal_clock) { + if (mmc->internal_clock) { reg = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0); reg |= OMAP2_MMCSDIO1ADPCLKISEL; omap_ctrl_writel(reg, OMAP2_CONTROL_DEVCONF0); @@ -115,7 +115,7 @@ static void hsmmc2_select_input_clk_src(struct omap_hsmmc_platform_data *mmc) u32 reg; reg = omap_ctrl_readl(control_devconf1_offset); - if (mmc->slots[0].internal_clock) + if (mmc->internal_clock) reg |= OMAP2_MMCSDIO2ADPCLKISEL; else reg &= ~OMAP2_MMCSDIO2ADPCLKISEL; @@ -127,8 +127,8 @@ static void hsmmc2_before_set_reg(struct device *dev, int slot, { struct omap_hsmmc_platform_data *mmc = dev->platform_data; - if (mmc->slots[0].remux) - mmc->slots[0].remux(dev, slot, power_on); + if (mmc->remux) + mmc->remux(dev, slot, power_on); if (power_on) hsmmc2_select_input_clk_src(mmc); @@ -154,14 +154,14 @@ static int nop_mmc_set_power(struct device *dev, int slot, int power_on, static inline void omap_hsmmc_mux(struct omap_hsmmc_platform_data *mmc_controller, int controller_nr) { - if (gpio_is_valid(mmc_controller->slots[0].switch_pin) && - (mmc_controller->slots[0].switch_pin < OMAP_MAX_GPIO_LINES)) - omap_mux_init_gpio(mmc_controller->slots[0].switch_pin, - OMAP_PIN_INPUT_PULLUP); - if (gpio_is_valid(mmc_controller->slots[0].gpio_wp) && - (mmc_controller->slots[0].gpio_wp < OMAP_MAX_GPIO_LINES)) - omap_mux_init_gpio(mmc_controller->slots[0].gpio_wp, - OMAP_PIN_INPUT_PULLUP); + if (gpio_is_valid(mmc_controller->switch_pin) && + (mmc_controller->switch_pin < OMAP_MAX_GPIO_LINES)) + omap_mux_init_gpio(mmc_controller->switch_pin, + OMAP_PIN_INPUT_PULLUP); + if (gpio_is_valid(mmc_controller->gpio_wp) && + (mmc_controller->gpio_wp < OMAP_MAX_GPIO_LINES)) + omap_mux_init_gpio(mmc_controller->gpio_wp, + OMAP_PIN_INPUT_PULLUP); if (cpu_is_omap34xx()) { if (controller_nr == 0) { omap_mux_init_signal("sdmmc1_clk", @@ -170,7 +170,7 @@ static inline void omap_hsmmc_mux(struct omap_hsmmc_platform_data OMAP_PIN_INPUT_PULLUP); omap_mux_init_signal("sdmmc1_dat0", OMAP_PIN_INPUT_PULLUP); - if (mmc_controller->slots[0].caps & + if (mmc_controller->caps & (MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA)) { omap_mux_init_signal("sdmmc1_dat1", OMAP_PIN_INPUT_PULLUP); @@ -179,7 +179,7 @@ static inline void omap_hsmmc_mux(struct omap_hsmmc_platform_data omap_mux_init_signal("sdmmc1_dat3", OMAP_PIN_INPUT_PULLUP); } - if (mmc_controller->slots[0].caps & + if (mmc_controller->caps & MMC_CAP_8_BIT_DATA) { omap_mux_init_signal("sdmmc1_dat4", OMAP_PIN_INPUT_PULLUP); @@ -204,7 +204,7 @@ static inline void omap_hsmmc_mux(struct omap_hsmmc_platform_data * For 8 wire configurations, Lines DAT4, 5, 6 and 7 * need to be muxed in the board-*.c files */ - if (mmc_controller->slots[0].caps & + if (mmc_controller->caps & (MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA)) { omap_mux_init_signal("sdmmc2_dat1", OMAP_PIN_INPUT_PULLUP); @@ -213,7 +213,7 @@ static inline void omap_hsmmc_mux(struct omap_hsmmc_platform_data omap_mux_init_signal("sdmmc2_dat3", OMAP_PIN_INPUT_PULLUP); } - if (mmc_controller->slots[0].caps & + if (mmc_controller->caps & MMC_CAP_8_BIT_DATA) { omap_mux_init_signal("sdmmc2_dat4.sdmmc2_dat4", OMAP_PIN_INPUT_PULLUP); @@ -249,23 +249,23 @@ static int __init omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c, else snprintf(hc_name, (HSMMC_NAME_LEN + 1), "mmc%islot%i", c->mmc, 1); - mmc->slots[0].name = hc_name; + mmc->name = hc_name; mmc->nr_slots = 1; - mmc->slots[0].caps = c->caps; - mmc->slots[0].internal_clock = !c->ext_clock; + mmc->caps = c->caps; + mmc->internal_clock = !c->ext_clock; mmc->reg_offset = 0; - mmc->slots[0].switch_pin = c->gpio_cd; - mmc->slots[0].gpio_wp = c->gpio_wp; + mmc->switch_pin = c->gpio_cd; + mmc->gpio_wp = c->gpio_wp; - mmc->slots[0].remux = c->remux; - mmc->slots[0].init_card = c->init_card; + mmc->remux = c->remux; + mmc->init_card = c->init_card; if (c->cover_only) - mmc->slots[0].cover = 1; + mmc->cover = 1; if (c->nonremovable) - mmc->slots[0].nonremovable = 1; + mmc->nonremovable = 1; /* * NOTE: MMC slots should have a Vcc regulator set up. @@ -275,42 +275,42 @@ static int __init omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c, * temporary HACK: ocr_mask instead of fixed supply */ if (soc_is_am35xx()) - mmc->slots[0].ocr_mask = MMC_VDD_165_195 | + mmc->ocr_mask = MMC_VDD_165_195 | MMC_VDD_26_27 | MMC_VDD_27_28 | MMC_VDD_29_30 | MMC_VDD_30_31 | MMC_VDD_31_32; else - mmc->slots[0].ocr_mask = c->ocr_mask; + mmc->ocr_mask = c->ocr_mask; if (!soc_is_am35xx()) - mmc->slots[0].features |= HSMMC_HAS_PBIAS; + mmc->features |= HSMMC_HAS_PBIAS; switch (c->mmc) { case 1: - if (mmc->slots[0].features & HSMMC_HAS_PBIAS) { + if (mmc->features & HSMMC_HAS_PBIAS) { /* on-chip level shifting via PBIAS0/PBIAS1 */ - mmc->slots[0].before_set_reg = + mmc->before_set_reg = omap_hsmmc1_before_set_reg; - mmc->slots[0].after_set_reg = + mmc->after_set_reg = omap_hsmmc1_after_set_reg; } if (soc_is_am35xx()) - mmc->slots[0].set_power = nop_mmc_set_power; + mmc->set_power = nop_mmc_set_power; /* OMAP3630 HSMMC1 supports only 4-bit */ if (cpu_is_omap3630() && (c->caps & MMC_CAP_8_BIT_DATA)) { c->caps &= ~MMC_CAP_8_BIT_DATA; c->caps |= MMC_CAP_4_BIT_DATA; - mmc->slots[0].caps = c->caps; + mmc->caps = c->caps; } break; case 2: if (soc_is_am35xx()) - mmc->slots[0].set_power = am35x_hsmmc2_set_power; + mmc->set_power = am35x_hsmmc2_set_power; if (c->ext_clock) c->transceiver = 1; @@ -318,17 +318,17 @@ static int __init omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c, c->caps &= ~MMC_CAP_8_BIT_DATA; c->caps |= MMC_CAP_4_BIT_DATA; } - if (mmc->slots[0].features & HSMMC_HAS_PBIAS) { + if (mmc->features & HSMMC_HAS_PBIAS) { /* off-chip level shifting, or none */ - mmc->slots[0].before_set_reg = hsmmc2_before_set_reg; - mmc->slots[0].after_set_reg = NULL; + mmc->before_set_reg = hsmmc2_before_set_reg; + mmc->after_set_reg = NULL; } break; case 3: case 4: case 5: - mmc->slots[0].before_set_reg = NULL; - mmc->slots[0].after_set_reg = NULL; + mmc->before_set_reg = NULL; + mmc->after_set_reg = NULL; break; default: pr_err("MMC%d configuration not supported!\n", c->mmc); @@ -363,8 +363,8 @@ void omap_hsmmc_late_init(struct omap2_hsmmc_info *c) if (!mmc_pdata) continue; - mmc_pdata->slots[0].switch_pin = c->gpio_cd; - mmc_pdata->slots[0].gpio_wp = c->gpio_wp; + mmc_pdata->switch_pin = c->gpio_cd; + mmc_pdata->gpio_wp = c->gpio_wp; res = omap_device_register(pdev); if (res) @@ -464,7 +464,7 @@ put_pdev: platform_device_put(pdev); free_name: - kfree(mmc_data->slots[0].name); + kfree(mmc_data->name); free_mmc: kfree(mmc_data); diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 03e8e9aa3756..291b9e125d46 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -155,7 +155,7 @@ * omap.c controller driver. Luckily this is not currently done on any known * omap_hsmmc.c device. */ -#define mmc_slot(host) (host->pdata->slots[host->slot_id]) +#define mmc_pdata(host) host->pdata /* * MMC Host controller read/write API's @@ -236,7 +236,7 @@ static int omap_hsmmc_card_detect(struct device *dev, int slot) struct omap_hsmmc_platform_data *mmc = host->pdata; /* NOTE: assumes card detect signal is active-low */ - return !gpio_get_value_cansleep(mmc->slots[0].switch_pin); + return !gpio_get_value_cansleep(mmc->switch_pin); } static int omap_hsmmc_get_wp(struct device *dev, int slot) @@ -245,7 +245,7 @@ static int omap_hsmmc_get_wp(struct device *dev, int slot) struct omap_hsmmc_platform_data *mmc = host->pdata; /* NOTE: assumes write protect signal is active-high */ - return gpio_get_value_cansleep(mmc->slots[0].gpio_wp); + return gpio_get_value_cansleep(mmc->gpio_wp); } static int omap_hsmmc_get_cover_state(struct device *dev, int slot) @@ -254,7 +254,7 @@ static int omap_hsmmc_get_cover_state(struct device *dev, int slot) struct omap_hsmmc_platform_data *mmc = host->pdata; /* NOTE: assumes card detect signal is active-low */ - return !gpio_get_value_cansleep(mmc->slots[0].switch_pin); + return !gpio_get_value_cansleep(mmc->switch_pin); } #ifdef CONFIG_PM @@ -264,7 +264,7 @@ static int omap_hsmmc_suspend_cdirq(struct device *dev, int slot) struct omap_hsmmc_host *host = dev_get_drvdata(dev); struct omap_hsmmc_platform_data *mmc = host->pdata; - disable_irq(mmc->slots[0].card_detect_irq); + disable_irq(mmc->card_detect_irq); return 0; } @@ -273,7 +273,7 @@ static int omap_hsmmc_resume_cdirq(struct device *dev, int slot) struct omap_hsmmc_host *host = dev_get_drvdata(dev); struct omap_hsmmc_platform_data *mmc = host->pdata; - enable_irq(mmc->slots[0].card_detect_irq); + enable_irq(mmc->card_detect_irq); return 0; } @@ -300,8 +300,8 @@ static int omap_hsmmc_set_power(struct device *dev, int slot, int power_on, if (!host->vcc) return 0; - if (mmc_slot(host).before_set_reg) - mmc_slot(host).before_set_reg(dev, slot, power_on, vdd); + if (mmc_pdata(host)->before_set_reg) + mmc_pdata(host)->before_set_reg(dev, slot, power_on, vdd); if (host->pbias) { if (host->pbias_enabled == 1) { @@ -363,8 +363,8 @@ static int omap_hsmmc_set_power(struct device *dev, int slot, int power_on, } } - if (mmc_slot(host).after_set_reg) - mmc_slot(host).after_set_reg(dev, slot, power_on, vdd); + if (mmc_pdata(host)->after_set_reg) + mmc_pdata(host)->after_set_reg(dev, slot, power_on, vdd); error_set_power: return ret; @@ -383,18 +383,18 @@ static int omap_hsmmc_reg_get(struct omap_hsmmc_host *host) } else { host->vcc = reg; ocr_value = mmc_regulator_get_ocrmask(reg); - if (!mmc_slot(host).ocr_mask) { - mmc_slot(host).ocr_mask = ocr_value; + if (!mmc_pdata(host)->ocr_mask) { + mmc_pdata(host)->ocr_mask = ocr_value; } else { - if (!(mmc_slot(host).ocr_mask & ocr_value)) { + if (!(mmc_pdata(host)->ocr_mask & ocr_value)) { dev_err(host->dev, "ocrmask %x is not supported\n", - mmc_slot(host).ocr_mask); - mmc_slot(host).ocr_mask = 0; + mmc_pdata(host)->ocr_mask); + mmc_pdata(host)->ocr_mask = 0; return -EINVAL; } } } - mmc_slot(host).set_power = omap_hsmmc_set_power; + mmc_pdata(host)->set_power = omap_hsmmc_set_power; /* Allow an aux regulator */ reg = devm_regulator_get_optional(host->dev, "vmmc_aux"); @@ -404,7 +404,7 @@ static int omap_hsmmc_reg_get(struct omap_hsmmc_host *host) host->pbias = IS_ERR(reg) ? NULL : reg; /* For eMMC do not power off when not in sleep state */ - if (mmc_slot(host).no_regulator_off_init) + if (mmc_pdata(host)->no_regulator_off_init) return 0; /* * To disable boot_on regulator, enable regulator @@ -412,10 +412,10 @@ static int omap_hsmmc_reg_get(struct omap_hsmmc_host *host) */ if ((host->vcc && regulator_is_enabled(host->vcc) > 0) || (host->vcc_aux && regulator_is_enabled(host->vcc_aux))) { - int vdd = ffs(mmc_slot(host).ocr_mask) - 1; + int vdd = ffs(mmc_pdata(host)->ocr_mask) - 1; - mmc_slot(host).set_power(host->dev, host->slot_id, 1, vdd); - mmc_slot(host).set_power(host->dev, host->slot_id, 0, 0); + mmc_pdata(host)->set_power(host->dev, host->slot_id, 1, vdd); + mmc_pdata(host)->set_power(host->dev, host->slot_id, 0, 0); } return 0; @@ -423,7 +423,7 @@ static int omap_hsmmc_reg_get(struct omap_hsmmc_host *host) static void omap_hsmmc_reg_put(struct omap_hsmmc_host *host) { - mmc_slot(host).set_power = NULL; + mmc_pdata(host)->set_power = NULL; } static inline int omap_hsmmc_have_reg(void) @@ -453,51 +453,53 @@ static int omap_hsmmc_gpio_init(struct omap_hsmmc_platform_data *pdata) { int ret; - if (gpio_is_valid(pdata->slots[0].switch_pin)) { - if (pdata->slots[0].cover) - pdata->slots[0].get_cover_state = + if (gpio_is_valid(pdata->switch_pin)) { + if (pdata->cover) + pdata->get_cover_state = omap_hsmmc_get_cover_state; else - pdata->slots[0].card_detect = omap_hsmmc_card_detect; - pdata->slots[0].card_detect_irq = - gpio_to_irq(pdata->slots[0].switch_pin); - ret = gpio_request(pdata->slots[0].switch_pin, "mmc_cd"); + pdata->card_detect = omap_hsmmc_card_detect; + pdata->card_detect_irq = + gpio_to_irq(pdata->switch_pin); + ret = gpio_request(pdata->switch_pin, "mmc_cd"); if (ret) return ret; - ret = gpio_direction_input(pdata->slots[0].switch_pin); + ret = gpio_direction_input(pdata->switch_pin); if (ret) goto err_free_sp; - } else - pdata->slots[0].switch_pin = -EINVAL; + } else { + pdata->switch_pin = -EINVAL; + } - if (gpio_is_valid(pdata->slots[0].gpio_wp)) { - pdata->slots[0].get_ro = omap_hsmmc_get_wp; - ret = gpio_request(pdata->slots[0].gpio_wp, "mmc_wp"); + if (gpio_is_valid(pdata->gpio_wp)) { + pdata->get_ro = omap_hsmmc_get_wp; + ret = gpio_request(pdata->gpio_wp, "mmc_wp"); if (ret) goto err_free_cd; - ret = gpio_direction_input(pdata->slots[0].gpio_wp); + ret = gpio_direction_input(pdata->gpio_wp); if (ret) goto err_free_wp; - } else - pdata->slots[0].gpio_wp = -EINVAL; + } else { + pdata->gpio_wp = -EINVAL; + } return 0; err_free_wp: - gpio_free(pdata->slots[0].gpio_wp); + gpio_free(pdata->gpio_wp); err_free_cd: - if (gpio_is_valid(pdata->slots[0].switch_pin)) + if (gpio_is_valid(pdata->switch_pin)) err_free_sp: - gpio_free(pdata->slots[0].switch_pin); + gpio_free(pdata->switch_pin); return ret; } static void omap_hsmmc_gpio_free(struct omap_hsmmc_platform_data *pdata) { - if (gpio_is_valid(pdata->slots[0].gpio_wp)) - gpio_free(pdata->slots[0].gpio_wp); - if (gpio_is_valid(pdata->slots[0].switch_pin)) - gpio_free(pdata->slots[0].switch_pin); + if (gpio_is_valid(pdata->gpio_wp)) + gpio_free(pdata->gpio_wp); + if (gpio_is_valid(pdata->switch_pin)) + gpio_free(pdata->switch_pin); } /* @@ -607,7 +609,7 @@ static void omap_hsmmc_set_clock(struct omap_hsmmc_host *host) * in capabilities register * - MMC/SD clock coming out of controller > 25MHz */ - if ((mmc_slot(host).features & HSMMC_HAS_HSPE_SUPPORT) && + if ((mmc_pdata(host)->features & HSMMC_HAS_HSPE_SUPPORT) && (ios->timing != MMC_TIMING_MMC_DDR52) && ((OMAP_HSMMC_READ(host->base, CAPA) & HSS) == HSS)) { regval = OMAP_HSMMC_READ(host->base, HCTL); @@ -791,8 +793,8 @@ int omap_hsmmc_cover_is_closed(struct omap_hsmmc_host *host) { int r = 1; - if (mmc_slot(host).get_cover_state) - r = mmc_slot(host).get_cover_state(host->dev, host->slot_id); + if (mmc_pdata(host)->get_cover_state) + r = mmc_pdata(host)->get_cover_state(host->dev, host->slot_id); return r; } @@ -816,7 +818,7 @@ omap_hsmmc_show_slot_name(struct device *dev, struct device_attribute *attr, struct mmc_host *mmc = container_of(dev, struct mmc_host, class_dev); struct omap_hsmmc_host *host = mmc_priv(mmc); - return sprintf(buf, "%s\n", mmc_slot(host).name); + return sprintf(buf, "%s\n", mmc_pdata(host)->name); } static DEVICE_ATTR(slot_name, S_IRUGO, omap_hsmmc_show_slot_name, NULL); @@ -1061,7 +1063,7 @@ static inline void omap_hsmmc_reset_controller_fsm(struct omap_hsmmc_host *host, * OMAP4 ES2 and greater has an updated reset logic. * Monitor a 0->1 transition first */ - if (mmc_slot(host).features & HSMMC_HAS_UPDATED_RESET) { + if (mmc_pdata(host)->features & HSMMC_HAS_UPDATED_RESET) { while ((!(OMAP_HSMMC_READ(host->base, SYSCTL) & bit)) && (i++ < limit)) udelay(1); @@ -1210,12 +1212,12 @@ static int omap_hsmmc_switch_opcond(struct omap_hsmmc_host *host, int vdd) clk_disable_unprepare(host->dbclk); /* Turn the power off */ - ret = mmc_slot(host).set_power(host->dev, host->slot_id, 0, 0); + ret = mmc_pdata(host)->set_power(host->dev, host->slot_id, 0, 0); /* Turn the power ON with given VDD 1.8 or 3.0v */ if (!ret) - ret = mmc_slot(host).set_power(host->dev, host->slot_id, 1, - vdd); + ret = mmc_pdata(host)->set_power(host->dev, host->slot_id, 1, + vdd); pm_runtime_get_sync(host->dev); if (host->dbclk) clk_prepare_enable(host->dbclk); @@ -1259,11 +1261,11 @@ err: /* Protect the card while the cover is open */ static void omap_hsmmc_protect_card(struct omap_hsmmc_host *host) { - if (!mmc_slot(host).get_cover_state) + if (!mmc_pdata(host)->get_cover_state) return; host->reqs_blocked = 0; - if (mmc_slot(host).get_cover_state(host->dev, host->slot_id)) { + if (mmc_pdata(host)->get_cover_state(host->dev, host->slot_id)) { if (host->protect_card) { dev_info(host->dev, "%s: cover is closed, " "card is now accessible\n", @@ -1286,13 +1288,13 @@ static void omap_hsmmc_protect_card(struct omap_hsmmc_host *host) static irqreturn_t omap_hsmmc_detect(int irq, void *dev_id) { struct omap_hsmmc_host *host = dev_id; - struct omap_hsmmc_slot_data *slot = &mmc_slot(host); + struct omap_hsmmc_platform_data *pdata = host->pdata; int carddetect; sysfs_notify(&host->mmc->class_dev.kobj, NULL, "cover_switch"); - if (slot->card_detect) - carddetect = slot->card_detect(host->dev, host->slot_id); + if (pdata->card_detect) + carddetect = pdata->card_detect(host->dev, host->slot_id); else { omap_hsmmc_protect_card(host); carddetect = -ENOSYS; @@ -1618,12 +1620,12 @@ static void omap_hsmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) if (ios->power_mode != host->power_mode) { switch (ios->power_mode) { case MMC_POWER_OFF: - mmc_slot(host).set_power(host->dev, host->slot_id, - 0, 0); + mmc_pdata(host)->set_power(host->dev, host->slot_id, + 0, 0); break; case MMC_POWER_UP: - mmc_slot(host).set_power(host->dev, host->slot_id, - 1, ios->vdd); + mmc_pdata(host)->set_power(host->dev, host->slot_id, + 1, ios->vdd); break; case MMC_POWER_ON: do_send_init_stream = 1; @@ -1668,26 +1670,26 @@ static int omap_hsmmc_get_cd(struct mmc_host *mmc) { struct omap_hsmmc_host *host = mmc_priv(mmc); - if (!mmc_slot(host).card_detect) + if (!mmc_pdata(host)->card_detect) return -ENOSYS; - return mmc_slot(host).card_detect(host->dev, host->slot_id); + return mmc_pdata(host)->card_detect(host->dev, host->slot_id); } static int omap_hsmmc_get_ro(struct mmc_host *mmc) { struct omap_hsmmc_host *host = mmc_priv(mmc); - if (!mmc_slot(host).get_ro) + if (!mmc_pdata(host)->get_ro) return -ENOSYS; - return mmc_slot(host).get_ro(host->dev, 0); + return mmc_pdata(host)->get_ro(host->dev, 0); } static void omap_hsmmc_init_card(struct mmc_host *mmc, struct mmc_card *card) { struct omap_hsmmc_host *host = mmc_priv(mmc); - if (mmc_slot(host).init_card) - mmc_slot(host).init_card(card); + if (mmc_pdata(host)->init_card) + mmc_pdata(host)->init_card(card); } static void omap_hsmmc_enable_sdio_irq(struct mmc_host *mmc, int enable) @@ -1978,33 +1980,33 @@ static struct omap_hsmmc_platform_data *of_get_hsmmc_pdata(struct device *dev) /* This driver only supports 1 slot */ pdata->nr_slots = 1; - pdata->slots[0].switch_pin = cd_gpio; - pdata->slots[0].gpio_wp = wp_gpio; + pdata->switch_pin = cd_gpio; + pdata->gpio_wp = wp_gpio; if (of_find_property(np, "ti,non-removable", NULL)) { - pdata->slots[0].nonremovable = true; - pdata->slots[0].no_regulator_off_init = true; + pdata->nonremovable = true; + pdata->no_regulator_off_init = true; } of_property_read_u32(np, "bus-width", &bus_width); if (bus_width == 4) - pdata->slots[0].caps |= MMC_CAP_4_BIT_DATA; + pdata->caps |= MMC_CAP_4_BIT_DATA; else if (bus_width == 8) - pdata->slots[0].caps |= MMC_CAP_8_BIT_DATA; + pdata->caps |= MMC_CAP_8_BIT_DATA; if (of_find_property(np, "ti,needs-special-reset", NULL)) - pdata->slots[0].features |= HSMMC_HAS_UPDATED_RESET; + pdata->features |= HSMMC_HAS_UPDATED_RESET; if (!of_property_read_u32(np, "max-frequency", &max_freq)) pdata->max_freq = max_freq; if (of_find_property(np, "ti,needs-special-hs-handling", NULL)) - pdata->slots[0].features |= HSMMC_HAS_HSPE_SUPPORT; + pdata->features |= HSMMC_HAS_HSPE_SUPPORT; if (of_find_property(np, "keep-power-in-suspend", NULL)) - pdata->slots[0].pm_caps |= MMC_PM_KEEP_POWER; + pdata->pm_caps |= MMC_PM_KEEP_POWER; if (of_find_property(np, "enable-sdio-wakeup", NULL)) - pdata->slots[0].pm_caps |= MMC_PM_WAKE_SDIO_IRQ; + pdata->pm_caps |= MMC_PM_WAKE_SDIO_IRQ; return pdata; } @@ -2144,14 +2146,14 @@ static int omap_hsmmc_probe(struct platform_device *pdev) mmc->caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED | MMC_CAP_WAIT_WHILE_BUSY | MMC_CAP_ERASE; - mmc->caps |= mmc_slot(host).caps; + mmc->caps |= mmc_pdata(host)->caps; if (mmc->caps & MMC_CAP_8_BIT_DATA) mmc->caps |= MMC_CAP_4_BIT_DATA; - if (mmc_slot(host).nonremovable) + if (mmc_pdata(host)->nonremovable) mmc->caps |= MMC_CAP_NONREMOVABLE; - mmc->pm_caps = mmc_slot(host).pm_caps; + mmc->pm_caps = mmc_pdata(host)->pm_caps; omap_hsmmc_conf_bus_power(host); @@ -2204,19 +2206,19 @@ static int omap_hsmmc_probe(struct platform_device *pdev) goto err_irq; } - if (omap_hsmmc_have_reg() && !mmc_slot(host).set_power) { + if (omap_hsmmc_have_reg() && !mmc_pdata(host)->set_power) { ret = omap_hsmmc_reg_get(host); if (ret) goto err_irq; host->use_reg = 1; } - mmc->ocr_avail = mmc_slot(host).ocr_mask; + mmc->ocr_avail = mmc_pdata(host)->ocr_mask; /* Request IRQ for card detect */ - if ((mmc_slot(host).card_detect_irq)) { + if ((mmc_pdata(host)->card_detect_irq)) { ret = devm_request_threaded_irq(&pdev->dev, - mmc_slot(host).card_detect_irq, + mmc_pdata(host)->card_detect_irq, NULL, omap_hsmmc_detect, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, mmc_hostname(mmc), host); @@ -2247,12 +2249,13 @@ static int omap_hsmmc_probe(struct platform_device *pdev) mmc_add_host(mmc); - if (mmc_slot(host).name != NULL) { + if (mmc_pdata(host)->name != NULL) { ret = device_create_file(&mmc->class_dev, &dev_attr_slot_name); if (ret < 0) goto err_slot_name; } - if (mmc_slot(host).card_detect_irq && mmc_slot(host).get_cover_state) { + if (mmc_pdata(host)->card_detect_irq && + mmc_pdata(host)->get_cover_state) { ret = device_create_file(&mmc->class_dev, &dev_attr_cover_switch); if (ret < 0) diff --git a/include/linux/platform_data/hsmmc-omap.h b/include/linux/platform_data/hsmmc-omap.h index 35d494f7d62f..26912143adc0 100644 --- a/include/linux/platform_data/hsmmc-omap.h +++ b/include/linux/platform_data/hsmmc-omap.h @@ -8,8 +8,6 @@ * published by the Free Software Foundation. */ -#define OMAP_HSMMC_MAX_SLOTS 1 - /* * struct omap_hsmmc_dev_attr.flags possibilities * @@ -57,62 +55,60 @@ struct omap_hsmmc_platform_data { /* Register offset deviation */ u16 reg_offset; - struct omap_hsmmc_slot_data { - /* - * 4/8 wires and any additional host capabilities - * need to OR'd all capabilities (ref. linux/mmc/host.h) - */ - u32 caps; /* Used for the MMC driver on 2430 and later */ - u32 pm_caps; /* PM capabilities of the mmc */ + /* + * 4/8 wires and any additional host capabilities + * need to OR'd all capabilities (ref. linux/mmc/host.h) + */ + u32 caps; /* Used for the MMC driver on 2430 and later */ + u32 pm_caps; /* PM capabilities of the mmc */ - /* switch pin can be for card detect (default) or card cover */ - unsigned cover:1; + /* switch pin can be for card detect (default) or card cover */ + unsigned cover:1; - /* use the internal clock */ - unsigned internal_clock:1; + /* use the internal clock */ + unsigned internal_clock:1; - /* nonremovable e.g. eMMC */ - unsigned nonremovable:1; + /* nonremovable e.g. eMMC */ + unsigned nonremovable:1; - /* eMMC does not handle power off when not in sleep state */ - unsigned no_regulator_off_init:1; + /* eMMC does not handle power off when not in sleep state */ + unsigned no_regulator_off_init:1; - /* we can put the features above into this variable */ + /* we can put the features above into this variable */ #define HSMMC_HAS_PBIAS (1 << 0) #define HSMMC_HAS_UPDATED_RESET (1 << 1) #define HSMMC_HAS_HSPE_SUPPORT (1 << 2) - unsigned features; - - int switch_pin; /* gpio (card detect) */ - int gpio_wp; /* gpio (write protect) */ - - int (*set_power)(struct device *dev, int slot, - int power_on, int vdd); - int (*get_ro)(struct device *dev, int slot); - void (*remux)(struct device *dev, int slot, int power_on); - /* Call back before enabling / disabling regulators */ - void (*before_set_reg)(struct device *dev, int slot, - int power_on, int vdd); - /* Call back after enabling / disabling regulators */ - void (*after_set_reg)(struct device *dev, int slot, - int power_on, int vdd); - /* if we have special card, init it using this callback */ - void (*init_card)(struct mmc_card *card); - - /* return MMC cover switch state, can be NULL if not supported. - * - * possible return values: - * 0 - closed - * 1 - open - */ - int (*get_cover_state)(struct device *dev, int slot); - - const char *name; - u32 ocr_mask; - - /* Card detection IRQs */ - int card_detect_irq; - - int (*card_detect)(struct device *dev, int slot); - } slots[OMAP_HSMMC_MAX_SLOTS]; + unsigned features; + + int switch_pin; /* gpio (card detect) */ + int gpio_wp; /* gpio (write protect) */ + + int (*set_power)(struct device *dev, int slot, + int power_on, int vdd); + int (*get_ro)(struct device *dev, int slot); + void (*remux)(struct device *dev, int slot, int power_on); + /* Call back before enabling / disabling regulators */ + void (*before_set_reg)(struct device *dev, int slot, + int power_on, int vdd); + /* Call back after enabling / disabling regulators */ + void (*after_set_reg)(struct device *dev, int slot, + int power_on, int vdd); + /* if we have special card, init it using this callback */ + void (*init_card)(struct mmc_card *card); + + /* return MMC cover switch state, can be NULL if not supported. + * + * possible return values: + * 0 - closed + * 1 - open + */ + int (*get_cover_state)(struct device *dev, int slot); + + const char *name; + u32 ocr_mask; + + /* Card detection IRQs */ + int card_detect_irq; + + int (*card_detect)(struct device *dev, int slot); }; -- cgit v1.2.3 From b5cd43f062717b6c92f93bc0c593764e144ea331 Mon Sep 17 00:00:00 2001 From: Andreas Fenkart Date: Sat, 8 Nov 2014 15:33:16 +0100 Subject: mmc: omap_hsmmc: Remove unnecessary callbacks from platform data These callbacks are set during driver probe and not from the platform init, -- evtl. they had been for oamp 1/2 -- for omap3 they are local functions of the driver. These indirection could be dropped altogether in favor of regular function calls TODO Acked-by: Tony Lindgren Signed-off-by: Andreas Fenkart Signed-off-by: Ulf Hansson --- drivers/mmc/host/omap_hsmmc.c | 75 +++++++++++++++++++------------- include/linux/platform_data/hsmmc-omap.h | 18 -------- 2 files changed, 45 insertions(+), 48 deletions(-) (limited to 'include/linux') diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 8a216c92c5a8..f4f1bcd632f3 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -221,6 +221,25 @@ struct omap_hsmmc_host { #define HSMMC_WAKE_IRQ_ENABLED (1 << 2) struct omap_hsmmc_next next_data; struct omap_hsmmc_platform_data *pdata; + + /* To handle board related suspend/resume functionality for MMC */ + int (*suspend)(struct device *dev, int slot); + int (*resume)(struct device *dev, int slot); + + /* return MMC cover switch state, can be NULL if not supported. + * + * possible return values: + * 0 - closed + * 1 - open + */ + int (*get_cover_state)(struct device *dev, int slot); + + /* Card detection IRQs */ + int card_detect_irq; + + int (*card_detect)(struct device *dev, int slot); + int (*get_ro)(struct device *dev, int slot); + }; struct omap_mmc_of_data { @@ -262,18 +281,16 @@ static int omap_hsmmc_get_cover_state(struct device *dev, int slot) static int omap_hsmmc_suspend_cdirq(struct device *dev, int slot) { struct omap_hsmmc_host *host = dev_get_drvdata(dev); - struct omap_hsmmc_platform_data *mmc = host->pdata; - disable_irq(mmc->card_detect_irq); + disable_irq(host->card_detect_irq); return 0; } static int omap_hsmmc_resume_cdirq(struct device *dev, int slot) { struct omap_hsmmc_host *host = dev_get_drvdata(dev); - struct omap_hsmmc_platform_data *mmc = host->pdata; - enable_irq(mmc->card_detect_irq); + enable_irq(host->card_detect_irq); return 0; } @@ -456,11 +473,11 @@ static int omap_hsmmc_gpio_init(struct omap_hsmmc_host *host, if (gpio_is_valid(pdata->switch_pin)) { if (pdata->cover) - pdata->get_cover_state = - omap_hsmmc_get_cover_state; + host->get_cover_state = + omap_hsmmc_get_cover_state; else - pdata->card_detect = omap_hsmmc_card_detect; - pdata->card_detect_irq = + host->card_detect = omap_hsmmc_card_detect; + host->card_detect_irq = gpio_to_irq(pdata->switch_pin); ret = gpio_request(pdata->switch_pin, "mmc_cd"); if (ret) @@ -473,7 +490,7 @@ static int omap_hsmmc_gpio_init(struct omap_hsmmc_host *host, } if (gpio_is_valid(pdata->gpio_wp)) { - pdata->get_ro = omap_hsmmc_get_wp; + host->get_ro = omap_hsmmc_get_wp; ret = gpio_request(pdata->gpio_wp, "mmc_wp"); if (ret) goto err_free_cd; @@ -795,8 +812,8 @@ int omap_hsmmc_cover_is_closed(struct omap_hsmmc_host *host) { int r = 1; - if (mmc_pdata(host)->get_cover_state) - r = mmc_pdata(host)->get_cover_state(host->dev, host->slot_id); + if (host->get_cover_state) + r = host->get_cover_state(host->dev, host->slot_id); return r; } @@ -1263,11 +1280,11 @@ err: /* Protect the card while the cover is open */ static void omap_hsmmc_protect_card(struct omap_hsmmc_host *host) { - if (!mmc_pdata(host)->get_cover_state) + if (!host->get_cover_state) return; host->reqs_blocked = 0; - if (mmc_pdata(host)->get_cover_state(host->dev, host->slot_id)) { + if (host->get_cover_state(host->dev, host->slot_id)) { if (host->protect_card) { dev_info(host->dev, "%s: cover is closed, " "card is now accessible\n", @@ -1290,13 +1307,12 @@ static void omap_hsmmc_protect_card(struct omap_hsmmc_host *host) static irqreturn_t omap_hsmmc_detect(int irq, void *dev_id) { struct omap_hsmmc_host *host = dev_id; - struct omap_hsmmc_platform_data *pdata = host->pdata; int carddetect; sysfs_notify(&host->mmc->class_dev.kobj, NULL, "cover_switch"); - if (pdata->card_detect) - carddetect = pdata->card_detect(host->dev, host->slot_id); + if (host->card_detect) + carddetect = host->card_detect(host->dev, host->slot_id); else { omap_hsmmc_protect_card(host); carddetect = -ENOSYS; @@ -1672,18 +1688,18 @@ static int omap_hsmmc_get_cd(struct mmc_host *mmc) { struct omap_hsmmc_host *host = mmc_priv(mmc); - if (!mmc_pdata(host)->card_detect) + if (!host->card_detect) return -ENOSYS; - return mmc_pdata(host)->card_detect(host->dev, host->slot_id); + return host->card_detect(host->dev, host->slot_id); } static int omap_hsmmc_get_ro(struct mmc_host *mmc) { struct omap_hsmmc_host *host = mmc_priv(mmc); - if (!mmc_pdata(host)->get_ro) + if (!host->get_ro) return -ENOSYS; - return mmc_pdata(host)->get_ro(host->dev, 0); + return host->get_ro(host->dev, 0); } static void omap_hsmmc_init_card(struct mmc_host *mmc, struct mmc_card *card) @@ -2218,9 +2234,9 @@ static int omap_hsmmc_probe(struct platform_device *pdev) mmc->ocr_avail = mmc_pdata(host)->ocr_mask; /* Request IRQ for card detect */ - if ((mmc_pdata(host)->card_detect_irq)) { + if (host->card_detect_irq) { ret = devm_request_threaded_irq(&pdev->dev, - mmc_pdata(host)->card_detect_irq, + host->card_detect_irq, NULL, omap_hsmmc_detect, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, mmc_hostname(mmc), host); @@ -2229,8 +2245,8 @@ static int omap_hsmmc_probe(struct platform_device *pdev) "Unable to grab MMC CD IRQ\n"); goto err_irq_cd; } - pdata->suspend = omap_hsmmc_suspend_cdirq; - pdata->resume = omap_hsmmc_resume_cdirq; + host->suspend = omap_hsmmc_suspend_cdirq; + host->resume = omap_hsmmc_resume_cdirq; } omap_hsmmc_disable_irq(host); @@ -2256,8 +2272,7 @@ static int omap_hsmmc_probe(struct platform_device *pdev) if (ret < 0) goto err_slot_name; } - if (mmc_pdata(host)->card_detect_irq && - mmc_pdata(host)->get_cover_state) { + if (host->card_detect_irq && host->get_cover_state) { ret = device_create_file(&mmc->class_dev, &dev_attr_cover_switch); if (ret < 0) @@ -2322,8 +2337,8 @@ static int omap_hsmmc_prepare(struct device *dev) { struct omap_hsmmc_host *host = dev_get_drvdata(dev); - if (host->pdata->suspend) - return host->pdata->suspend(dev, host->slot_id); + if (host->suspend) + return host->suspend(dev, host->slot_id); return 0; } @@ -2332,8 +2347,8 @@ static void omap_hsmmc_complete(struct device *dev) { struct omap_hsmmc_host *host = dev_get_drvdata(dev); - if (host->pdata->resume) - host->pdata->resume(dev, host->slot_id); + if (host->resume) + host->resume(dev, host->slot_id); } diff --git a/include/linux/platform_data/hsmmc-omap.h b/include/linux/platform_data/hsmmc-omap.h index 26912143adc0..68ffec14b56a 100644 --- a/include/linux/platform_data/hsmmc-omap.h +++ b/include/linux/platform_data/hsmmc-omap.h @@ -45,10 +45,6 @@ struct omap_hsmmc_platform_data { * maximum frequency on the MMC bus */ unsigned int max_freq; - /* To handle board related suspend/resume functionality for MMC */ - int (*suspend)(struct device *dev, int slot); - int (*resume)(struct device *dev, int slot); - /* Integrating attributes from the omap_hwmod layer */ u8 controller_flags; @@ -85,7 +81,6 @@ struct omap_hsmmc_platform_data { int (*set_power)(struct device *dev, int slot, int power_on, int vdd); - int (*get_ro)(struct device *dev, int slot); void (*remux)(struct device *dev, int slot, int power_on); /* Call back before enabling / disabling regulators */ void (*before_set_reg)(struct device *dev, int slot, @@ -96,19 +91,6 @@ struct omap_hsmmc_platform_data { /* if we have special card, init it using this callback */ void (*init_card)(struct mmc_card *card); - /* return MMC cover switch state, can be NULL if not supported. - * - * possible return values: - * 0 - closed - * 1 - open - */ - int (*get_cover_state)(struct device *dev, int slot); - const char *name; u32 ocr_mask; - - /* Card detection IRQs */ - int card_detect_irq; - - int (*card_detect)(struct device *dev, int slot); }; -- cgit v1.2.3 From 80412ca8abf087354891108d2f888ad3de56e73c Mon Sep 17 00:00:00 2001 From: Andreas Fenkart Date: Sat, 8 Nov 2014 15:33:17 +0100 Subject: mmc: omap_hsmmc: remove unused slot_id parameter omap_hsmmc only supports one slot. So slot id is always zero, and slot id was never used in the callbacks anyway Acked-by: Tony Lindgren Signed-off-by: Andreas Fenkart Signed-off-by: Ulf Hansson --- arch/arm/mach-omap2/board-rx51-peripherals.c | 2 +- arch/arm/mach-omap2/hsmmc.c | 21 ++++----- arch/arm/mach-omap2/hsmmc.h | 2 +- drivers/mmc/host/omap_hsmmc.c | 65 +++++++++++----------------- include/linux/platform_data/hsmmc-omap.h | 14 ++---- 5 files changed, 40 insertions(+), 64 deletions(-) (limited to 'include/linux') diff --git a/arch/arm/mach-omap2/board-rx51-peripherals.c b/arch/arm/mach-omap2/board-rx51-peripherals.c index 0a8ac844b75b..3d5040f82e90 100644 --- a/arch/arm/mach-omap2/board-rx51-peripherals.c +++ b/arch/arm/mach-omap2/board-rx51-peripherals.c @@ -484,7 +484,7 @@ static struct omap_mux_partition *partition; * Current flows to eMMC when eMMC is off and the data lines are pulled up, * so pull them down. N.B. we pull 8 lines because we are using 8 lines. */ -static void rx51_mmc2_remux(struct device *dev, int slot, int power_on) +static void rx51_mmc2_remux(struct device *dev, int power_on) { if (power_on) omap_mux_write_array(partition, rx51_mmc2_on_mux); diff --git a/arch/arm/mach-omap2/hsmmc.c b/arch/arm/mach-omap2/hsmmc.c index 4e2896ad0119..dc6e79c4484a 100644 --- a/arch/arm/mach-omap2/hsmmc.c +++ b/arch/arm/mach-omap2/hsmmc.c @@ -33,14 +33,14 @@ static u16 control_devconf1_offset; #define HSMMC_NAME_LEN 9 -static void omap_hsmmc1_before_set_reg(struct device *dev, int slot, - int power_on, int vdd) +static void omap_hsmmc1_before_set_reg(struct device *dev, + int power_on, int vdd) { u32 reg, prog_io; struct omap_hsmmc_platform_data *mmc = dev->platform_data; if (mmc->remux) - mmc->remux(dev, slot, power_on); + mmc->remux(dev, power_on); /* * Assume we power both OMAP VMMC1 (for CMD, CLK, DAT0..3) and the @@ -86,8 +86,7 @@ static void omap_hsmmc1_before_set_reg(struct device *dev, int slot, } } -static void omap_hsmmc1_after_set_reg(struct device *dev, int slot, - int power_on, int vdd) +static void omap_hsmmc1_after_set_reg(struct device *dev, int power_on, int vdd) { u32 reg; @@ -122,20 +121,18 @@ static void hsmmc2_select_input_clk_src(struct omap_hsmmc_platform_data *mmc) omap_ctrl_writel(reg, control_devconf1_offset); } -static void hsmmc2_before_set_reg(struct device *dev, int slot, - int power_on, int vdd) +static void hsmmc2_before_set_reg(struct device *dev, int power_on, int vdd) { struct omap_hsmmc_platform_data *mmc = dev->platform_data; if (mmc->remux) - mmc->remux(dev, slot, power_on); + mmc->remux(dev, power_on); if (power_on) hsmmc2_select_input_clk_src(mmc); } -static int am35x_hsmmc2_set_power(struct device *dev, int slot, - int power_on, int vdd) +static int am35x_hsmmc2_set_power(struct device *dev, int power_on, int vdd) { struct omap_hsmmc_platform_data *mmc = dev->platform_data; @@ -145,8 +142,7 @@ static int am35x_hsmmc2_set_power(struct device *dev, int slot, return 0; } -static int nop_mmc_set_power(struct device *dev, int slot, int power_on, - int vdd) +static int nop_mmc_set_power(struct device *dev, int power_on, int vdd) { return 0; } @@ -250,7 +246,6 @@ static int __init omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c, snprintf(hc_name, (HSMMC_NAME_LEN + 1), "mmc%islot%i", c->mmc, 1); mmc->name = hc_name; - mmc->nr_slots = 1; mmc->caps = c->caps; mmc->internal_clock = !c->ext_clock; mmc->reg_offset = 0; diff --git a/arch/arm/mach-omap2/hsmmc.h b/arch/arm/mach-omap2/hsmmc.h index 30c78c17eb7e..148cd9b15499 100644 --- a/arch/arm/mach-omap2/hsmmc.h +++ b/arch/arm/mach-omap2/hsmmc.h @@ -23,7 +23,7 @@ struct omap2_hsmmc_info { struct platform_device *pdev; /* mmc controller instance */ int ocr_mask; /* temporary HACK */ /* Remux (pad configuration) when powering on/off */ - void (*remux)(struct device *dev, int slot, int power_on); + void (*remux)(struct device *dev, int power_on); /* init some special card */ void (*init_card)(struct mmc_card *card); }; diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index f4f1bcd632f3..82b40b85293f 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -207,7 +207,6 @@ struct omap_hsmmc_host { int use_dma, dma_ch; struct dma_chan *tx_chan; struct dma_chan *rx_chan; - int slot_id; int response_busy; int context_loss; int protect_card; @@ -223,8 +222,8 @@ struct omap_hsmmc_host { struct omap_hsmmc_platform_data *pdata; /* To handle board related suspend/resume functionality for MMC */ - int (*suspend)(struct device *dev, int slot); - int (*resume)(struct device *dev, int slot); + int (*suspend)(struct device *dev); + int (*resume)(struct device *dev); /* return MMC cover switch state, can be NULL if not supported. * @@ -232,13 +231,13 @@ struct omap_hsmmc_host { * 0 - closed * 1 - open */ - int (*get_cover_state)(struct device *dev, int slot); + int (*get_cover_state)(struct device *dev); /* Card detection IRQs */ int card_detect_irq; - int (*card_detect)(struct device *dev, int slot); - int (*get_ro)(struct device *dev, int slot); + int (*card_detect)(struct device *dev); + int (*get_ro)(struct device *dev); }; @@ -249,7 +248,7 @@ struct omap_mmc_of_data { static void omap_hsmmc_start_dma_transfer(struct omap_hsmmc_host *host); -static int omap_hsmmc_card_detect(struct device *dev, int slot) +static int omap_hsmmc_card_detect(struct device *dev) { struct omap_hsmmc_host *host = dev_get_drvdata(dev); struct omap_hsmmc_platform_data *mmc = host->pdata; @@ -258,7 +257,7 @@ static int omap_hsmmc_card_detect(struct device *dev, int slot) return !gpio_get_value_cansleep(mmc->switch_pin); } -static int omap_hsmmc_get_wp(struct device *dev, int slot) +static int omap_hsmmc_get_wp(struct device *dev) { struct omap_hsmmc_host *host = dev_get_drvdata(dev); struct omap_hsmmc_platform_data *mmc = host->pdata; @@ -267,7 +266,7 @@ static int omap_hsmmc_get_wp(struct device *dev, int slot) return gpio_get_value_cansleep(mmc->gpio_wp); } -static int omap_hsmmc_get_cover_state(struct device *dev, int slot) +static int omap_hsmmc_get_cover_state(struct device *dev) { struct omap_hsmmc_host *host = dev_get_drvdata(dev); struct omap_hsmmc_platform_data *mmc = host->pdata; @@ -278,7 +277,7 @@ static int omap_hsmmc_get_cover_state(struct device *dev, int slot) #ifdef CONFIG_PM -static int omap_hsmmc_suspend_cdirq(struct device *dev, int slot) +static int omap_hsmmc_suspend_cdirq(struct device *dev) { struct omap_hsmmc_host *host = dev_get_drvdata(dev); @@ -286,7 +285,7 @@ static int omap_hsmmc_suspend_cdirq(struct device *dev, int slot) return 0; } -static int omap_hsmmc_resume_cdirq(struct device *dev, int slot) +static int omap_hsmmc_resume_cdirq(struct device *dev) { struct omap_hsmmc_host *host = dev_get_drvdata(dev); @@ -303,8 +302,7 @@ static int omap_hsmmc_resume_cdirq(struct device *dev, int slot) #ifdef CONFIG_REGULATOR -static int omap_hsmmc_set_power(struct device *dev, int slot, int power_on, - int vdd) +static int omap_hsmmc_set_power(struct device *dev, int power_on, int vdd) { struct omap_hsmmc_host *host = platform_get_drvdata(to_platform_device(dev)); @@ -318,7 +316,7 @@ static int omap_hsmmc_set_power(struct device *dev, int slot, int power_on, return 0; if (mmc_pdata(host)->before_set_reg) - mmc_pdata(host)->before_set_reg(dev, slot, power_on, vdd); + mmc_pdata(host)->before_set_reg(dev, power_on, vdd); if (host->pbias) { if (host->pbias_enabled == 1) { @@ -381,7 +379,7 @@ static int omap_hsmmc_set_power(struct device *dev, int slot, int power_on, } if (mmc_pdata(host)->after_set_reg) - mmc_pdata(host)->after_set_reg(dev, slot, power_on, vdd); + mmc_pdata(host)->after_set_reg(dev, power_on, vdd); error_set_power: return ret; @@ -431,8 +429,8 @@ static int omap_hsmmc_reg_get(struct omap_hsmmc_host *host) (host->vcc_aux && regulator_is_enabled(host->vcc_aux))) { int vdd = ffs(mmc_pdata(host)->ocr_mask) - 1; - mmc_pdata(host)->set_power(host->dev, host->slot_id, 1, vdd); - mmc_pdata(host)->set_power(host->dev, host->slot_id, 0, 0); + mmc_pdata(host)->set_power(host->dev, 1, vdd); + mmc_pdata(host)->set_power(host->dev, 0, 0); } return 0; @@ -813,7 +811,7 @@ int omap_hsmmc_cover_is_closed(struct omap_hsmmc_host *host) int r = 1; if (host->get_cover_state) - r = host->get_cover_state(host->dev, host->slot_id); + r = host->get_cover_state(host->dev); return r; } @@ -1231,12 +1229,11 @@ static int omap_hsmmc_switch_opcond(struct omap_hsmmc_host *host, int vdd) clk_disable_unprepare(host->dbclk); /* Turn the power off */ - ret = mmc_pdata(host)->set_power(host->dev, host->slot_id, 0, 0); + ret = mmc_pdata(host)->set_power(host->dev, 0, 0); /* Turn the power ON with given VDD 1.8 or 3.0v */ if (!ret) - ret = mmc_pdata(host)->set_power(host->dev, host->slot_id, 1, - vdd); + ret = mmc_pdata(host)->set_power(host->dev, 1, vdd); pm_runtime_get_sync(host->dev); if (host->dbclk) clk_prepare_enable(host->dbclk); @@ -1284,7 +1281,7 @@ static void omap_hsmmc_protect_card(struct omap_hsmmc_host *host) return; host->reqs_blocked = 0; - if (host->get_cover_state(host->dev, host->slot_id)) { + if (host->get_cover_state(host->dev)) { if (host->protect_card) { dev_info(host->dev, "%s: cover is closed, " "card is now accessible\n", @@ -1312,7 +1309,7 @@ static irqreturn_t omap_hsmmc_detect(int irq, void *dev_id) sysfs_notify(&host->mmc->class_dev.kobj, NULL, "cover_switch"); if (host->card_detect) - carddetect = host->card_detect(host->dev, host->slot_id); + carddetect = host->card_detect(host->dev); else { omap_hsmmc_protect_card(host); carddetect = -ENOSYS; @@ -1638,12 +1635,10 @@ static void omap_hsmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) if (ios->power_mode != host->power_mode) { switch (ios->power_mode) { case MMC_POWER_OFF: - mmc_pdata(host)->set_power(host->dev, host->slot_id, - 0, 0); + mmc_pdata(host)->set_power(host->dev, 0, 0); break; case MMC_POWER_UP: - mmc_pdata(host)->set_power(host->dev, host->slot_id, - 1, ios->vdd); + mmc_pdata(host)->set_power(host->dev, 1, ios->vdd); break; case MMC_POWER_ON: do_send_init_stream = 1; @@ -1690,7 +1685,7 @@ static int omap_hsmmc_get_cd(struct mmc_host *mmc) if (!host->card_detect) return -ENOSYS; - return host->card_detect(host->dev, host->slot_id); + return host->card_detect(host->dev); } static int omap_hsmmc_get_ro(struct mmc_host *mmc) @@ -1699,7 +1694,7 @@ static int omap_hsmmc_get_ro(struct mmc_host *mmc) if (!host->get_ro) return -ENOSYS; - return host->get_ro(host->dev, 0); + return host->get_ro(host->dev); } static void omap_hsmmc_init_card(struct mmc_host *mmc, struct mmc_card *card) @@ -1996,8 +1991,6 @@ static struct omap_hsmmc_platform_data *of_get_hsmmc_pdata(struct device *dev) if (of_find_property(np, "ti,dual-volt", NULL)) pdata->controller_flags |= OMAP_HSMMC_SUPPORTS_DUAL_VOLT; - /* This driver only supports 1 slot */ - pdata->nr_slots = 1; pdata->switch_pin = cd_gpio; pdata->gpio_wp = wp_gpio; @@ -2068,11 +2061,6 @@ static int omap_hsmmc_probe(struct platform_device *pdev) return -ENXIO; } - if (pdata->nr_slots == 0) { - dev_err(&pdev->dev, "No Slots\n"); - return -ENXIO; - } - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); irq = platform_get_irq(pdev, 0); if (res == NULL || irq < 0) @@ -2095,7 +2083,6 @@ static int omap_hsmmc_probe(struct platform_device *pdev) host->use_dma = 1; host->dma_ch = -1; host->irq = irq; - host->slot_id = 0; host->mapbase = res->start + pdata->reg_offset; host->base = base + pdata->reg_offset; host->power_mode = MMC_POWER_OFF; @@ -2338,7 +2325,7 @@ static int omap_hsmmc_prepare(struct device *dev) struct omap_hsmmc_host *host = dev_get_drvdata(dev); if (host->suspend) - return host->suspend(dev, host->slot_id); + return host->suspend(dev); return 0; } @@ -2348,7 +2335,7 @@ static void omap_hsmmc_complete(struct device *dev) struct omap_hsmmc_host *host = dev_get_drvdata(dev); if (host->resume) - host->resume(dev, host->slot_id); + host->resume(dev); } diff --git a/include/linux/platform_data/hsmmc-omap.h b/include/linux/platform_data/hsmmc-omap.h index 68ffec14b56a..67bbcf0785f6 100644 --- a/include/linux/platform_data/hsmmc-omap.h +++ b/include/linux/platform_data/hsmmc-omap.h @@ -38,9 +38,6 @@ struct omap_hsmmc_platform_data { /* back-link to device */ struct device *dev; - /* number of slots per controller */ - unsigned nr_slots:2; - /* set if your board has components or wiring that limits the * maximum frequency on the MMC bus */ unsigned int max_freq; @@ -79,15 +76,12 @@ struct omap_hsmmc_platform_data { int switch_pin; /* gpio (card detect) */ int gpio_wp; /* gpio (write protect) */ - int (*set_power)(struct device *dev, int slot, - int power_on, int vdd); - void (*remux)(struct device *dev, int slot, int power_on); + int (*set_power)(struct device *dev, int power_on, int vdd); + void (*remux)(struct device *dev, int power_on); /* Call back before enabling / disabling regulators */ - void (*before_set_reg)(struct device *dev, int slot, - int power_on, int vdd); + void (*before_set_reg)(struct device *dev, int power_on, int vdd); /* Call back after enabling / disabling regulators */ - void (*after_set_reg)(struct device *dev, int slot, - int power_on, int vdd); + void (*after_set_reg)(struct device *dev, int power_on, int vdd); /* if we have special card, init it using this callback */ void (*init_card)(struct mmc_card *card); -- cgit v1.2.3 From 767562348b72cb2612f5991ad35a5c0448254939 Mon Sep 17 00:00:00 2001 From: Addy Ke Date: Tue, 4 Nov 2014 22:03:09 +0800 Subject: mmc: dw_mmc: add support for the other bit of sdio interrupt The bit of sdio interrupt is 16 in designware implementation, but it is 24 on Rockchip SoCs.This patch add sdio_id0 for the number of slot0 in the SDIO interrupt registers. Signed-off-by: Addy Ke Reviewed-by: Doug Anderson Acked-by: Jaehoon Chung Signed-off-by: Ulf Hansson --- drivers/mmc/host/dw_mmc-rockchip.c | 10 ++++++++++ drivers/mmc/host/dw_mmc.c | 12 +++++++----- drivers/mmc/host/dw_mmc.h | 2 ++ include/linux/mmc/dw_mmc.h | 3 +++ 4 files changed, 22 insertions(+), 5 deletions(-) (limited to 'include/linux') diff --git a/drivers/mmc/host/dw_mmc-rockchip.c b/drivers/mmc/host/dw_mmc-rockchip.c index bbb4ec386e56..5650ac488cf3 100644 --- a/drivers/mmc/host/dw_mmc-rockchip.c +++ b/drivers/mmc/host/dw_mmc-rockchip.c @@ -68,14 +68,24 @@ static void dw_mci_rk3288_set_ios(struct dw_mci *host, struct mmc_ios *ios) } } +static int dw_mci_rockchip_init(struct dw_mci *host) +{ + /* It is slot 8 on Rockchip SoCs */ + host->sdio_id0 = 8; + + return 0; +} + static const struct dw_mci_drv_data rk2928_drv_data = { .prepare_command = dw_mci_rockchip_prepare_command, + .init = dw_mci_rockchip_init, }; static const struct dw_mci_drv_data rk3288_drv_data = { .prepare_command = dw_mci_rockchip_prepare_command, .set_ios = dw_mci_rk3288_set_ios, .setup_clock = dw_mci_rk3288_setup_clock, + .init = dw_mci_rockchip_init, }; static const struct of_device_id dw_mci_rockchip_match[] = { diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index 5a37c33879a1..b4c30448566e 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -919,7 +919,7 @@ static void dw_mci_setup_bus(struct dw_mci_slot *slot, bool force_clkinit) /* enable clock; only low power if no SDIO */ clk_en_a = SDMMC_CLKEN_ENABLE << slot->id; - if (!(mci_readl(host, INTMASK) & SDMMC_INT_SDIO(slot->id))) + if (!(mci_readl(host, INTMASK) & SDMMC_INT_SDIO(slot->sdio_id))) clk_en_a |= SDMMC_CLKEN_LOW_PWR << slot->id; mci_writel(host, CLKENA, clk_en_a); @@ -1280,10 +1280,10 @@ static void dw_mci_enable_sdio_irq(struct mmc_host *mmc, int enb) dw_mci_disable_low_power(slot); mci_writel(host, INTMASK, - (int_mask | SDMMC_INT_SDIO(slot->id))); + (int_mask | SDMMC_INT_SDIO(slot->sdio_id))); } else { mci_writel(host, INTMASK, - (int_mask & ~SDMMC_INT_SDIO(slot->id))); + (int_mask & ~SDMMC_INT_SDIO(slot->sdio_id))); } } @@ -2152,8 +2152,9 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id) /* Handle SDIO Interrupts */ for (i = 0; i < host->num_slots; i++) { struct dw_mci_slot *slot = host->slot[i]; - if (pending & SDMMC_INT_SDIO(i)) { - mci_writel(host, RINTSTS, SDMMC_INT_SDIO(i)); + if (pending & SDMMC_INT_SDIO(slot->sdio_id)) { + mci_writel(host, RINTSTS, + SDMMC_INT_SDIO(slot->sdio_id)); mmc_signal_sdio_irq(slot->mmc); } } @@ -2252,6 +2253,7 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id) slot = mmc_priv(mmc); slot->id = id; + slot->sdio_id = host->sdio_id0 + id; slot->mmc = mmc; slot->host = host; host->slot[id] = slot; diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h index 58d8a54d644b..0d0f7a271d63 100644 --- a/drivers/mmc/host/dw_mmc.h +++ b/drivers/mmc/host/dw_mmc.h @@ -225,6 +225,7 @@ extern int dw_mci_resume(struct dw_mci *host); * with CONFIG_MMC_CLKGATE. * @flags: Random state bits associated with the slot. * @id: Number of this slot. + * @sdio_id: Number of this slot in the SDIO interrupt registers. */ struct dw_mci_slot { struct mmc_host *mmc; @@ -244,6 +245,7 @@ struct dw_mci_slot { #define DW_MMC_CARD_PRESENT 0 #define DW_MMC_CARD_NEED_INIT 1 int id; + int sdio_id; }; struct dw_mci_tuning_data { diff --git a/include/linux/mmc/dw_mmc.h b/include/linux/mmc/dw_mmc.h index 0a551152d600..42b724e8d503 100644 --- a/include/linux/mmc/dw_mmc.h +++ b/include/linux/mmc/dw_mmc.h @@ -97,6 +97,7 @@ struct mmc_data; * @quirks: Set of quirks that apply to specific versions of the IP. * @irq_flags: The flags to be passed to request_irq. * @irq: The irq value to be passed to request_irq. + * @sdio_id0: Number of slot0 in the SDIO interrupt registers. * * Locking * ======= @@ -193,6 +194,8 @@ struct dw_mci { bool vqmmc_enabled; unsigned long irq_flags; /* IRQ flags */ int irq; + + int sdio_id0; }; /* DMA ops for Internal/External DMAC interface */ -- cgit v1.2.3 From 996903de92f0c7a32d8c83f37d7ebcea0def8660 Mon Sep 17 00:00:00 2001 From: Minda Chen Date: Wed, 26 Nov 2014 13:05:33 +0800 Subject: mmc: core: add core-level function for sending tuning commands According to the SD card spec, Add a manual tuning command function for SDR104/HS200. Sending command 19 or command 21 to read data and compare with the tunning block pattern. This patch will help to decrease some platform private codes in SDHCI platform_execute_tuning() callbacks. Signed-off-by: Minda Chen Signed-off-by: Barry Song Signed-off-by: Ulf Hansson --- drivers/mmc/core/mmc_ops.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++ include/linux/mmc/core.h | 1 + 2 files changed, 71 insertions(+) (limited to 'include/linux') diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c index 23aa3a380f27..12b2a32df346 100644 --- a/drivers/mmc/core/mmc_ops.c +++ b/drivers/mmc/core/mmc_ops.c @@ -547,6 +547,76 @@ int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, } EXPORT_SYMBOL_GPL(mmc_switch); +int mmc_send_tuning(struct mmc_card *card) +{ + struct mmc_request mrq = {NULL}; + struct mmc_command cmd = {0}; + struct mmc_data data = {0}; + struct scatterlist sg; + struct mmc_host *mmc = card->host; + struct mmc_ios *ios = &mmc->ios; + const u8 *tuning_block_pattern; + int size, err = 0; + u8 *data_buf; + u32 opcode; + + if (ios->bus_width == MMC_BUS_WIDTH_8) { + tuning_block_pattern = tuning_blk_pattern_8bit; + size = sizeof(tuning_blk_pattern_8bit); + opcode = MMC_SEND_TUNING_BLOCK_HS200; + } else if (ios->bus_width == MMC_BUS_WIDTH_4) { + tuning_block_pattern = tuning_blk_pattern_4bit; + size = sizeof(tuning_blk_pattern_4bit); + opcode = MMC_SEND_TUNING_BLOCK; + } else + return -EINVAL; + + data_buf = kzalloc(size, GFP_KERNEL); + if (!data_buf) + return -ENOMEM; + + mrq.cmd = &cmd; + mrq.data = &data; + + cmd.opcode = opcode; + cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; + + data.blksz = size; + data.blocks = 1; + data.flags = MMC_DATA_READ; + + /* + * According to the tuning specs, Tuning process + * is normally shorter 40 executions of CMD19, + * and timeout value should be shorter than 150 ms + */ + data.timeout_ns = 150 * NSEC_PER_MSEC; + + data.sg = &sg; + data.sg_len = 1; + sg_init_one(&sg, data_buf, size); + + mmc_wait_for_req(mmc, &mrq); + + if (cmd.error) { + err = cmd.error; + goto out; + } + + if (data.error) { + err = data.error; + goto out; + } + + if (memcmp(data_buf, tuning_block_pattern, size)) + err = -EIO; + +out: + kfree(data_buf); + return err; +} +EXPORT_SYMBOL_GPL(mmc_send_tuning); + static int mmc_send_bus_test(struct mmc_card *card, struct mmc_host *host, u8 opcode, u8 len) diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h index b11e43c10631..c4bdaa128693 100644 --- a/include/linux/mmc/core.h +++ b/include/linux/mmc/core.h @@ -154,6 +154,7 @@ extern void mmc_start_bkops(struct mmc_card *card, bool from_exception); extern int __mmc_switch(struct mmc_card *, u8, u8, u8, unsigned int, bool, bool, bool); extern int mmc_switch(struct mmc_card *, u8, u8, u8, unsigned int); +extern int mmc_send_tuning(struct mmc_card *card); extern int mmc_get_ext_csd(struct mmc_card *card, u8 **new_ext_csd); #define MMC_ERASE_ARG 0x00000000 -- cgit v1.2.3 From 87e1e0f29f703e91c54e81f05d831432ec659dde Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Mon, 10 Nov 2014 14:43:52 +0100 Subject: regulator: Add mode mapping function to struct regulator_desc The "regulator-initial-mode" and "regulator-mode" DT properties allows to configure the regulator operating modes at startup or when a system enters into a susend state. But these properties use as valid values the operating modes supported by each device while the core deals with the standard operating modes. So a mapping function is needed to translate from the hardware specific modes to the standard ones. This mapping is a non-varying configuration for each regulator, so add a function pointer to struct regulator_desc that will allow drivers to define their callback to do the modes translation. Signed-off-by: Javier Martinez Canillas Signed-off-by: Mark Brown --- include/linux/regulator/driver.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'include/linux') diff --git a/include/linux/regulator/driver.h b/include/linux/regulator/driver.h index fc0ee0ce8325..73dd073afef5 100644 --- a/include/linux/regulator/driver.h +++ b/include/linux/regulator/driver.h @@ -243,6 +243,8 @@ enum regulator_type { * * @enable_time: Time taken for initial enable of regulator (in uS). * @off_on_delay: guard time (in uS), before re-enabling a regulator + * + * @of_map_mode: Maps a hardware mode defined in a DeviceTree to a standard mode */ struct regulator_desc { const char *name; @@ -285,6 +287,8 @@ struct regulator_desc { unsigned int enable_time; unsigned int off_on_delay; + + unsigned int (*of_map_mode)(unsigned int mode); }; /** -- cgit v1.2.3 From 072e78b12bf5182a3e2e460388214a291023ef1c Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Mon, 10 Nov 2014 14:43:53 +0100 Subject: regulator: of: Add regulator desc param to of_get_regulator_init_data() The of_get_regulator_init_data() function is used to extract the regulator init_data but information on how to extract certain data is defined in the static regulator descriptor (e.g: how to map the hardware operating modes). Add a const struct regulator_desc * parameter to the function signature so the parsing logic could use the information in the struct regulator_desc. of_get_regulator_init_data() relies on of_get_regulation_constraints() to actually extract the init_data so it has to pass the struct regulator_desc but that is modified on a later patch. Signed-off-by: Javier Martinez Canillas Signed-off-by: Mark Brown --- drivers/regulator/88pm8607.c | 3 ++- drivers/regulator/anatop-regulator.c | 5 ++-- drivers/regulator/arizona-ldo1.c | 8 +++--- drivers/regulator/arizona-micsupp.c | 8 +++--- drivers/regulator/da9052-regulator.c | 3 ++- drivers/regulator/da9210-regulator.c | 2 +- drivers/regulator/fan53555.c | 17 ++++++------ drivers/regulator/fixed.c | 19 +++++++------ drivers/regulator/gpio-regulator.c | 18 +++++++------ drivers/regulator/max8952.c | 2 +- drivers/regulator/max8973-regulator.c | 3 ++- drivers/regulator/max8997.c | 3 ++- drivers/regulator/max8998.c | 5 ++-- drivers/regulator/mc13xxx-regulator-core.c | 3 ++- drivers/regulator/of_regulator.c | 9 ++++--- drivers/regulator/pwm-regulator.c | 3 ++- drivers/regulator/qcom_rpm-regulator.c | 9 ++++--- drivers/regulator/s5m8767.c | 3 ++- drivers/regulator/sky81452-regulator.c | 2 +- drivers/regulator/stw481x-vmmc.c | 3 ++- drivers/regulator/ti-abb-regulator.c | 3 ++- drivers/regulator/tps51632-regulator.c | 43 ++++++++++++++++-------------- drivers/regulator/tps62360-regulator.c | 31 +++++++++++---------- drivers/regulator/tps65218-regulator.c | 3 ++- drivers/regulator/twl-regulator.c | 3 ++- drivers/regulator/vexpress.c | 3 ++- include/linux/regulator/of_regulator.h | 8 ++++-- 27 files changed, 130 insertions(+), 92 deletions(-) (limited to 'include/linux') diff --git a/drivers/regulator/88pm8607.c b/drivers/regulator/88pm8607.c index 6d77dcd7dcf6..3fe47bd66153 100644 --- a/drivers/regulator/88pm8607.c +++ b/drivers/regulator/88pm8607.c @@ -330,7 +330,8 @@ static int pm8607_regulator_dt_init(struct platform_device *pdev, for_each_child_of_node(nproot, np) { if (!of_node_cmp(np->name, info->desc.name)) { config->init_data = - of_get_regulator_init_data(&pdev->dev, np); + of_get_regulator_init_data(&pdev->dev, np, + &info->desc); config->of_node = np; break; } diff --git a/drivers/regulator/anatop-regulator.c b/drivers/regulator/anatop-regulator.c index 4f730af70e7c..6eaef9f64420 100644 --- a/drivers/regulator/anatop-regulator.c +++ b/drivers/regulator/anatop-regulator.c @@ -189,17 +189,18 @@ static int anatop_regulator_probe(struct platform_device *pdev) int ret = 0; u32 val; - initdata = of_get_regulator_init_data(dev, np); sreg = devm_kzalloc(dev, sizeof(*sreg), GFP_KERNEL); if (!sreg) return -ENOMEM; - sreg->initdata = initdata; sreg->name = of_get_property(np, "regulator-name", NULL); rdesc = &sreg->rdesc; rdesc->name = sreg->name; rdesc->type = REGULATOR_VOLTAGE; rdesc->owner = THIS_MODULE; + initdata = of_get_regulator_init_data(dev, np, rdesc); + sreg->initdata = initdata; + anatop_np = of_get_parent(np); if (!anatop_np) return -ENODEV; diff --git a/drivers/regulator/arizona-ldo1.c b/drivers/regulator/arizona-ldo1.c index 4c9db589f6c1..b1eea7f76489 100644 --- a/drivers/regulator/arizona-ldo1.c +++ b/drivers/regulator/arizona-ldo1.c @@ -179,7 +179,8 @@ static const struct regulator_init_data arizona_ldo1_default = { }; static int arizona_ldo1_of_get_pdata(struct arizona *arizona, - struct regulator_config *config) + struct regulator_config *config, + const struct regulator_desc *desc) { struct arizona_pdata *pdata = &arizona->pdata; struct arizona_ldo1 *ldo1 = config->driver_data; @@ -194,7 +195,8 @@ static int arizona_ldo1_of_get_pdata(struct arizona *arizona, if (init_node) { config->of_node = init_node; - init_data = of_get_regulator_init_data(arizona->dev, init_node); + init_data = of_get_regulator_init_data(arizona->dev, init_node, + desc); if (init_data) { init_data->consumer_supplies = &ldo1->supply; @@ -257,7 +259,7 @@ static int arizona_ldo1_probe(struct platform_device *pdev) if (IS_ENABLED(CONFIG_OF)) { if (!dev_get_platdata(arizona->dev)) { - ret = arizona_ldo1_of_get_pdata(arizona, &config); + ret = arizona_ldo1_of_get_pdata(arizona, &config, desc); if (ret < 0) return ret; } diff --git a/drivers/regulator/arizona-micsupp.c b/drivers/regulator/arizona-micsupp.c index ce9aca5f8ee7..c313ef4c3a2f 100644 --- a/drivers/regulator/arizona-micsupp.c +++ b/drivers/regulator/arizona-micsupp.c @@ -198,7 +198,8 @@ static const struct regulator_init_data arizona_micsupp_ext_default = { }; static int arizona_micsupp_of_get_pdata(struct arizona *arizona, - struct regulator_config *config) + struct regulator_config *config, + const struct regulator_desc *desc) { struct arizona_pdata *pdata = &arizona->pdata; struct arizona_micsupp *micsupp = config->driver_data; @@ -210,7 +211,7 @@ static int arizona_micsupp_of_get_pdata(struct arizona *arizona, if (np) { config->of_node = np; - init_data = of_get_regulator_init_data(arizona->dev, np); + init_data = of_get_regulator_init_data(arizona->dev, np, desc); if (init_data) { init_data->consumer_supplies = &micsupp->supply; @@ -264,7 +265,8 @@ static int arizona_micsupp_probe(struct platform_device *pdev) if (IS_ENABLED(CONFIG_OF)) { if (!dev_get_platdata(arizona->dev)) { - ret = arizona_micsupp_of_get_pdata(arizona, &config); + ret = arizona_micsupp_of_get_pdata(arizona, &config, + desc); if (ret < 0) return ret; } diff --git a/drivers/regulator/da9052-regulator.c b/drivers/regulator/da9052-regulator.c index 00033625a09c..3945f1006d23 100644 --- a/drivers/regulator/da9052-regulator.c +++ b/drivers/regulator/da9052-regulator.c @@ -436,7 +436,8 @@ static int da9052_regulator_probe(struct platform_device *pdev) if (!of_node_cmp(np->name, regulator->info->reg_desc.name)) { config.init_data = of_get_regulator_init_data( - &pdev->dev, np); + &pdev->dev, np, + ®ulator->info->reg_desc); config.of_node = np; break; } diff --git a/drivers/regulator/da9210-regulator.c b/drivers/regulator/da9210-regulator.c index 7a320dd11c46..bc6100103f7f 100644 --- a/drivers/regulator/da9210-regulator.c +++ b/drivers/regulator/da9210-regulator.c @@ -147,7 +147,7 @@ static int da9210_i2c_probe(struct i2c_client *i2c, config.dev = &i2c->dev; config.init_data = pdata ? &pdata->da9210_constraints : - of_get_regulator_init_data(dev, dev->of_node); + of_get_regulator_init_data(dev, dev->of_node, &da9210_reg); config.driver_data = chip; config.regmap = chip->regmap; config.of_node = dev->of_node; diff --git a/drivers/regulator/fan53555.c b/drivers/regulator/fan53555.c index f8e4257aef92..6c43ab2d5121 100644 --- a/drivers/regulator/fan53555.c +++ b/drivers/regulator/fan53555.c @@ -302,7 +302,8 @@ static struct regmap_config fan53555_regmap_config = { }; static struct fan53555_platform_data *fan53555_parse_dt(struct device *dev, - struct device_node *np) + struct device_node *np, + const struct regulator_desc *desc) { struct fan53555_platform_data *pdata; int ret; @@ -312,7 +313,7 @@ static struct fan53555_platform_data *fan53555_parse_dt(struct device *dev, if (!pdata) return NULL; - pdata->regulator = of_get_regulator_init_data(dev, np); + pdata->regulator = of_get_regulator_init_data(dev, np, desc); ret = of_property_read_u32(np, "fcs,suspend-voltage-selector", &tmp); @@ -347,20 +348,20 @@ static int fan53555_regulator_probe(struct i2c_client *client, unsigned int val; int ret; + di = devm_kzalloc(&client->dev, sizeof(struct fan53555_device_info), + GFP_KERNEL); + if (!di) + return -ENOMEM; + pdata = dev_get_platdata(&client->dev); if (!pdata) - pdata = fan53555_parse_dt(&client->dev, np); + pdata = fan53555_parse_dt(&client->dev, np, &di->desc); if (!pdata || !pdata->regulator) { dev_err(&client->dev, "Platform data not found!\n"); return -ENODEV; } - di = devm_kzalloc(&client->dev, sizeof(struct fan53555_device_info), - GFP_KERNEL); - if (!di) - return -ENOMEM; - di->regulator = pdata->regulator; if (client->dev.of_node) { const struct of_device_id *match; diff --git a/drivers/regulator/fixed.c b/drivers/regulator/fixed.c index 354105eff1f8..6cfcbc8b6594 100644 --- a/drivers/regulator/fixed.c +++ b/drivers/regulator/fixed.c @@ -40,13 +40,15 @@ struct fixed_voltage_data { /** * of_get_fixed_voltage_config - extract fixed_voltage_config structure info * @dev: device requesting for fixed_voltage_config + * @desc: regulator description * * Populates fixed_voltage_config structure by extracting data from device * tree node, returns a pointer to the populated structure of NULL if memory * alloc fails. */ static struct fixed_voltage_config * -of_get_fixed_voltage_config(struct device *dev) +of_get_fixed_voltage_config(struct device *dev, + const struct regulator_desc *desc) { struct fixed_voltage_config *config; struct device_node *np = dev->of_node; @@ -57,7 +59,7 @@ of_get_fixed_voltage_config(struct device *dev) if (!config) return ERR_PTR(-ENOMEM); - config->init_data = of_get_regulator_init_data(dev, dev->of_node); + config->init_data = of_get_regulator_init_data(dev, dev->of_node, desc); if (!config->init_data) return ERR_PTR(-EINVAL); @@ -112,8 +114,14 @@ static int reg_fixed_voltage_probe(struct platform_device *pdev) struct regulator_config cfg = { }; int ret; + drvdata = devm_kzalloc(&pdev->dev, sizeof(struct fixed_voltage_data), + GFP_KERNEL); + if (!drvdata) + return -ENOMEM; + if (pdev->dev.of_node) { - config = of_get_fixed_voltage_config(&pdev->dev); + config = of_get_fixed_voltage_config(&pdev->dev, + &drvdata->desc); if (IS_ERR(config)) return PTR_ERR(config); } else { @@ -123,11 +131,6 @@ static int reg_fixed_voltage_probe(struct platform_device *pdev) if (!config) return -ENOMEM; - drvdata = devm_kzalloc(&pdev->dev, sizeof(struct fixed_voltage_data), - GFP_KERNEL); - if (!drvdata) - return -ENOMEM; - drvdata->desc.name = devm_kstrdup(&pdev->dev, config->supply_name, GFP_KERNEL); diff --git a/drivers/regulator/gpio-regulator.c b/drivers/regulator/gpio-regulator.c index 989b23b377c0..5c3bcae478b9 100644 --- a/drivers/regulator/gpio-regulator.c +++ b/drivers/regulator/gpio-regulator.c @@ -133,7 +133,8 @@ static struct regulator_ops gpio_regulator_voltage_ops = { }; static struct gpio_regulator_config * -of_get_gpio_regulator_config(struct device *dev, struct device_node *np) +of_get_gpio_regulator_config(struct device *dev, struct device_node *np, + const struct regulator_desc *desc) { struct gpio_regulator_config *config; const char *regtype; @@ -146,7 +147,7 @@ of_get_gpio_regulator_config(struct device *dev, struct device_node *np) if (!config) return ERR_PTR(-ENOMEM); - config->init_data = of_get_regulator_init_data(dev, np); + config->init_data = of_get_regulator_init_data(dev, np, desc); if (!config->init_data) return ERR_PTR(-EINVAL); @@ -243,17 +244,18 @@ static int gpio_regulator_probe(struct platform_device *pdev) struct regulator_config cfg = { }; int ptr, ret, state; - if (np) { - config = of_get_gpio_regulator_config(&pdev->dev, np); - if (IS_ERR(config)) - return PTR_ERR(config); - } - drvdata = devm_kzalloc(&pdev->dev, sizeof(struct gpio_regulator_data), GFP_KERNEL); if (drvdata == NULL) return -ENOMEM; + if (np) { + config = of_get_gpio_regulator_config(&pdev->dev, np, + &drvdata->desc); + if (IS_ERR(config)) + return PTR_ERR(config); + } + drvdata->desc.name = kstrdup(config->supply_name, GFP_KERNEL); if (drvdata->desc.name == NULL) { dev_err(&pdev->dev, "Failed to allocate supply name\n"); diff --git a/drivers/regulator/max8952.c b/drivers/regulator/max8952.c index f7f9efcfedb7..6e54d786b22c 100644 --- a/drivers/regulator/max8952.c +++ b/drivers/regulator/max8952.c @@ -174,7 +174,7 @@ static struct max8952_platform_data *max8952_parse_dt(struct device *dev) if (of_property_read_u32(np, "max8952,ramp-speed", &pd->ramp_speed)) dev_warn(dev, "max8952,ramp-speed property not specified, defaulting to 32mV/us\n"); - pd->reg_data = of_get_regulator_init_data(dev, np); + pd->reg_data = of_get_regulator_init_data(dev, np, ®ulator); if (!pd->reg_data) { dev_err(dev, "Failed to parse regulator init data\n"); return NULL; diff --git a/drivers/regulator/max8973-regulator.c b/drivers/regulator/max8973-regulator.c index dbedf1768db0..c3d55c2db593 100644 --- a/drivers/regulator/max8973-regulator.c +++ b/drivers/regulator/max8973-regulator.c @@ -458,7 +458,8 @@ static int max8973_probe(struct i2c_client *client, config.dev = &client->dev; config.init_data = pdata ? pdata->reg_init_data : - of_get_regulator_init_data(&client->dev, client->dev.of_node); + of_get_regulator_init_data(&client->dev, client->dev.of_node, + &max->desc); config.driver_data = max; config.of_node = client->dev.of_node; config.regmap = max->regmap; diff --git a/drivers/regulator/max8997.c b/drivers/regulator/max8997.c index 9c31e215a521..726fde1d883e 100644 --- a/drivers/regulator/max8997.c +++ b/drivers/regulator/max8997.c @@ -953,7 +953,8 @@ static int max8997_pmic_dt_parse_pdata(struct platform_device *pdev, rdata->id = i; rdata->initdata = of_get_regulator_init_data(&pdev->dev, - reg_np); + reg_np, + ®ulators[i]); rdata->reg_node = reg_np; rdata++; } diff --git a/drivers/regulator/max8998.c b/drivers/regulator/max8998.c index 961091b46557..59e34a05a4a2 100644 --- a/drivers/regulator/max8998.c +++ b/drivers/regulator/max8998.c @@ -686,8 +686,9 @@ static int max8998_pmic_dt_parse_pdata(struct max8998_dev *iodev, continue; rdata->id = regulators[i].id; - rdata->initdata = of_get_regulator_init_data( - iodev->dev, reg_np); + rdata->initdata = of_get_regulator_init_data(iodev->dev, + reg_np, + ®ulators[i]); rdata->reg_node = reg_np; ++rdata; } diff --git a/drivers/regulator/mc13xxx-regulator-core.c b/drivers/regulator/mc13xxx-regulator-core.c index afba024953e1..0281c31ae2ed 100644 --- a/drivers/regulator/mc13xxx-regulator-core.c +++ b/drivers/regulator/mc13xxx-regulator-core.c @@ -194,7 +194,8 @@ struct mc13xxx_regulator_init_data *mc13xxx_parse_regulators_dt( regulators[i].desc.name)) { p->id = i; p->init_data = of_get_regulator_init_data( - &pdev->dev, child); + &pdev->dev, child, + ®ulators[i].desc); p->node = child; p++; diff --git a/drivers/regulator/of_regulator.c b/drivers/regulator/of_regulator.c index 50be70878d2d..3687a1c38c1c 100644 --- a/drivers/regulator/of_regulator.c +++ b/drivers/regulator/of_regulator.c @@ -120,13 +120,16 @@ static void of_get_regulation_constraints(struct device_node *np, /** * of_get_regulator_init_data - extract regulator_init_data structure info * @dev: device requesting for regulator_init_data + * @node: regulator device node + * @desc: regulator description * * Populates regulator_init_data structure by extracting data from device * tree node, returns a pointer to the populated struture or NULL if memory * alloc fails. */ struct regulator_init_data *of_get_regulator_init_data(struct device *dev, - struct device_node *node) + struct device_node *node, + const struct regulator_desc *desc) { struct regulator_init_data *init_data; @@ -218,7 +221,7 @@ int of_regulator_match(struct device *dev, struct device_node *node, continue; match->init_data = - of_get_regulator_init_data(dev, child); + of_get_regulator_init_data(dev, child, NULL); if (!match->init_data) { dev_err(dev, "failed to parse DT for regulator %s\n", @@ -265,7 +268,7 @@ struct regulator_init_data *regulator_of_get_init_data(struct device *dev, if (strcmp(desc->of_match, name)) continue; - init_data = of_get_regulator_init_data(dev, child); + init_data = of_get_regulator_init_data(dev, child, desc); if (!init_data) { dev_err(dev, "failed to parse DT for regulator %s\n", diff --git a/drivers/regulator/pwm-regulator.c b/drivers/regulator/pwm-regulator.c index d3f55eaea058..91f34ca3a9ac 100644 --- a/drivers/regulator/pwm-regulator.c +++ b/drivers/regulator/pwm-regulator.c @@ -149,7 +149,8 @@ static int pwm_regulator_probe(struct platform_device *pdev) return ret; } - config.init_data = of_get_regulator_init_data(&pdev->dev, np); + config.init_data = of_get_regulator_init_data(&pdev->dev, np, + &drvdata->desc); if (!config.init_data) return -ENOMEM; diff --git a/drivers/regulator/qcom_rpm-regulator.c b/drivers/regulator/qcom_rpm-regulator.c index b55cd5b50ebe..dabd28a359dc 100644 --- a/drivers/regulator/qcom_rpm-regulator.c +++ b/drivers/regulator/qcom_rpm-regulator.c @@ -643,10 +643,6 @@ static int rpm_reg_probe(struct platform_device *pdev) match = of_match_device(rpm_of_match, &pdev->dev); template = match->data; - initdata = of_get_regulator_init_data(&pdev->dev, pdev->dev.of_node); - if (!initdata) - return -EINVAL; - vreg = devm_kmalloc(&pdev->dev, sizeof(*vreg), GFP_KERNEL); if (!vreg) { dev_err(&pdev->dev, "failed to allocate vreg\n"); @@ -666,6 +662,11 @@ static int rpm_reg_probe(struct platform_device *pdev) return -ENODEV; } + initdata = of_get_regulator_init_data(&pdev->dev, pdev->dev.of_node, + &vreg->desc); + if (!initdata) + return -EINVAL; + key = "reg"; ret = of_property_read_u32(pdev->dev.of_node, key, &val); if (ret) { diff --git a/drivers/regulator/s5m8767.c b/drivers/regulator/s5m8767.c index 0ab5cbeeb797..26932fe42b47 100644 --- a/drivers/regulator/s5m8767.c +++ b/drivers/regulator/s5m8767.c @@ -581,7 +581,8 @@ static int s5m8767_pmic_dt_parse_pdata(struct platform_device *pdev, rdata->id = i; rdata->initdata = of_get_regulator_init_data( - &pdev->dev, reg_np); + &pdev->dev, reg_np, + ®ulators[i]); rdata->reg_node = reg_np; rdata++; rmode->id = i; diff --git a/drivers/regulator/sky81452-regulator.c b/drivers/regulator/sky81452-regulator.c index 97aff0ccd65f..75deae706f84 100644 --- a/drivers/regulator/sky81452-regulator.c +++ b/drivers/regulator/sky81452-regulator.c @@ -76,7 +76,7 @@ static struct regulator_init_data *sky81452_reg_parse_dt(struct device *dev) return NULL; } - init_data = of_get_regulator_init_data(dev, np); + init_data = of_get_regulator_init_data(dev, np, &sky81452_reg); of_node_put(np); return init_data; diff --git a/drivers/regulator/stw481x-vmmc.c b/drivers/regulator/stw481x-vmmc.c index a7e152696a02..b4f1696456a7 100644 --- a/drivers/regulator/stw481x-vmmc.c +++ b/drivers/regulator/stw481x-vmmc.c @@ -72,7 +72,8 @@ static int stw481x_vmmc_regulator_probe(struct platform_device *pdev) config.regmap = stw481x->map; config.of_node = pdev->dev.of_node; config.init_data = of_get_regulator_init_data(&pdev->dev, - pdev->dev.of_node); + pdev->dev.of_node, + &vmmc_regulator); stw481x->vmmc_regulator = devm_regulator_register(&pdev->dev, &vmmc_regulator, &config); diff --git a/drivers/regulator/ti-abb-regulator.c b/drivers/regulator/ti-abb-regulator.c index a2dabb575b97..1ef5aba96f17 100644 --- a/drivers/regulator/ti-abb-regulator.c +++ b/drivers/regulator/ti-abb-regulator.c @@ -837,7 +837,8 @@ skip_opt: return -EINVAL; } - initdata = of_get_regulator_init_data(dev, pdev->dev.of_node); + initdata = of_get_regulator_init_data(dev, pdev->dev.of_node, + &abb->rdesc); if (!initdata) { dev_err(dev, "%s: Unable to alloc regulator init data\n", __func__); diff --git a/drivers/regulator/tps51632-regulator.c b/drivers/regulator/tps51632-regulator.c index f31f22e3e1bd..c213e37eb69e 100644 --- a/drivers/regulator/tps51632-regulator.c +++ b/drivers/regulator/tps51632-regulator.c @@ -221,7 +221,8 @@ static const struct of_device_id tps51632_of_match[] = { MODULE_DEVICE_TABLE(of, tps51632_of_match); static struct tps51632_regulator_platform_data * - of_get_tps51632_platform_data(struct device *dev) + of_get_tps51632_platform_data(struct device *dev, + const struct regulator_desc *desc) { struct tps51632_regulator_platform_data *pdata; struct device_node *np = dev->of_node; @@ -230,7 +231,8 @@ static struct tps51632_regulator_platform_data * if (!pdata) return NULL; - pdata->reg_init_data = of_get_regulator_init_data(dev, dev->of_node); + pdata->reg_init_data = of_get_regulator_init_data(dev, dev->of_node, + desc); if (!pdata->reg_init_data) { dev_err(dev, "Not able to get OF regulator init data\n"); return NULL; @@ -248,7 +250,8 @@ static struct tps51632_regulator_platform_data * } #else static struct tps51632_regulator_platform_data * - of_get_tps51632_platform_data(struct device *dev) + of_get_tps51632_platform_data(struct device *dev, + const struct regulator_desc *desc) { return NULL; } @@ -273,9 +276,25 @@ static int tps51632_probe(struct i2c_client *client, } } + tps = devm_kzalloc(&client->dev, sizeof(*tps), GFP_KERNEL); + if (!tps) + return -ENOMEM; + + tps->dev = &client->dev; + tps->desc.name = client->name; + tps->desc.id = 0; + tps->desc.ramp_delay = TPS51632_DEFAULT_RAMP_DELAY; + tps->desc.min_uV = TPS51632_MIN_VOLTAGE; + tps->desc.uV_step = TPS51632_VOLTAGE_STEP_10mV; + tps->desc.linear_min_sel = TPS51632_MIN_VSEL; + tps->desc.n_voltages = TPS51632_MAX_VSEL + 1; + tps->desc.ops = &tps51632_dcdc_ops; + tps->desc.type = REGULATOR_VOLTAGE; + tps->desc.owner = THIS_MODULE; + pdata = dev_get_platdata(&client->dev); if (!pdata && client->dev.of_node) - pdata = of_get_tps51632_platform_data(&client->dev); + pdata = of_get_tps51632_platform_data(&client->dev, &tps->desc); if (!pdata) { dev_err(&client->dev, "No Platform data\n"); return -EINVAL; @@ -296,22 +315,6 @@ static int tps51632_probe(struct i2c_client *client, } } - tps = devm_kzalloc(&client->dev, sizeof(*tps), GFP_KERNEL); - if (!tps) - return -ENOMEM; - - tps->dev = &client->dev; - tps->desc.name = client->name; - tps->desc.id = 0; - tps->desc.ramp_delay = TPS51632_DEFAULT_RAMP_DELAY; - tps->desc.min_uV = TPS51632_MIN_VOLTAGE; - tps->desc.uV_step = TPS51632_VOLTAGE_STEP_10mV; - tps->desc.linear_min_sel = TPS51632_MIN_VSEL; - tps->desc.n_voltages = TPS51632_MAX_VSEL + 1; - tps->desc.ops = &tps51632_dcdc_ops; - tps->desc.type = REGULATOR_VOLTAGE; - tps->desc.owner = THIS_MODULE; - if (pdata->enable_pwm_dvfs) tps->desc.vsel_reg = TPS51632_VOLTAGE_BASE_REG; else diff --git a/drivers/regulator/tps62360-regulator.c b/drivers/regulator/tps62360-regulator.c index a1672044e519..a1fd626c6c96 100644 --- a/drivers/regulator/tps62360-regulator.c +++ b/drivers/regulator/tps62360-regulator.c @@ -293,7 +293,8 @@ static const struct regmap_config tps62360_regmap_config = { }; static struct tps62360_regulator_platform_data * - of_get_tps62360_platform_data(struct device *dev) + of_get_tps62360_platform_data(struct device *dev, + const struct regulator_desc *desc) { struct tps62360_regulator_platform_data *pdata; struct device_node *np = dev->of_node; @@ -302,7 +303,8 @@ static struct tps62360_regulator_platform_data * if (!pdata) return NULL; - pdata->reg_init_data = of_get_regulator_init_data(dev, dev->of_node); + pdata->reg_init_data = of_get_regulator_init_data(dev, dev->of_node, + desc); if (!pdata->reg_init_data) { dev_err(dev, "Not able to get OF regulator init data\n"); return NULL; @@ -350,6 +352,17 @@ static int tps62360_probe(struct i2c_client *client, pdata = dev_get_platdata(&client->dev); + tps = devm_kzalloc(&client->dev, sizeof(*tps), GFP_KERNEL); + if (!tps) + return -ENOMEM; + + tps->desc.name = client->name; + tps->desc.id = 0; + tps->desc.ops = &tps62360_dcdc_ops; + tps->desc.type = REGULATOR_VOLTAGE; + tps->desc.owner = THIS_MODULE; + tps->desc.uV_step = 10000; + if (client->dev.of_node) { const struct of_device_id *match; match = of_match_device(of_match_ptr(tps62360_of_match), @@ -360,7 +373,8 @@ static int tps62360_probe(struct i2c_client *client, } chip_id = (int)(long)match->data; if (!pdata) - pdata = of_get_tps62360_platform_data(&client->dev); + pdata = of_get_tps62360_platform_data(&client->dev, + &tps->desc); } else if (id) { chip_id = id->driver_data; } else { @@ -374,10 +388,6 @@ static int tps62360_probe(struct i2c_client *client, return -EIO; } - tps = devm_kzalloc(&client->dev, sizeof(*tps), GFP_KERNEL); - if (!tps) - return -ENOMEM; - tps->en_discharge = pdata->en_discharge; tps->en_internal_pulldn = pdata->en_internal_pulldn; tps->vsel0_gpio = pdata->vsel0_gpio; @@ -401,13 +411,6 @@ static int tps62360_probe(struct i2c_client *client, return -ENODEV; } - tps->desc.name = client->name; - tps->desc.id = 0; - tps->desc.ops = &tps62360_dcdc_ops; - tps->desc.type = REGULATOR_VOLTAGE; - tps->desc.owner = THIS_MODULE; - tps->desc.uV_step = 10000; - tps->regmap = devm_regmap_init_i2c(client, &tps62360_regmap_config); if (IS_ERR(tps->regmap)) { ret = PTR_ERR(tps->regmap); diff --git a/drivers/regulator/tps65218-regulator.c b/drivers/regulator/tps65218-regulator.c index f0a40281b9c1..263cc85d6202 100644 --- a/drivers/regulator/tps65218-regulator.c +++ b/drivers/regulator/tps65218-regulator.c @@ -231,7 +231,8 @@ static int tps65218_regulator_probe(struct platform_device *pdev) template = match->data; id = template->id; - init_data = of_get_regulator_init_data(&pdev->dev, pdev->dev.of_node); + init_data = of_get_regulator_init_data(&pdev->dev, pdev->dev.of_node, + ®ulators[id]); platform_set_drvdata(pdev, tps); diff --git a/drivers/regulator/twl-regulator.c b/drivers/regulator/twl-regulator.c index 0b4f8660fdb4..dd727bca1983 100644 --- a/drivers/regulator/twl-regulator.c +++ b/drivers/regulator/twl-regulator.c @@ -1104,7 +1104,8 @@ static int twlreg_probe(struct platform_device *pdev) template = match->data; id = template->desc.id; initdata = of_get_regulator_init_data(&pdev->dev, - pdev->dev.of_node); + pdev->dev.of_node, + &template->desc); drvdata = NULL; } else { id = pdev->id; diff --git a/drivers/regulator/vexpress.c b/drivers/regulator/vexpress.c index 02e7267ccf92..5e7c789023a9 100644 --- a/drivers/regulator/vexpress.c +++ b/drivers/regulator/vexpress.c @@ -74,7 +74,8 @@ static int vexpress_regulator_probe(struct platform_device *pdev) reg->desc.owner = THIS_MODULE; reg->desc.continuous_voltage_range = true; - init_data = of_get_regulator_init_data(&pdev->dev, pdev->dev.of_node); + init_data = of_get_regulator_init_data(&pdev->dev, pdev->dev.of_node, + ®->desc); if (!init_data) return -EINVAL; diff --git a/include/linux/regulator/of_regulator.h b/include/linux/regulator/of_regulator.h index f9217965aaa3..8d1d136c0fb9 100644 --- a/include/linux/regulator/of_regulator.h +++ b/include/linux/regulator/of_regulator.h @@ -6,6 +6,8 @@ #ifndef __LINUX_OF_REG_H #define __LINUX_OF_REG_H +struct regulator_desc; + struct of_regulator_match { const char *name; void *driver_data; @@ -16,14 +18,16 @@ struct of_regulator_match { #if defined(CONFIG_OF) extern struct regulator_init_data *of_get_regulator_init_data(struct device *dev, - struct device_node *node); + struct device_node *node, + const struct regulator_desc *desc); extern int of_regulator_match(struct device *dev, struct device_node *node, struct of_regulator_match *matches, unsigned int num_matches); #else static inline struct regulator_init_data *of_get_regulator_init_data(struct device *dev, - struct device_node *node) + struct device_node *node, + const struct regulator_desc *desc) { return NULL; } -- cgit v1.2.3 From 75d6b2faf79cbe9086e831351d5d9085f1852928 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Mon, 10 Nov 2014 14:43:54 +0100 Subject: regulator: of: Pass the regulator description in the match table Drivers can use the of_regulator_match() function to parse the regulator init_data from DT. A match table is used to specify the name of the node containing the regulators, the device node and to return the init_data to the caller. But also the static regulator descriptor is needed to correctly extract some DT properties like the regulator initial and suspend modes. Use the match table to pass that information. Signed-off-by: Javier Martinez Canillas Signed-off-by: Mark Brown --- drivers/regulator/of_regulator.c | 3 ++- include/linux/regulator/of_regulator.h | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'include/linux') diff --git a/drivers/regulator/of_regulator.c b/drivers/regulator/of_regulator.c index 3687a1c38c1c..64c09a37ac7f 100644 --- a/drivers/regulator/of_regulator.c +++ b/drivers/regulator/of_regulator.c @@ -221,7 +221,8 @@ int of_regulator_match(struct device *dev, struct device_node *node, continue; match->init_data = - of_get_regulator_init_data(dev, child, NULL); + of_get_regulator_init_data(dev, child, + match->desc); if (!match->init_data) { dev_err(dev, "failed to parse DT for regulator %s\n", diff --git a/include/linux/regulator/of_regulator.h b/include/linux/regulator/of_regulator.h index 8d1d136c0fb9..763953f7e3b8 100644 --- a/include/linux/regulator/of_regulator.h +++ b/include/linux/regulator/of_regulator.h @@ -13,6 +13,7 @@ struct of_regulator_match { void *driver_data; struct regulator_init_data *init_data; struct device_node *of_node; + const struct regulator_desc *desc; }; #if defined(CONFIG_OF) -- cgit v1.2.3 From 81cc3f868d30884c6f2d2bf5d1861fbeb24ddebd Mon Sep 17 00:00:00 2001 From: Pawel Moll Date: Tue, 25 Nov 2014 18:17:34 +0000 Subject: ARM: vexpress: Remove non-DT code Now, with the CLCD DT support available, there is no more reason to keep the non-DT support for V2P-CA9. Removed, together with "some" supporting code. It was necessary to make PLAT_VERSATILE_SCHED_CLOCK optional and selected by the machines still interested in it. Acked-by: Mike Turquette Signed-off-by: Pawel Moll Signed-off-by: Arnd Bergmann --- arch/arm/Kconfig | 2 + arch/arm/mach-vexpress/Kconfig | 3 - arch/arm/mach-vexpress/Makefile | 3 +- arch/arm/mach-vexpress/core.h | 7 - arch/arm/mach-vexpress/ct-ca9x4.c | 212 ------------ arch/arm/mach-vexpress/include/mach/ct-ca9x4.h | 47 --- arch/arm/mach-vexpress/include/mach/hardware.h | 1 - arch/arm/mach-vexpress/include/mach/irqs.h | 6 - arch/arm/mach-vexpress/include/mach/motherboard.h | 88 ----- arch/arm/mach-vexpress/platsmp.c | 42 --- arch/arm/mach-vexpress/v2m.c | 374 ---------------------- arch/arm/plat-versatile/Kconfig | 2 +- drivers/clk/versatile/Makefile | 1 - drivers/clk/versatile/clk-vexpress-osc.c | 7 - drivers/clk/versatile/clk-vexpress.c | 86 ----- drivers/misc/vexpress-syscfg.c | 60 +--- include/linux/vexpress.h | 19 -- 17 files changed, 17 insertions(+), 943 deletions(-) delete mode 100644 arch/arm/mach-vexpress/ct-ca9x4.c delete mode 100644 arch/arm/mach-vexpress/include/mach/ct-ca9x4.h delete mode 100644 arch/arm/mach-vexpress/include/mach/hardware.h delete mode 100644 arch/arm/mach-vexpress/include/mach/irqs.h delete mode 100644 arch/arm/mach-vexpress/include/mach/motherboard.h delete mode 100644 drivers/clk/versatile/clk-vexpress.c (limited to 'include/linux') diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 89c4b5ccc68d..6c6fdb8a36e1 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -350,6 +350,7 @@ config ARCH_REALVIEW select ICST select NEED_MACH_MEMORY_H select PLAT_VERSATILE + select PLAT_VERSATILE_SCHED_CLOCK help This enables support for ARM Ltd RealView boards. @@ -365,6 +366,7 @@ config ARCH_VERSATILE select ICST select PLAT_VERSATILE select PLAT_VERSATILE_CLOCK + select PLAT_VERSATILE_SCHED_CLOCK select VERSATILE_FPGA_IRQ help This enables support for ARM Ltd Versatile board. diff --git a/arch/arm/mach-vexpress/Kconfig b/arch/arm/mach-vexpress/Kconfig index b2cfba16c4e8..9a96bab12ef3 100644 --- a/arch/arm/mach-vexpress/Kconfig +++ b/arch/arm/mach-vexpress/Kconfig @@ -49,9 +49,6 @@ config ARCH_VEXPRESS_CORTEX_A5_A9_ERRATA build a working kernel, you must also enable relevant core tile support or Flattened Device Tree based support options. -config ARCH_VEXPRESS_CA9X4 - bool "Versatile Express Cortex-A9x4 tile" - config ARCH_VEXPRESS_DCSCB bool "Dual Cluster System Control Block (DCSCB) support" depends on MCPM diff --git a/arch/arm/mach-vexpress/Makefile b/arch/arm/mach-vexpress/Makefile index fc649bc09d0c..f5c1006dd6a1 100644 --- a/arch/arm/mach-vexpress/Makefile +++ b/arch/arm/mach-vexpress/Makefile @@ -1,11 +1,10 @@ # # Makefile for the linux kernel. # -ccflags-$(CONFIG_ARCH_MULTIPLATFORM) := -I$(srctree)/$(src)/include \ +ccflags-$(CONFIG_ARCH_MULTIPLATFORM) := \ -I$(srctree)/arch/arm/plat-versatile/include obj-y := v2m.o -obj-$(CONFIG_ARCH_VEXPRESS_CA9X4) += ct-ca9x4.o obj-$(CONFIG_ARCH_VEXPRESS_DCSCB) += dcscb.o dcscb_setup.o CFLAGS_dcscb.o += -march=armv7-a CFLAGS_REMOVE_dcscb.o = -pg diff --git a/arch/arm/mach-vexpress/core.h b/arch/arm/mach-vexpress/core.h index 152fad91b3ae..2a11d3ac8c68 100644 --- a/arch/arm/mach-vexpress/core.h +++ b/arch/arm/mach-vexpress/core.h @@ -1,12 +1,5 @@ -/* 2MB large area for motherboard's peripherals static mapping */ -#define V2M_PERIPH 0xf8000000 - -/* Tile's peripherals static mappings should start here */ -#define V2T_PERIPH 0xf8200000 - bool vexpress_smp_init_ops(void); -extern struct smp_operations vexpress_smp_ops; extern struct smp_operations vexpress_smp_dt_ops; extern void vexpress_cpu_die(unsigned int cpu); diff --git a/arch/arm/mach-vexpress/ct-ca9x4.c b/arch/arm/mach-vexpress/ct-ca9x4.c deleted file mode 100644 index 27bea049380a..000000000000 --- a/arch/arm/mach-vexpress/ct-ca9x4.c +++ /dev/null @@ -1,212 +0,0 @@ -/* - * Versatile Express Core Tile Cortex A9x4 Support - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include - -#include - -#include -#include - -#include "core.h" - -#include -#include - -static struct map_desc ct_ca9x4_io_desc[] __initdata = { - { - .virtual = V2T_PERIPH, - .pfn = __phys_to_pfn(CT_CA9X4_MPIC), - .length = SZ_8K, - .type = MT_DEVICE, - }, -}; - -static void __init ct_ca9x4_map_io(void) -{ - iotable_init(ct_ca9x4_io_desc, ARRAY_SIZE(ct_ca9x4_io_desc)); -} - -static void __init ca9x4_l2_init(void) -{ -#ifdef CONFIG_CACHE_L2X0 - void __iomem *l2x0_base = ioremap(CT_CA9X4_L2CC, SZ_4K); - - if (l2x0_base) { - /* set RAM latencies to 1 cycle for this core tile. */ - writel(0, l2x0_base + L310_TAG_LATENCY_CTRL); - writel(0, l2x0_base + L310_DATA_LATENCY_CTRL); - - l2x0_init(l2x0_base, 0x00400000, 0xfe0fffff); - } else { - pr_err("L2C: unable to map L2 cache controller\n"); - } -#endif -} - -#ifdef CONFIG_HAVE_ARM_TWD -static DEFINE_TWD_LOCAL_TIMER(twd_local_timer, A9_MPCORE_TWD, IRQ_LOCALTIMER); - -static void __init ca9x4_twd_init(void) -{ - int err = twd_local_timer_register(&twd_local_timer); - if (err) - pr_err("twd_local_timer_register failed %d\n", err); -} -#else -#define ca9x4_twd_init() do {} while(0) -#endif - -static void __init ct_ca9x4_init_irq(void) -{ - gic_init(0, 29, ioremap(A9_MPCORE_GIC_DIST, SZ_4K), - ioremap(A9_MPCORE_GIC_CPU, SZ_256)); - ca9x4_twd_init(); - ca9x4_l2_init(); -} - -static int ct_ca9x4_clcd_setup(struct clcd_fb *fb) -{ - unsigned long framesize = 1024 * 768 * 2; - - fb->panel = versatile_clcd_get_panel("XVGA"); - if (!fb->panel) - return -EINVAL; - - return versatile_clcd_setup_dma(fb, framesize); -} - -static struct clcd_board ct_ca9x4_clcd_data = { - .name = "CT-CA9X4", - .caps = CLCD_CAP_5551 | CLCD_CAP_565, - .check = clcdfb_check, - .decode = clcdfb_decode, - .setup = ct_ca9x4_clcd_setup, - .mmap = versatile_clcd_mmap_dma, - .remove = versatile_clcd_remove_dma, -}; - -static AMBA_AHB_DEVICE(clcd, "ct:clcd", 0, CT_CA9X4_CLCDC, IRQ_CT_CA9X4_CLCDC, &ct_ca9x4_clcd_data); -static AMBA_APB_DEVICE(dmc, "ct:dmc", 0, CT_CA9X4_DMC, IRQ_CT_CA9X4_DMC, NULL); -static AMBA_APB_DEVICE(smc, "ct:smc", 0, CT_CA9X4_SMC, IRQ_CT_CA9X4_SMC, NULL); -static AMBA_APB_DEVICE(gpio, "ct:gpio", 0, CT_CA9X4_GPIO, IRQ_CT_CA9X4_GPIO, NULL); - -static struct amba_device *ct_ca9x4_amba_devs[] __initdata = { - &clcd_device, - &dmc_device, - &smc_device, - &gpio_device, -}; - -static struct resource pmu_resources[] = { - [0] = { - .start = IRQ_CT_CA9X4_PMU_CPU0, - .end = IRQ_CT_CA9X4_PMU_CPU0, - .flags = IORESOURCE_IRQ, - }, - [1] = { - .start = IRQ_CT_CA9X4_PMU_CPU1, - .end = IRQ_CT_CA9X4_PMU_CPU1, - .flags = IORESOURCE_IRQ, - }, - [2] = { - .start = IRQ_CT_CA9X4_PMU_CPU2, - .end = IRQ_CT_CA9X4_PMU_CPU2, - .flags = IORESOURCE_IRQ, - }, - [3] = { - .start = IRQ_CT_CA9X4_PMU_CPU3, - .end = IRQ_CT_CA9X4_PMU_CPU3, - .flags = IORESOURCE_IRQ, - }, -}; - -static struct platform_device pmu_device = { - .name = "arm-pmu", - .id = -1, - .num_resources = ARRAY_SIZE(pmu_resources), - .resource = pmu_resources, -}; - -static struct clk_lookup osc1_lookup = { - .dev_id = "ct:clcd", -}; - -static struct platform_device osc1_device = { - .name = "vexpress-osc", - .id = 1, - .num_resources = 1, - .resource = (struct resource []) { - VEXPRESS_RES_FUNC(0xf, 1), - }, - .dev.platform_data = &osc1_lookup, -}; - -static void __init ct_ca9x4_init(void) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(ct_ca9x4_amba_devs); i++) - amba_device_register(ct_ca9x4_amba_devs[i], &iomem_resource); - - platform_device_register(&pmu_device); - vexpress_syscfg_device_register(&osc1_device); -} - -#ifdef CONFIG_SMP -static void *ct_ca9x4_scu_base __initdata; - -static void __init ct_ca9x4_init_cpu_map(void) -{ - int i, ncores; - - ct_ca9x4_scu_base = ioremap(A9_MPCORE_SCU, SZ_128); - if (WARN_ON(!ct_ca9x4_scu_base)) - return; - - ncores = scu_get_core_count(ct_ca9x4_scu_base); - - if (ncores > nr_cpu_ids) { - pr_warn("SMP: %u cores greater than maximum (%u), clipping\n", - ncores, nr_cpu_ids); - ncores = nr_cpu_ids; - } - - for (i = 0; i < ncores; ++i) - set_cpu_possible(i, true); -} - -static void __init ct_ca9x4_smp_enable(unsigned int max_cpus) -{ - scu_enable(ct_ca9x4_scu_base); -} -#endif - -struct ct_desc ct_ca9x4_desc __initdata = { - .id = V2M_CT_ID_CA9, - .name = "CA9x4", - .map_io = ct_ca9x4_map_io, - .init_irq = ct_ca9x4_init_irq, - .init_tile = ct_ca9x4_init, -#ifdef CONFIG_SMP - .init_cpu_map = ct_ca9x4_init_cpu_map, - .smp_enable = ct_ca9x4_smp_enable, -#endif -}; diff --git a/arch/arm/mach-vexpress/include/mach/ct-ca9x4.h b/arch/arm/mach-vexpress/include/mach/ct-ca9x4.h deleted file mode 100644 index 84acf8439d4b..000000000000 --- a/arch/arm/mach-vexpress/include/mach/ct-ca9x4.h +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef __MACH_CT_CA9X4_H -#define __MACH_CT_CA9X4_H - -/* - * Physical base addresses - */ -#define CT_CA9X4_CLCDC (0x10020000) -#define CT_CA9X4_AXIRAM (0x10060000) -#define CT_CA9X4_DMC (0x100e0000) -#define CT_CA9X4_SMC (0x100e1000) -#define CT_CA9X4_SCC (0x100e2000) -#define CT_CA9X4_SP804_TIMER (0x100e4000) -#define CT_CA9X4_SP805_WDT (0x100e5000) -#define CT_CA9X4_TZPC (0x100e6000) -#define CT_CA9X4_GPIO (0x100e8000) -#define CT_CA9X4_FASTAXI (0x100e9000) -#define CT_CA9X4_SLOWAXI (0x100ea000) -#define CT_CA9X4_TZASC (0x100ec000) -#define CT_CA9X4_CORESIGHT (0x10200000) -#define CT_CA9X4_MPIC (0x1e000000) -#define CT_CA9X4_SYSTIMER (0x1e004000) -#define CT_CA9X4_SYSWDT (0x1e007000) -#define CT_CA9X4_L2CC (0x1e00a000) - -#define A9_MPCORE_SCU (CT_CA9X4_MPIC + 0x0000) -#define A9_MPCORE_GIC_CPU (CT_CA9X4_MPIC + 0x0100) -#define A9_MPCORE_GIT (CT_CA9X4_MPIC + 0x0200) -#define A9_MPCORE_TWD (CT_CA9X4_MPIC + 0x0600) -#define A9_MPCORE_GIC_DIST (CT_CA9X4_MPIC + 0x1000) - -/* - * Interrupts. Those in {} are for AMBA devices - */ -#define IRQ_CT_CA9X4_CLCDC { 76 } -#define IRQ_CT_CA9X4_DMC { 0 } -#define IRQ_CT_CA9X4_SMC { 77, 78 } -#define IRQ_CT_CA9X4_TIMER0 80 -#define IRQ_CT_CA9X4_TIMER1 81 -#define IRQ_CT_CA9X4_GPIO { 82 } -#define IRQ_CT_CA9X4_PMU_CPU0 92 -#define IRQ_CT_CA9X4_PMU_CPU1 93 -#define IRQ_CT_CA9X4_PMU_CPU2 94 -#define IRQ_CT_CA9X4_PMU_CPU3 95 - -extern struct ct_desc ct_ca9x4_desc; - -#endif diff --git a/arch/arm/mach-vexpress/include/mach/hardware.h b/arch/arm/mach-vexpress/include/mach/hardware.h deleted file mode 100644 index 40a8c178f10d..000000000000 --- a/arch/arm/mach-vexpress/include/mach/hardware.h +++ /dev/null @@ -1 +0,0 @@ -/* empty */ diff --git a/arch/arm/mach-vexpress/include/mach/irqs.h b/arch/arm/mach-vexpress/include/mach/irqs.h deleted file mode 100644 index f8f7f782eb55..000000000000 --- a/arch/arm/mach-vexpress/include/mach/irqs.h +++ /dev/null @@ -1,6 +0,0 @@ -#define IRQ_LOCALTIMER 29 -#define IRQ_LOCALWDOG 30 - -#ifndef CONFIG_SPARSE_IRQ -#define NR_IRQS 256 -#endif diff --git a/arch/arm/mach-vexpress/include/mach/motherboard.h b/arch/arm/mach-vexpress/include/mach/motherboard.h deleted file mode 100644 index 68abc8b72781..000000000000 --- a/arch/arm/mach-vexpress/include/mach/motherboard.h +++ /dev/null @@ -1,88 +0,0 @@ -#ifndef __MACH_MOTHERBOARD_H -#define __MACH_MOTHERBOARD_H - -/* - * Physical addresses, offset from V2M_PA_CS0-3 - */ -#define V2M_NOR0 (V2M_PA_CS0) -#define V2M_NOR1 (V2M_PA_CS1) -#define V2M_SRAM (V2M_PA_CS2) -#define V2M_VIDEO_SRAM (V2M_PA_CS3 + 0x00000000) -#define V2M_LAN9118 (V2M_PA_CS3 + 0x02000000) -#define V2M_ISP1761 (V2M_PA_CS3 + 0x03000000) - -/* - * Physical addresses, offset from V2M_PA_CS7 - */ -#define V2M_SYSREGS (V2M_PA_CS7 + 0x00000000) -#define V2M_SYSCTL (V2M_PA_CS7 + 0x00001000) -#define V2M_SERIAL_BUS_PCI (V2M_PA_CS7 + 0x00002000) - -#define V2M_AACI (V2M_PA_CS7 + 0x00004000) -#define V2M_MMCI (V2M_PA_CS7 + 0x00005000) -#define V2M_KMI0 (V2M_PA_CS7 + 0x00006000) -#define V2M_KMI1 (V2M_PA_CS7 + 0x00007000) - -#define V2M_UART0 (V2M_PA_CS7 + 0x00009000) -#define V2M_UART1 (V2M_PA_CS7 + 0x0000a000) -#define V2M_UART2 (V2M_PA_CS7 + 0x0000b000) -#define V2M_UART3 (V2M_PA_CS7 + 0x0000c000) - -#define V2M_WDT (V2M_PA_CS7 + 0x0000f000) - -#define V2M_TIMER01 (V2M_PA_CS7 + 0x00011000) -#define V2M_TIMER23 (V2M_PA_CS7 + 0x00012000) - -#define V2M_SERIAL_BUS_DVI (V2M_PA_CS7 + 0x00016000) -#define V2M_RTC (V2M_PA_CS7 + 0x00017000) - -#define V2M_CF (V2M_PA_CS7 + 0x0001a000) -#define V2M_CLCD (V2M_PA_CS7 + 0x0001f000) - - -/* - * Interrupts. Those in {} are for AMBA devices - */ -#define IRQ_V2M_WDT { (32 + 0) } -#define IRQ_V2M_TIMER0 (32 + 2) -#define IRQ_V2M_TIMER1 (32 + 2) -#define IRQ_V2M_TIMER2 (32 + 3) -#define IRQ_V2M_TIMER3 (32 + 3) -#define IRQ_V2M_RTC { (32 + 4) } -#define IRQ_V2M_UART0 { (32 + 5) } -#define IRQ_V2M_UART1 { (32 + 6) } -#define IRQ_V2M_UART2 { (32 + 7) } -#define IRQ_V2M_UART3 { (32 + 8) } -#define IRQ_V2M_MMCI { (32 + 9), (32 + 10) } -#define IRQ_V2M_AACI { (32 + 11) } -#define IRQ_V2M_KMI0 { (32 + 12) } -#define IRQ_V2M_KMI1 { (32 + 13) } -#define IRQ_V2M_CLCD { (32 + 14) } -#define IRQ_V2M_LAN9118 (32 + 15) -#define IRQ_V2M_ISP1761 (32 + 16) -#define IRQ_V2M_PCIE (32 + 17) - - -/* - * Core tile IDs - */ -#define V2M_CT_ID_CA9 0x0c000191 -#define V2M_CT_ID_UNSUPPORTED 0xff000191 -#define V2M_CT_ID_MASK 0xff000fff - -struct ct_desc { - u32 id; - const char *name; - void (*map_io)(void); - void (*init_early)(void); - void (*init_irq)(void); - void (*init_tile)(void); -#ifdef CONFIG_SMP - void (*init_cpu_map)(void); - void (*smp_enable)(unsigned int); -#endif -}; - -extern struct ct_desc *ct_desc; - -#endif diff --git a/arch/arm/mach-vexpress/platsmp.c b/arch/arm/mach-vexpress/platsmp.c index a1f3804fd5a5..83188cf1875d 100644 --- a/arch/arm/mach-vexpress/platsmp.c +++ b/arch/arm/mach-vexpress/platsmp.c @@ -19,48 +19,10 @@ #include #include -#include - #include #include "core.h" -/* - * Initialise the CPU possible map early - this describes the CPUs - * which may be present or become present in the system. - */ -static void __init vexpress_smp_init_cpus(void) -{ - ct_desc->init_cpu_map(); -} - -static void __init vexpress_smp_prepare_cpus(unsigned int max_cpus) -{ - /* - * Initialise the present map, which describes the set of CPUs - * actually populated at the present time. - */ - ct_desc->smp_enable(max_cpus); - - /* - * Write the address of secondary startup into the - * system-wide flags register. The boot monitor waits - * until it receives a soft interrupt, and then the - * secondary CPU branches to this address. - */ - vexpress_flags_set(virt_to_phys(versatile_secondary_startup)); -} - -struct smp_operations __initdata vexpress_smp_ops = { - .smp_init_cpus = vexpress_smp_init_cpus, - .smp_prepare_cpus = vexpress_smp_prepare_cpus, - .smp_secondary_init = versatile_secondary_init, - .smp_boot_secondary = versatile_boot_secondary, -#ifdef CONFIG_HOTPLUG_CPU - .cpu_die = vexpress_cpu_die, -#endif -}; - bool __init vexpress_smp_init_ops(void) { #ifdef CONFIG_MCPM @@ -79,8 +41,6 @@ bool __init vexpress_smp_init_ops(void) return false; } -#if defined(CONFIG_OF) - static const struct of_device_id vexpress_smp_dt_scu_match[] __initconst = { { .compatible = "arm,cortex-a5-scu", }, { .compatible = "arm,cortex-a9-scu", }, @@ -112,5 +72,3 @@ struct smp_operations __initdata vexpress_smp_dt_ops = { .cpu_die = vexpress_cpu_die, #endif }; - -#endif diff --git a/arch/arm/mach-vexpress/v2m.c b/arch/arm/mach-vexpress/v2m.c index 6ff681a24ba7..a0400f4cca89 100644 --- a/arch/arm/mach-vexpress/v2m.c +++ b/arch/arm/mach-vexpress/v2m.c @@ -1,380 +1,7 @@ -/* - * Versatile Express V2M Motherboard Support - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include #include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include #include "core.h" -#define V2M_PA_CS0 0x40000000 -#define V2M_PA_CS1 0x44000000 -#define V2M_PA_CS2 0x48000000 -#define V2M_PA_CS3 0x4c000000 -#define V2M_PA_CS7 0x10000000 - -static struct map_desc v2m_io_desc[] __initdata = { - { - .virtual = V2M_PERIPH, - .pfn = __phys_to_pfn(V2M_PA_CS7), - .length = SZ_128K, - .type = MT_DEVICE, - }, -}; - -static void __init v2m_sp804_init(void __iomem *base, unsigned int irq) -{ - if (WARN_ON(!base || irq == NO_IRQ)) - return; - - sp804_clocksource_init(base + TIMER_2_BASE, "v2m-timer1"); - sp804_clockevents_init(base + TIMER_1_BASE, irq, "v2m-timer0"); -} - - -static struct resource v2m_pcie_i2c_resource = { - .start = V2M_SERIAL_BUS_PCI, - .end = V2M_SERIAL_BUS_PCI + SZ_4K - 1, - .flags = IORESOURCE_MEM, -}; - -static struct platform_device v2m_pcie_i2c_device = { - .name = "versatile-i2c", - .id = 0, - .num_resources = 1, - .resource = &v2m_pcie_i2c_resource, -}; - -static struct resource v2m_ddc_i2c_resource = { - .start = V2M_SERIAL_BUS_DVI, - .end = V2M_SERIAL_BUS_DVI + SZ_4K - 1, - .flags = IORESOURCE_MEM, -}; - -static struct platform_device v2m_ddc_i2c_device = { - .name = "versatile-i2c", - .id = 1, - .num_resources = 1, - .resource = &v2m_ddc_i2c_resource, -}; - -static struct resource v2m_eth_resources[] = { - { - .start = V2M_LAN9118, - .end = V2M_LAN9118 + SZ_64K - 1, - .flags = IORESOURCE_MEM, - }, { - .start = IRQ_V2M_LAN9118, - .end = IRQ_V2M_LAN9118, - .flags = IORESOURCE_IRQ, - }, -}; - -static struct smsc911x_platform_config v2m_eth_config = { - .flags = SMSC911X_USE_32BIT, - .irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_HIGH, - .irq_type = SMSC911X_IRQ_TYPE_PUSH_PULL, - .phy_interface = PHY_INTERFACE_MODE_MII, -}; - -static struct platform_device v2m_eth_device = { - .name = "smsc911x", - .id = -1, - .resource = v2m_eth_resources, - .num_resources = ARRAY_SIZE(v2m_eth_resources), - .dev.platform_data = &v2m_eth_config, -}; - -static struct regulator_consumer_supply v2m_eth_supplies[] = { - REGULATOR_SUPPLY("vddvario", "smsc911x"), - REGULATOR_SUPPLY("vdd33a", "smsc911x"), -}; - -static struct resource v2m_usb_resources[] = { - { - .start = V2M_ISP1761, - .end = V2M_ISP1761 + SZ_128K - 1, - .flags = IORESOURCE_MEM, - }, { - .start = IRQ_V2M_ISP1761, - .end = IRQ_V2M_ISP1761, - .flags = IORESOURCE_IRQ, - }, -}; - -static struct isp1760_platform_data v2m_usb_config = { - .is_isp1761 = true, - .bus_width_16 = false, - .port1_otg = true, - .analog_oc = false, - .dack_polarity_high = false, - .dreq_polarity_high = false, -}; - -static struct platform_device v2m_usb_device = { - .name = "isp1760", - .id = -1, - .resource = v2m_usb_resources, - .num_resources = ARRAY_SIZE(v2m_usb_resources), - .dev.platform_data = &v2m_usb_config, -}; - -static struct physmap_flash_data v2m_flash_data = { - .width = 4, -}; - -static struct resource v2m_flash_resources[] = { - { - .start = V2M_NOR0, - .end = V2M_NOR0 + SZ_64M - 1, - .flags = IORESOURCE_MEM, - }, { - .start = V2M_NOR1, - .end = V2M_NOR1 + SZ_64M - 1, - .flags = IORESOURCE_MEM, - }, -}; - -static struct platform_device v2m_flash_device = { - .name = "physmap-flash", - .id = -1, - .resource = v2m_flash_resources, - .num_resources = ARRAY_SIZE(v2m_flash_resources), - .dev.platform_data = &v2m_flash_data, -}; - -static struct pata_platform_info v2m_pata_data = { - .ioport_shift = 2, -}; - -static struct resource v2m_pata_resources[] = { - { - .start = V2M_CF, - .end = V2M_CF + 0xff, - .flags = IORESOURCE_MEM, - }, { - .start = V2M_CF + 0x100, - .end = V2M_CF + SZ_4K - 1, - .flags = IORESOURCE_MEM, - }, -}; - -static struct platform_device v2m_cf_device = { - .name = "pata_platform", - .id = -1, - .resource = v2m_pata_resources, - .num_resources = ARRAY_SIZE(v2m_pata_resources), - .dev.platform_data = &v2m_pata_data, -}; - -static struct mmci_platform_data v2m_mmci_data = { - .ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34, - .status = vexpress_get_mci_cardin, - .gpio_cd = -1, - .gpio_wp = -1, -}; - -static struct resource v2m_sysreg_resources[] = { - { - .start = V2M_SYSREGS, - .end = V2M_SYSREGS + 0xfff, - .flags = IORESOURCE_MEM, - }, -}; - -static struct platform_device v2m_sysreg_device = { - .name = "vexpress-sysreg", - .id = -1, - .resource = v2m_sysreg_resources, - .num_resources = ARRAY_SIZE(v2m_sysreg_resources), -}; - -static struct platform_device v2m_muxfpga_device = { - .name = "vexpress-muxfpga", - .id = 0, - .num_resources = 1, - .resource = (struct resource []) { - VEXPRESS_RES_FUNC(0, 7), - } -}; - -static struct platform_device v2m_shutdown_device = { - .name = "vexpress-shutdown", - .id = 0, - .num_resources = 1, - .resource = (struct resource []) { - VEXPRESS_RES_FUNC(0, 8), - } -}; - -static struct platform_device v2m_reboot_device = { - .name = "vexpress-reboot", - .id = 0, - .num_resources = 1, - .resource = (struct resource []) { - VEXPRESS_RES_FUNC(0, 9), - } -}; - -static struct platform_device v2m_dvimode_device = { - .name = "vexpress-dvimode", - .id = 0, - .num_resources = 1, - .resource = (struct resource []) { - VEXPRESS_RES_FUNC(0, 11), - } -}; - -static AMBA_APB_DEVICE(aaci, "mb:aaci", 0, V2M_AACI, IRQ_V2M_AACI, NULL); -static AMBA_APB_DEVICE(mmci, "mb:mmci", 0, V2M_MMCI, IRQ_V2M_MMCI, &v2m_mmci_data); -static AMBA_APB_DEVICE(kmi0, "mb:kmi0", 0, V2M_KMI0, IRQ_V2M_KMI0, NULL); -static AMBA_APB_DEVICE(kmi1, "mb:kmi1", 0, V2M_KMI1, IRQ_V2M_KMI1, NULL); -static AMBA_APB_DEVICE(uart0, "mb:uart0", 0, V2M_UART0, IRQ_V2M_UART0, NULL); -static AMBA_APB_DEVICE(uart1, "mb:uart1", 0, V2M_UART1, IRQ_V2M_UART1, NULL); -static AMBA_APB_DEVICE(uart2, "mb:uart2", 0, V2M_UART2, IRQ_V2M_UART2, NULL); -static AMBA_APB_DEVICE(uart3, "mb:uart3", 0, V2M_UART3, IRQ_V2M_UART3, NULL); -static AMBA_APB_DEVICE(wdt, "mb:wdt", 0, V2M_WDT, IRQ_V2M_WDT, NULL); -static AMBA_APB_DEVICE(rtc, "mb:rtc", 0, V2M_RTC, IRQ_V2M_RTC, NULL); - -static struct amba_device *v2m_amba_devs[] __initdata = { - &aaci_device, - &mmci_device, - &kmi0_device, - &kmi1_device, - &uart0_device, - &uart1_device, - &uart2_device, - &uart3_device, - &wdt_device, - &rtc_device, -}; - -static void __init v2m_timer_init(void) -{ - vexpress_clk_init(ioremap(V2M_SYSCTL, SZ_4K)); - v2m_sp804_init(ioremap(V2M_TIMER01, SZ_4K), IRQ_V2M_TIMER0); -} - -static void __init v2m_init_early(void) -{ - if (ct_desc->init_early) - ct_desc->init_early(); - versatile_sched_clock_init(vexpress_get_24mhz_clock_base(), 24000000); -} - -struct ct_desc *ct_desc; - -static struct ct_desc *ct_descs[] __initdata = { -#ifdef CONFIG_ARCH_VEXPRESS_CA9X4 - &ct_ca9x4_desc, -#endif -}; - -static void __init v2m_populate_ct_desc(void) -{ - int i; - u32 current_tile_id; - - ct_desc = NULL; - current_tile_id = vexpress_get_procid(VEXPRESS_SITE_MASTER) - & V2M_CT_ID_MASK; - - for (i = 0; i < ARRAY_SIZE(ct_descs) && !ct_desc; ++i) - if (ct_descs[i]->id == current_tile_id) - ct_desc = ct_descs[i]; - - if (!ct_desc) - panic("vexpress: this kernel does not support core tile ID 0x%08x when booting via ATAGs.\n" - "You may need a device tree blob or a different kernel to boot on this board.\n", - current_tile_id); -} - -static void __init v2m_map_io(void) -{ - iotable_init(v2m_io_desc, ARRAY_SIZE(v2m_io_desc)); - vexpress_sysreg_early_init(ioremap(V2M_SYSREGS, SZ_4K)); - v2m_populate_ct_desc(); - ct_desc->map_io(); -} - -static void __init v2m_init_irq(void) -{ - ct_desc->init_irq(); -} - -static void __init v2m_init(void) -{ - int i; - - regulator_register_fixed(0, v2m_eth_supplies, - ARRAY_SIZE(v2m_eth_supplies)); - - platform_device_register(&v2m_sysreg_device); - platform_device_register(&v2m_pcie_i2c_device); - platform_device_register(&v2m_ddc_i2c_device); - platform_device_register(&v2m_flash_device); - platform_device_register(&v2m_cf_device); - platform_device_register(&v2m_eth_device); - platform_device_register(&v2m_usb_device); - - for (i = 0; i < ARRAY_SIZE(v2m_amba_devs); i++) - amba_device_register(v2m_amba_devs[i], &iomem_resource); - - vexpress_syscfg_device_register(&v2m_muxfpga_device); - vexpress_syscfg_device_register(&v2m_shutdown_device); - vexpress_syscfg_device_register(&v2m_reboot_device); - vexpress_syscfg_device_register(&v2m_dvimode_device); - - ct_desc->init_tile(); -} - -MACHINE_START(VEXPRESS, "ARM-Versatile Express") - .atag_offset = 0x100, - .smp = smp_ops(vexpress_smp_ops), - .map_io = v2m_map_io, - .init_early = v2m_init_early, - .init_irq = v2m_init_irq, - .init_time = v2m_timer_init, - .init_machine = v2m_init, -MACHINE_END - -static void __init v2m_dt_init(void) -{ - of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); -} - static const char * const v2m_dt_match[] __initconst = { "arm,vexpress", NULL, @@ -386,5 +13,4 @@ DT_MACHINE_START(VEXPRESS_DT, "ARM-Versatile Express") .l2c_aux_mask = 0xfe0fffff, .smp = smp_ops(vexpress_smp_dt_ops), .smp_init = smp_init_ops(vexpress_smp_init_ops), - .init_machine = v2m_dt_init, MACHINE_END diff --git a/arch/arm/plat-versatile/Kconfig b/arch/arm/plat-versatile/Kconfig index a301ca2c7d00..49b8ef91584a 100644 --- a/arch/arm/plat-versatile/Kconfig +++ b/arch/arm/plat-versatile/Kconfig @@ -4,6 +4,6 @@ config PLAT_VERSATILE_CLOCK bool config PLAT_VERSATILE_SCHED_CLOCK - def_bool y + bool endif diff --git a/drivers/clk/versatile/Makefile b/drivers/clk/versatile/Makefile index 162e519cb0f9..8ff03744fe98 100644 --- a/drivers/clk/versatile/Makefile +++ b/drivers/clk/versatile/Makefile @@ -2,6 +2,5 @@ obj-$(CONFIG_ICST) += clk-icst.o clk-versatile.o obj-$(CONFIG_INTEGRATOR_IMPD1) += clk-impd1.o obj-$(CONFIG_ARCH_REALVIEW) += clk-realview.o -obj-$(CONFIG_ARCH_VEXPRESS) += clk-vexpress.o obj-$(CONFIG_CLK_SP810) += clk-sp810.o obj-$(CONFIG_CLK_VEXPRESS_OSC) += clk-vexpress-osc.o diff --git a/drivers/clk/versatile/clk-vexpress-osc.c b/drivers/clk/versatile/clk-vexpress-osc.c index 529a59c0fbfa..765f1e0eeeb2 100644 --- a/drivers/clk/versatile/clk-vexpress-osc.c +++ b/drivers/clk/versatile/clk-vexpress-osc.c @@ -70,7 +70,6 @@ static struct clk_ops vexpress_osc_ops = { static int vexpress_osc_probe(struct platform_device *pdev) { - struct clk_lookup *cl = pdev->dev.platform_data; /* Non-DT lookup */ struct clk_init_data init; struct vexpress_osc *osc; struct clk *clk; @@ -106,12 +105,6 @@ static int vexpress_osc_probe(struct platform_device *pdev) of_clk_add_provider(pdev->dev.of_node, of_clk_src_simple_get, clk); - /* Only happens for non-DT cases */ - if (cl) { - cl->clk = clk; - clkdev_add(cl); - } - dev_dbg(&pdev->dev, "Registered clock '%s'\n", init.name); return 0; diff --git a/drivers/clk/versatile/clk-vexpress.c b/drivers/clk/versatile/clk-vexpress.c deleted file mode 100644 index 2d5e1b4820e0..000000000000 --- a/drivers/clk/versatile/clk-vexpress.c +++ /dev/null @@ -1,86 +0,0 @@ -/* - * 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. - * - * 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. - * - * Copyright (C) 2012 ARM Limited - */ - -#include -#include -#include -#include -#include - -static struct clk *vexpress_sp810_timerclken[4]; -static DEFINE_SPINLOCK(vexpress_sp810_lock); - -static void __init vexpress_sp810_init(void __iomem *base) -{ - int i; - - if (WARN_ON(!base)) - return; - - for (i = 0; i < ARRAY_SIZE(vexpress_sp810_timerclken); i++) { - char name[12]; - const char *parents[] = { - "v2m:refclk32khz", /* REFCLK */ - "v2m:refclk1mhz" /* TIMCLK */ - }; - - snprintf(name, ARRAY_SIZE(name), "timerclken%d", i); - - vexpress_sp810_timerclken[i] = clk_register_mux(NULL, name, - parents, 2, CLK_SET_RATE_NO_REPARENT, - base + SCCTRL, SCCTRL_TIMERENnSEL_SHIFT(i), 1, - 0, &vexpress_sp810_lock); - - if (WARN_ON(IS_ERR(vexpress_sp810_timerclken[i]))) - break; - } -} - - -static const char * const vexpress_clk_24mhz_periphs[] __initconst = { - "mb:uart0", "mb:uart1", "mb:uart2", "mb:uart3", - "mb:mmci", "mb:kmi0", "mb:kmi1" -}; - -void __init vexpress_clk_init(void __iomem *sp810_base) -{ - struct clk *clk; - int i; - - clk = clk_register_fixed_rate(NULL, "dummy_apb_pclk", NULL, - CLK_IS_ROOT, 0); - WARN_ON(clk_register_clkdev(clk, "apb_pclk", NULL)); - - clk = clk_register_fixed_rate(NULL, "v2m:clk_24mhz", NULL, - CLK_IS_ROOT, 24000000); - for (i = 0; i < ARRAY_SIZE(vexpress_clk_24mhz_periphs); i++) - WARN_ON(clk_register_clkdev(clk, NULL, - vexpress_clk_24mhz_periphs[i])); - - clk = clk_register_fixed_rate(NULL, "v2m:refclk32khz", NULL, - CLK_IS_ROOT, 32768); - WARN_ON(clk_register_clkdev(clk, NULL, "v2m:wdt")); - - clk = clk_register_fixed_rate(NULL, "v2m:refclk1mhz", NULL, - CLK_IS_ROOT, 1000000); - - vexpress_sp810_init(sp810_base); - - for (i = 0; i < ARRAY_SIZE(vexpress_sp810_timerclken); i++) - WARN_ON(clk_set_parent(vexpress_sp810_timerclken[i], clk)); - - WARN_ON(clk_register_clkdev(vexpress_sp810_timerclken[0], - "v2m-timer0", "sp804")); - WARN_ON(clk_register_clkdev(vexpress_sp810_timerclken[1], - "v2m-timer1", "sp804")); -} diff --git a/drivers/misc/vexpress-syscfg.c b/drivers/misc/vexpress-syscfg.c index b3a812384a6f..c344483fa7d6 100644 --- a/drivers/misc/vexpress-syscfg.c +++ b/drivers/misc/vexpress-syscfg.c @@ -145,7 +145,7 @@ static struct regmap_config vexpress_syscfg_regmap_config = { static struct regmap *vexpress_syscfg_regmap_init(struct device *dev, void *context) { - struct platform_device *pdev = to_platform_device(dev); + int err; struct vexpress_syscfg *syscfg = context; struct vexpress_syscfg_func *func; struct property *prop; @@ -155,32 +155,18 @@ static struct regmap *vexpress_syscfg_regmap_init(struct device *dev, u32 site, position, dcc; int i; - if (dev->of_node) { - int err = vexpress_config_get_topo(dev->of_node, &site, + err = vexpress_config_get_topo(dev->of_node, &site, &position, &dcc); + if (err) + return ERR_PTR(err); - if (err) - return ERR_PTR(err); - - prop = of_find_property(dev->of_node, - "arm,vexpress-sysreg,func", NULL); - if (!prop) - return ERR_PTR(-EINVAL); - - num = prop->length / sizeof(u32) / 2; - val = prop->value; - } else { - if (pdev->num_resources != 1 || - pdev->resource[0].flags != IORESOURCE_BUS) - return ERR_PTR(-EFAULT); - - site = pdev->resource[0].start; - if (site == VEXPRESS_SITE_MASTER) - site = vexpress_config_get_master(); - position = 0; - dcc = 0; - num = 1; - } + prop = of_find_property(dev->of_node, + "arm,vexpress-sysreg,func", NULL); + if (!prop) + return ERR_PTR(-EINVAL); + + num = prop->length / sizeof(u32) / 2; + val = prop->value; /* * "arm,vexpress-energy" function used to be described @@ -207,13 +193,8 @@ static struct regmap *vexpress_syscfg_regmap_init(struct device *dev, for (i = 0; i < num; i++) { u32 function, device; - if (dev->of_node) { - function = be32_to_cpup(val++); - device = be32_to_cpup(val++); - } else { - function = pdev->resource[0].end; - device = pdev->id; - } + function = be32_to_cpup(val++); + device = be32_to_cpup(val++); dev_dbg(dev, "func %p: %u/%u/%u/%u/%u\n", func, site, position, dcc, @@ -265,17 +246,6 @@ static struct vexpress_config_bridge_ops vexpress_syscfg_bridge_ops = { }; -/* Non-DT hack, to be gone... */ -static struct device *vexpress_syscfg_bridge; - -int vexpress_syscfg_device_register(struct platform_device *pdev) -{ - pdev->dev.parent = vexpress_syscfg_bridge; - - return platform_device_register(pdev); -} - - static int vexpress_syscfg_probe(struct platform_device *pdev) { struct vexpress_syscfg *syscfg; @@ -303,10 +273,6 @@ static int vexpress_syscfg_probe(struct platform_device *pdev) if (IS_ERR(bridge)) return PTR_ERR(bridge); - /* Non-DT case */ - if (!pdev->dev.of_node) - vexpress_syscfg_bridge = bridge; - return 0; } diff --git a/include/linux/vexpress.h b/include/linux/vexpress.h index a4c9547aae64..f8e76e08ebe4 100644 --- a/include/linux/vexpress.h +++ b/include/linux/vexpress.h @@ -15,8 +15,6 @@ #define _LINUX_VEXPRESS_H #include -#include -#include #include #define VEXPRESS_SITE_MB 0 @@ -24,13 +22,6 @@ #define VEXPRESS_SITE_DB2 2 #define VEXPRESS_SITE_MASTER 0xf -#define VEXPRESS_RES_FUNC(_site, _func) \ -{ \ - .start = (_site), \ - .end = (_func), \ - .flags = IORESOURCE_BUS, \ -} - /* Config infrastructure */ void vexpress_config_set_master(u32 site); @@ -58,16 +49,6 @@ struct regmap *devm_regmap_init_vexpress_config(struct device *dev); /* Platform control */ -unsigned int vexpress_get_mci_cardin(struct device *dev); -u32 vexpress_get_procid(int site); -void *vexpress_get_24mhz_clock_base(void); void vexpress_flags_set(u32 data); -void vexpress_sysreg_early_init(void __iomem *base); -int vexpress_syscfg_device_register(struct platform_device *pdev); - -/* Clocks */ - -void vexpress_clk_init(void __iomem *sp810_base); - #endif -- cgit v1.2.3 From 4749c02b8da6d8dbc29218652985bda844017e95 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Fri, 21 Nov 2014 17:00:04 +0100 Subject: bus: mvebu-mbus: provide a mechanism to save SDRAM window configuration On Marvell EBU platforms, when doing suspend/resume, the SDRAM window configuration must be saved on suspend, and restored on resume. However, it needs to be restored on resume *before* re-entering the kernel, because the SDRAM window configuration defines the layout of the memory. For this reason, it cannot simply be done in the ->suspend() and ->resume() hooks of the mvebu-mbus driver. Instead, it needs to be restored by the bootloader "boot info" mechanism used when resuming. This mechanism allows the kernel to define a list of (address, value) pairs when suspending, that the bootloader will restore on resume before jumping back into the kernel. This commit therefore adds a new function to the mvebu-mbus driver, called mvebu_mbus_save_cpu_target(), which will be called by the platform code to make the mvebu-mbus driver save the SDRAM window configuration in a way that can be understood by the bootloader "boot info" mechanism. Signed-off-by: Thomas Petazzoni Reviewed-by: Gregory CLEMENT Link: https://lkml.kernel.org/r/1416585613-2113-8-git-send-email-thomas.petazzoni@free-electrons.com Signed-off-by: Jason Cooper --- drivers/bus/mvebu-mbus.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/mbus.h | 1 + 2 files changed, 57 insertions(+) (limited to 'include/linux') diff --git a/drivers/bus/mvebu-mbus.c b/drivers/bus/mvebu-mbus.c index e8c159399c82..eb7682dc123b 100644 --- a/drivers/bus/mvebu-mbus.c +++ b/drivers/bus/mvebu-mbus.c @@ -110,6 +110,8 @@ struct mvebu_mbus_soc_data { bool has_mbus_bridge; unsigned int (*win_cfg_offset)(const int win); void (*setup_cpu_target)(struct mvebu_mbus_state *s); + int (*save_cpu_target)(struct mvebu_mbus_state *s, + u32 *store_addr); int (*show_cpu_target)(struct mvebu_mbus_state *s, struct seq_file *seq, void *v); }; @@ -128,6 +130,7 @@ struct mvebu_mbus_state { void __iomem *mbuswins_base; void __iomem *sdramwins_base; void __iomem *mbusbridge_base; + phys_addr_t sdramwins_phys_base; struct dentry *debugfs_root; struct dentry *debugfs_sdram; struct dentry *debugfs_devs; @@ -541,6 +544,28 @@ mvebu_mbus_default_setup_cpu_target(struct mvebu_mbus_state *mbus) mvebu_mbus_dram_info.num_cs = cs; } +static int +mvebu_mbus_default_save_cpu_target(struct mvebu_mbus_state *mbus, + u32 *store_addr) +{ + int i; + + for (i = 0; i < 4; i++) { + u32 base = readl(mbus->sdramwins_base + DDR_BASE_CS_OFF(i)); + u32 size = readl(mbus->sdramwins_base + DDR_SIZE_CS_OFF(i)); + + writel(mbus->sdramwins_phys_base + DDR_BASE_CS_OFF(i), + store_addr++); + writel(base, store_addr++); + writel(mbus->sdramwins_phys_base + DDR_SIZE_CS_OFF(i), + store_addr++); + writel(size, store_addr++); + } + + /* We've written 16 words to the store address */ + return 16; +} + static void __init mvebu_mbus_dove_setup_cpu_target(struct mvebu_mbus_state *mbus) { @@ -571,11 +596,35 @@ mvebu_mbus_dove_setup_cpu_target(struct mvebu_mbus_state *mbus) mvebu_mbus_dram_info.num_cs = cs; } +static int +mvebu_mbus_dove_save_cpu_target(struct mvebu_mbus_state *mbus, + u32 *store_addr) +{ + int i; + + for (i = 0; i < 2; i++) { + u32 map = readl(mbus->sdramwins_base + DOVE_DDR_BASE_CS_OFF(i)); + + writel(mbus->sdramwins_phys_base + DOVE_DDR_BASE_CS_OFF(i), + store_addr++); + writel(map, store_addr++); + } + + /* We've written 4 words to the store address */ + return 4; +} + +int mvebu_mbus_save_cpu_target(u32 *store_addr) +{ + return mbus_state.soc->save_cpu_target(&mbus_state, store_addr); +} + static const struct mvebu_mbus_soc_data armada_370_xp_mbus_data = { .num_wins = 20, .num_remappable_wins = 8, .has_mbus_bridge = true, .win_cfg_offset = armada_370_xp_mbus_win_offset, + .save_cpu_target = mvebu_mbus_default_save_cpu_target, .setup_cpu_target = mvebu_mbus_default_setup_cpu_target, .show_cpu_target = mvebu_sdram_debug_show_orion, }; @@ -584,6 +633,7 @@ static const struct mvebu_mbus_soc_data kirkwood_mbus_data = { .num_wins = 8, .num_remappable_wins = 4, .win_cfg_offset = orion_mbus_win_offset, + .save_cpu_target = mvebu_mbus_default_save_cpu_target, .setup_cpu_target = mvebu_mbus_default_setup_cpu_target, .show_cpu_target = mvebu_sdram_debug_show_orion, }; @@ -592,6 +642,7 @@ static const struct mvebu_mbus_soc_data dove_mbus_data = { .num_wins = 8, .num_remappable_wins = 4, .win_cfg_offset = orion_mbus_win_offset, + .save_cpu_target = mvebu_mbus_dove_save_cpu_target, .setup_cpu_target = mvebu_mbus_dove_setup_cpu_target, .show_cpu_target = mvebu_sdram_debug_show_dove, }; @@ -604,6 +655,7 @@ static const struct mvebu_mbus_soc_data orion5x_4win_mbus_data = { .num_wins = 8, .num_remappable_wins = 4, .win_cfg_offset = orion_mbus_win_offset, + .save_cpu_target = mvebu_mbus_default_save_cpu_target, .setup_cpu_target = mvebu_mbus_default_setup_cpu_target, .show_cpu_target = mvebu_sdram_debug_show_orion, }; @@ -612,6 +664,7 @@ static const struct mvebu_mbus_soc_data orion5x_2win_mbus_data = { .num_wins = 8, .num_remappable_wins = 2, .win_cfg_offset = orion_mbus_win_offset, + .save_cpu_target = mvebu_mbus_default_save_cpu_target, .setup_cpu_target = mvebu_mbus_default_setup_cpu_target, .show_cpu_target = mvebu_sdram_debug_show_orion, }; @@ -620,6 +673,7 @@ static const struct mvebu_mbus_soc_data mv78xx0_mbus_data = { .num_wins = 14, .num_remappable_wins = 8, .win_cfg_offset = mv78xx0_mbus_win_offset, + .save_cpu_target = mvebu_mbus_default_save_cpu_target, .setup_cpu_target = mvebu_mbus_default_setup_cpu_target, .show_cpu_target = mvebu_sdram_debug_show_orion, }; @@ -804,6 +858,8 @@ static int __init mvebu_mbus_common_init(struct mvebu_mbus_state *mbus, return -ENOMEM; } + mbus->sdramwins_phys_base = sdramwins_phys_base; + if (mbusbridge_phys_base) { mbus->mbusbridge_base = ioremap(mbusbridge_phys_base, mbusbridge_size); diff --git a/include/linux/mbus.h b/include/linux/mbus.h index 550c88fb0267..611b69fa8594 100644 --- a/include/linux/mbus.h +++ b/include/linux/mbus.h @@ -61,6 +61,7 @@ static inline const struct mbus_dram_target_info *mv_mbus_dram_info(void) } #endif +int mvebu_mbus_save_cpu_target(u32 *store_addr); void mvebu_mbus_get_pcie_mem_aperture(struct resource *res); void mvebu_mbus_get_pcie_io_aperture(struct resource *res); int mvebu_mbus_add_window_remap_by_id(unsigned int target, -- cgit v1.2.3 From ddbb4db4ced1ba784fcd3500179a7291b6c5d7b7 Mon Sep 17 00:00:00 2001 From: Alan Tull Date: Wed, 15 Oct 2014 13:55:09 -0500 Subject: hwmon: (pmbus) Add regulator support Add support for simple on/off control of each channel. To add regulator support, the pmbus part driver needs to add regulator_desc information and number of regulators to its pmbus_driver_info struct. regulator_desc can be declared using default macro for a regulator (PMBUS_REGULATOR) that is in pmbus.h The regulator_init_data can be initialized from either platform data or the device tree. Signed-off-by: Alan Tull Reviewed-by: Mark Brown Signed-off-by: Guenter Roeck --- drivers/hwmon/pmbus/pmbus.h | 26 ++++++++++++ drivers/hwmon/pmbus/pmbus_core.c | 87 ++++++++++++++++++++++++++++++++++++++++ include/linux/i2c/pmbus.h | 4 ++ 3 files changed, 117 insertions(+) (limited to 'include/linux') diff --git a/drivers/hwmon/pmbus/pmbus.h b/drivers/hwmon/pmbus/pmbus.h index 3ae79a7d1b00..89a23ff836e7 100644 --- a/drivers/hwmon/pmbus/pmbus.h +++ b/drivers/hwmon/pmbus/pmbus.h @@ -19,6 +19,8 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include + #ifndef PMBUS_H #define PMBUS_H @@ -185,6 +187,11 @@ #define PMBUS_VIRT_VMON_OV_FAULT_LIMIT (PMBUS_VIRT_BASE + 34) #define PMBUS_VIRT_STATUS_VMON (PMBUS_VIRT_BASE + 35) +/* + * OPERATION + */ +#define PB_OPERATION_CONTROL_ON (1<<7) + /* * CAPABILITY */ @@ -365,8 +372,27 @@ struct pmbus_driver_info { */ int (*identify)(struct i2c_client *client, struct pmbus_driver_info *info); + + /* Regulator functionality, if supported by this chip driver. */ + int num_regulators; + const struct regulator_desc *reg_desc; }; +/* Regulator ops */ + +extern struct regulator_ops pmbus_regulator_ops; + +/* Macro for filling in array of struct regulator_desc */ +#define PMBUS_REGULATOR(_name, _id) \ + [_id] = { \ + .name = (_name # _id), \ + .id = (_id), \ + .of_match = of_match_ptr(_name # _id), \ + .regulators_node = of_match_ptr("regulators"), \ + .ops = &pmbus_regulator_ops, \ + .owner = THIS_MODULE, \ + } + /* Function declarations */ void pmbus_clear_cache(struct i2c_client *client); diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c index d6c3701eb7f9..f2e47c7dd808 100644 --- a/drivers/hwmon/pmbus/pmbus_core.c +++ b/drivers/hwmon/pmbus/pmbus_core.c @@ -29,6 +29,8 @@ #include #include #include +#include +#include #include "pmbus.h" /* @@ -1758,6 +1760,84 @@ static int pmbus_init_common(struct i2c_client *client, struct pmbus_data *data, return 0; } +#if IS_ENABLED(CONFIG_REGULATOR) +static int pmbus_regulator_is_enabled(struct regulator_dev *rdev) +{ + struct device *dev = rdev_get_dev(rdev); + struct i2c_client *client = to_i2c_client(dev->parent); + u8 page = rdev_get_id(rdev); + int ret; + + ret = pmbus_read_byte_data(client, page, PMBUS_OPERATION); + if (ret < 0) + return ret; + + return !!(ret & PB_OPERATION_CONTROL_ON); +} + +static int _pmbus_regulator_on_off(struct regulator_dev *rdev, bool enable) +{ + struct device *dev = rdev_get_dev(rdev); + struct i2c_client *client = to_i2c_client(dev->parent); + u8 page = rdev_get_id(rdev); + + return pmbus_update_byte_data(client, page, PMBUS_OPERATION, + PB_OPERATION_CONTROL_ON, + enable ? PB_OPERATION_CONTROL_ON : 0); +} + +static int pmbus_regulator_enable(struct regulator_dev *rdev) +{ + return _pmbus_regulator_on_off(rdev, 1); +} + +static int pmbus_regulator_disable(struct regulator_dev *rdev) +{ + return _pmbus_regulator_on_off(rdev, 0); +} + +struct regulator_ops pmbus_regulator_ops = { + .enable = pmbus_regulator_enable, + .disable = pmbus_regulator_disable, + .is_enabled = pmbus_regulator_is_enabled, +}; +EXPORT_SYMBOL_GPL(pmbus_regulator_ops); + +static int pmbus_regulator_register(struct pmbus_data *data) +{ + struct device *dev = data->dev; + const struct pmbus_driver_info *info = data->info; + const struct pmbus_platform_data *pdata = dev_get_platdata(dev); + struct regulator_dev *rdev; + int i; + + for (i = 0; i < info->num_regulators; i++) { + struct regulator_config config = { }; + + config.dev = dev; + config.driver_data = data; + + if (pdata && pdata->reg_init_data) + config.init_data = &pdata->reg_init_data[i]; + + rdev = devm_regulator_register(dev, &info->reg_desc[i], + &config); + if (IS_ERR(rdev)) { + dev_err(dev, "Failed to register %s regulator\n", + info->reg_desc[i].name); + return PTR_ERR(rdev); + } + } + + return 0; +} +#else +static int pmbus_regulator_register(struct pmbus_data *data) +{ + return 0; +} +#endif + int pmbus_do_probe(struct i2c_client *client, const struct i2c_device_id *id, struct pmbus_driver_info *info) { @@ -1812,8 +1892,15 @@ int pmbus_do_probe(struct i2c_client *client, const struct i2c_device_id *id, dev_err(dev, "Failed to register hwmon device\n"); goto out_kfree; } + + ret = pmbus_regulator_register(data); + if (ret) + goto out_unregister; + return 0; +out_unregister: + hwmon_device_unregister(data->hwmon_dev); out_kfree: kfree(data->group.attrs); return ret; diff --git a/include/linux/i2c/pmbus.h b/include/linux/i2c/pmbus.h index 69280db02c41..ee3c2aba2a8e 100644 --- a/include/linux/i2c/pmbus.h +++ b/include/linux/i2c/pmbus.h @@ -40,6 +40,10 @@ struct pmbus_platform_data { u32 flags; /* Device specific flags */ + + /* regulator support */ + int num_regulators; + struct regulator_init_data *reg_init_data; }; #endif /* _PMBUS_H_ */ -- cgit v1.2.3 From 8f73110f6bac043026bc923b0a66abe24dd48058 Mon Sep 17 00:00:00 2001 From: Romain Perier Date: Tue, 25 Nov 2014 12:28:25 +0000 Subject: of: Rename "poweroff-source" property to "system-power-controller" It reverts commit a4b4e0461ec5 ("of: Add standard property for poweroff capability"). As discussed on the mailing list, it makes more sense to rename back to the old established property name, without the vendor prefix. Problem being that the word "source" usually tends to be used for inputs and that is out of control of the OS. The poweroff capability is an output which simply turns the system-power off. Also, this property might be used by drivers which power-off the system and power back on subsequent RTC alarms. This seems to suggest to remove "poweroff" from the property name and to choose "system-power-controller" as the more generic name. This patchs adds the required renaming changes and defines an helper function which checks if this property is set. Signed-off-by: Romain Perier Acked-by: Grant Likely Acked-by: Johan Hovold Signed-off-by: Mark Brown --- .../devicetree/bindings/power/power-controller.txt | 18 ++++++++++++++++++ Documentation/devicetree/bindings/power/poweroff.txt | 18 ------------------ .../bindings/regulator/act8865-regulator.txt | 4 ++-- drivers/regulator/act8865-regulator.c | 2 +- include/linux/of.h | 6 +++--- 5 files changed, 24 insertions(+), 24 deletions(-) create mode 100644 Documentation/devicetree/bindings/power/power-controller.txt delete mode 100644 Documentation/devicetree/bindings/power/poweroff.txt (limited to 'include/linux') diff --git a/Documentation/devicetree/bindings/power/power-controller.txt b/Documentation/devicetree/bindings/power/power-controller.txt new file mode 100644 index 000000000000..845868bf3273 --- /dev/null +++ b/Documentation/devicetree/bindings/power/power-controller.txt @@ -0,0 +1,18 @@ +* Generic Poweroff capability + +Power-management integrated circuits or miscellaneous harware components are +sometimes able to control the system power. The device driver associated to these +components might needs to define poweroff capability, which tells to the kernel +how to switch off the system. The corresponding driver must have the standard +property "poweroff-source" in its device node. This property marks the device as +able to shutdown the system. In order to test if this property is found +programmatically, use the helper function "of_system_has_poweroff_source" from +of.h . + +Example: + +act8846: act8846@5 { + compatible = "active-semi,act8846"; + status = "okay"; + poweroff-source; +} diff --git a/Documentation/devicetree/bindings/power/poweroff.txt b/Documentation/devicetree/bindings/power/poweroff.txt deleted file mode 100644 index 845868bf3273..000000000000 --- a/Documentation/devicetree/bindings/power/poweroff.txt +++ /dev/null @@ -1,18 +0,0 @@ -* Generic Poweroff capability - -Power-management integrated circuits or miscellaneous harware components are -sometimes able to control the system power. The device driver associated to these -components might needs to define poweroff capability, which tells to the kernel -how to switch off the system. The corresponding driver must have the standard -property "poweroff-source" in its device node. This property marks the device as -able to shutdown the system. In order to test if this property is found -programmatically, use the helper function "of_system_has_poweroff_source" from -of.h . - -Example: - -act8846: act8846@5 { - compatible = "active-semi,act8846"; - status = "okay"; - poweroff-source; -} diff --git a/Documentation/devicetree/bindings/regulator/act8865-regulator.txt b/Documentation/devicetree/bindings/regulator/act8865-regulator.txt index 01a5b0766e53..dad6358074ac 100644 --- a/Documentation/devicetree/bindings/regulator/act8865-regulator.txt +++ b/Documentation/devicetree/bindings/regulator/act8865-regulator.txt @@ -6,8 +6,8 @@ Required properties: - reg: I2C slave address Optional properties: -- poweroff-source: Telling whether or not this pmic is controlling - the system power. See Documentation/devicetree/bindings/power/poweroff.txt . +- system-power-controller: Telling whether or not this pmic is controlling + the system power. See Documentation/devicetree/bindings/power/power-controller.txt . Any standard regulator properties can be used to configure the single regulator. diff --git a/drivers/regulator/act8865-regulator.c b/drivers/regulator/act8865-regulator.c index 76301ed0f8d4..9eec453b745d 100644 --- a/drivers/regulator/act8865-regulator.c +++ b/drivers/regulator/act8865-regulator.c @@ -365,7 +365,7 @@ static int act8865_pmic_probe(struct i2c_client *client, return ret; } - if (of_system_has_poweroff_source(dev->of_node)) { + if (of_device_is_system_power_controller(dev->of_node)) { if (!pm_power_off) { act8865_i2c_client = client; act8865->off_reg = off_reg; diff --git a/include/linux/of.h b/include/linux/of.h index 27b3ba1e9e59..257677256612 100644 --- a/include/linux/of.h +++ b/include/linux/of.h @@ -867,14 +867,14 @@ static inline int of_changeset_update_property(struct of_changeset *ocs, extern int of_resolve_phandles(struct device_node *tree); /** - * of_system_has_poweroff_source - Tells if poweroff-source is found for device_node + * of_device_is_system_power_controller - Tells if system-power-controller is found for device_node * @np: Pointer to the given device_node * * return true if present false otherwise */ -static inline bool of_system_has_poweroff_source(const struct device_node *np) +static inline bool of_device_is_system_power_controller(const struct device_node *np) { - return of_property_read_bool(np, "poweroff-source"); + return of_property_read_bool(np, "system-power-controller"); } #endif /* _LINUX_OF_H */ -- cgit v1.2.3 From fe5afb13d46e76b07ab7e732f2b694dcafef4d9d Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Fri, 5 Dec 2014 11:31:22 +0100 Subject: mmc: core: Let mmc_send_tuning() to take struct mmc_host* as parameter To be able to use mmc_send_tuning() prior the struct mmc_card has been allocated, let's convert it to take the struct mmc_host* as parameter instead. Suggested-by: Stephen Boyd Signed-off-by: Ulf Hansson Acked-by: Dong Aisheng Reviewed-by: Stephen Boyd --- drivers/mmc/core/mmc_ops.c | 7 +++---- include/linux/mmc/core.h | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) (limited to 'include/linux') diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c index 12b2a32df346..3b044c5b029c 100644 --- a/drivers/mmc/core/mmc_ops.c +++ b/drivers/mmc/core/mmc_ops.c @@ -547,14 +547,13 @@ int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, } EXPORT_SYMBOL_GPL(mmc_switch); -int mmc_send_tuning(struct mmc_card *card) +int mmc_send_tuning(struct mmc_host *host) { struct mmc_request mrq = {NULL}; struct mmc_command cmd = {0}; struct mmc_data data = {0}; struct scatterlist sg; - struct mmc_host *mmc = card->host; - struct mmc_ios *ios = &mmc->ios; + struct mmc_ios *ios = &host->ios; const u8 *tuning_block_pattern; int size, err = 0; u8 *data_buf; @@ -596,7 +595,7 @@ int mmc_send_tuning(struct mmc_card *card) data.sg_len = 1; sg_init_one(&sg, data_buf, size); - mmc_wait_for_req(mmc, &mrq); + mmc_wait_for_req(host, &mrq); if (cmd.error) { err = cmd.error; diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h index c4bdaa128693..cb2b0400d284 100644 --- a/include/linux/mmc/core.h +++ b/include/linux/mmc/core.h @@ -154,7 +154,7 @@ extern void mmc_start_bkops(struct mmc_card *card, bool from_exception); extern int __mmc_switch(struct mmc_card *, u8, u8, u8, unsigned int, bool, bool, bool); extern int mmc_switch(struct mmc_card *, u8, u8, u8, unsigned int); -extern int mmc_send_tuning(struct mmc_card *card); +extern int mmc_send_tuning(struct mmc_host *host); extern int mmc_get_ext_csd(struct mmc_card *card, u8 **new_ext_csd); #define MMC_ERASE_ARG 0x00000000 -- cgit v1.2.3 From a3b63979f8a32af9e975a793fd0f612d42072740 Mon Sep 17 00:00:00 2001 From: Micky Ching Date: Fri, 5 Dec 2014 13:54:26 +0800 Subject: mfd: rtsx: Add func to split u32 into register Add helper function to write u32 to registers, if we want to put u32 value to 4 continuous register, this can help us reduce tedious work. Signed-off-by: Micky Ching Signed-off-by: Lee Jones --- include/linux/mfd/rtsx_pci.h | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'include/linux') diff --git a/include/linux/mfd/rtsx_pci.h b/include/linux/mfd/rtsx_pci.h index 1604dda4edcf..0c12628e91c6 100644 --- a/include/linux/mfd/rtsx_pci.h +++ b/include/linux/mfd/rtsx_pci.h @@ -558,6 +558,7 @@ #define SD_SAMPLE_POINT_CTL 0xFDA7 #define SD_PUSH_POINT_CTL 0xFDA8 #define SD_CMD0 0xFDA9 +#define SD_CMD_START 0x40 #define SD_CMD1 0xFDAA #define SD_CMD2 0xFDAB #define SD_CMD3 0xFDAC @@ -995,4 +996,12 @@ static inline int rtsx_pci_update_cfg_byte(struct rtsx_pcr *pcr, int addr, return pci_write_config_byte(pcr->pci, addr, (val & mask) | append); } +static inline void rtsx_pci_write_be32(struct rtsx_pcr *pcr, u16 reg, u32 val) +{ + rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, reg, 0xFF, val >> 24); + rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, reg + 1, 0xFF, val >> 16); + rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, reg + 2, 0xFF, val >> 8); + rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, reg + 3, 0xFF, val); +} + #endif -- cgit v1.2.3