diff options
Diffstat (limited to 'drivers')
87 files changed, 1459 insertions, 1604 deletions
diff --git a/drivers/base/property.c b/drivers/base/property.c index ff03f2348f77..2d75366c61e0 100644 --- a/drivers/base/property.c +++ b/drivers/base/property.c @@ -611,13 +611,15 @@ static void *device_get_mac_addr(struct device *dev, */ void *device_get_mac_address(struct device *dev, char *addr, int alen) { - addr = device_get_mac_addr(dev, "mac-address", addr, alen); - if (addr) - return addr; + char *res; - addr = device_get_mac_addr(dev, "local-mac-address", addr, alen); - if (addr) - return addr; + res = device_get_mac_addr(dev, "mac-address", addr, alen); + if (res) + return res; + + res = device_get_mac_addr(dev, "local-mac-address", addr, alen); + if (res) + return res; return device_get_mac_addr(dev, "address", addr, alen); } diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index d4d05f064d39..e93899cc6f60 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c @@ -478,8 +478,7 @@ static int virtblk_get_cache_mode(struct virtio_device *vdev) struct virtio_blk_config, wce, &writeback); if (err) - writeback = virtio_has_feature(vdev, VIRTIO_BLK_F_WCE) || - virtio_has_feature(vdev, VIRTIO_F_VERSION_1); + writeback = virtio_has_feature(vdev, VIRTIO_BLK_F_WCE); return writeback; } @@ -657,6 +656,7 @@ static int virtblk_probe(struct virtio_device *vdev) vblk->disk->private_data = vblk; vblk->disk->fops = &virtblk_fops; vblk->disk->driverfs_dev = &vdev->dev; + vblk->disk->flags |= GENHD_FL_EXT_DEVT; vblk->index = index; /* configure queue flush support */ @@ -840,7 +840,7 @@ static unsigned int features_legacy[] = { static unsigned int features[] = { VIRTIO_BLK_F_SEG_MAX, VIRTIO_BLK_F_SIZE_MAX, VIRTIO_BLK_F_GEOMETRY, VIRTIO_BLK_F_RO, VIRTIO_BLK_F_BLK_SIZE, - VIRTIO_BLK_F_TOPOLOGY, + VIRTIO_BLK_F_WCE, VIRTIO_BLK_F_TOPOLOGY, VIRTIO_BLK_F_CONFIG_WCE, VIRTIO_BLK_F_MQ, }; diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c index 15083539df15..0823a96902f8 100644 --- a/drivers/block/xen-blkfront.c +++ b/drivers/block/xen-blkfront.c @@ -249,7 +249,7 @@ static struct grant *get_grant(grant_ref_t *gref_head, struct blkfront_info *info) { struct grant *gnt_list_entry; - unsigned long buffer_mfn; + unsigned long buffer_gfn; BUG_ON(list_empty(&info->grants)); gnt_list_entry = list_first_entry(&info->grants, struct grant, @@ -268,10 +268,10 @@ static struct grant *get_grant(grant_ref_t *gref_head, BUG_ON(!pfn); gnt_list_entry->pfn = pfn; } - buffer_mfn = pfn_to_mfn(gnt_list_entry->pfn); + buffer_gfn = pfn_to_gfn(gnt_list_entry->pfn); gnttab_grant_foreign_access_ref(gnt_list_entry->gref, info->xbdev->otherend_id, - buffer_mfn, 0); + buffer_gfn, 0); return gnt_list_entry; } diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c index 251f48dcd12d..7f370d3e0983 100644 --- a/drivers/clk/samsung/clk-exynos4.c +++ b/drivers/clk/samsung/clk-exynos4.c @@ -1398,6 +1398,45 @@ static const struct exynos_cpuclk_cfg_data e4210_armclk_d[] __initconst = { { 0 }, }; +static const struct exynos_cpuclk_cfg_data e4212_armclk_d[] __initconst = { + { 1500000, E4210_CPU_DIV0(2, 1, 6, 0, 7, 3), E4210_CPU_DIV1(2, 6), }, + { 1400000, E4210_CPU_DIV0(2, 1, 6, 0, 7, 3), E4210_CPU_DIV1(2, 6), }, + { 1300000, E4210_CPU_DIV0(2, 1, 5, 0, 7, 3), E4210_CPU_DIV1(2, 5), }, + { 1200000, E4210_CPU_DIV0(2, 1, 5, 0, 7, 3), E4210_CPU_DIV1(2, 5), }, + { 1100000, E4210_CPU_DIV0(2, 1, 4, 0, 6, 3), E4210_CPU_DIV1(2, 4), }, + { 1000000, E4210_CPU_DIV0(1, 1, 4, 0, 5, 2), E4210_CPU_DIV1(2, 4), }, + { 900000, E4210_CPU_DIV0(1, 1, 3, 0, 5, 2), E4210_CPU_DIV1(2, 3), }, + { 800000, E4210_CPU_DIV0(1, 1, 3, 0, 5, 2), E4210_CPU_DIV1(2, 3), }, + { 700000, E4210_CPU_DIV0(1, 1, 3, 0, 4, 2), E4210_CPU_DIV1(2, 3), }, + { 600000, E4210_CPU_DIV0(1, 1, 3, 0, 4, 2), E4210_CPU_DIV1(2, 3), }, + { 500000, E4210_CPU_DIV0(1, 1, 3, 0, 4, 2), E4210_CPU_DIV1(2, 3), }, + { 400000, E4210_CPU_DIV0(1, 1, 3, 0, 4, 2), E4210_CPU_DIV1(2, 3), }, + { 300000, E4210_CPU_DIV0(1, 1, 2, 0, 4, 2), E4210_CPU_DIV1(2, 3), }, + { 200000, E4210_CPU_DIV0(1, 1, 1, 0, 3, 1), E4210_CPU_DIV1(2, 3), }, + { 0 }, +}; + +#define E4412_CPU_DIV1(cores, hpm, copy) \ + (((cores) << 8) | ((hpm) << 4) | ((copy) << 0)) + +static const struct exynos_cpuclk_cfg_data e4412_armclk_d[] __initconst = { + { 1500000, E4210_CPU_DIV0(2, 1, 6, 0, 7, 3), E4412_CPU_DIV1(7, 0, 6), }, + { 1400000, E4210_CPU_DIV0(2, 1, 6, 0, 7, 3), E4412_CPU_DIV1(6, 0, 6), }, + { 1300000, E4210_CPU_DIV0(2, 1, 5, 0, 7, 3), E4412_CPU_DIV1(6, 0, 5), }, + { 1200000, E4210_CPU_DIV0(2, 1, 5, 0, 7, 3), E4412_CPU_DIV1(5, 0, 5), }, + { 1100000, E4210_CPU_DIV0(2, 1, 4, 0, 6, 3), E4412_CPU_DIV1(5, 0, 4), }, + { 1000000, E4210_CPU_DIV0(1, 1, 4, 0, 5, 2), E4412_CPU_DIV1(4, 0, 4), }, + { 900000, E4210_CPU_DIV0(1, 1, 3, 0, 5, 2), E4412_CPU_DIV1(4, 0, 3), }, + { 800000, E4210_CPU_DIV0(1, 1, 3, 0, 5, 2), E4412_CPU_DIV1(3, 0, 3), }, + { 700000, E4210_CPU_DIV0(1, 1, 3, 0, 4, 2), E4412_CPU_DIV1(3, 0, 3), }, + { 600000, E4210_CPU_DIV0(1, 1, 3, 0, 4, 2), E4412_CPU_DIV1(2, 0, 3), }, + { 500000, E4210_CPU_DIV0(1, 1, 3, 0, 4, 2), E4412_CPU_DIV1(2, 0, 3), }, + { 400000, E4210_CPU_DIV0(1, 1, 3, 0, 4, 2), E4412_CPU_DIV1(1, 0, 3), }, + { 300000, E4210_CPU_DIV0(1, 1, 2, 0, 4, 2), E4412_CPU_DIV1(1, 0, 3), }, + { 200000, E4210_CPU_DIV0(1, 1, 1, 0, 3, 1), E4412_CPU_DIV1(0, 0, 3), }, + { 0 }, +}; + /* register exynos4 clocks */ static void __init exynos4_clk_init(struct device_node *np, enum exynos4_soc soc) @@ -1491,6 +1530,17 @@ static void __init exynos4_clk_init(struct device_node *np, samsung_clk_register_fixed_factor(ctx, exynos4x12_fixed_factor_clks, ARRAY_SIZE(exynos4x12_fixed_factor_clks)); + if (of_machine_is_compatible("samsung,exynos4412")) { + exynos_register_cpu_clock(ctx, CLK_ARM_CLK, "armclk", + mout_core_p4x12[0], mout_core_p4x12[1], 0x14200, + e4412_armclk_d, ARRAY_SIZE(e4412_armclk_d), + CLK_CPU_NEEDS_DEBUG_ALT_DIV | CLK_CPU_HAS_DIV1); + } else { + exynos_register_cpu_clock(ctx, CLK_ARM_CLK, "armclk", + mout_core_p4x12[0], mout_core_p4x12[1], 0x14200, + e4212_armclk_d, ARRAY_SIZE(e4212_armclk_d), + CLK_CPU_NEEDS_DEBUG_ALT_DIV | CLK_CPU_HAS_DIV1); + } } samsung_clk_register_alias(ctx, exynos4_aliases, diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm index 77aa34eae92c..5f498d9f1825 100644 --- a/drivers/cpufreq/Kconfig.arm +++ b/drivers/cpufreq/Kconfig.arm @@ -24,55 +24,6 @@ config ARM_VEXPRESS_SPC_CPUFREQ This add the CPUfreq driver support for Versatile Express big.LITTLE platforms using SPC for power management. - -config ARM_EXYNOS_CPUFREQ - tristate "SAMSUNG EXYNOS CPUfreq Driver" - depends on CPU_EXYNOS4210 || SOC_EXYNOS4212 || SOC_EXYNOS4412 || SOC_EXYNOS5250 - depends on THERMAL - help - This adds the CPUFreq driver for Samsung EXYNOS platforms. - Supported SoC versions are: - Exynos4210, Exynos4212, Exynos4412, and Exynos5250. - - If in doubt, say N. - -config ARM_EXYNOS4X12_CPUFREQ - bool "SAMSUNG EXYNOS4x12" - depends on SOC_EXYNOS4212 || SOC_EXYNOS4412 - depends on ARM_EXYNOS_CPUFREQ - default y - help - This adds the CPUFreq driver for Samsung EXYNOS4X12 - SoC (EXYNOS4212 or EXYNOS4412). - - If in doubt, say N. - -config ARM_EXYNOS5250_CPUFREQ - bool "SAMSUNG EXYNOS5250" - depends on SOC_EXYNOS5250 - depends on ARM_EXYNOS_CPUFREQ - default y - help - This adds the CPUFreq driver for Samsung EXYNOS5250 - SoC. - - If in doubt, say N. - -config ARM_EXYNOS_CPU_FREQ_BOOST_SW - bool "EXYNOS Frequency Overclocking - Software" - depends on ARM_EXYNOS_CPUFREQ && THERMAL - select CPU_FREQ_BOOST_SW - select EXYNOS_THERMAL - help - This driver supports software managed overclocking (BOOST). - It allows usage of special frequencies for Samsung Exynos - processors if thermal conditions are appropriate. - - It requires, for safe operation, thermal framework with properly - defined trip points. - - If in doubt, say N. - config ARM_EXYNOS5440_CPUFREQ tristate "SAMSUNG EXYNOS5440" depends on SOC_EXYNOS5440 diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile index 60a57ca5b22d..41340384f11f 100644 --- a/drivers/cpufreq/Makefile +++ b/drivers/cpufreq/Makefile @@ -52,10 +52,6 @@ obj-$(CONFIG_ARM_DT_BL_CPUFREQ) += arm_big_little_dt.o obj-$(CONFIG_ARCH_DAVINCI) += davinci-cpufreq.o obj-$(CONFIG_UX500_SOC_DB8500) += dbx500-cpufreq.o -obj-$(CONFIG_ARM_EXYNOS_CPUFREQ) += arm-exynos-cpufreq.o -arm-exynos-cpufreq-y := exynos-cpufreq.o -arm-exynos-cpufreq-$(CONFIG_ARM_EXYNOS4X12_CPUFREQ) += exynos4x12-cpufreq.o -arm-exynos-cpufreq-$(CONFIG_ARM_EXYNOS5250_CPUFREQ) += exynos5250-cpufreq.o obj-$(CONFIG_ARM_EXYNOS5440_CPUFREQ) += exynos5440-cpufreq.o obj-$(CONFIG_ARM_HIGHBANK_CPUFREQ) += highbank-cpufreq.o obj-$(CONFIG_ARM_HISI_ACPU_CPUFREQ) += hisi-acpu-cpufreq.o diff --git a/drivers/cpufreq/exynos-cpufreq.c b/drivers/cpufreq/exynos-cpufreq.c deleted file mode 100644 index fa3dd840a837..000000000000 --- a/drivers/cpufreq/exynos-cpufreq.c +++ /dev/null @@ -1,239 +0,0 @@ -/* - * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd. - * http://www.samsung.com - * - * EXYNOS - CPU frequency scaling support for EXYNOS series - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. -*/ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/err.h> -#include <linux/clk.h> -#include <linux/io.h> -#include <linux/slab.h> -#include <linux/regulator/consumer.h> -#include <linux/cpufreq.h> -#include <linux/platform_device.h> -#include <linux/of.h> -#include <linux/cpu_cooling.h> -#include <linux/cpu.h> - -#include "exynos-cpufreq.h" - -static struct exynos_dvfs_info *exynos_info; -static struct thermal_cooling_device *cdev; -static struct regulator *arm_regulator; -static unsigned int locking_frequency; - -static int exynos_cpufreq_get_index(unsigned int freq) -{ - struct cpufreq_frequency_table *freq_table = exynos_info->freq_table; - struct cpufreq_frequency_table *pos; - - cpufreq_for_each_entry(pos, freq_table) - if (pos->frequency == freq) - break; - - if (pos->frequency == CPUFREQ_TABLE_END) - return -EINVAL; - - return pos - freq_table; -} - -static int exynos_cpufreq_scale(unsigned int target_freq) -{ - struct cpufreq_frequency_table *freq_table = exynos_info->freq_table; - unsigned int *volt_table = exynos_info->volt_table; - struct cpufreq_policy *policy = cpufreq_cpu_get(0); - unsigned int arm_volt, safe_arm_volt = 0; - unsigned int mpll_freq_khz = exynos_info->mpll_freq_khz; - struct device *dev = exynos_info->dev; - unsigned int old_freq; - int index, old_index; - int ret = 0; - - old_freq = policy->cur; - - /* - * The policy max have been changed so that we cannot get proper - * old_index with cpufreq_frequency_table_target(). Thus, ignore - * policy and get the index from the raw frequency table. - */ - old_index = exynos_cpufreq_get_index(old_freq); - if (old_index < 0) { - ret = old_index; - goto out; - } - - index = exynos_cpufreq_get_index(target_freq); - if (index < 0) { - ret = index; - goto out; - } - - /* - * ARM clock source will be changed APLL to MPLL temporary - * To support this level, need to control regulator for - * required voltage level - */ - if (exynos_info->need_apll_change != NULL) { - if (exynos_info->need_apll_change(old_index, index) && - (freq_table[index].frequency < mpll_freq_khz) && - (freq_table[old_index].frequency < mpll_freq_khz)) - safe_arm_volt = volt_table[exynos_info->pll_safe_idx]; - } - arm_volt = volt_table[index]; - - /* When the new frequency is higher than current frequency */ - if ((target_freq > old_freq) && !safe_arm_volt) { - /* Firstly, voltage up to increase frequency */ - ret = regulator_set_voltage(arm_regulator, arm_volt, arm_volt); - if (ret) { - dev_err(dev, "failed to set cpu voltage to %d\n", - arm_volt); - return ret; - } - } - - if (safe_arm_volt) { - ret = regulator_set_voltage(arm_regulator, safe_arm_volt, - safe_arm_volt); - if (ret) { - dev_err(dev, "failed to set cpu voltage to %d\n", - safe_arm_volt); - return ret; - } - } - - exynos_info->set_freq(old_index, index); - - /* When the new frequency is lower than current frequency */ - if ((target_freq < old_freq) || - ((target_freq > old_freq) && safe_arm_volt)) { - /* down the voltage after frequency change */ - ret = regulator_set_voltage(arm_regulator, arm_volt, - arm_volt); - if (ret) { - dev_err(dev, "failed to set cpu voltage to %d\n", - arm_volt); - goto out; - } - } - -out: - cpufreq_cpu_put(policy); - - return ret; -} - -static int exynos_target(struct cpufreq_policy *policy, unsigned int index) -{ - return exynos_cpufreq_scale(exynos_info->freq_table[index].frequency); -} - -static int exynos_cpufreq_cpu_init(struct cpufreq_policy *policy) -{ - policy->clk = exynos_info->cpu_clk; - policy->suspend_freq = locking_frequency; - return cpufreq_generic_init(policy, exynos_info->freq_table, 100000); -} - -static struct cpufreq_driver exynos_driver = { - .flags = CPUFREQ_STICKY | CPUFREQ_NEED_INITIAL_FREQ_CHECK, - .verify = cpufreq_generic_frequency_table_verify, - .target_index = exynos_target, - .get = cpufreq_generic_get, - .init = exynos_cpufreq_cpu_init, - .name = "exynos_cpufreq", - .attr = cpufreq_generic_attr, -#ifdef CONFIG_ARM_EXYNOS_CPU_FREQ_BOOST_SW - .boost_supported = true, -#endif -#ifdef CONFIG_PM - .suspend = cpufreq_generic_suspend, -#endif -}; - -static int exynos_cpufreq_probe(struct platform_device *pdev) -{ - struct device_node *cpu0; - int ret = -EINVAL; - - exynos_info = kzalloc(sizeof(*exynos_info), GFP_KERNEL); - if (!exynos_info) - return -ENOMEM; - - exynos_info->dev = &pdev->dev; - - if (of_machine_is_compatible("samsung,exynos4212")) { - exynos_info->type = EXYNOS_SOC_4212; - ret = exynos4x12_cpufreq_init(exynos_info); - } else if (of_machine_is_compatible("samsung,exynos4412")) { - exynos_info->type = EXYNOS_SOC_4412; - ret = exynos4x12_cpufreq_init(exynos_info); - } else if (of_machine_is_compatible("samsung,exynos5250")) { - exynos_info->type = EXYNOS_SOC_5250; - ret = exynos5250_cpufreq_init(exynos_info); - } else { - pr_err("%s: Unknown SoC type\n", __func__); - ret = -ENODEV; - } - - if (ret) - goto err_vdd_arm; - - if (exynos_info->set_freq == NULL) { - dev_err(&pdev->dev, "No set_freq function (ERR)\n"); - ret = -EINVAL; - goto err_vdd_arm; - } - - arm_regulator = regulator_get(NULL, "vdd_arm"); - if (IS_ERR(arm_regulator)) { - dev_err(&pdev->dev, "failed to get resource vdd_arm\n"); - ret = -EINVAL; - goto err_vdd_arm; - } - - /* Done here as we want to capture boot frequency */ - locking_frequency = clk_get_rate(exynos_info->cpu_clk) / 1000; - - ret = cpufreq_register_driver(&exynos_driver); - if (ret) - goto err_cpufreq_reg; - - cpu0 = of_get_cpu_node(0, NULL); - if (!cpu0) { - pr_err("failed to find cpu0 node\n"); - return 0; - } - - if (of_find_property(cpu0, "#cooling-cells", NULL)) { - cdev = of_cpufreq_cooling_register(cpu0, - cpu_present_mask); - if (IS_ERR(cdev)) - pr_err("running cpufreq without cooling device: %ld\n", - PTR_ERR(cdev)); - } - - return 0; - -err_cpufreq_reg: - dev_err(&pdev->dev, "failed to register cpufreq driver\n"); - regulator_put(arm_regulator); -err_vdd_arm: - kfree(exynos_info); - return ret; -} - -static struct platform_driver exynos_cpufreq_platdrv = { - .driver = { - .name = "exynos-cpufreq", - }, - .probe = exynos_cpufreq_probe, -}; -module_platform_driver(exynos_cpufreq_platdrv); diff --git a/drivers/cpufreq/exynos-cpufreq.h b/drivers/cpufreq/exynos-cpufreq.h deleted file mode 100644 index a3855e4d913d..000000000000 --- a/drivers/cpufreq/exynos-cpufreq.h +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (c) 2010 Samsung Electronics Co., Ltd. - * http://www.samsung.com - * - * EXYNOS - CPUFreq support - * - * 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. -*/ - -enum cpufreq_level_index { - L0, L1, L2, L3, L4, - L5, L6, L7, L8, L9, - L10, L11, L12, L13, L14, - L15, L16, L17, L18, L19, - L20, -}; - -enum exynos_soc_type { - EXYNOS_SOC_4212, - EXYNOS_SOC_4412, - EXYNOS_SOC_5250, -}; - -#define APLL_FREQ(f, a0, a1, a2, a3, a4, a5, a6, a7, b0, b1, b2, m, p, s) \ - { \ - .freq = (f) * 1000, \ - .clk_div_cpu0 = ((a0) | (a1) << 4 | (a2) << 8 | (a3) << 12 | \ - (a4) << 16 | (a5) << 20 | (a6) << 24 | (a7) << 28), \ - .clk_div_cpu1 = (b0 << 0 | b1 << 4 | b2 << 8), \ - .mps = ((m) << 16 | (p) << 8 | (s)), \ - } - -struct apll_freq { - unsigned int freq; - u32 clk_div_cpu0; - u32 clk_div_cpu1; - u32 mps; -}; - -struct exynos_dvfs_info { - enum exynos_soc_type type; - struct device *dev; - unsigned long mpll_freq_khz; - unsigned int pll_safe_idx; - struct clk *cpu_clk; - unsigned int *volt_table; - struct cpufreq_frequency_table *freq_table; - void (*set_freq)(unsigned int, unsigned int); - bool (*need_apll_change)(unsigned int, unsigned int); - void __iomem *cmu_regs; -}; - -#ifdef CONFIG_ARM_EXYNOS4X12_CPUFREQ -extern int exynos4x12_cpufreq_init(struct exynos_dvfs_info *); -#else -static inline int exynos4x12_cpufreq_init(struct exynos_dvfs_info *info) -{ - return -EOPNOTSUPP; -} -#endif -#ifdef CONFIG_ARM_EXYNOS5250_CPUFREQ -extern int exynos5250_cpufreq_init(struct exynos_dvfs_info *); -#else -static inline int exynos5250_cpufreq_init(struct exynos_dvfs_info *info) -{ - return -EOPNOTSUPP; -} -#endif - -#define EXYNOS4_CLKSRC_CPU 0x14200 -#define EXYNOS4_CLKMUX_STATCPU 0x14400 - -#define EXYNOS4_CLKDIV_CPU 0x14500 -#define EXYNOS4_CLKDIV_CPU1 0x14504 -#define EXYNOS4_CLKDIV_STATCPU 0x14600 -#define EXYNOS4_CLKDIV_STATCPU1 0x14604 - -#define EXYNOS4_CLKSRC_CPU_MUXCORE_SHIFT (16) -#define EXYNOS4_CLKMUX_STATCPU_MUXCORE_MASK (0x7 << EXYNOS4_CLKSRC_CPU_MUXCORE_SHIFT) - -#define EXYNOS5_APLL_LOCK 0x00000 -#define EXYNOS5_APLL_CON0 0x00100 -#define EXYNOS5_CLKMUX_STATCPU 0x00400 -#define EXYNOS5_CLKDIV_CPU0 0x00500 -#define EXYNOS5_CLKDIV_CPU1 0x00504 -#define EXYNOS5_CLKDIV_STATCPU0 0x00600 -#define EXYNOS5_CLKDIV_STATCPU1 0x00604 diff --git a/drivers/cpufreq/exynos4x12-cpufreq.c b/drivers/cpufreq/exynos4x12-cpufreq.c deleted file mode 100644 index 9e78a850e29f..000000000000 --- a/drivers/cpufreq/exynos4x12-cpufreq.c +++ /dev/null @@ -1,236 +0,0 @@ -/* - * Copyright (c) 2010-2012 Samsung Electronics Co., Ltd. - * http://www.samsung.com - * - * EXYNOS4X12 - CPU frequency scaling support - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. -*/ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/err.h> -#include <linux/clk.h> -#include <linux/io.h> -#include <linux/slab.h> -#include <linux/cpufreq.h> -#include <linux/of.h> -#include <linux/of_address.h> - -#include "exynos-cpufreq.h" - -static struct clk *cpu_clk; -static struct clk *moutcore; -static struct clk *mout_mpll; -static struct clk *mout_apll; -static struct exynos_dvfs_info *cpufreq; - -static unsigned int exynos4x12_volt_table[] = { - 1350000, 1287500, 1250000, 1187500, 1137500, 1087500, 1037500, - 1000000, 987500, 975000, 950000, 925000, 900000, 900000 -}; - -static struct cpufreq_frequency_table exynos4x12_freq_table[] = { - {CPUFREQ_BOOST_FREQ, L0, 1500 * 1000}, - {0, L1, 1400 * 1000}, - {0, L2, 1300 * 1000}, - {0, L3, 1200 * 1000}, - {0, L4, 1100 * 1000}, - {0, L5, 1000 * 1000}, - {0, L6, 900 * 1000}, - {0, L7, 800 * 1000}, - {0, L8, 700 * 1000}, - {0, L9, 600 * 1000}, - {0, L10, 500 * 1000}, - {0, L11, 400 * 1000}, - {0, L12, 300 * 1000}, - {0, L13, 200 * 1000}, - {0, 0, CPUFREQ_TABLE_END}, -}; - -static struct apll_freq *apll_freq_4x12; - -static struct apll_freq apll_freq_4212[] = { - /* - * values: - * freq - * clock divider for CORE, COREM0, COREM1, PERIPH, ATB, PCLK_DBG, APLL, CORE2 - * clock divider for COPY, HPM, RESERVED - * PLL M, P, S - */ - APLL_FREQ(1500, 0, 3, 7, 0, 6, 1, 2, 0, 6, 2, 0, 250, 4, 0), - APLL_FREQ(1400, 0, 3, 7, 0, 6, 1, 2, 0, 6, 2, 0, 175, 3, 0), - APLL_FREQ(1300, 0, 3, 7, 0, 5, 1, 2, 0, 5, 2, 0, 325, 6, 0), - APLL_FREQ(1200, 0, 3, 7, 0, 5, 1, 2, 0, 5, 2, 0, 200, 4, 0), - APLL_FREQ(1100, 0, 3, 6, 0, 4, 1, 2, 0, 4, 2, 0, 275, 6, 0), - APLL_FREQ(1000, 0, 2, 5, 0, 4, 1, 1, 0, 4, 2, 0, 125, 3, 0), - APLL_FREQ(900, 0, 2, 5, 0, 3, 1, 1, 0, 3, 2, 0, 150, 4, 0), - APLL_FREQ(800, 0, 2, 5, 0, 3, 1, 1, 0, 3, 2, 0, 100, 3, 0), - APLL_FREQ(700, 0, 2, 4, 0, 3, 1, 1, 0, 3, 2, 0, 175, 3, 1), - APLL_FREQ(600, 0, 2, 4, 0, 3, 1, 1, 0, 3, 2, 0, 200, 4, 1), - APLL_FREQ(500, 0, 2, 4, 0, 3, 1, 1, 0, 3, 2, 0, 125, 3, 1), - APLL_FREQ(400, 0, 2, 4, 0, 3, 1, 1, 0, 3, 2, 0, 100, 3, 1), - APLL_FREQ(300, 0, 2, 4, 0, 2, 1, 1, 0, 3, 2, 0, 200, 4, 2), - APLL_FREQ(200, 0, 1, 3, 0, 1, 1, 1, 0, 3, 2, 0, 100, 3, 2), -}; - -static struct apll_freq apll_freq_4412[] = { - /* - * values: - * freq - * clock divider for CORE, COREM0, COREM1, PERIPH, ATB, PCLK_DBG, APLL, CORE2 - * clock divider for COPY, HPM, CORES - * PLL M, P, S - */ - APLL_FREQ(1500, 0, 3, 7, 0, 6, 1, 2, 0, 6, 0, 7, 250, 4, 0), - APLL_FREQ(1400, 0, 3, 7, 0, 6, 1, 2, 0, 6, 0, 6, 175, 3, 0), - APLL_FREQ(1300, 0, 3, 7, 0, 5, 1, 2, 0, 5, 0, 6, 325, 6, 0), - APLL_FREQ(1200, 0, 3, 7, 0, 5, 1, 2, 0, 5, 0, 5, 200, 4, 0), - APLL_FREQ(1100, 0, 3, 6, 0, 4, 1, 2, 0, 4, 0, 5, 275, 6, 0), - APLL_FREQ(1000, 0, 2, 5, 0, 4, 1, 1, 0, 4, 0, 4, 125, 3, 0), - APLL_FREQ(900, 0, 2, 5, 0, 3, 1, 1, 0, 3, 0, 4, 150, 4, 0), - APLL_FREQ(800, 0, 2, 5, 0, 3, 1, 1, 0, 3, 0, 3, 100, 3, 0), - APLL_FREQ(700, 0, 2, 4, 0, 3, 1, 1, 0, 3, 0, 3, 175, 3, 1), - APLL_FREQ(600, 0, 2, 4, 0, 3, 1, 1, 0, 3, 0, 2, 200, 4, 1), - APLL_FREQ(500, 0, 2, 4, 0, 3, 1, 1, 0, 3, 0, 2, 125, 3, 1), - APLL_FREQ(400, 0, 2, 4, 0, 3, 1, 1, 0, 3, 0, 1, 100, 3, 1), - APLL_FREQ(300, 0, 2, 4, 0, 2, 1, 1, 0, 3, 0, 1, 200, 4, 2), - APLL_FREQ(200, 0, 1, 3, 0, 1, 1, 1, 0, 3, 0, 0, 100, 3, 2), -}; - -static void exynos4x12_set_clkdiv(unsigned int div_index) -{ - unsigned int tmp; - - /* Change Divider - CPU0 */ - - tmp = apll_freq_4x12[div_index].clk_div_cpu0; - - __raw_writel(tmp, cpufreq->cmu_regs + EXYNOS4_CLKDIV_CPU); - - while (__raw_readl(cpufreq->cmu_regs + EXYNOS4_CLKDIV_STATCPU) - & 0x11111111) - cpu_relax(); - - /* Change Divider - CPU1 */ - tmp = apll_freq_4x12[div_index].clk_div_cpu1; - - __raw_writel(tmp, cpufreq->cmu_regs + EXYNOS4_CLKDIV_CPU1); - - do { - cpu_relax(); - tmp = __raw_readl(cpufreq->cmu_regs + EXYNOS4_CLKDIV_STATCPU1); - } while (tmp != 0x0); -} - -static void exynos4x12_set_apll(unsigned int index) -{ - unsigned int tmp, freq = apll_freq_4x12[index].freq; - - /* MUX_CORE_SEL = MPLL, ARMCLK uses MPLL for lock time */ - clk_set_parent(moutcore, mout_mpll); - - do { - cpu_relax(); - tmp = (__raw_readl(cpufreq->cmu_regs + EXYNOS4_CLKMUX_STATCPU) - >> EXYNOS4_CLKSRC_CPU_MUXCORE_SHIFT); - tmp &= 0x7; - } while (tmp != 0x2); - - clk_set_rate(mout_apll, freq * 1000); - - /* MUX_CORE_SEL = APLL */ - clk_set_parent(moutcore, mout_apll); - - do { - cpu_relax(); - tmp = __raw_readl(cpufreq->cmu_regs + EXYNOS4_CLKMUX_STATCPU); - tmp &= EXYNOS4_CLKMUX_STATCPU_MUXCORE_MASK; - } while (tmp != (0x1 << EXYNOS4_CLKSRC_CPU_MUXCORE_SHIFT)); -} - -static void exynos4x12_set_frequency(unsigned int old_index, - unsigned int new_index) -{ - if (old_index > new_index) { - exynos4x12_set_clkdiv(new_index); - exynos4x12_set_apll(new_index); - } else if (old_index < new_index) { - exynos4x12_set_apll(new_index); - exynos4x12_set_clkdiv(new_index); - } -} - -int exynos4x12_cpufreq_init(struct exynos_dvfs_info *info) -{ - struct device_node *np; - unsigned long rate; - - /* - * HACK: This is a temporary workaround to get access to clock - * controller registers directly and remove static mappings and - * dependencies on platform headers. It is necessary to enable - * Exynos multi-platform support and will be removed together with - * this whole driver as soon as Exynos gets migrated to use - * cpufreq-dt driver. - */ - np = of_find_compatible_node(NULL, NULL, "samsung,exynos4412-clock"); - if (!np) { - pr_err("%s: failed to find clock controller DT node\n", - __func__); - return -ENODEV; - } - - info->cmu_regs = of_iomap(np, 0); - if (!info->cmu_regs) { - pr_err("%s: failed to map CMU registers\n", __func__); - return -EFAULT; - } - - cpu_clk = clk_get(NULL, "armclk"); - if (IS_ERR(cpu_clk)) - return PTR_ERR(cpu_clk); - - moutcore = clk_get(NULL, "moutcore"); - if (IS_ERR(moutcore)) - goto err_moutcore; - - mout_mpll = clk_get(NULL, "mout_mpll"); - if (IS_ERR(mout_mpll)) - goto err_mout_mpll; - - rate = clk_get_rate(mout_mpll) / 1000; - - mout_apll = clk_get(NULL, "mout_apll"); - if (IS_ERR(mout_apll)) - goto err_mout_apll; - - if (info->type == EXYNOS_SOC_4212) - apll_freq_4x12 = apll_freq_4212; - else - apll_freq_4x12 = apll_freq_4412; - - info->mpll_freq_khz = rate; - /* 800Mhz */ - info->pll_safe_idx = L7; - info->cpu_clk = cpu_clk; - info->volt_table = exynos4x12_volt_table; - info->freq_table = exynos4x12_freq_table; - info->set_freq = exynos4x12_set_frequency; - - cpufreq = info; - - return 0; - -err_mout_apll: - clk_put(mout_mpll); -err_mout_mpll: - clk_put(moutcore); -err_moutcore: - clk_put(cpu_clk); - - pr_debug("%s: failed initialization\n", __func__); - return -EINVAL; -} diff --git a/drivers/cpufreq/exynos5250-cpufreq.c b/drivers/cpufreq/exynos5250-cpufreq.c deleted file mode 100644 index 3eafdc7ba787..000000000000 --- a/drivers/cpufreq/exynos5250-cpufreq.c +++ /dev/null @@ -1,210 +0,0 @@ -/* - * Copyright (c) 2010-20122Samsung Electronics Co., Ltd. - * http://www.samsung.com - * - * EXYNOS5250 - CPU frequency scaling support - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. -*/ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/err.h> -#include <linux/clk.h> -#include <linux/io.h> -#include <linux/slab.h> -#include <linux/cpufreq.h> -#include <linux/of.h> -#include <linux/of_address.h> - -#include "exynos-cpufreq.h" - -static struct clk *cpu_clk; -static struct clk *moutcore; -static struct clk *mout_mpll; -static struct clk *mout_apll; -static struct exynos_dvfs_info *cpufreq; - -static unsigned int exynos5250_volt_table[] = { - 1300000, 1250000, 1225000, 1200000, 1150000, - 1125000, 1100000, 1075000, 1050000, 1025000, - 1012500, 1000000, 975000, 950000, 937500, - 925000 -}; - -static struct cpufreq_frequency_table exynos5250_freq_table[] = { - {0, L0, 1700 * 1000}, - {0, L1, 1600 * 1000}, - {0, L2, 1500 * 1000}, - {0, L3, 1400 * 1000}, - {0, L4, 1300 * 1000}, - {0, L5, 1200 * 1000}, - {0, L6, 1100 * 1000}, - {0, L7, 1000 * 1000}, - {0, L8, 900 * 1000}, - {0, L9, 800 * 1000}, - {0, L10, 700 * 1000}, - {0, L11, 600 * 1000}, - {0, L12, 500 * 1000}, - {0, L13, 400 * 1000}, - {0, L14, 300 * 1000}, - {0, L15, 200 * 1000}, - {0, 0, CPUFREQ_TABLE_END}, -}; - -static struct apll_freq apll_freq_5250[] = { - /* - * values: - * freq - * clock divider for ARM, CPUD, ACP, PERIPH, ATB, PCLK_DBG, APLL, ARM2 - * clock divider for COPY, HPM, RESERVED - * PLL M, P, S - */ - APLL_FREQ(1700, 0, 3, 7, 7, 7, 3, 5, 0, 0, 2, 0, 425, 6, 0), - APLL_FREQ(1600, 0, 3, 7, 7, 7, 1, 4, 0, 0, 2, 0, 200, 3, 0), - APLL_FREQ(1500, 0, 2, 7, 7, 7, 1, 4, 0, 0, 2, 0, 250, 4, 0), - APLL_FREQ(1400, 0, 2, 7, 7, 6, 1, 4, 0, 0, 2, 0, 175, 3, 0), - APLL_FREQ(1300, 0, 2, 7, 7, 6, 1, 3, 0, 0, 2, 0, 325, 6, 0), - APLL_FREQ(1200, 0, 2, 7, 7, 5, 1, 3, 0, 0, 2, 0, 200, 4, 0), - APLL_FREQ(1100, 0, 3, 7, 7, 5, 1, 3, 0, 0, 2, 0, 275, 6, 0), - APLL_FREQ(1000, 0, 1, 7, 7, 4, 1, 2, 0, 0, 2, 0, 125, 3, 0), - APLL_FREQ(900, 0, 1, 7, 7, 4, 1, 2, 0, 0, 2, 0, 150, 4, 0), - APLL_FREQ(800, 0, 1, 7, 7, 4, 1, 2, 0, 0, 2, 0, 100, 3, 0), - APLL_FREQ(700, 0, 1, 7, 7, 3, 1, 1, 0, 0, 2, 0, 175, 3, 1), - APLL_FREQ(600, 0, 1, 7, 7, 3, 1, 1, 0, 0, 2, 0, 200, 4, 1), - APLL_FREQ(500, 0, 1, 7, 7, 2, 1, 1, 0, 0, 2, 0, 125, 3, 1), - APLL_FREQ(400, 0, 1, 7, 7, 2, 1, 1, 0, 0, 2, 0, 100, 3, 1), - APLL_FREQ(300, 0, 1, 7, 7, 1, 1, 1, 0, 0, 2, 0, 200, 4, 2), - APLL_FREQ(200, 0, 1, 7, 7, 1, 1, 1, 0, 0, 2, 0, 100, 3, 2), -}; - -static void set_clkdiv(unsigned int div_index) -{ - unsigned int tmp; - - /* Change Divider - CPU0 */ - - tmp = apll_freq_5250[div_index].clk_div_cpu0; - - __raw_writel(tmp, cpufreq->cmu_regs + EXYNOS5_CLKDIV_CPU0); - - while (__raw_readl(cpufreq->cmu_regs + EXYNOS5_CLKDIV_STATCPU0) - & 0x11111111) - cpu_relax(); - - /* Change Divider - CPU1 */ - tmp = apll_freq_5250[div_index].clk_div_cpu1; - - __raw_writel(tmp, cpufreq->cmu_regs + EXYNOS5_CLKDIV_CPU1); - - while (__raw_readl(cpufreq->cmu_regs + EXYNOS5_CLKDIV_STATCPU1) & 0x11) - cpu_relax(); -} - -static void set_apll(unsigned int index) -{ - unsigned int tmp; - unsigned int freq = apll_freq_5250[index].freq; - - /* MUX_CORE_SEL = MPLL, ARMCLK uses MPLL for lock time */ - clk_set_parent(moutcore, mout_mpll); - - do { - cpu_relax(); - tmp = (__raw_readl(cpufreq->cmu_regs + EXYNOS5_CLKMUX_STATCPU) - >> 16); - tmp &= 0x7; - } while (tmp != 0x2); - - clk_set_rate(mout_apll, freq * 1000); - - /* MUX_CORE_SEL = APLL */ - clk_set_parent(moutcore, mout_apll); - - do { - cpu_relax(); - tmp = __raw_readl(cpufreq->cmu_regs + EXYNOS5_CLKMUX_STATCPU); - tmp &= (0x7 << 16); - } while (tmp != (0x1 << 16)); -} - -static void exynos5250_set_frequency(unsigned int old_index, - unsigned int new_index) -{ - if (old_index > new_index) { - set_clkdiv(new_index); - set_apll(new_index); - } else if (old_index < new_index) { - set_apll(new_index); - set_clkdiv(new_index); - } -} - -int exynos5250_cpufreq_init(struct exynos_dvfs_info *info) -{ - struct device_node *np; - unsigned long rate; - - /* - * HACK: This is a temporary workaround to get access to clock - * controller registers directly and remove static mappings and - * dependencies on platform headers. It is necessary to enable - * Exynos multi-platform support and will be removed together with - * this whole driver as soon as Exynos gets migrated to use - * cpufreq-dt driver. - */ - np = of_find_compatible_node(NULL, NULL, "samsung,exynos5250-clock"); - if (!np) { - pr_err("%s: failed to find clock controller DT node\n", - __func__); - return -ENODEV; - } - - info->cmu_regs = of_iomap(np, 0); - if (!info->cmu_regs) { - pr_err("%s: failed to map CMU registers\n", __func__); - return -EFAULT; - } - - cpu_clk = clk_get(NULL, "armclk"); - if (IS_ERR(cpu_clk)) - return PTR_ERR(cpu_clk); - - moutcore = clk_get(NULL, "mout_cpu"); - if (IS_ERR(moutcore)) - goto err_moutcore; - - mout_mpll = clk_get(NULL, "mout_mpll"); - if (IS_ERR(mout_mpll)) - goto err_mout_mpll; - - rate = clk_get_rate(mout_mpll) / 1000; - - mout_apll = clk_get(NULL, "mout_apll"); - if (IS_ERR(mout_apll)) - goto err_mout_apll; - - info->mpll_freq_khz = rate; - /* 800Mhz */ - info->pll_safe_idx = L9; - info->cpu_clk = cpu_clk; - info->volt_table = exynos5250_volt_table; - info->freq_table = exynos5250_freq_table; - info->set_freq = exynos5250_set_frequency; - - cpufreq = info; - - return 0; - -err_mout_apll: - clk_put(mout_mpll); -err_mout_mpll: - clk_put(moutcore); -err_moutcore: - clk_put(cpu_clk); - - pr_err("%s: failed initialization\n", __func__); - return -EINVAL; -} diff --git a/drivers/input/misc/xen-kbdfront.c b/drivers/input/misc/xen-kbdfront.c index 95599e478e19..23d0549539d4 100644 --- a/drivers/input/misc/xen-kbdfront.c +++ b/drivers/input/misc/xen-kbdfront.c @@ -232,7 +232,7 @@ static int xenkbd_connect_backend(struct xenbus_device *dev, struct xenbus_transaction xbt; ret = gnttab_grant_foreign_access(dev->otherend_id, - virt_to_mfn(info->page), 0); + virt_to_gfn(info->page), 0); if (ret < 0) return ret; info->gref = ret; @@ -255,7 +255,7 @@ static int xenkbd_connect_backend(struct xenbus_device *dev, goto error_irqh; } ret = xenbus_printf(xbt, dev->nodename, "page-ref", "%lu", - virt_to_mfn(info->page)); + virt_to_gfn(info->page)); if (ret) goto error_xenbus; ret = xenbus_printf(xbt, dev->nodename, "page-gref", "%u", info->gref); diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile index 1f897ec3c242..075a027632b5 100644 --- a/drivers/mtd/nand/Makefile +++ b/drivers/mtd/nand/Makefile @@ -26,7 +26,8 @@ obj-$(CONFIG_MTD_NAND_CS553X) += cs553x_nand.o obj-$(CONFIG_MTD_NAND_NDFC) += ndfc.o obj-$(CONFIG_MTD_NAND_ATMEL) += atmel_nand.o obj-$(CONFIG_MTD_NAND_GPIO) += gpio.o -obj-$(CONFIG_MTD_NAND_OMAP2) += omap2.o +omap2_nand-objs := omap2.o +obj-$(CONFIG_MTD_NAND_OMAP2) += omap2_nand.o obj-$(CONFIG_MTD_NAND_OMAP_BCH_BUILD) += omap_elm.o obj-$(CONFIG_MTD_NAND_CM_X270) += cmx270_nand.o obj-$(CONFIG_MTD_NAND_PXA3xx) += pxa3xx_nand.o diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index c27d427fead4..f59aedfe1462 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -586,6 +586,7 @@ static const struct flash_info spi_nor_ids[] = { /* Micron */ { "n25q032", INFO(0x20ba16, 0, 64 * 1024, 64, SPI_NOR_QUAD_READ) }, { "n25q064", INFO(0x20ba17, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_QUAD_READ) }, + { "n25q064a", INFO(0x20bb17, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_QUAD_READ) }, { "n25q128a11", INFO(0x20bb18, 0, 64 * 1024, 256, SPI_NOR_QUAD_READ) }, { "n25q128a13", INFO(0x20ba18, 0, 64 * 1024, 256, SPI_NOR_QUAD_READ) }, { "n25q256a", INFO(0x20ba19, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_QUAD_READ) }, @@ -602,7 +603,7 @@ static const struct flash_info spi_nor_ids[] = { * for the chips listed here (without boot sectors). */ { "s25sl032p", INFO(0x010215, 0x4d00, 64 * 1024, 64, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, - { "s25sl064p", INFO(0x010216, 0x4d00, 64 * 1024, 128, 0) }, + { "s25sl064p", INFO(0x010216, 0x4d00, 64 * 1024, 128, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, { "s25fl256s0", INFO(0x010219, 0x4d00, 256 * 1024, 128, 0) }, { "s25fl256s1", INFO(0x010219, 0x4d01, 64 * 1024, 512, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, { "s25fl512s", INFO(0x010220, 0x4d00, 256 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, @@ -610,8 +611,8 @@ static const struct flash_info spi_nor_ids[] = { { "s25sl12800", INFO(0x012018, 0x0300, 256 * 1024, 64, 0) }, { "s25sl12801", INFO(0x012018, 0x0301, 64 * 1024, 256, 0) }, { "s25fl128s", INFO6(0x012018, 0x4d0180, 64 * 1024, 256, SECT_4K | SPI_NOR_QUAD_READ) }, - { "s25fl129p0", INFO(0x012018, 0x4d00, 256 * 1024, 64, 0) }, - { "s25fl129p1", INFO(0x012018, 0x4d01, 64 * 1024, 256, 0) }, + { "s25fl129p0", INFO(0x012018, 0x4d00, 256 * 1024, 64, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, + { "s25fl129p1", INFO(0x012018, 0x4d01, 64 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, { "s25sl004a", INFO(0x010212, 0, 64 * 1024, 8, 0) }, { "s25sl008a", INFO(0x010213, 0, 64 * 1024, 16, 0) }, { "s25sl016a", INFO(0x010214, 0, 64 * 1024, 32, 0) }, @@ -633,6 +634,7 @@ static const struct flash_info spi_nor_ids[] = { { "sst25wf512", INFO(0xbf2501, 0, 64 * 1024, 1, SECT_4K | SST_WRITE) }, { "sst25wf010", INFO(0xbf2502, 0, 64 * 1024, 2, SECT_4K | SST_WRITE) }, { "sst25wf020", INFO(0xbf2503, 0, 64 * 1024, 4, SECT_4K | SST_WRITE) }, + { "sst25wf020a", INFO(0x621612, 0, 64 * 1024, 4, SECT_4K) }, { "sst25wf040", INFO(0xbf2504, 0, 64 * 1024, 8, SECT_4K | SST_WRITE) }, { "sst25wf080", INFO(0xbf2505, 0, 64 * 1024, 16, SECT_4K | SST_WRITE) }, @@ -1216,7 +1218,7 @@ static const struct flash_info *spi_nor_match_id(const char *name) { const struct flash_info *id = spi_nor_ids; - while (id->name[0]) { + while (id->name) { if (!strcmp(name, id->name)) return id; id++; diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c index 289e20443d83..9d56515f4c4d 100644 --- a/drivers/net/dsa/bcm_sf2.c +++ b/drivers/net/dsa/bcm_sf2.c @@ -418,7 +418,7 @@ static int bcm_sf2_sw_fast_age_port(struct dsa_switch *ds, int port) core_writel(priv, port, CORE_FAST_AGE_PORT); reg = core_readl(priv, CORE_FAST_AGE_CTRL); - reg |= EN_AGE_PORT | FAST_AGE_STR_DONE; + reg |= EN_AGE_PORT | EN_AGE_DYNAMIC | FAST_AGE_STR_DONE; core_writel(priv, reg, CORE_FAST_AGE_CTRL); do { @@ -432,6 +432,8 @@ static int bcm_sf2_sw_fast_age_port(struct dsa_switch *ds, int port) if (!timeout) return -ETIMEDOUT; + core_writel(priv, 0, CORE_FAST_AGE_CTRL); + return 0; } @@ -507,7 +509,7 @@ static int bcm_sf2_sw_br_set_stp_state(struct dsa_switch *ds, int port, u32 reg; reg = core_readl(priv, CORE_G_PCTL_PORT(port)); - cur_hw_state = reg >> G_MISTP_STATE_SHIFT; + cur_hw_state = reg & (G_MISTP_STATE_MASK << G_MISTP_STATE_SHIFT); switch (state) { case BR_STATE_DISABLED: @@ -531,10 +533,12 @@ static int bcm_sf2_sw_br_set_stp_state(struct dsa_switch *ds, int port, } /* Fast-age ARL entries if we are moving a port from Learning or - * Forwarding state to Disabled, Blocking or Listening state + * Forwarding (cur_hw_state) state to Disabled, Blocking or Listening + * state (hw_state) */ if (cur_hw_state != hw_state) { - if (cur_hw_state & 4 && !(hw_state & 4)) { + if (cur_hw_state >= G_MISTP_LEARN_STATE && + hw_state <= G_MISTP_LISTEN_STATE) { ret = bcm_sf2_sw_fast_age_port(ds, port); if (ret) { pr_err("%s: fast-ageing failed\n", __func__); diff --git a/drivers/net/dsa/bcm_sf2.h b/drivers/net/dsa/bcm_sf2.h index 22e2ebf31333..789d7b7737da 100644 --- a/drivers/net/dsa/bcm_sf2.h +++ b/drivers/net/dsa/bcm_sf2.h @@ -112,8 +112,8 @@ static inline u64 name##_readq(struct bcm_sf2_priv *priv, u32 off) \ spin_unlock(&priv->indir_lock); \ return (u64)indir << 32 | dir; \ } \ -static inline void name##_writeq(struct bcm_sf2_priv *priv, u32 off, \ - u64 val) \ +static inline void name##_writeq(struct bcm_sf2_priv *priv, u64 val, \ + u32 off) \ { \ spin_lock(&priv->indir_lock); \ reg_writel(priv, upper_32_bits(val), REG_DIR_DATA_WRITE); \ diff --git a/drivers/net/dsa/mv88e6171.c b/drivers/net/dsa/mv88e6171.c index d54b7400e8d8..c2daaf087761 100644 --- a/drivers/net/dsa/mv88e6171.c +++ b/drivers/net/dsa/mv88e6171.c @@ -117,6 +117,11 @@ struct dsa_switch_driver mv88e6171_switch_driver = { .port_join_bridge = mv88e6xxx_join_bridge, .port_leave_bridge = mv88e6xxx_leave_bridge, .port_stp_update = mv88e6xxx_port_stp_update, + .port_pvid_get = mv88e6xxx_port_pvid_get, + .port_pvid_set = mv88e6xxx_port_pvid_set, + .port_vlan_add = mv88e6xxx_port_vlan_add, + .port_vlan_del = mv88e6xxx_port_vlan_del, + .vlan_getnext = mv88e6xxx_vlan_getnext, .port_fdb_add = mv88e6xxx_port_fdb_add, .port_fdb_del = mv88e6xxx_port_fdb_del, .port_fdb_getnext = mv88e6xxx_port_fdb_getnext, diff --git a/drivers/net/ethernet/altera/altera_tse_main.c b/drivers/net/ethernet/altera/altera_tse_main.c index da48e66377b5..fe644823ceaf 100644 --- a/drivers/net/ethernet/altera/altera_tse_main.c +++ b/drivers/net/ethernet/altera/altera_tse_main.c @@ -511,8 +511,7 @@ static int tse_poll(struct napi_struct *napi, int budget) if (rxcomplete < budget) { - napi_gro_flush(napi, false); - __napi_complete(napi); + napi_complete(napi); netdev_dbg(priv->dev, "NAPI Complete, did %d packets with budget %d\n", @@ -1518,6 +1517,7 @@ static int altera_tse_probe(struct platform_device *pdev) spin_lock_init(&priv->tx_lock); spin_lock_init(&priv->rxdma_irq_lock); + netif_carrier_off(ndev); ret = register_netdev(ndev); if (ret) { dev_err(&pdev->dev, "failed to register TSE net device\n"); diff --git a/drivers/net/ethernet/cavium/liquidio/lio_main.c b/drivers/net/ethernet/cavium/liquidio/lio_main.c index 0660deecc2c9..f683d97d7614 100644 --- a/drivers/net/ethernet/cavium/liquidio/lio_main.c +++ b/drivers/net/ethernet/cavium/liquidio/lio_main.c @@ -818,10 +818,9 @@ static int setup_glist(struct lio *lio) INIT_LIST_HEAD(&lio->glist); for (i = 0; i < lio->tx_qsize; i++) { - g = kmalloc(sizeof(*g), GFP_KERNEL); + g = kzalloc(sizeof(*g), GFP_KERNEL); if (!g) break; - memset(g, 0, sizeof(struct octnic_gather)); g->sg_size = ((ROUNDUP4(OCTNIC_MAX_SG) >> 2) * OCT_SG_ENTRY_SIZE); diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c index eb22d58743e2..f5dcde27e402 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c @@ -4568,28 +4568,23 @@ static void free_some_resources(struct adapter *adapter) static int get_chip_type(struct pci_dev *pdev, u32 pl_rev) { - int ver, chip; u16 device_id; /* Retrieve adapter's device ID */ pci_read_config_word(pdev, PCI_DEVICE_ID, &device_id); - ver = device_id >> 12; - switch (ver) { + + switch (device_id >> 12) { case CHELSIO_T4: - chip |= CHELSIO_CHIP_CODE(CHELSIO_T4, pl_rev); - break; + return CHELSIO_CHIP_CODE(CHELSIO_T4, pl_rev); case CHELSIO_T5: - chip |= CHELSIO_CHIP_CODE(CHELSIO_T5, pl_rev); - break; + return CHELSIO_CHIP_CODE(CHELSIO_T5, pl_rev); case CHELSIO_T6: - chip |= CHELSIO_CHIP_CODE(CHELSIO_T6, pl_rev); - break; + return CHELSIO_CHIP_CODE(CHELSIO_T6, pl_rev); default: dev_err(&pdev->dev, "Device %d is not supported\n", device_id); - return -EINVAL; } - return chip; + return -EINVAL; } static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent) @@ -4724,8 +4719,6 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent) err = -ENOMEM; goto out_free_adapter; } - t4_write_reg(adapter, SGE_STAT_CFG_A, - STATSOURCE_T5_V(7) | STATMODE_V(0)); } setup_memwin(adapter); @@ -4737,6 +4730,11 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent) if (err) goto out_unmap_bar; + /* configure SGE_STAT_CFG_A to read WC stats */ + if (!is_t4(adapter->params.chip)) + t4_write_reg(adapter, SGE_STAT_CFG_A, + STATSOURCE_T5_V(7) | STATMODE_V(0)); + for_each_port(adapter, i) { struct net_device *netdev; diff --git a/drivers/net/ethernet/chelsio/cxgb4/sge.c b/drivers/net/ethernet/chelsio/cxgb4/sge.c index 78f446c58422..9162746d7729 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/sge.c +++ b/drivers/net/ethernet/chelsio/cxgb4/sge.c @@ -807,7 +807,7 @@ static inline unsigned int calc_tx_flits(const struct sk_buff *skb) * message or, if we're doing a Large Send Offload, an LSO CPL message * with an embedded TX Packet Write CPL message. */ - flits = sgl_len(skb_shinfo(skb)->nr_frags + 1) + 4; + flits = sgl_len(skb_shinfo(skb)->nr_frags + 1); if (skb_shinfo(skb)->gso_size) flits += (sizeof(struct fw_eth_tx_pkt_wr) + sizeof(struct cpl_tx_pkt_lso_core) + diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h b/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h index ab4674684acc..a32de30ea663 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h +++ b/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h @@ -762,8 +762,6 @@ enum fw_ldst_func_mod_index { struct fw_ldst_cmd { __be32 op_to_addrspace; -#define FW_LDST_CMD_ADDRSPACE_S 0 -#define FW_LDST_CMD_ADDRSPACE_V(x) ((x) << FW_LDST_CMD_ADDRSPACE_S) __be32 cycles_to_len16; union fw_ldst { struct fw_ldst_addrval { @@ -788,6 +786,13 @@ struct fw_ldst_cmd { __be16 vctl; __be16 rval; } mdio; + struct fw_ldst_cim_rq { + u8 req_first64[8]; + u8 req_second64[8]; + u8 resp_first64[8]; + u8 resp_second64[8]; + __be32 r3[2]; + } cim_rq; union fw_ldst_mps { struct fw_ldst_mps_rplc { __be16 fid_idx; @@ -828,9 +833,33 @@ struct fw_ldst_cmd { __be16 nset_pkd; __be32 data[12]; } pcie; + struct fw_ldst_i2c_deprecated { + u8 pid_pkd; + u8 base; + u8 boffset; + u8 data; + __be32 r9; + } i2c_deprecated; + struct fw_ldst_i2c { + u8 pid; + u8 did; + u8 boffset; + u8 blen; + __be32 r9; + __u8 data[48]; + } i2c; + struct fw_ldst_le { + __be32 index; + __be32 r9; + u8 val[33]; + u8 r11[7]; + } le; } u; }; +#define FW_LDST_CMD_ADDRSPACE_S 0 +#define FW_LDST_CMD_ADDRSPACE_V(x) ((x) << FW_LDST_CMD_ADDRSPACE_S) + #define FW_LDST_CMD_MSG_S 31 #define FW_LDST_CMD_MSG_V(x) ((x) << FW_LDST_CMD_MSG_S) diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4fw_version.h b/drivers/net/ethernet/chelsio/cxgb4/t4fw_version.h index 92bafa793de6..c4b262ca7d43 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/t4fw_version.h +++ b/drivers/net/ethernet/chelsio/cxgb4/t4fw_version.h @@ -36,8 +36,8 @@ #define __T4FW_VERSION_H__ #define T4FW_VERSION_MAJOR 0x01 -#define T4FW_VERSION_MINOR 0x0D -#define T4FW_VERSION_MICRO 0x20 +#define T4FW_VERSION_MINOR 0x0E +#define T4FW_VERSION_MICRO 0x04 #define T4FW_VERSION_BUILD 0x00 #define T4FW_MIN_VERSION_MAJOR 0x01 @@ -45,8 +45,8 @@ #define T4FW_MIN_VERSION_MICRO 0x00 #define T5FW_VERSION_MAJOR 0x01 -#define T5FW_VERSION_MINOR 0x0D -#define T5FW_VERSION_MICRO 0x20 +#define T5FW_VERSION_MINOR 0x0E +#define T5FW_VERSION_MICRO 0x04 #define T5FW_VERSION_BUILD 0x00 #define T5FW_MIN_VERSION_MAJOR 0x00 @@ -54,8 +54,8 @@ #define T5FW_MIN_VERSION_MICRO 0x00 #define T6FW_VERSION_MAJOR 0x01 -#define T6FW_VERSION_MINOR 0x0D -#define T6FW_VERSION_MICRO 0x2D +#define T6FW_VERSION_MINOR 0x0E +#define T6FW_VERSION_MICRO 0x04 #define T6FW_VERSION_BUILD 0x00 #define T6FW_MIN_VERSION_MAJOR 0x00 diff --git a/drivers/net/ethernet/davicom/dm9000.c b/drivers/net/ethernet/davicom/dm9000.c index c0a7813603c3..cf94b72dbacd 100644 --- a/drivers/net/ethernet/davicom/dm9000.c +++ b/drivers/net/ethernet/davicom/dm9000.c @@ -1226,7 +1226,7 @@ static irqreturn_t dm9000_interrupt(int irq, void *dev_id) if (int_status & ISR_PRS) dm9000_rx(dev); - /* Trnasmit Interrupt check */ + /* Transmit Interrupt check */ if (int_status & ISR_PTS) dm9000_tx_done(dev, db); diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c index 3be1fbdcdd02..eb323913cd39 100644 --- a/drivers/net/ethernet/emulex/benet/be_cmds.c +++ b/drivers/net/ethernet/emulex/benet/be_cmds.c @@ -1968,7 +1968,7 @@ static int __be_cmd_rx_filter(struct be_adapter *adapter, u32 flags, u32 value) memcpy(req->mcast_mac[i++].byte, ha->addr, ETH_ALEN); } - status = be_mcc_notify(adapter); + status = be_mcc_notify_wait(adapter); err: spin_unlock_bh(&adapter->mcc_lock); return status; diff --git a/drivers/net/ethernet/ethoc.c b/drivers/net/ethernet/ethoc.c index 442410cd2ca4..a2c96fd88393 100644 --- a/drivers/net/ethernet/ethoc.c +++ b/drivers/net/ethernet/ethoc.c @@ -1132,10 +1132,6 @@ static int ethoc_probe(struct platform_device *pdev) memcpy(netdev->dev_addr, pdata->hwaddr, IFHWADDRLEN); priv->phy_id = pdata->phy_id; } else { - priv->phy_id = -1; - -#ifdef CONFIG_OF - { const uint8_t *mac; mac = of_get_property(pdev->dev.of_node, @@ -1143,8 +1139,7 @@ static int ethoc_probe(struct platform_device *pdev) NULL); if (mac) memcpy(netdev->dev_addr, mac, IFHWADDRLEN); - } -#endif + priv->phy_id = -1; } /* Check that the given MAC address is valid. If it isn't, read the diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index 91925e38705e..dd4ca39d5d8f 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -1816,11 +1816,13 @@ static int fec_enet_mdio_write(struct mii_bus *bus, int mii_id, int regnum, struct fec_enet_private *fep = bus->priv; struct device *dev = &fep->pdev->dev; unsigned long time_left; - int ret = 0; + int ret; ret = pm_runtime_get_sync(dev); if (ret < 0) return ret; + else + ret = 0; fep->mii_timeout = 0; reinit_completion(&fep->mdio_done); @@ -3029,6 +3031,14 @@ fec_set_mac_address(struct net_device *ndev, void *p) memcpy(ndev->dev_addr, addr->sa_data, ndev->addr_len); } + /* Add netif status check here to avoid system hang in below case: + * ifconfig ethx down; ifconfig ethx hw ether xx:xx:xx:xx:xx:xx; + * After ethx down, fec all clocks are gated off and then register + * access causes system hang. + */ + if (!netif_running(ndev)) + return 0; + writel(ndev->dev_addr[3] | (ndev->dev_addr[2] << 8) | (ndev->dev_addr[1] << 16) | (ndev->dev_addr[0] << 24), fep->hwp + FEC_ADDR_LOW); diff --git a/drivers/net/ethernet/jme.c b/drivers/net/ethernet/jme.c index 6e9a792097d3..060dd3922974 100644 --- a/drivers/net/ethernet/jme.c +++ b/drivers/net/ethernet/jme.c @@ -583,7 +583,7 @@ jme_setup_tx_resources(struct jme_adapter *jme) atomic_set(&txring->next_to_clean, 0); atomic_set(&txring->nr_free, jme->tx_ring_size); - txring->bufinf = kmalloc(sizeof(struct jme_buffer_info) * + txring->bufinf = kzalloc(sizeof(struct jme_buffer_info) * jme->tx_ring_size, GFP_ATOMIC); if (unlikely(!(txring->bufinf))) goto err_free_txring; @@ -592,8 +592,6 @@ jme_setup_tx_resources(struct jme_adapter *jme) * Initialize Transmit Descriptors */ memset(txring->alloc, 0, TX_RING_ALLOC_SIZE(jme->tx_ring_size)); - memset(txring->bufinf, 0, - sizeof(struct jme_buffer_info) * jme->tx_ring_size); return 0; @@ -845,7 +843,7 @@ jme_setup_rx_resources(struct jme_adapter *jme) rxring->next_to_use = 0; atomic_set(&rxring->next_to_clean, 0); - rxring->bufinf = kmalloc(sizeof(struct jme_buffer_info) * + rxring->bufinf = kzalloc(sizeof(struct jme_buffer_info) * jme->rx_ring_size, GFP_ATOMIC); if (unlikely(!(rxring->bufinf))) goto err_free_rxring; @@ -853,8 +851,6 @@ jme_setup_rx_resources(struct jme_adapter *jme) /* * Initiallize Receive Descriptors */ - memset(rxring->bufinf, 0, - sizeof(struct jme_buffer_info) * jme->rx_ring_size); for (i = 0 ; i < jme->rx_ring_size ; ++i) { if (unlikely(jme_make_new_rx_buf(jme, i))) { jme_free_rx_resources(jme); diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c index d52639bc491f..960169efe636 100644 --- a/drivers/net/ethernet/marvell/mv643xx_eth.c +++ b/drivers/net/ethernet/marvell/mv643xx_eth.c @@ -1859,14 +1859,11 @@ oom: return; } - mc_spec = kmalloc(0x200, GFP_ATOMIC); + mc_spec = kzalloc(0x200, GFP_ATOMIC); if (mc_spec == NULL) goto oom; mc_other = mc_spec + (0x100 >> 2); - memset(mc_spec, 0, 0x100); - memset(mc_other, 0, 0x100); - netdev_for_each_mc_addr(ha, dev) { u8 *a = ha->addr; u32 *table; diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c index 5ab3adf88166..9f0bdd993955 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c @@ -918,8 +918,6 @@ int qlcnic_83xx_alloc_mbx_args(struct qlcnic_cmd_args *mbx, mbx->req.arg = NULL; return -ENOMEM; } - memset(mbx->req.arg, 0, sizeof(u32) * mbx->req.num); - memset(mbx->rsp.arg, 0, sizeof(u32) * mbx->rsp.num); temp = adapter->ahw->fw_hal_version << 29; mbx->req.arg[0] = (type | (mbx->req.num << 16) | temp); mbx->cmd_op = type; diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c index 6e6f18fc5d76..a5f422f26cb4 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c @@ -73,8 +73,6 @@ int qlcnic_82xx_alloc_mbx_args(struct qlcnic_cmd_args *mbx, mbx->req.arg = NULL; return -ENOMEM; } - memset(mbx->req.arg, 0, sizeof(u32) * mbx->req.num); - memset(mbx->rsp.arg, 0, sizeof(u32) * mbx->rsp.num); mbx->req.arg[0] = type; break; } diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c index 546cd5f1c85a..7327b729ba2e 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c @@ -729,8 +729,6 @@ static int qlcnic_sriov_alloc_bc_mbx_args(struct qlcnic_cmd_args *mbx, u32 type) mbx->req.arg = NULL; return -ENOMEM; } - memset(mbx->req.arg, 0, sizeof(u32) * mbx->req.num); - memset(mbx->rsp.arg, 0, sizeof(u32) * mbx->rsp.num); mbx->req.arg[0] = (type | (mbx->req.num << 16) | (3 << 29)); mbx->rsp.arg[0] = (type & 0xffff) | mbx->rsp.num << 16; diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c index 24dcbe62412a..2b32e0c5a0b4 100644 --- a/drivers/net/ethernet/realtek/r8169.c +++ b/drivers/net/ethernet/realtek/r8169.c @@ -833,7 +833,8 @@ struct rtl8169_private { unsigned features; struct mii_if_info mii; - struct rtl8169_counters counters; + dma_addr_t counters_phys_addr; + struct rtl8169_counters *counters; struct rtl8169_tc_offsets tc_offset; u32 saved_wolopts; u32 opts1_mask; @@ -2190,53 +2191,37 @@ static int rtl8169_get_sset_count(struct net_device *dev, int sset) } } -static struct rtl8169_counters *rtl8169_map_counters(struct net_device *dev, - dma_addr_t *paddr, - u32 counter_cmd) +DECLARE_RTL_COND(rtl_counters_cond) { - struct rtl8169_private *tp = netdev_priv(dev); void __iomem *ioaddr = tp->mmio_addr; - struct device *d = &tp->pci_dev->dev; - struct rtl8169_counters *counters; - u32 cmd; - counters = dma_alloc_coherent(d, sizeof(*counters), paddr, GFP_KERNEL); - if (counters) { - RTL_W32(CounterAddrHigh, (u64)*paddr >> 32); - cmd = (u64)*paddr & DMA_BIT_MASK(32); - RTL_W32(CounterAddrLow, cmd); - RTL_W32(CounterAddrLow, cmd | counter_cmd); - } - return counters; + return RTL_R32(CounterAddrLow) & (CounterReset | CounterDump); } -static void rtl8169_unmap_counters (struct net_device *dev, - dma_addr_t paddr, - struct rtl8169_counters *counters) +static bool rtl8169_do_counters(struct net_device *dev, u32 counter_cmd) { struct rtl8169_private *tp = netdev_priv(dev); void __iomem *ioaddr = tp->mmio_addr; - struct device *d = &tp->pci_dev->dev; + dma_addr_t paddr = tp->counters_phys_addr; + u32 cmd; + bool ret; - RTL_W32(CounterAddrLow, 0); - RTL_W32(CounterAddrHigh, 0); + RTL_W32(CounterAddrHigh, (u64)paddr >> 32); + cmd = (u64)paddr & DMA_BIT_MASK(32); + RTL_W32(CounterAddrLow, cmd); + RTL_W32(CounterAddrLow, cmd | counter_cmd); - dma_free_coherent(d, sizeof(*counters), counters, paddr); -} + ret = rtl_udelay_loop_wait_low(tp, &rtl_counters_cond, 10, 1000); -DECLARE_RTL_COND(rtl_reset_counters_cond) -{ - void __iomem *ioaddr = tp->mmio_addr; + RTL_W32(CounterAddrLow, 0); + RTL_W32(CounterAddrHigh, 0); - return RTL_R32(CounterAddrLow) & CounterReset; + return ret; } static bool rtl8169_reset_counters(struct net_device *dev) { struct rtl8169_private *tp = netdev_priv(dev); - struct rtl8169_counters *counters; - dma_addr_t paddr; - bool ret = true; /* * Versions prior to RTL_GIGA_MAC_VER_19 don't support resetting the @@ -2245,32 +2230,13 @@ static bool rtl8169_reset_counters(struct net_device *dev) if (tp->mac_version < RTL_GIGA_MAC_VER_19) return true; - counters = rtl8169_map_counters(dev, &paddr, CounterReset); - if (!counters) - return false; - - if (!rtl_udelay_loop_wait_low(tp, &rtl_reset_counters_cond, 10, 1000)) - ret = false; - - rtl8169_unmap_counters(dev, paddr, counters); - - return ret; -} - -DECLARE_RTL_COND(rtl_counters_cond) -{ - void __iomem *ioaddr = tp->mmio_addr; - - return RTL_R32(CounterAddrLow) & CounterDump; + return rtl8169_do_counters(dev, CounterReset); } static bool rtl8169_update_counters(struct net_device *dev) { struct rtl8169_private *tp = netdev_priv(dev); void __iomem *ioaddr = tp->mmio_addr; - struct rtl8169_counters *counters; - dma_addr_t paddr; - bool ret = true; /* * Some chips are unable to dump tally counters when the receiver @@ -2279,23 +2245,13 @@ static bool rtl8169_update_counters(struct net_device *dev) if ((RTL_R8(ChipCmd) & CmdRxEnb) == 0) return true; - counters = rtl8169_map_counters(dev, &paddr, CounterDump); - if (!counters) - return false; - - if (rtl_udelay_loop_wait_low(tp, &rtl_counters_cond, 10, 1000)) - memcpy(&tp->counters, counters, sizeof(*counters)); - else - ret = false; - - rtl8169_unmap_counters(dev, paddr, counters); - - return ret; + return rtl8169_do_counters(dev, CounterDump); } static bool rtl8169_init_counter_offsets(struct net_device *dev) { struct rtl8169_private *tp = netdev_priv(dev); + struct rtl8169_counters *counters = tp->counters; bool ret = false; /* @@ -2323,9 +2279,9 @@ static bool rtl8169_init_counter_offsets(struct net_device *dev) if (rtl8169_update_counters(dev)) ret = true; - tp->tc_offset.tx_errors = tp->counters.tx_errors; - tp->tc_offset.tx_multi_collision = tp->counters.tx_multi_collision; - tp->tc_offset.tx_aborted = tp->counters.tx_aborted; + tp->tc_offset.tx_errors = counters->tx_errors; + tp->tc_offset.tx_multi_collision = counters->tx_multi_collision; + tp->tc_offset.tx_aborted = counters->tx_aborted; tp->tc_offset.inited = true; return ret; @@ -2335,24 +2291,25 @@ static void rtl8169_get_ethtool_stats(struct net_device *dev, struct ethtool_stats *stats, u64 *data) { struct rtl8169_private *tp = netdev_priv(dev); + struct rtl8169_counters *counters = tp->counters; ASSERT_RTNL(); rtl8169_update_counters(dev); - data[0] = le64_to_cpu(tp->counters.tx_packets); - data[1] = le64_to_cpu(tp->counters.rx_packets); - data[2] = le64_to_cpu(tp->counters.tx_errors); - data[3] = le32_to_cpu(tp->counters.rx_errors); - data[4] = le16_to_cpu(tp->counters.rx_missed); - data[5] = le16_to_cpu(tp->counters.align_errors); - data[6] = le32_to_cpu(tp->counters.tx_one_collision); - data[7] = le32_to_cpu(tp->counters.tx_multi_collision); - data[8] = le64_to_cpu(tp->counters.rx_unicast); - data[9] = le64_to_cpu(tp->counters.rx_broadcast); - data[10] = le32_to_cpu(tp->counters.rx_multicast); - data[11] = le16_to_cpu(tp->counters.tx_aborted); - data[12] = le16_to_cpu(tp->counters.tx_underun); + data[0] = le64_to_cpu(counters->tx_packets); + data[1] = le64_to_cpu(counters->rx_packets); + data[2] = le64_to_cpu(counters->tx_errors); + data[3] = le32_to_cpu(counters->rx_errors); + data[4] = le16_to_cpu(counters->rx_missed); + data[5] = le16_to_cpu(counters->align_errors); + data[6] = le32_to_cpu(counters->tx_one_collision); + data[7] = le32_to_cpu(counters->tx_multi_collision); + data[8] = le64_to_cpu(counters->rx_unicast); + data[9] = le64_to_cpu(counters->rx_broadcast); + data[10] = le32_to_cpu(counters->rx_multicast); + data[11] = le16_to_cpu(counters->tx_aborted); + data[12] = le16_to_cpu(counters->tx_underun); } static void rtl8169_get_strings(struct net_device *dev, u32 stringset, u8 *data) @@ -7780,6 +7737,7 @@ rtl8169_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats) { struct rtl8169_private *tp = netdev_priv(dev); void __iomem *ioaddr = tp->mmio_addr; + struct rtl8169_counters *counters = tp->counters; unsigned int start; if (netif_running(dev)) @@ -7816,11 +7774,11 @@ rtl8169_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats) * Subtract values fetched during initalization. * See rtl8169_init_counter_offsets for a description why we do that. */ - stats->tx_errors = le64_to_cpu(tp->counters.tx_errors) - + stats->tx_errors = le64_to_cpu(counters->tx_errors) - le64_to_cpu(tp->tc_offset.tx_errors); - stats->collisions = le32_to_cpu(tp->counters.tx_multi_collision) - + stats->collisions = le32_to_cpu(counters->tx_multi_collision) - le32_to_cpu(tp->tc_offset.tx_multi_collision); - stats->tx_aborted_errors = le16_to_cpu(tp->counters.tx_aborted) - + stats->tx_aborted_errors = le16_to_cpu(counters->tx_aborted) - le16_to_cpu(tp->tc_offset.tx_aborted); return stats; @@ -8022,6 +7980,9 @@ static void rtl_remove_one(struct pci_dev *pdev) unregister_netdev(dev); + dma_free_coherent(&tp->pci_dev->dev, sizeof(*tp->counters), + tp->counters, tp->counters_phys_addr); + rtl_release_firmware(tp); if (pci_dev_run_wake(pdev)) @@ -8447,9 +8408,16 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) tp->rtl_fw = RTL_FIRMWARE_UNKNOWN; + tp->counters = dma_alloc_coherent (&pdev->dev, sizeof(*tp->counters), + &tp->counters_phys_addr, GFP_KERNEL); + if (!tp->counters) { + rc = -ENOMEM; + goto err_out_msi_4; + } + rc = register_netdev(dev); if (rc < 0) - goto err_out_msi_4; + goto err_out_cnt_5; pci_set_drvdata(pdev, dev); @@ -8483,6 +8451,9 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) out: return rc; +err_out_cnt_5: + dma_free_coherent(&pdev->dev, sizeof(*tp->counters), tp->counters, + tp->counters_phys_addr); err_out_msi_4: netif_napi_del(&tp->napi); rtl_disable_msi(pdev, tp); diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 864b476f7fd5..925f2f8659b8 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -837,8 +837,11 @@ static int stmmac_init_phy(struct net_device *dev) interface); } - if (IS_ERR(phydev)) { + if (IS_ERR_OR_NULL(phydev)) { pr_err("%s: Could not attach to PHY\n", dev->name); + if (!phydev) + return -ENODEV; + return PTR_ERR(phydev); } diff --git a/drivers/net/ethernet/synopsys/Kconfig b/drivers/net/ethernet/synopsys/Kconfig index a8f315106742..8276ee5a7d54 100644 --- a/drivers/net/ethernet/synopsys/Kconfig +++ b/drivers/net/ethernet/synopsys/Kconfig @@ -20,7 +20,7 @@ config SYNOPSYS_DWC_ETH_QOS select PHYLIB select CRC32 select MII - depends on OF + depends on OF && HAS_DMA ---help--- This driver supports the DWC Ethernet QoS from Synopsys diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index c07030dbe748..c5ad98ace5d0 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig @@ -127,6 +127,11 @@ config DP83867_PHY ---help--- Currently supports the DP83867 PHY. +config MICROCHIP_PHY + tristate "Drivers for Microchip PHYs" + help + Supports the LAN88XX PHYs. + config FIXED_PHY tristate "Driver for MDIO Bus/PHY emulation with fixed speed/link PHYs" depends on PHYLIB diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile index 9bb103358c74..87f079c4b2c7 100644 --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile @@ -37,3 +37,4 @@ obj-$(CONFIG_MDIO_BUS_MUX_MMIOREG) += mdio-mux-mmioreg.o obj-$(CONFIG_MDIO_SUN4I) += mdio-sun4i.o obj-$(CONFIG_MDIO_MOXART) += mdio-moxart.o obj-$(CONFIG_MDIO_BCM_UNIMAC) += mdio-bcm-unimac.o +obj-$(CONFIG_MICROCHIP_PHY) += microchip.o diff --git a/drivers/net/phy/fixed_phy.c b/drivers/net/phy/fixed_phy.c index 12c7eb2c604e..fb1299c6326e 100644 --- a/drivers/net/phy/fixed_phy.c +++ b/drivers/net/phy/fixed_phy.c @@ -325,7 +325,7 @@ struct phy_device *fixed_phy_register(unsigned int irq, phy_addr = phy_fixed_addr++; spin_unlock(&phy_fixed_addr_lock); - ret = fixed_phy_add(PHY_POLL, phy_addr, status, link_gpio); + ret = fixed_phy_add(irq, phy_addr, status, link_gpio); if (ret < 0) return ERR_PTR(ret); diff --git a/drivers/net/phy/microchip.c b/drivers/net/phy/microchip.c new file mode 100644 index 000000000000..c0a20ebd083b --- /dev/null +++ b/drivers/net/phy/microchip.c @@ -0,0 +1,148 @@ +/* + * Copyright (C) 2015 Microchip Technology + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <http://www.gnu.org/licenses/>. + */ +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/mii.h> +#include <linux/ethtool.h> +#include <linux/phy.h> +#include <linux/microchipphy.h> + +#define DRIVER_AUTHOR "WOOJUNG HUH <woojung.huh@microchip.com>" +#define DRIVER_DESC "Microchip LAN88XX PHY driver" + +struct lan88xx_priv { + int chip_id; + int chip_rev; + __u32 wolopts; +}; + +static int lan88xx_phy_config_intr(struct phy_device *phydev) +{ + int rc; + + if (phydev->interrupts == PHY_INTERRUPT_ENABLED) { + /* unmask all source and clear them before enable */ + rc = phy_write(phydev, LAN88XX_INT_MASK, 0x7FFF); + rc = phy_read(phydev, LAN88XX_INT_STS); + rc = phy_write(phydev, LAN88XX_INT_MASK, + LAN88XX_INT_MASK_MDINTPIN_EN_ | + LAN88XX_INT_MASK_LINK_CHANGE_); + } else { + rc = phy_write(phydev, LAN88XX_INT_MASK, 0); + } + + return rc < 0 ? rc : 0; +} + +static int lan88xx_phy_ack_interrupt(struct phy_device *phydev) +{ + int rc = phy_read(phydev, LAN88XX_INT_STS); + + return rc < 0 ? rc : 0; +} + +int lan88xx_suspend(struct phy_device *phydev) +{ + struct lan88xx_priv *priv = phydev->priv; + + /* do not power down PHY when WOL is enabled */ + if (!priv->wolopts) + genphy_suspend(phydev); + + return 0; +} + +static int lan88xx_probe(struct phy_device *phydev) +{ + struct device *dev = &phydev->dev; + struct lan88xx_priv *priv; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->wolopts = 0; + + /* these values can be used to identify internal PHY */ + priv->chip_id = phy_read_mmd_indirect(phydev, LAN88XX_MMD3_CHIP_ID, + 3, phydev->addr); + priv->chip_rev = phy_read_mmd_indirect(phydev, LAN88XX_MMD3_CHIP_REV, + 3, phydev->addr); + + phydev->priv = priv; + + return 0; +} + +static void lan88xx_remove(struct phy_device *phydev) +{ + struct device *dev = &phydev->dev; + struct lan88xx_priv *priv = phydev->priv; + + if (priv) + devm_kfree(dev, priv); +} + +static int lan88xx_set_wol(struct phy_device *phydev, + struct ethtool_wolinfo *wol) +{ + struct lan88xx_priv *priv = phydev->priv; + + priv->wolopts = wol->wolopts; + + return 0; +} + +static struct phy_driver microchip_phy_driver[] = { +{ + .phy_id = 0x0007c130, + .phy_id_mask = 0xfffffff0, + .name = "Microchip LAN88xx", + + .features = (PHY_GBIT_FEATURES | + SUPPORTED_Pause | SUPPORTED_Asym_Pause), + .flags = PHY_HAS_INTERRUPT | PHY_HAS_MAGICANEG, + + .probe = lan88xx_probe, + .remove = lan88xx_remove, + + .config_init = genphy_config_init, + .config_aneg = genphy_config_aneg, + .read_status = genphy_read_status, + + .ack_interrupt = lan88xx_phy_ack_interrupt, + .config_intr = lan88xx_phy_config_intr, + + .suspend = lan88xx_suspend, + .resume = genphy_resume, + .set_wol = lan88xx_set_wol, + + .driver = { .owner = THIS_MODULE, } +} }; + +module_phy_driver(microchip_phy_driver); + +static struct mdio_device_id __maybe_unused microchip_tbl[] = { + { 0x0007c130, 0xfffffff0 }, + { } +}; + +MODULE_DEVICE_TABLE(mdio, microchip_tbl); + +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_LICENSE("GPL"); diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c index 39364a45af40..a39518fc93aa 100644 --- a/drivers/net/usb/lan78xx.c +++ b/drivers/net/usb/lan78xx.c @@ -1049,8 +1049,7 @@ static int lan78xx_link_reset(struct lan78xx_net *dev) { struct mii_if_info *mii = &dev->mii; struct ethtool_cmd ecmd = { .cmd = ETHTOOL_GSET }; - u16 ladv, radv; - int ret; + int ladv, radv, ret; u32 buf; /* clear PHY interrupt status */ @@ -1104,12 +1103,12 @@ static int lan78xx_link_reset(struct lan78xx_net *dev) } ladv = lan78xx_mdio_read(dev->net, mii->phy_id, MII_ADVERTISE); - if (unlikely(ladv < 0)) - return -EIO; + if (ladv < 0) + return ladv; radv = lan78xx_mdio_read(dev->net, mii->phy_id, MII_LPA); - if (unlikely(radv < 0)) - return -EIO; + if (radv < 0) + return radv; netif_dbg(dev, link, dev->net, "speed: %u duplex: %d anadv: 0x%04x anlpa: 0x%04x", diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c index fe4ec324aebc..d9427ca3dba7 100644 --- a/drivers/net/usb/r8152.c +++ b/drivers/net/usb/r8152.c @@ -26,8 +26,13 @@ #include <linux/mdio.h> #include <linux/usb/cdc.h> -/* Version Information */ -#define DRIVER_VERSION "v1.08.1 (2015/07/28)" +/* Information for net-next */ +#define NETNEXT_VERSION "08" + +/* Information for net */ +#define NET_VERSION "2" + +#define DRIVER_VERSION "v1." NETNEXT_VERSION "." NET_VERSION #define DRIVER_AUTHOR "Realtek linux nic maintainers <nic_swsd@realtek.com>" #define DRIVER_DESC "Realtek RTL8152/RTL8153 Based USB Ethernet Adapters" #define MODULENAME "r8152" @@ -143,6 +148,7 @@ #define OCP_EEE_ABLE 0xa5c4 #define OCP_EEE_ADV 0xa5d0 #define OCP_EEE_LPABLE 0xa5d2 +#define OCP_PHY_STATE 0xa708 /* nway state for 8153 */ #define OCP_ADC_CFG 0xbc06 /* SRAM Register */ @@ -427,6 +433,10 @@ /* OCP_DOWN_SPEED */ #define EN_10M_BGOFF 0x0080 +/* OCP_PHY_STATE */ +#define TXDIS_STATE 0x01 +#define ABD_STATE 0x02 + /* OCP_ADC_CFG */ #define CKADSEL_L 0x0100 #define ADC_EN 0x0080 @@ -604,6 +614,7 @@ struct r8152 { void (*unload)(struct r8152 *); int (*eee_get)(struct r8152 *, struct ethtool_eee *); int (*eee_set)(struct r8152 *, struct ethtool_eee *); + bool (*in_nway)(struct r8152 *); } rtl_ops; int intr_interval; @@ -2941,6 +2952,32 @@ static void rtl8153_down(struct r8152 *tp) r8153_enable_aldps(tp); } +static bool rtl8152_in_nway(struct r8152 *tp) +{ + u16 nway_state; + + ocp_write_word(tp, MCU_TYPE_PLA, PLA_OCP_GPHY_BASE, 0x2000); + tp->ocp_base = 0x2000; + ocp_write_byte(tp, MCU_TYPE_PLA, 0xb014, 0x4c); /* phy state */ + nway_state = ocp_read_word(tp, MCU_TYPE_PLA, 0xb01a); + + /* bit 15: TXDIS_STATE, bit 14: ABD_STATE */ + if (nway_state & 0xc000) + return false; + else + return true; +} + +static bool rtl8153_in_nway(struct r8152 *tp) +{ + u16 phy_state = ocp_reg_read(tp, OCP_PHY_STATE) & 0xff; + + if (phy_state == TXDIS_STATE || phy_state == ABD_STATE) + return false; + else + return true; +} + static void set_carrier(struct r8152 *tp) { struct net_device *netdev = tp->netdev; @@ -3405,6 +3442,27 @@ static int rtl8152_post_reset(struct usb_interface *intf) return 0; } +static bool delay_autosuspend(struct r8152 *tp) +{ + bool sw_linking = !!netif_carrier_ok(tp->netdev); + bool hw_linking = !!(rtl8152_get_speed(tp) & LINK_STATUS); + + /* This means a linking change occurs and the driver doesn't detect it, + * yet. If the driver has disabled tx/rx and hw is linking on, the + * device wouldn't wake up by receiving any packet. + */ + if (work_busy(&tp->schedule.work) || sw_linking != hw_linking) + return true; + + /* If the linking down is occurred by nway, the device may miss the + * linking change event. And it wouldn't wake when linking on. + */ + if (!sw_linking && tp->rtl_ops.in_nway(tp)) + return true; + else + return false; +} + static int rtl8152_suspend(struct usb_interface *intf, pm_message_t message) { struct r8152 *tp = usb_get_intfdata(intf); @@ -3414,7 +3472,7 @@ static int rtl8152_suspend(struct usb_interface *intf, pm_message_t message) mutex_lock(&tp->control); if (PMSG_IS_AUTO(message)) { - if (netif_running(netdev) && work_busy(&tp->schedule.work)) { + if (netif_running(netdev) && delay_autosuspend(tp)) { ret = -EBUSY; goto out1; } @@ -4044,6 +4102,7 @@ static int rtl_ops_init(struct r8152 *tp) ops->unload = rtl8152_unload; ops->eee_get = r8152_get_eee; ops->eee_set = r8152_set_eee; + ops->in_nway = rtl8152_in_nway; break; case RTL_VER_03: @@ -4058,6 +4117,7 @@ static int rtl_ops_init(struct r8152 *tp) ops->unload = rtl8153_unload; ops->eee_get = r8153_get_eee; ops->eee_set = r8153_set_eee; + ops->in_nway = rtl8153_in_nway; break; default: diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index e0498571ae26..b4cf10781348 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c @@ -428,12 +428,18 @@ static enum skb_state defer_bh(struct usbnet *dev, struct sk_buff *skb, old_state = entry->state; entry->state = state; __skb_unlink(skb, list); - spin_unlock(&list->lock); - spin_lock(&dev->done.lock); + + /* defer_bh() is never called with list == &dev->done. + * spin_lock_nested() tells lockdep that it is OK to take + * dev->done.lock here with list->lock held. + */ + spin_lock_nested(&dev->done.lock, SINGLE_DEPTH_NESTING); + __skb_queue_tail(&dev->done, skb); if (dev->done.qlen == 1) tasklet_schedule(&dev->bh); - spin_unlock_irqrestore(&dev->done.lock, flags); + spin_unlock(&dev->done.lock); + spin_unlock_irqrestore(&list->lock, flags); return old_state; } @@ -749,6 +755,20 @@ EXPORT_SYMBOL_GPL(usbnet_unlink_rx_urbs); /*-------------------------------------------------------------------------*/ +static void wait_skb_queue_empty(struct sk_buff_head *q) +{ + unsigned long flags; + + spin_lock_irqsave(&q->lock, flags); + while (!skb_queue_empty(q)) { + spin_unlock_irqrestore(&q->lock, flags); + schedule_timeout(msecs_to_jiffies(UNLINK_TIMEOUT_MS)); + set_current_state(TASK_UNINTERRUPTIBLE); + spin_lock_irqsave(&q->lock, flags); + } + spin_unlock_irqrestore(&q->lock, flags); +} + // precondition: never called in_interrupt static void usbnet_terminate_urbs(struct usbnet *dev) { @@ -762,14 +782,11 @@ static void usbnet_terminate_urbs(struct usbnet *dev) unlink_urbs(dev, &dev->rxq); /* maybe wait for deletions to finish. */ - while (!skb_queue_empty(&dev->rxq) - && !skb_queue_empty(&dev->txq) - && !skb_queue_empty(&dev->done)) { - schedule_timeout(msecs_to_jiffies(UNLINK_TIMEOUT_MS)); - set_current_state(TASK_UNINTERRUPTIBLE); - netif_dbg(dev, ifdown, dev->net, - "waited for %d urb completions\n", temp); - } + wait_skb_queue_empty(&dev->rxq); + wait_skb_queue_empty(&dev->txq); + wait_skb_queue_empty(&dev->done); + netif_dbg(dev, ifdown, dev->net, + "waited for %d urb completions\n", temp); set_current_state(TASK_RUNNING); remove_wait_queue(&dev->wait, &wait); } diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index ce988fd01b34..cf8b7f0473b3 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -1223,7 +1223,6 @@ drop: static int vxlan_udp_encap_recv(struct sock *sk, struct sk_buff *skb) { struct metadata_dst *tun_dst = NULL; - struct ip_tunnel_info *info; struct vxlan_sock *vs; struct vxlanhdr *vxh; u32 flags, vni; @@ -1270,8 +1269,7 @@ static int vxlan_udp_encap_recv(struct sock *sk, struct sk_buff *skb) if (!tun_dst) goto drop; - info = &tun_dst->u.tun_info; - md = ip_tunnel_info_opts(info); + md = ip_tunnel_info_opts(&tun_dst->u.tun_info); } else { memset(md, 0, sizeof(*md)); } @@ -1286,7 +1284,7 @@ static int vxlan_udp_encap_recv(struct sock *sk, struct sk_buff *skb) md->gbp = ntohs(gbp->policy_id); if (tun_dst) - info->key.tun_flags |= TUNNEL_VXLAN_OPT; + tun_dst->u.tun_info.key.tun_flags |= TUNNEL_VXLAN_OPT; if (gbp->dont_learn) md->gbp |= VXLAN_GBP_DONT_LEARN; diff --git a/drivers/net/wan/sbni.c b/drivers/net/wan/sbni.c index 758c4ba1e97c..8fef8d83436d 100644 --- a/drivers/net/wan/sbni.c +++ b/drivers/net/wan/sbni.c @@ -1358,6 +1358,8 @@ sbni_ioctl( struct net_device *dev, struct ifreq *ifr, int cmd ) if( !slave_dev || !(slave_dev->flags & IFF_UP) ) { netdev_err(dev, "trying to enslave non-active device %s\n", slave_name); + if (slave_dev) + dev_put(slave_dev); return -EPERM; } diff --git a/drivers/net/xen-netback/common.h b/drivers/net/xen-netback/common.h index 6dc76c1e807b..a7bf74727116 100644 --- a/drivers/net/xen-netback/common.h +++ b/drivers/net/xen-netback/common.h @@ -200,11 +200,6 @@ struct xenvif_queue { /* Per-queue data for xenvif */ struct xenvif_stats stats; }; -/* Maximum number of Rx slots a to-guest packet may use, including the - * slot needed for GSO meta-data. - */ -#define XEN_NETBK_RX_SLOTS_MAX (MAX_SKB_FRAGS + 1) - enum state_bit_shift { /* This bit marks that the vif is connected */ VIF_STATUS_CONNECTED, @@ -317,11 +312,6 @@ int xenvif_dealloc_kthread(void *data); void xenvif_rx_queue_tail(struct xenvif_queue *queue, struct sk_buff *skb); -/* Determine whether the needed number of slots (req) are available, - * and set req_event if not. - */ -bool xenvif_rx_ring_slots_available(struct xenvif_queue *queue, int needed); - void xenvif_carrier_on(struct xenvif *vif); /* Callback from stack when TX packet can be released */ diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c index 42569b994ea8..ec98d43916a8 100644 --- a/drivers/net/xen-netback/netback.c +++ b/drivers/net/xen-netback/netback.c @@ -149,9 +149,20 @@ static inline pending_ring_idx_t pending_index(unsigned i) return i & (MAX_PENDING_REQS-1); } -bool xenvif_rx_ring_slots_available(struct xenvif_queue *queue, int needed) +static int xenvif_rx_ring_slots_needed(struct xenvif *vif) +{ + if (vif->gso_mask) + return DIV_ROUND_UP(vif->dev->gso_max_size, PAGE_SIZE) + 1; + else + return DIV_ROUND_UP(vif->dev->mtu, PAGE_SIZE); +} + +static bool xenvif_rx_ring_slots_available(struct xenvif_queue *queue) { RING_IDX prod, cons; + int needed; + + needed = xenvif_rx_ring_slots_needed(queue->vif); do { prod = queue->rx.sring->req_prod; @@ -314,7 +325,7 @@ static void xenvif_gop_frag_copy(struct xenvif_queue *queue, struct sk_buff *skb } else { copy_gop->source.domid = DOMID_SELF; copy_gop->source.u.gmfn = - virt_to_mfn(page_address(page)); + virt_to_gfn(page_address(page)); } copy_gop->source.offset = offset; @@ -513,7 +524,7 @@ static void xenvif_rx_action(struct xenvif_queue *queue) skb_queue_head_init(&rxq); - while (xenvif_rx_ring_slots_available(queue, XEN_NETBK_RX_SLOTS_MAX) + while (xenvif_rx_ring_slots_available(queue) && (skb = xenvif_rx_dequeue(queue)) != NULL) { queue->last_rx_time = jiffies; @@ -1395,7 +1406,7 @@ static void xenvif_tx_build_gops(struct xenvif_queue *queue, queue->tx_copy_ops[*copy_ops].source.offset = txreq.offset; queue->tx_copy_ops[*copy_ops].dest.u.gmfn = - virt_to_mfn(skb->data); + virt_to_gfn(skb->data); queue->tx_copy_ops[*copy_ops].dest.domid = DOMID_SELF; queue->tx_copy_ops[*copy_ops].dest.offset = offset_in_page(skb->data); @@ -1938,8 +1949,7 @@ static bool xenvif_rx_queue_stalled(struct xenvif_queue *queue) prod = queue->rx.sring->req_prod; cons = queue->rx.req_cons; - return !queue->stalled - && prod - cons < XEN_NETBK_RX_SLOTS_MAX + return !queue->stalled && prod - cons < 1 && time_after(jiffies, queue->last_rx_time + queue->vif->stall_timeout); } @@ -1951,14 +1961,13 @@ static bool xenvif_rx_queue_ready(struct xenvif_queue *queue) prod = queue->rx.sring->req_prod; cons = queue->rx.req_cons; - return queue->stalled - && prod - cons >= XEN_NETBK_RX_SLOTS_MAX; + return queue->stalled && prod - cons >= 1; } static bool xenvif_have_rx_work(struct xenvif_queue *queue) { return (!skb_queue_empty(&queue->rx_queue) - && xenvif_rx_ring_slots_available(queue, XEN_NETBK_RX_SLOTS_MAX)) + && xenvif_rx_ring_slots_available(queue)) || (queue->vif->stall_timeout && (xenvif_rx_queue_stalled(queue) || xenvif_rx_queue_ready(queue))) @@ -2105,8 +2114,11 @@ static int __init netback_init(void) if (!xen_domain()) return -ENODEV; - /* Allow as many queues as there are CPUs, by default */ - xenvif_max_queues = num_online_cpus(); + /* Allow as many queues as there are CPUs if user has not + * specified a value. + */ + if (xenvif_max_queues == 0) + xenvif_max_queues = num_online_cpus(); if (fatal_skb_slots < XEN_NETBK_LEGACY_SLOTS_MAX) { pr_info("fatal_skb_slots too small (%d), bump it to XEN_NETBK_LEGACY_SLOTS_MAX (%d)\n", diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c index e27e6d2ea6d2..f821a97d7827 100644 --- a/drivers/net/xen-netfront.c +++ b/drivers/net/xen-netfront.c @@ -291,7 +291,7 @@ static void xennet_alloc_rx_buffers(struct netfront_queue *queue) struct sk_buff *skb; unsigned short id; grant_ref_t ref; - unsigned long pfn; + unsigned long gfn; struct xen_netif_rx_request *req; skb = xennet_alloc_one_rx_buffer(queue); @@ -307,12 +307,12 @@ static void xennet_alloc_rx_buffers(struct netfront_queue *queue) BUG_ON((signed short)ref < 0); queue->grant_rx_ref[id] = ref; - pfn = page_to_pfn(skb_frag_page(&skb_shinfo(skb)->frags[0])); + gfn = xen_page_to_gfn(skb_frag_page(&skb_shinfo(skb)->frags[0])); req = RING_GET_REQUEST(&queue->rx, req_prod); gnttab_grant_foreign_access_ref(ref, queue->info->xbdev->otherend_id, - pfn_to_mfn(pfn), + gfn, 0); req->id = id; @@ -430,8 +430,10 @@ static struct xen_netif_tx_request *xennet_make_one_txreq( ref = gnttab_claim_grant_reference(&queue->gref_tx_head); BUG_ON((signed short)ref < 0); - gnttab_grant_foreign_access_ref(ref, queue->info->xbdev->otherend_id, - page_to_mfn(page), GNTMAP_readonly); + gnttab_grant_foreign_access_ref(ref, + queue->info->xbdev->otherend_id, + xen_page_to_gfn(page), + GNTMAP_readonly); queue->tx_skbs[id].skb = skb; queue->grant_tx_page[id] = page; @@ -2132,8 +2134,11 @@ static int __init netif_init(void) pr_info("Initialising Xen virtual ethernet driver\n"); - /* Allow as many queues as there are CPUs, by default */ - xennet_max_queues = num_online_cpus(); + /* Allow as many queues as there are CPUs if user has not + * specified a value. + */ + if (xennet_max_queues == 0) + xennet_max_queues = num_online_cpus(); return xenbus_register_frontend(&netfront_driver); } diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig index 948d9abd27f1..062630ab7424 100644 --- a/drivers/pwm/Kconfig +++ b/drivers/pwm/Kconfig @@ -180,6 +180,18 @@ config PWM_LP3943 To compile this driver as a module, choose M here: the module will be called pwm-lp3943. +config PWM_LPC18XX_SCT + tristate "LPC18xx/43xx PWM/SCT support" + depends on ARCH_LPC18XX + help + Generic PWM framework driver for NXP LPC18xx PWM/SCT which + supports 16 channels. + A maximum of 15 channels can be requested simultaneously and + must have the same period. + + To compile this driver as a module, choose M here: the module + will be called pwm-lpc18xx-sct. + config PWM_LPC32XX tristate "LPC32XX PWM support" depends on ARCH_LPC32XX diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile index d186f35a6538..a0e00c09ead3 100644 --- a/drivers/pwm/Makefile +++ b/drivers/pwm/Makefile @@ -15,6 +15,7 @@ obj-$(CONFIG_PWM_IMG) += pwm-img.o obj-$(CONFIG_PWM_IMX) += pwm-imx.o obj-$(CONFIG_PWM_JZ4740) += pwm-jz4740.o obj-$(CONFIG_PWM_LP3943) += pwm-lp3943.o +obj-$(CONFIG_PWM_LPC18XX_SCT) += pwm-lpc18xx-sct.o obj-$(CONFIG_PWM_LPC32XX) += pwm-lpc32xx.o obj-$(CONFIG_PWM_LPSS) += pwm-lpss.o obj-$(CONFIG_PWM_LPSS_PCI) += pwm-lpss-pci.o diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c index 3a7769fe53de..3f9df3ea3350 100644 --- a/drivers/pwm/core.c +++ b/drivers/pwm/core.c @@ -200,6 +200,8 @@ static void of_pwmchip_remove(struct pwm_chip *chip) * pwm_set_chip_data() - set private chip data for a PWM * @pwm: PWM device * @data: pointer to chip-specific data + * + * Returns: 0 on success or a negative error code on failure. */ int pwm_set_chip_data(struct pwm_device *pwm, void *data) { @@ -215,6 +217,8 @@ EXPORT_SYMBOL_GPL(pwm_set_chip_data); /** * pwm_get_chip_data() - get private chip data for a PWM * @pwm: PWM device + * + * Returns: A pointer to the chip-private data for the PWM device. */ void *pwm_get_chip_data(struct pwm_device *pwm) { @@ -230,6 +234,8 @@ EXPORT_SYMBOL_GPL(pwm_get_chip_data); * Register a new PWM chip. If chip->base < 0 then a dynamically assigned base * will be used. The initial polarity for all channels is specified by the * @polarity parameter. + * + * Returns: 0 on success or a negative error code on failure. */ int pwmchip_add_with_polarity(struct pwm_chip *chip, enum pwm_polarity polarity) @@ -291,6 +297,8 @@ EXPORT_SYMBOL_GPL(pwmchip_add_with_polarity); * * Register a new PWM chip. If chip->base < 0 then a dynamically assigned base * will be used. The initial polarity for all channels is normal. + * + * Returns: 0 on success or a negative error code on failure. */ int pwmchip_add(struct pwm_chip *chip) { @@ -304,6 +312,8 @@ EXPORT_SYMBOL_GPL(pwmchip_add); * * Removes a PWM chip. This function may return busy if the PWM chip provides * a PWM device that is still requested. + * + * Returns: 0 on success or a negative error code on failure. */ int pwmchip_remove(struct pwm_chip *chip) { @@ -338,10 +348,13 @@ EXPORT_SYMBOL_GPL(pwmchip_remove); /** * pwm_request() - request a PWM device - * @pwm_id: global PWM device index + * @pwm: global PWM device index * @label: PWM device label * * This function is deprecated, use pwm_get() instead. + * + * Returns: A pointer to a PWM device or an ERR_PTR()-encoded error code on + * failure. */ struct pwm_device *pwm_request(int pwm, const char *label) { @@ -376,9 +389,9 @@ EXPORT_SYMBOL_GPL(pwm_request); * @index: per-chip index of the PWM to request * @label: a literal description string of this PWM * - * Returns the PWM at the given index of the given PWM chip. A negative error - * code is returned if the index is not valid for the specified PWM chip or - * if the PWM device cannot be requested. + * Returns: A pointer to the PWM device at the given index of the given PWM + * chip. A negative error code is returned if the index is not valid for the + * specified PWM chip or if the PWM device cannot be requested. */ struct pwm_device *pwm_request_from_chip(struct pwm_chip *chip, unsigned int index, @@ -419,6 +432,8 @@ EXPORT_SYMBOL_GPL(pwm_free); * @pwm: PWM device * @duty_ns: "on" time (in nanoseconds) * @period_ns: duration (in nanoseconds) of one cycle + * + * Returns: 0 on success or a negative error code on failure. */ int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns) { @@ -443,7 +458,10 @@ EXPORT_SYMBOL_GPL(pwm_config); * @pwm: PWM device * @polarity: new polarity of the PWM signal * - * Note that the polarity cannot be configured while the PWM device is enabled + * Note that the polarity cannot be configured while the PWM device is + * enabled. + * + * Returns: 0 on success or a negative error code on failure. */ int pwm_set_polarity(struct pwm_device *pwm, enum pwm_polarity polarity) { @@ -455,7 +473,7 @@ int pwm_set_polarity(struct pwm_device *pwm, enum pwm_polarity polarity) if (!pwm->chip->ops->set_polarity) return -ENOSYS; - if (test_bit(PWMF_ENABLED, &pwm->flags)) + if (pwm_is_enabled(pwm)) return -EBUSY; err = pwm->chip->ops->set_polarity(pwm->chip, pwm, polarity); @@ -471,6 +489,8 @@ EXPORT_SYMBOL_GPL(pwm_set_polarity); /** * pwm_enable() - start a PWM output toggling * @pwm: PWM device + * + * Returns: 0 on success or a negative error code on failure. */ int pwm_enable(struct pwm_device *pwm) { @@ -524,6 +544,9 @@ static struct pwm_chip *of_node_to_pwmchip(struct device_node *np) * lookup of the PWM index. This also means that the "pwm-names" property * becomes mandatory for devices that look up the PWM device via the con_id * parameter. + * + * Returns: A pointer to the requested PWM device or an ERR_PTR()-encoded + * error code on failure. */ struct pwm_device *of_pwm_get(struct device_node *np, const char *con_id) { @@ -630,6 +653,9 @@ void pwm_remove_table(struct pwm_lookup *table, size_t num) * * Once a PWM chip has been found the specified PWM device will be requested * and is ready to be used. + * + * Returns: A pointer to the requested PWM device or an ERR_PTR()-encoded + * error code on failure. */ struct pwm_device *pwm_get(struct device *dev, const char *con_id) { @@ -752,6 +778,9 @@ static void devm_pwm_release(struct device *dev, void *res) * * This function performs like pwm_get() but the acquired PWM device will * automatically be released on driver detach. + * + * Returns: A pointer to the requested PWM device or an ERR_PTR()-encoded + * error code on failure. */ struct pwm_device *devm_pwm_get(struct device *dev, const char *con_id) { @@ -781,6 +810,9 @@ EXPORT_SYMBOL_GPL(devm_pwm_get); * * This function performs like of_pwm_get() but the acquired PWM device will * automatically be released on driver detach. + * + * Returns: A pointer to the requested PWM device or an ERR_PTR()-encoded + * error code on failure. */ struct pwm_device *devm_of_pwm_get(struct device *dev, struct device_node *np, const char *con_id) @@ -832,7 +864,7 @@ EXPORT_SYMBOL_GPL(devm_pwm_put); * pwm_can_sleep() - report whether PWM access will sleep * @pwm: PWM device * - * It returns true if accessing the PWM can sleep, false otherwise. + * Returns: True if accessing the PWM can sleep, false otherwise. */ bool pwm_can_sleep(struct pwm_device *pwm) { @@ -853,7 +885,7 @@ static void pwm_dbg_show(struct pwm_chip *chip, struct seq_file *s) if (test_bit(PWMF_REQUESTED, &pwm->flags)) seq_puts(s, " requested"); - if (test_bit(PWMF_ENABLED, &pwm->flags)) + if (pwm_is_enabled(pwm)) seq_puts(s, " enabled"); seq_puts(s, "\n"); @@ -924,6 +956,5 @@ static int __init pwm_debugfs_init(void) return 0; } - subsys_initcall(pwm_debugfs_init); #endif /* CONFIG_DEBUG_FS */ diff --git a/drivers/pwm/pwm-atmel-hlcdc.c b/drivers/pwm/pwm-atmel-hlcdc.c index fa5feaba25a5..5df1db40fc07 100644 --- a/drivers/pwm/pwm-atmel-hlcdc.c +++ b/drivers/pwm/pwm-atmel-hlcdc.c @@ -218,6 +218,11 @@ static const struct atmel_hlcdc_pwm_errata atmel_hlcdc_pwm_sama5d3_errata = { static const struct of_device_id atmel_hlcdc_dt_ids[] = { { + .compatible = "atmel,at91sam9n12-hlcdc", + /* 9n12 has same errata as 9x5 HLCDC PWM */ + .data = &atmel_hlcdc_pwm_at91sam9x5_errata, + }, + { .compatible = "atmel,at91sam9x5-hlcdc", .data = &atmel_hlcdc_pwm_at91sam9x5_errata, }, diff --git a/drivers/pwm/pwm-atmel-tcb.c b/drivers/pwm/pwm-atmel-tcb.c index d14e0677c92d..6da01b3bf6f4 100644 --- a/drivers/pwm/pwm-atmel-tcb.c +++ b/drivers/pwm/pwm-atmel-tcb.c @@ -347,7 +347,7 @@ static int atmel_tcb_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, tcbpwm->duty = duty; /* If the PWM is enabled, call enable to apply the new conf */ - if (test_bit(PWMF_ENABLED, &pwm->flags)) + if (pwm_is_enabled(pwm)) atmel_tcb_pwm_enable(chip, pwm); return 0; diff --git a/drivers/pwm/pwm-atmel.c b/drivers/pwm/pwm-atmel.c index a947c9095d9d..0e4bd4e8e582 100644 --- a/drivers/pwm/pwm-atmel.c +++ b/drivers/pwm/pwm-atmel.c @@ -114,7 +114,7 @@ static int atmel_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, u32 val; int ret; - if (test_bit(PWMF_ENABLED, &pwm->flags) && (period_ns != pwm->period)) { + if (pwm_is_enabled(pwm) && (period_ns != pwm_get_period(pwm))) { dev_err(chip->dev, "cannot change PWM period while enabled\n"); return -EBUSY; } @@ -176,7 +176,7 @@ static void atmel_pwm_config_v1(struct pwm_chip *chip, struct pwm_device *pwm, * If the PWM channel is enabled, only update CDTY by using the update * register, it needs to set bit 10 of CMR to 0 */ - if (test_bit(PWMF_ENABLED, &pwm->flags)) + if (pwm_is_enabled(pwm)) return; /* * If the PWM channel is disabled, write value to duty and period @@ -191,7 +191,7 @@ static void atmel_pwm_config_v2(struct pwm_chip *chip, struct pwm_device *pwm, { struct atmel_pwm_chip *atmel_pwm = to_atmel_pwm_chip(chip); - if (test_bit(PWMF_ENABLED, &pwm->flags)) { + if (pwm_is_enabled(pwm)) { /* * If the PWM channel is enabled, using the duty update register * to update the value. diff --git a/drivers/pwm/pwm-bcm-kona.c b/drivers/pwm/pwm-bcm-kona.c index 7af8fea2dc5b..c63418322023 100644 --- a/drivers/pwm/pwm-bcm-kona.c +++ b/drivers/pwm/pwm-bcm-kona.c @@ -76,19 +76,36 @@ static inline struct kona_pwmc *to_kona_pwmc(struct pwm_chip *_chip) return container_of(_chip, struct kona_pwmc, chip); } -static void kona_pwmc_apply_settings(struct kona_pwmc *kp, unsigned int chan) +/* + * Clear trigger bit but set smooth bit to maintain old output. + */ +static void kona_pwmc_prepare_for_settings(struct kona_pwmc *kp, + unsigned int chan) { unsigned int value = readl(kp->base + PWM_CONTROL_OFFSET); - /* Clear trigger bit but set smooth bit to maintain old output */ value |= 1 << PWM_CONTROL_SMOOTH_SHIFT(chan); value &= ~(1 << PWM_CONTROL_TRIGGER_SHIFT(chan)); writel(value, kp->base + PWM_CONTROL_OFFSET); + /* + * There must be a min 400ns delay between clearing trigger and setting + * it. Failing to do this may result in no PWM signal. + */ + ndelay(400); +} + +static void kona_pwmc_apply_settings(struct kona_pwmc *kp, unsigned int chan) +{ + unsigned int value = readl(kp->base + PWM_CONTROL_OFFSET); + /* Set trigger bit and clear smooth bit to apply new settings */ value &= ~(1 << PWM_CONTROL_SMOOTH_SHIFT(chan)); value |= 1 << PWM_CONTROL_TRIGGER_SHIFT(chan); writel(value, kp->base + PWM_CONTROL_OFFSET); + + /* Trigger bit must be held high for at least 400 ns. */ + ndelay(400); } static int kona_pwmc_config(struct pwm_chip *chip, struct pwm_device *pwm, @@ -133,8 +150,14 @@ static int kona_pwmc_config(struct pwm_chip *chip, struct pwm_device *pwm, return -EINVAL; } - /* If the PWM channel is enabled, write the settings to the HW */ - if (test_bit(PWMF_ENABLED, &pwm->flags)) { + /* + * Don't apply settings if disabled. The period and duty cycle are + * always calculated above to ensure the new values are + * validated immediately instead of on enable. + */ + if (pwm_is_enabled(pwm)) { + kona_pwmc_prepare_for_settings(kp, chan); + value = readl(kp->base + PRESCALE_OFFSET); value &= ~PRESCALE_MASK(chan); value |= prescale << PRESCALE_SHIFT(chan); @@ -164,6 +187,8 @@ static int kona_pwmc_set_polarity(struct pwm_chip *chip, struct pwm_device *pwm, return ret; } + kona_pwmc_prepare_for_settings(kp, chan); + value = readl(kp->base + PWM_CONTROL_OFFSET); if (polarity == PWM_POLARITY_NORMAL) @@ -175,9 +200,6 @@ static int kona_pwmc_set_polarity(struct pwm_chip *chip, struct pwm_device *pwm, kona_pwmc_apply_settings(kp, chan); - /* Wait for waveform to settle before gating off the clock */ - ndelay(400); - clk_disable_unprepare(kp->clk); return 0; @@ -194,7 +216,8 @@ static int kona_pwmc_enable(struct pwm_chip *chip, struct pwm_device *pwm) return ret; } - ret = kona_pwmc_config(chip, pwm, pwm->duty_cycle, pwm->period); + ret = kona_pwmc_config(chip, pwm, pwm_get_duty_cycle(pwm), + pwm_get_period(pwm)); if (ret < 0) { clk_disable_unprepare(kp->clk); return ret; @@ -207,13 +230,20 @@ static void kona_pwmc_disable(struct pwm_chip *chip, struct pwm_device *pwm) { struct kona_pwmc *kp = to_kona_pwmc(chip); unsigned int chan = pwm->hwpwm; + unsigned int value; + + kona_pwmc_prepare_for_settings(kp, chan); /* Simulate a disable by configuring for zero duty */ writel(0, kp->base + DUTY_CYCLE_HIGH_OFFSET(chan)); - kona_pwmc_apply_settings(kp, chan); + writel(0, kp->base + PERIOD_COUNT_OFFSET(chan)); - /* Wait for waveform to settle before gating off the clock */ - ndelay(400); + /* Set prescale to 0 for this channel */ + value = readl(kp->base + PRESCALE_OFFSET); + value &= ~PRESCALE_MASK(chan); + writel(value, kp->base + PRESCALE_OFFSET); + + kona_pwmc_apply_settings(kp, chan); clk_disable_unprepare(kp->clk); } @@ -287,7 +317,7 @@ static int kona_pwmc_remove(struct platform_device *pdev) unsigned int chan; for (chan = 0; chan < kp->chip.npwm; chan++) - if (test_bit(PWMF_ENABLED, &kp->chip.pwms[chan].flags)) + if (pwm_is_enabled(&kp->chip.pwms[chan])) clk_disable_unprepare(kp->clk); return pwmchip_remove(&kp->chip); diff --git a/drivers/pwm/pwm-ep93xx.c b/drivers/pwm/pwm-ep93xx.c index e593e9c45c51..bbf10ae02f0e 100644 --- a/drivers/pwm/pwm-ep93xx.c +++ b/drivers/pwm/pwm-ep93xx.c @@ -82,7 +82,7 @@ static int ep93xx_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, * The clock needs to be enabled to access the PWM registers. * Configuration can be changed at any time. */ - if (!test_bit(PWMF_ENABLED, &pwm->flags)) { + if (!pwm_is_enabled(pwm)) { ret = clk_enable(ep93xx_pwm->clk); if (ret) return ret; @@ -113,7 +113,7 @@ static int ep93xx_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, ret = -EINVAL; } - if (!test_bit(PWMF_ENABLED, &pwm->flags)) + if (!pwm_is_enabled(pwm)) clk_disable(ep93xx_pwm->clk); return ret; diff --git a/drivers/pwm/pwm-imx.c b/drivers/pwm/pwm-imx.c index 66d6f0c5c421..d600fd5cd4ba 100644 --- a/drivers/pwm/pwm-imx.c +++ b/drivers/pwm/pwm-imx.c @@ -114,7 +114,7 @@ static int imx_pwm_config_v2(struct pwm_chip *chip, unsigned long long c; unsigned long period_cycles, duty_cycles, prescale; unsigned int period_ms; - bool enable = test_bit(PWMF_ENABLED, &pwm->flags); + bool enable = pwm_is_enabled(pwm); int wait_count = 0, fifoav; u32 cr, sr; @@ -129,7 +129,8 @@ static int imx_pwm_config_v2(struct pwm_chip *chip, sr = readl(imx->mmio_base + MX3_PWMSR); fifoav = sr & MX3_PWMSR_FIFOAV_MASK; if (fifoav == MX3_PWMSR_FIFOAV_4WORDS) { - period_ms = DIV_ROUND_UP(pwm->period, NSEC_PER_MSEC); + period_ms = DIV_ROUND_UP(pwm_get_period(pwm), + NSEC_PER_MSEC); msleep(period_ms); sr = readl(imx->mmio_base + MX3_PWMSR); diff --git a/drivers/pwm/pwm-lpc18xx-sct.c b/drivers/pwm/pwm-lpc18xx-sct.c new file mode 100644 index 000000000000..9163085101bc --- /dev/null +++ b/drivers/pwm/pwm-lpc18xx-sct.c @@ -0,0 +1,465 @@ +/* + * NXP LPC18xx State Configurable Timer - Pulse Width Modulator driver + * + * Copyright (c) 2015 Ariel D'Alessandro <ariel@vanguardiasur.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. + * + * Notes + * ===== + * NXP LPC18xx provides a State Configurable Timer (SCT) which can be configured + * as a Pulse Width Modulator. + * + * SCT supports 16 outputs, 16 events and 16 registers. Each event will be + * triggered when its related register matches the SCT counter value, and it + * will set or clear a selected output. + * + * One of the events is preselected to generate the period, thus the maximum + * number of simultaneous channels is limited to 15. Notice that period is + * global to all the channels, thus PWM driver will refuse setting different + * values to it, unless there's only one channel requested. + */ + +#include <linux/clk.h> +#include <linux/err.h> +#include <linux/io.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/pwm.h> + +/* LPC18xx SCT registers */ +#define LPC18XX_PWM_CONFIG 0x000 +#define LPC18XX_PWM_CONFIG_UNIFY BIT(0) +#define LPC18XX_PWM_CONFIG_NORELOAD BIT(7) + +#define LPC18XX_PWM_CTRL 0x004 +#define LPC18XX_PWM_CTRL_HALT BIT(2) +#define LPC18XX_PWM_BIDIR BIT(4) +#define LPC18XX_PWM_PRE_SHIFT 5 +#define LPC18XX_PWM_PRE_MASK (0xff << LPC18XX_PWM_PRE_SHIFT) +#define LPC18XX_PWM_PRE(x) (x << LPC18XX_PWM_PRE_SHIFT) + +#define LPC18XX_PWM_LIMIT 0x008 + +#define LPC18XX_PWM_RES_BASE 0x058 +#define LPC18XX_PWM_RES_SHIFT(_ch) (_ch * 2) +#define LPC18XX_PWM_RES(_ch, _action) (_action << LPC18XX_PWM_RES_SHIFT(_ch)) +#define LPC18XX_PWM_RES_MASK(_ch) (0x3 << LPC18XX_PWM_RES_SHIFT(_ch)) + +#define LPC18XX_PWM_MATCH_BASE 0x100 +#define LPC18XX_PWM_MATCH(_ch) (LPC18XX_PWM_MATCH_BASE + _ch * 4) + +#define LPC18XX_PWM_MATCHREL_BASE 0x200 +#define LPC18XX_PWM_MATCHREL(_ch) (LPC18XX_PWM_MATCHREL_BASE + _ch * 4) + +#define LPC18XX_PWM_EVSTATEMSK_BASE 0x300 +#define LPC18XX_PWM_EVSTATEMSK(_ch) (LPC18XX_PWM_EVSTATEMSK_BASE + _ch * 8) +#define LPC18XX_PWM_EVSTATEMSK_ALL 0xffffffff + +#define LPC18XX_PWM_EVCTRL_BASE 0x304 +#define LPC18XX_PWM_EVCTRL(_ev) (LPC18XX_PWM_EVCTRL_BASE + _ev * 8) + +#define LPC18XX_PWM_EVCTRL_MATCH(_ch) _ch + +#define LPC18XX_PWM_EVCTRL_COMB_SHIFT 12 +#define LPC18XX_PWM_EVCTRL_COMB_MATCH (0x1 << LPC18XX_PWM_EVCTRL_COMB_SHIFT) + +#define LPC18XX_PWM_OUTPUTSET_BASE 0x500 +#define LPC18XX_PWM_OUTPUTSET(_ch) (LPC18XX_PWM_OUTPUTSET_BASE + _ch * 8) + +#define LPC18XX_PWM_OUTPUTCL_BASE 0x504 +#define LPC18XX_PWM_OUTPUTCL(_ch) (LPC18XX_PWM_OUTPUTCL_BASE + _ch * 8) + +/* LPC18xx SCT unified counter */ +#define LPC18XX_PWM_TIMER_MAX 0xffffffff + +/* LPC18xx SCT events */ +#define LPC18XX_PWM_EVENT_PERIOD 0 +#define LPC18XX_PWM_EVENT_MAX 16 + +/* SCT conflict resolution */ +enum lpc18xx_pwm_res_action { + LPC18XX_PWM_RES_NONE, + LPC18XX_PWM_RES_SET, + LPC18XX_PWM_RES_CLEAR, + LPC18XX_PWM_RES_TOGGLE, +}; + +struct lpc18xx_pwm_data { + unsigned int duty_event; +}; + +struct lpc18xx_pwm_chip { + struct device *dev; + struct pwm_chip chip; + void __iomem *base; + struct clk *pwm_clk; + unsigned long clk_rate; + unsigned int period_ns; + unsigned int min_period_ns; + unsigned int max_period_ns; + unsigned int period_event; + unsigned long event_map; + struct mutex res_lock; + struct mutex period_lock; +}; + +static inline struct lpc18xx_pwm_chip * +to_lpc18xx_pwm_chip(struct pwm_chip *chip) +{ + return container_of(chip, struct lpc18xx_pwm_chip, chip); +} + +static inline void lpc18xx_pwm_writel(struct lpc18xx_pwm_chip *lpc18xx_pwm, + u32 reg, u32 val) +{ + writel(val, lpc18xx_pwm->base + reg); +} + +static inline u32 lpc18xx_pwm_readl(struct lpc18xx_pwm_chip *lpc18xx_pwm, + u32 reg) +{ + return readl(lpc18xx_pwm->base + reg); +} + +static void lpc18xx_pwm_set_conflict_res(struct lpc18xx_pwm_chip *lpc18xx_pwm, + struct pwm_device *pwm, + enum lpc18xx_pwm_res_action action) +{ + u32 val; + + mutex_lock(&lpc18xx_pwm->res_lock); + + /* + * Simultaneous set and clear may happen on an output, that is the case + * when duty_ns == period_ns. LPC18xx SCT allows to set a conflict + * resolution action to be taken in such a case. + */ + val = lpc18xx_pwm_readl(lpc18xx_pwm, LPC18XX_PWM_RES_BASE); + val &= ~LPC18XX_PWM_RES_MASK(pwm->hwpwm); + val |= LPC18XX_PWM_RES(pwm->hwpwm, action); + lpc18xx_pwm_writel(lpc18xx_pwm, LPC18XX_PWM_RES_BASE, val); + + mutex_unlock(&lpc18xx_pwm->res_lock); +} + +static void lpc18xx_pwm_config_period(struct pwm_chip *chip, int period_ns) +{ + struct lpc18xx_pwm_chip *lpc18xx_pwm = to_lpc18xx_pwm_chip(chip); + u64 val; + + val = (u64)period_ns * lpc18xx_pwm->clk_rate; + do_div(val, NSEC_PER_SEC); + + lpc18xx_pwm_writel(lpc18xx_pwm, + LPC18XX_PWM_MATCH(lpc18xx_pwm->period_event), + (u32)val - 1); + + lpc18xx_pwm_writel(lpc18xx_pwm, + LPC18XX_PWM_MATCHREL(lpc18xx_pwm->period_event), + (u32)val - 1); +} + +static void lpc18xx_pwm_config_duty(struct pwm_chip *chip, + struct pwm_device *pwm, int duty_ns) +{ + struct lpc18xx_pwm_chip *lpc18xx_pwm = to_lpc18xx_pwm_chip(chip); + struct lpc18xx_pwm_data *lpc18xx_data = pwm_get_chip_data(pwm); + u64 val; + + val = (u64)duty_ns * lpc18xx_pwm->clk_rate; + do_div(val, NSEC_PER_SEC); + + lpc18xx_pwm_writel(lpc18xx_pwm, + LPC18XX_PWM_MATCH(lpc18xx_data->duty_event), + (u32)val); + + lpc18xx_pwm_writel(lpc18xx_pwm, + LPC18XX_PWM_MATCHREL(lpc18xx_data->duty_event), + (u32)val); +} + +static int lpc18xx_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, + int duty_ns, int period_ns) +{ + struct lpc18xx_pwm_chip *lpc18xx_pwm = to_lpc18xx_pwm_chip(chip); + int requested_events, i; + + if (period_ns < lpc18xx_pwm->min_period_ns || + period_ns > lpc18xx_pwm->max_period_ns) { + dev_err(chip->dev, "period %d not in range\n", period_ns); + return -ERANGE; + } + + mutex_lock(&lpc18xx_pwm->period_lock); + + requested_events = bitmap_weight(&lpc18xx_pwm->event_map, + LPC18XX_PWM_EVENT_MAX); + + /* + * The PWM supports only a single period for all PWM channels. + * Once the period is set, it can only be changed if no more than one + * channel is requested at that moment. + */ + if (requested_events > 2 && lpc18xx_pwm->period_ns != period_ns && + lpc18xx_pwm->period_ns) { + dev_err(chip->dev, "conflicting period requested for PWM %u\n", + pwm->hwpwm); + mutex_unlock(&lpc18xx_pwm->period_lock); + return -EBUSY; + } + + if ((requested_events <= 2 && lpc18xx_pwm->period_ns != period_ns) || + !lpc18xx_pwm->period_ns) { + lpc18xx_pwm->period_ns = period_ns; + for (i = 0; i < chip->npwm; i++) + pwm_set_period(&chip->pwms[i], period_ns); + lpc18xx_pwm_config_period(chip, period_ns); + } + + mutex_unlock(&lpc18xx_pwm->period_lock); + + lpc18xx_pwm_config_duty(chip, pwm, duty_ns); + + return 0; +} + +static int lpc18xx_pwm_set_polarity(struct pwm_chip *chip, + struct pwm_device *pwm, + enum pwm_polarity polarity) +{ + return 0; +} + +static int lpc18xx_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) +{ + struct lpc18xx_pwm_chip *lpc18xx_pwm = to_lpc18xx_pwm_chip(chip); + struct lpc18xx_pwm_data *lpc18xx_data = pwm_get_chip_data(pwm); + enum lpc18xx_pwm_res_action res_action; + unsigned int set_event, clear_event; + + lpc18xx_pwm_writel(lpc18xx_pwm, + LPC18XX_PWM_EVCTRL(lpc18xx_data->duty_event), + LPC18XX_PWM_EVCTRL_MATCH(lpc18xx_data->duty_event) | + LPC18XX_PWM_EVCTRL_COMB_MATCH); + + lpc18xx_pwm_writel(lpc18xx_pwm, + LPC18XX_PWM_EVSTATEMSK(lpc18xx_data->duty_event), + LPC18XX_PWM_EVSTATEMSK_ALL); + + if (pwm->polarity == PWM_POLARITY_NORMAL) { + set_event = lpc18xx_pwm->period_event; + clear_event = lpc18xx_data->duty_event; + res_action = LPC18XX_PWM_RES_SET; + } else { + set_event = lpc18xx_data->duty_event; + clear_event = lpc18xx_pwm->period_event; + res_action = LPC18XX_PWM_RES_CLEAR; + } + + lpc18xx_pwm_writel(lpc18xx_pwm, LPC18XX_PWM_OUTPUTSET(pwm->hwpwm), + BIT(set_event)); + lpc18xx_pwm_writel(lpc18xx_pwm, LPC18XX_PWM_OUTPUTCL(pwm->hwpwm), + BIT(clear_event)); + lpc18xx_pwm_set_conflict_res(lpc18xx_pwm, pwm, res_action); + + return 0; +} + +static void lpc18xx_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) +{ + struct lpc18xx_pwm_chip *lpc18xx_pwm = to_lpc18xx_pwm_chip(chip); + struct lpc18xx_pwm_data *lpc18xx_data = pwm_get_chip_data(pwm); + + lpc18xx_pwm_writel(lpc18xx_pwm, + LPC18XX_PWM_EVCTRL(lpc18xx_data->duty_event), 0); + lpc18xx_pwm_writel(lpc18xx_pwm, LPC18XX_PWM_OUTPUTSET(pwm->hwpwm), 0); + lpc18xx_pwm_writel(lpc18xx_pwm, LPC18XX_PWM_OUTPUTCL(pwm->hwpwm), 0); +} + +static int lpc18xx_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm) +{ + struct lpc18xx_pwm_chip *lpc18xx_pwm = to_lpc18xx_pwm_chip(chip); + struct lpc18xx_pwm_data *lpc18xx_data = pwm_get_chip_data(pwm); + unsigned long event; + + event = find_first_zero_bit(&lpc18xx_pwm->event_map, + LPC18XX_PWM_EVENT_MAX); + + if (event >= LPC18XX_PWM_EVENT_MAX) { + dev_err(lpc18xx_pwm->dev, + "maximum number of simultaneous channels reached\n"); + return -EBUSY; + }; + + set_bit(event, &lpc18xx_pwm->event_map); + lpc18xx_data->duty_event = event; + lpc18xx_pwm_config_duty(chip, pwm, pwm_get_duty_cycle(pwm)); + + return 0; +} + +static void lpc18xx_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm) +{ + struct lpc18xx_pwm_chip *lpc18xx_pwm = to_lpc18xx_pwm_chip(chip); + struct lpc18xx_pwm_data *lpc18xx_data = pwm_get_chip_data(pwm); + + pwm_disable(pwm); + pwm_set_duty_cycle(pwm, 0); + clear_bit(lpc18xx_data->duty_event, &lpc18xx_pwm->event_map); +} + +static const struct pwm_ops lpc18xx_pwm_ops = { + .config = lpc18xx_pwm_config, + .set_polarity = lpc18xx_pwm_set_polarity, + .enable = lpc18xx_pwm_enable, + .disable = lpc18xx_pwm_disable, + .request = lpc18xx_pwm_request, + .free = lpc18xx_pwm_free, + .owner = THIS_MODULE, +}; + +static const struct of_device_id lpc18xx_pwm_of_match[] = { + { .compatible = "nxp,lpc1850-sct-pwm" }, + {} +}; +MODULE_DEVICE_TABLE(of, lpc18xx_pwm_of_match); + +static int lpc18xx_pwm_probe(struct platform_device *pdev) +{ + struct lpc18xx_pwm_chip *lpc18xx_pwm; + struct pwm_device *pwm; + struct resource *res; + int ret, i; + u64 val; + + lpc18xx_pwm = devm_kzalloc(&pdev->dev, sizeof(*lpc18xx_pwm), + GFP_KERNEL); + if (!lpc18xx_pwm) + return -ENOMEM; + + lpc18xx_pwm->dev = &pdev->dev; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + lpc18xx_pwm->base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(lpc18xx_pwm->base)) + return PTR_ERR(lpc18xx_pwm->base); + + lpc18xx_pwm->pwm_clk = devm_clk_get(&pdev->dev, "pwm"); + if (IS_ERR(lpc18xx_pwm->pwm_clk)) { + dev_err(&pdev->dev, "failed to get pwm clock\n"); + return PTR_ERR(lpc18xx_pwm->pwm_clk); + } + + ret = clk_prepare_enable(lpc18xx_pwm->pwm_clk); + if (ret < 0) { + dev_err(&pdev->dev, "could not prepare or enable pwm clock\n"); + return ret; + } + + lpc18xx_pwm->clk_rate = clk_get_rate(lpc18xx_pwm->pwm_clk); + + mutex_init(&lpc18xx_pwm->res_lock); + mutex_init(&lpc18xx_pwm->period_lock); + + val = (u64)NSEC_PER_SEC * LPC18XX_PWM_TIMER_MAX; + do_div(val, lpc18xx_pwm->clk_rate); + lpc18xx_pwm->max_period_ns = val; + + lpc18xx_pwm->min_period_ns = DIV_ROUND_UP(NSEC_PER_SEC, + lpc18xx_pwm->clk_rate); + + lpc18xx_pwm->chip.dev = &pdev->dev; + lpc18xx_pwm->chip.ops = &lpc18xx_pwm_ops; + lpc18xx_pwm->chip.base = -1; + lpc18xx_pwm->chip.npwm = 16; + lpc18xx_pwm->chip.of_xlate = of_pwm_xlate_with_flags; + lpc18xx_pwm->chip.of_pwm_n_cells = 3; + + /* SCT counter must be in unify (32 bit) mode */ + lpc18xx_pwm_writel(lpc18xx_pwm, LPC18XX_PWM_CONFIG, + LPC18XX_PWM_CONFIG_UNIFY); + + /* + * Everytime the timer counter reaches the period value, the related + * event will be triggered and the counter reset to 0. + */ + set_bit(LPC18XX_PWM_EVENT_PERIOD, &lpc18xx_pwm->event_map); + lpc18xx_pwm->period_event = LPC18XX_PWM_EVENT_PERIOD; + + lpc18xx_pwm_writel(lpc18xx_pwm, + LPC18XX_PWM_EVSTATEMSK(lpc18xx_pwm->period_event), + LPC18XX_PWM_EVSTATEMSK_ALL); + + val = LPC18XX_PWM_EVCTRL_MATCH(lpc18xx_pwm->period_event) | + LPC18XX_PWM_EVCTRL_COMB_MATCH; + lpc18xx_pwm_writel(lpc18xx_pwm, + LPC18XX_PWM_EVCTRL(lpc18xx_pwm->period_event), val); + + lpc18xx_pwm_writel(lpc18xx_pwm, LPC18XX_PWM_LIMIT, + BIT(lpc18xx_pwm->period_event)); + + ret = pwmchip_add(&lpc18xx_pwm->chip); + if (ret < 0) { + dev_err(&pdev->dev, "pwmchip_add failed: %d\n", ret); + goto disable_pwmclk; + } + + for (i = 0; i < lpc18xx_pwm->chip.npwm; i++) { + pwm = &lpc18xx_pwm->chip.pwms[i]; + pwm->chip_data = devm_kzalloc(lpc18xx_pwm->dev, + sizeof(struct lpc18xx_pwm_data), + GFP_KERNEL); + if (!pwm->chip_data) { + ret = -ENOMEM; + goto remove_pwmchip; + } + } + + platform_set_drvdata(pdev, lpc18xx_pwm); + + val = lpc18xx_pwm_readl(lpc18xx_pwm, LPC18XX_PWM_CTRL); + val &= ~LPC18XX_PWM_BIDIR; + val &= ~LPC18XX_PWM_CTRL_HALT; + val &= ~LPC18XX_PWM_PRE_MASK; + val |= LPC18XX_PWM_PRE(0); + lpc18xx_pwm_writel(lpc18xx_pwm, LPC18XX_PWM_CTRL, val); + + return 0; + +remove_pwmchip: + pwmchip_remove(&lpc18xx_pwm->chip); +disable_pwmclk: + clk_disable_unprepare(lpc18xx_pwm->pwm_clk); + return ret; +} + +static int lpc18xx_pwm_remove(struct platform_device *pdev) +{ + struct lpc18xx_pwm_chip *lpc18xx_pwm = platform_get_drvdata(pdev); + u32 val; + + val = lpc18xx_pwm_readl(lpc18xx_pwm, LPC18XX_PWM_CTRL); + lpc18xx_pwm_writel(lpc18xx_pwm, LPC18XX_PWM_CTRL, + val | LPC18XX_PWM_CTRL_HALT); + + clk_disable_unprepare(lpc18xx_pwm->pwm_clk); + + return pwmchip_remove(&lpc18xx_pwm->chip); +} + +static struct platform_driver lpc18xx_pwm_driver = { + .driver = { + .name = "lpc18xx-sct-pwm", + .of_match_table = lpc18xx_pwm_of_match, + }, + .probe = lpc18xx_pwm_probe, + .remove = lpc18xx_pwm_remove, +}; +module_platform_driver(lpc18xx_pwm_driver); + +MODULE_AUTHOR("Ariel D'Alessandro <ariel@vanguardiasur.com.ar>"); +MODULE_DESCRIPTION("NXP LPC18xx PWM driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/pwm/pwm-mxs.c b/drivers/pwm/pwm-mxs.c index b430811e14f5..9a596324ebef 100644 --- a/drivers/pwm/pwm-mxs.c +++ b/drivers/pwm/pwm-mxs.c @@ -77,7 +77,7 @@ static int mxs_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, * If the PWM channel is disabled, make sure to turn on the clock * before writing the register. Otherwise, keep it enabled. */ - if (!test_bit(PWMF_ENABLED, &pwm->flags)) { + if (!pwm_is_enabled(pwm)) { ret = clk_prepare_enable(mxs->clk); if (ret) return ret; @@ -92,7 +92,7 @@ static int mxs_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, /* * If the PWM is not enabled, turn the clock off again to save power. */ - if (!test_bit(PWMF_ENABLED, &pwm->flags)) + if (!pwm_is_enabled(pwm)) clk_disable_unprepare(mxs->clk); return 0; diff --git a/drivers/pwm/pwm-pca9685.c b/drivers/pwm/pwm-pca9685.c index 34b5c275a92a..70448a6079b0 100644 --- a/drivers/pwm/pwm-pca9685.c +++ b/drivers/pwm/pwm-pca9685.c @@ -2,6 +2,7 @@ * Driver for PCA9685 16-channel 12-bit PWM LED controller * * Copyright (C) 2013 Steffen Trumtrar <s.trumtrar@pengutronix.de> + * Copyright (C) 2015 Clemens Gruber <clemens.gruber@pqgruber.com> * * based on the pwm-twl-led.c driver * @@ -24,6 +25,15 @@ #include <linux/pwm.h> #include <linux/regmap.h> #include <linux/slab.h> +#include <linux/delay.h> + +/* + * Because the PCA9685 has only one prescaler per chip, changing the period of + * one channel affects the period of all 16 PWM outputs! + * However, the ratio between each configured duty cycle and the chip-wide + * period remains constant, because the OFF time is set in proportion to the + * counter range. + */ #define PCA9685_MODE1 0x00 #define PCA9685_MODE2 0x01 @@ -42,10 +52,18 @@ #define PCA9685_ALL_LED_OFF_H 0xFD #define PCA9685_PRESCALE 0xFE +#define PCA9685_PRESCALE_MIN 0x03 /* => max. frequency of 1526 Hz */ +#define PCA9685_PRESCALE_MAX 0xFF /* => min. frequency of 24 Hz */ + +#define PCA9685_COUNTER_RANGE 4096 +#define PCA9685_DEFAULT_PERIOD 5000000 /* Default period_ns = 1/200 Hz */ +#define PCA9685_OSC_CLOCK_MHZ 25 /* Internal oscillator with 25 MHz */ + #define PCA9685_NUMREGS 0xFF #define PCA9685_MAXCHAN 0x10 #define LED_FULL (1 << 4) +#define MODE1_RESTART (1 << 7) #define MODE1_SLEEP (1 << 4) #define MODE2_INVRT (1 << 4) #define MODE2_OUTDRV (1 << 2) @@ -59,6 +77,8 @@ struct pca9685 { struct pwm_chip chip; struct regmap *regmap; int active_cnt; + int duty_ns; + int period_ns; }; static inline struct pca9685 *to_pca(struct pwm_chip *chip) @@ -72,6 +92,47 @@ static int pca9685_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, struct pca9685 *pca = to_pca(chip); unsigned long long duty; unsigned int reg; + int prescale; + + if (period_ns != pca->period_ns) { + prescale = DIV_ROUND_CLOSEST(PCA9685_OSC_CLOCK_MHZ * period_ns, + PCA9685_COUNTER_RANGE * 1000) - 1; + + if (prescale >= PCA9685_PRESCALE_MIN && + prescale <= PCA9685_PRESCALE_MAX) { + /* Put chip into sleep mode */ + regmap_update_bits(pca->regmap, PCA9685_MODE1, + MODE1_SLEEP, MODE1_SLEEP); + + /* Change the chip-wide output frequency */ + regmap_write(pca->regmap, PCA9685_PRESCALE, prescale); + + /* Wake the chip up */ + regmap_update_bits(pca->regmap, PCA9685_MODE1, + MODE1_SLEEP, 0x0); + + /* Wait 500us for the oscillator to be back up */ + udelay(500); + + pca->period_ns = period_ns; + + /* + * If the duty cycle did not change, restart PWM with + * the same duty cycle to period ratio and return. + */ + if (duty_ns == pca->duty_ns) { + regmap_update_bits(pca->regmap, PCA9685_MODE1, + MODE1_RESTART, 0x1); + return 0; + } + } else { + dev_err(chip->dev, + "prescaler not set: period out of bounds!\n"); + return -EINVAL; + } + } + + pca->duty_ns = duty_ns; if (duty_ns < 1) { if (pwm->hwpwm >= PCA9685_MAXCHAN) @@ -85,6 +146,22 @@ static int pca9685_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, } if (duty_ns == period_ns) { + /* Clear both OFF registers */ + if (pwm->hwpwm >= PCA9685_MAXCHAN) + reg = PCA9685_ALL_LED_OFF_L; + else + reg = LED_N_OFF_L(pwm->hwpwm); + + regmap_write(pca->regmap, reg, 0x0); + + if (pwm->hwpwm >= PCA9685_MAXCHAN) + reg = PCA9685_ALL_LED_OFF_H; + else + reg = LED_N_OFF_H(pwm->hwpwm); + + regmap_write(pca->regmap, reg, 0x0); + + /* Set the full ON bit */ if (pwm->hwpwm >= PCA9685_MAXCHAN) reg = PCA9685_ALL_LED_ON_H; else @@ -95,7 +172,7 @@ static int pca9685_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, return 0; } - duty = 4096 * (unsigned long long)duty_ns; + duty = PCA9685_COUNTER_RANGE * (unsigned long long)duty_ns; duty = DIV_ROUND_UP_ULL(duty, period_ns); if (pwm->hwpwm >= PCA9685_MAXCHAN) @@ -112,6 +189,14 @@ static int pca9685_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, regmap_write(pca->regmap, reg, ((int)duty >> 8) & 0xf); + /* Clear the full ON bit, otherwise the set OFF time has no effect */ + if (pwm->hwpwm >= PCA9685_MAXCHAN) + reg = PCA9685_ALL_LED_ON_H; + else + reg = LED_N_ON_H(pwm->hwpwm); + + regmap_write(pca->regmap, reg, 0); + return 0; } @@ -228,6 +313,8 @@ static int pca9685_pwm_probe(struct i2c_client *client, ret); return ret; } + pca->duty_ns = 0; + pca->period_ns = PCA9685_DEFAULT_PERIOD; i2c_set_clientdata(client, pca); @@ -285,7 +372,6 @@ MODULE_DEVICE_TABLE(of, pca9685_dt_ids); static struct i2c_driver pca9685_i2c_driver = { .driver = { .name = "pca9685-pwm", - .owner = THIS_MODULE, .of_match_table = pca9685_dt_ids, }, .probe = pca9685_pwm_probe, diff --git a/drivers/pwm/pwm-renesas-tpu.c b/drivers/pwm/pwm-renesas-tpu.c index ee63f9e9d0fb..075c1a764ba2 100644 --- a/drivers/pwm/pwm-renesas-tpu.c +++ b/drivers/pwm/pwm-renesas-tpu.c @@ -301,7 +301,7 @@ static int tpu_pwm_config(struct pwm_chip *chip, struct pwm_device *_pwm, pwm->duty = duty; /* If the channel is disabled we're done. */ - if (!test_bit(PWMF_ENABLED, &_pwm->flags)) + if (!pwm_is_enabled(_pwm)) return 0; if (duty_only && pwm->timer_on) { diff --git a/drivers/pwm/pwm-rockchip.c b/drivers/pwm/pwm-rockchip.c index 9442df244101..7d9cc9049522 100644 --- a/drivers/pwm/pwm-rockchip.c +++ b/drivers/pwm/pwm-rockchip.c @@ -83,7 +83,7 @@ static void rockchip_pwm_set_enable_v2(struct pwm_chip *chip, PWM_CONTINUOUS; u32 val; - if (pwm->polarity == PWM_POLARITY_INVERSED) + if (pwm_get_polarity(pwm) == PWM_POLARITY_INVERSED) enable_conf |= PWM_DUTY_NEGATIVE | PWM_INACTIVE_POSITIVE; else enable_conf |= PWM_DUTY_POSITIVE | PWM_INACTIVE_NEGATIVE; diff --git a/drivers/pwm/pwm-tegra.c b/drivers/pwm/pwm-tegra.c index cabd7d8e05cc..d4de0607b502 100644 --- a/drivers/pwm/pwm-tegra.c +++ b/drivers/pwm/pwm-tegra.c @@ -112,7 +112,7 @@ static int tegra_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, * If the PWM channel is disabled, make sure to turn on the clock * before writing the register. Otherwise, keep it enabled. */ - if (!test_bit(PWMF_ENABLED, &pwm->flags)) { + if (!pwm_is_enabled(pwm)) { err = clk_prepare_enable(pc->clk); if (err < 0) return err; @@ -124,7 +124,7 @@ static int tegra_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, /* * If the PWM is not enabled, turn the clock off again to save power. */ - if (!test_bit(PWMF_ENABLED, &pwm->flags)) + if (!pwm_is_enabled(pwm)) clk_disable_unprepare(pc->clk); return 0; @@ -214,7 +214,7 @@ static int tegra_pwm_remove(struct platform_device *pdev) for (i = 0; i < NUM_PWM; i++) { struct pwm_device *pwm = &pc->chip.pwms[i]; - if (!test_bit(PWMF_ENABLED, &pwm->flags)) + if (!pwm_is_enabled(pwm)) if (clk_prepare_enable(pc->clk) < 0) continue; diff --git a/drivers/pwm/pwm-tiecap.c b/drivers/pwm/pwm-tiecap.c index e557befdf4e6..616af764a276 100644 --- a/drivers/pwm/pwm-tiecap.c +++ b/drivers/pwm/pwm-tiecap.c @@ -97,7 +97,7 @@ static int ecap_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, writew(reg_val, pc->mmio_base + ECCTL2); - if (!test_bit(PWMF_ENABLED, &pwm->flags)) { + if (!pwm_is_enabled(pwm)) { /* Update active registers if not running */ writel(duty_cycles, pc->mmio_base + CAP2); writel(period_cycles, pc->mmio_base + CAP1); @@ -111,7 +111,7 @@ static int ecap_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, writel(period_cycles, pc->mmio_base + CAP3); } - if (!test_bit(PWMF_ENABLED, &pwm->flags)) { + if (!pwm_is_enabled(pwm)) { reg_val = readw(pc->mmio_base + ECCTL2); /* Disable APWM mode to put APWM output Low */ reg_val &= ~ECCTL2_APWM_MODE; @@ -179,7 +179,7 @@ static void ecap_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) static void ecap_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm) { - if (test_bit(PWMF_ENABLED, &pwm->flags)) { + if (pwm_is_enabled(pwm)) { dev_warn(chip->dev, "Removing PWM device without disabling\n"); pm_runtime_put_sync(chip->dev); } @@ -306,7 +306,7 @@ static int ecap_pwm_suspend(struct device *dev) ecap_pwm_save_context(pc); /* Disable explicitly if PWM is running */ - if (test_bit(PWMF_ENABLED, &pwm->flags)) + if (pwm_is_enabled(pwm)) pm_runtime_put_sync(dev); return 0; @@ -318,7 +318,7 @@ static int ecap_pwm_resume(struct device *dev) struct pwm_device *pwm = pc->chip.pwms; /* Enable explicitly if PWM was running */ - if (test_bit(PWMF_ENABLED, &pwm->flags)) + if (pwm_is_enabled(pwm)) pm_runtime_get_sync(dev); ecap_pwm_restore_context(pc); diff --git a/drivers/pwm/pwm-tiehrpwm.c b/drivers/pwm/pwm-tiehrpwm.c index 694b3cf7694b..6a41e66015b6 100644 --- a/drivers/pwm/pwm-tiehrpwm.c +++ b/drivers/pwm/pwm-tiehrpwm.c @@ -407,7 +407,7 @@ static void ehrpwm_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm) { struct ehrpwm_pwm_chip *pc = to_ehrpwm_pwm_chip(chip); - if (test_bit(PWMF_ENABLED, &pwm->flags)) { + if (pwm_is_enabled(pwm)) { dev_warn(chip->dev, "Removing PWM device without disabling\n"); pm_runtime_put_sync(chip->dev); } @@ -565,7 +565,7 @@ static int ehrpwm_pwm_suspend(struct device *dev) for (i = 0; i < pc->chip.npwm; i++) { struct pwm_device *pwm = &pc->chip.pwms[i]; - if (!test_bit(PWMF_ENABLED, &pwm->flags)) + if (!pwm_is_enabled(pwm)) continue; /* Disable explicitly if PWM is running */ @@ -582,7 +582,7 @@ static int ehrpwm_pwm_resume(struct device *dev) for (i = 0; i < pc->chip.npwm; i++) { struct pwm_device *pwm = &pc->chip.pwms[i]; - if (!test_bit(PWMF_ENABLED, &pwm->flags)) + if (!pwm_is_enabled(pwm)) continue; /* Enable explicitly if PWM was running */ diff --git a/drivers/pwm/sysfs.c b/drivers/pwm/sysfs.c index 4bd0c639e16d..c472772f00a7 100644 --- a/drivers/pwm/sysfs.c +++ b/drivers/pwm/sysfs.c @@ -46,7 +46,7 @@ static ssize_t pwm_period_show(struct device *child, { const struct pwm_device *pwm = child_to_pwm_device(child); - return sprintf(buf, "%u\n", pwm->period); + return sprintf(buf, "%u\n", pwm_get_period(pwm)); } static ssize_t pwm_period_store(struct device *child, @@ -61,7 +61,7 @@ static ssize_t pwm_period_store(struct device *child, if (ret) return ret; - ret = pwm_config(pwm, pwm->duty_cycle, val); + ret = pwm_config(pwm, pwm_get_duty_cycle(pwm), val); return ret ? : size; } @@ -72,7 +72,7 @@ static ssize_t pwm_duty_cycle_show(struct device *child, { const struct pwm_device *pwm = child_to_pwm_device(child); - return sprintf(buf, "%u\n", pwm->duty_cycle); + return sprintf(buf, "%u\n", pwm_get_duty_cycle(pwm)); } static ssize_t pwm_duty_cycle_store(struct device *child, @@ -87,7 +87,7 @@ static ssize_t pwm_duty_cycle_store(struct device *child, if (ret) return ret; - ret = pwm_config(pwm, val, pwm->period); + ret = pwm_config(pwm, val, pwm_get_period(pwm)); return ret ? : size; } @@ -97,7 +97,7 @@ static ssize_t pwm_enable_show(struct device *child, char *buf) { const struct pwm_device *pwm = child_to_pwm_device(child); - int enabled = test_bit(PWMF_ENABLED, &pwm->flags); + int enabled = pwm_is_enabled(pwm); return sprintf(buf, "%d\n", enabled); } @@ -133,8 +133,19 @@ static ssize_t pwm_polarity_show(struct device *child, char *buf) { const struct pwm_device *pwm = child_to_pwm_device(child); + const char *polarity = "unknown"; - return sprintf(buf, "%s\n", pwm->polarity ? "inversed" : "normal"); + switch (pwm_get_polarity(pwm)) { + case PWM_POLARITY_NORMAL: + polarity = "normal"; + break; + + case PWM_POLARITY_INVERSED: + polarity = "inversed"; + break; + } + + return sprintf(buf, "%s\n", polarity); } static ssize_t pwm_polarity_store(struct device *child, @@ -301,9 +312,9 @@ static struct attribute *pwm_chip_attrs[] = { ATTRIBUTE_GROUPS(pwm_chip); static struct class pwm_class = { - .name = "pwm", - .owner = THIS_MODULE, - .dev_groups = pwm_chip_groups, + .name = "pwm", + .owner = THIS_MODULE, + .dev_groups = pwm_chip_groups, }; static int pwmchip_sysfs_match(struct device *parent, const void *data) diff --git a/drivers/reset/reset-ath79.c b/drivers/reset/reset-ath79.c index d2d290413113..9aaf646ece55 100644 --- a/drivers/reset/reset-ath79.c +++ b/drivers/reset/reset-ath79.c @@ -89,6 +89,7 @@ static int ath79_reset_probe(struct platform_device *pdev) if (IS_ERR(ath79_reset->base)) return PTR_ERR(ath79_reset->base); + spin_lock_init(&ath79_reset->lock); ath79_reset->rcdev.ops = &ath79_reset_ops; ath79_reset->rcdev.owner = THIS_MODULE; ath79_reset->rcdev.of_node = pdev->dev.of_node; diff --git a/drivers/scsi/xen-scsifront.c b/drivers/scsi/xen-scsifront.c index fad22caf0eff..9dc8687bf048 100644 --- a/drivers/scsi/xen-scsifront.c +++ b/drivers/scsi/xen-scsifront.c @@ -377,7 +377,6 @@ static int map_data_for_request(struct vscsifrnt_info *info, unsigned int data_len = scsi_bufflen(sc); unsigned int data_grants = 0, seg_grants = 0; struct scatterlist *sg; - unsigned long mfn; struct scsiif_request_segment *seg; ring_req->nr_segments = 0; @@ -420,9 +419,9 @@ static int map_data_for_request(struct vscsifrnt_info *info, ref = gnttab_claim_grant_reference(&gref_head); BUG_ON(ref == -ENOSPC); - mfn = pfn_to_mfn(page_to_pfn(page)); gnttab_grant_foreign_access_ref(ref, - info->dev->otherend_id, mfn, 1); + info->dev->otherend_id, + xen_page_to_gfn(page), 1); shadow->gref[ref_cnt] = ref; ring_req->seg[ref_cnt].gref = ref; ring_req->seg[ref_cnt].offset = (uint16_t)off; @@ -454,9 +453,10 @@ static int map_data_for_request(struct vscsifrnt_info *info, ref = gnttab_claim_grant_reference(&gref_head); BUG_ON(ref == -ENOSPC); - mfn = pfn_to_mfn(page_to_pfn(page)); gnttab_grant_foreign_access_ref(ref, - info->dev->otherend_id, mfn, grant_ro); + info->dev->otherend_id, + xen_page_to_gfn(page), + grant_ro); shadow->gref[ref_cnt] = ref; seg->gref = ref; diff --git a/drivers/soc/qcom/smd.c b/drivers/soc/qcom/smd.c index 327adcf117c1..a6155c917d52 100644 --- a/drivers/soc/qcom/smd.c +++ b/drivers/soc/qcom/smd.c @@ -96,6 +96,7 @@ static const struct { * @smd: handle to qcom_smd * @of_node: of_node handle for information related to this edge * @edge_id: identifier of this edge + * @remote_pid: identifier of remote processor * @irq: interrupt for signals on this edge * @ipc_regmap: regmap handle holding the outgoing ipc register * @ipc_offset: offset within @ipc_regmap of the register for ipc @@ -111,6 +112,7 @@ struct qcom_smd_edge { struct qcom_smd *smd; struct device_node *of_node; unsigned edge_id; + unsigned remote_pid; int irq; @@ -310,7 +312,7 @@ static void qcom_smd_channel_reset(struct qcom_smd_channel *channel) SET_TX_CHANNEL_INFO(channel, fHEAD, 0); SET_TX_CHANNEL_INFO(channel, fTAIL, 0); SET_TX_CHANNEL_INFO(channel, fSTATE, 1); - SET_TX_CHANNEL_INFO(channel, fBLOCKREADINTR, 0); + SET_TX_CHANNEL_INFO(channel, fBLOCKREADINTR, 1); SET_TX_CHANNEL_INFO(channel, head, 0); SET_TX_CHANNEL_INFO(channel, tail, 0); @@ -572,7 +574,7 @@ static irqreturn_t qcom_smd_edge_intr(int irq, void *data) * have to scan if the amount of available space in smem have changed * since last scan. */ - available = qcom_smem_get_free_space(edge->edge_id); + available = qcom_smem_get_free_space(edge->remote_pid); if (available != edge->smem_available) { edge->smem_available = available; edge->need_rescan = true; @@ -681,7 +683,7 @@ int qcom_smd_send(struct qcom_smd_channel *channel, const void *data, int len) goto out; } - SET_TX_CHANNEL_INFO(channel, fBLOCKREADINTR, 1); + SET_TX_CHANNEL_INFO(channel, fBLOCKREADINTR, 0); ret = wait_event_interruptible(channel->fblockread_event, qcom_smd_get_tx_avail(channel) >= tlen || @@ -689,7 +691,7 @@ int qcom_smd_send(struct qcom_smd_channel *channel, const void *data, int len) if (ret) goto out; - SET_TX_CHANNEL_INFO(channel, fBLOCKREADINTR, 0); + SET_TX_CHANNEL_INFO(channel, fBLOCKREADINTR, 1); } SET_TX_CHANNEL_INFO(channel, fTAIL, 0); @@ -976,7 +978,8 @@ static struct qcom_smd_channel *qcom_smd_create_channel(struct qcom_smd_edge *ed spin_lock_init(&channel->recv_lock); init_waitqueue_head(&channel->fblockread_event); - ret = qcom_smem_get(edge->edge_id, smem_info_item, (void **)&info, &info_size); + ret = qcom_smem_get(edge->remote_pid, smem_info_item, (void **)&info, + &info_size); if (ret) goto free_name_and_channel; @@ -997,7 +1000,8 @@ static struct qcom_smd_channel *qcom_smd_create_channel(struct qcom_smd_edge *ed goto free_name_and_channel; } - ret = qcom_smem_get(edge->edge_id, smem_fifo_item, &fifo_base, &fifo_size); + ret = qcom_smem_get(edge->remote_pid, smem_fifo_item, &fifo_base, + &fifo_size); if (ret) goto free_name_and_channel; @@ -1041,7 +1045,7 @@ static void qcom_discover_channels(struct qcom_smd_edge *edge) int i; for (tbl = 0; tbl < SMD_ALLOC_TBL_COUNT; tbl++) { - ret = qcom_smem_get(edge->edge_id, + ret = qcom_smem_get(edge->remote_pid, smem_items[tbl].alloc_tbl_id, (void **)&alloc_tbl, NULL); @@ -1184,6 +1188,10 @@ static int qcom_smd_parse_edge(struct device *dev, return -EINVAL; } + edge->remote_pid = QCOM_SMEM_HOST_ANY; + key = "qcom,remote-pid"; + of_property_read_u32(node, key, &edge->remote_pid); + syscon_np = of_parse_phandle(node, "qcom,ipc", 0); if (!syscon_np) { dev_err(dev, "no qcom,ipc node\n"); diff --git a/drivers/soc/qcom/smem.c b/drivers/soc/qcom/smem.c index 7c2c324c4b10..52365188a1c2 100644 --- a/drivers/soc/qcom/smem.c +++ b/drivers/soc/qcom/smem.c @@ -258,10 +258,6 @@ static int qcom_smem_alloc_private(struct qcom_smem *smem, size_t alloc_size; void *p; - /* We're not going to find it if there's no matching partition */ - if (host >= SMEM_HOST_COUNT || !smem->partitions[host]) - return -ENOENT; - phdr = smem->partitions[host]; p = (void *)phdr + sizeof(*phdr); @@ -371,8 +367,9 @@ int qcom_smem_alloc(unsigned host, unsigned item, size_t size) if (ret) return ret; - ret = qcom_smem_alloc_private(__smem, host, item, size); - if (ret == -ENOENT) + if (host < SMEM_HOST_COUNT && __smem->partitions[host]) + ret = qcom_smem_alloc_private(__smem, host, item, size); + else ret = qcom_smem_alloc_global(__smem, item, size); hwspin_unlock_irqrestore(__smem->hwlock, &flags); @@ -428,10 +425,6 @@ static int qcom_smem_get_private(struct qcom_smem *smem, struct smem_private_entry *hdr; void *p; - /* We're not going to find it if there's no matching partition */ - if (host >= SMEM_HOST_COUNT || !smem->partitions[host]) - return -ENOENT; - phdr = smem->partitions[host]; p = (void *)phdr + sizeof(*phdr); @@ -484,8 +477,9 @@ int qcom_smem_get(unsigned host, unsigned item, void **ptr, size_t *size) if (ret) return ret; - ret = qcom_smem_get_private(__smem, host, item, ptr, size); - if (ret == -ENOENT) + if (host < SMEM_HOST_COUNT && __smem->partitions[host]) + ret = qcom_smem_get_private(__smem, host, item, ptr, size); + else ret = qcom_smem_get_global(__smem, item, ptr, size); hwspin_unlock_irqrestore(__smem->hwlock, &flags); diff --git a/drivers/tty/hvc/hvc_xen.c b/drivers/tty/hvc/hvc_xen.c index a9d837f83ce8..10beb1589d83 100644 --- a/drivers/tty/hvc/hvc_xen.c +++ b/drivers/tty/hvc/hvc_xen.c @@ -200,7 +200,7 @@ static int xen_hvm_console_init(void) { int r; uint64_t v = 0; - unsigned long mfn; + unsigned long gfn; struct xencons_info *info; if (!xen_hvm_domain()) @@ -217,7 +217,7 @@ static int xen_hvm_console_init(void) } /* * If the toolstack (or the hypervisor) hasn't set these values, the - * default value is 0. Even though mfn = 0 and evtchn = 0 are + * default value is 0. Even though gfn = 0 and evtchn = 0 are * theoretically correct values, in practice they never are and they * mean that a legacy toolstack hasn't initialized the pv console correctly. */ @@ -229,8 +229,8 @@ static int xen_hvm_console_init(void) r = hvm_get_parameter(HVM_PARAM_CONSOLE_PFN, &v); if (r < 0 || v == 0) goto err; - mfn = v; - info->intf = xen_remap(mfn << PAGE_SHIFT, PAGE_SIZE); + gfn = v; + info->intf = xen_remap(gfn << PAGE_SHIFT, PAGE_SIZE); if (info->intf == NULL) goto err; info->vtermno = HVC_COOKIE; @@ -265,7 +265,8 @@ static int xen_pv_console_init(void) return 0; } info->evtchn = xen_start_info->console.domU.evtchn; - info->intf = mfn_to_virt(xen_start_info->console.domU.mfn); + /* GFN == MFN for PV guest */ + info->intf = gfn_to_virt(xen_start_info->console.domU.mfn); info->vtermno = HVC_COOKIE; spin_lock(&xencons_lock); @@ -374,7 +375,6 @@ static int xencons_connect_backend(struct xenbus_device *dev, int ret, evtchn, devid, ref, irq; struct xenbus_transaction xbt; grant_ref_t gref_head; - unsigned long mfn; ret = xenbus_alloc_evtchn(dev, &evtchn); if (ret) @@ -389,10 +389,6 @@ static int xencons_connect_backend(struct xenbus_device *dev, irq, &domU_hvc_ops, 256); if (IS_ERR(info->hvc)) return PTR_ERR(info->hvc); - if (xen_pv_domain()) - mfn = virt_to_mfn(info->intf); - else - mfn = __pa(info->intf) >> PAGE_SHIFT; ret = gnttab_alloc_grant_references(1, &gref_head); if (ret < 0) return ret; @@ -401,7 +397,7 @@ static int xencons_connect_backend(struct xenbus_device *dev, if (ref < 0) return ref; gnttab_grant_foreign_access_ref(ref, info->xbdev->otherend_id, - mfn, 0); + virt_to_gfn(info->intf), 0); again: ret = xenbus_transaction_start(&xbt); diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index ed299b9e6375..687b1ea294b7 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -47,12 +47,12 @@ config SERIAL_AMBA_PL010_CONSOLE config SERIAL_AMBA_PL011 tristate "ARM AMBA PL011 serial port support" - depends on ARM_AMBA || SOC_ZX296702 + depends on ARM_AMBA select SERIAL_CORE help This selects the ARM(R) AMBA(R) PrimeCell PL011 UART. If you have an Integrator/PP2, Integrator/CP or Versatile platform, say Y or M - here. Say Y or M if you have SOC_ZX296702. + here. If unsure, say N. diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index 2af09ab153b6..fd27e986b1dd 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -74,13 +74,8 @@ /* There is by now at least one vendor with differing details, so handle it */ struct vendor_data { unsigned int ifls; - unsigned int fr_busy; - unsigned int fr_dsr; - unsigned int fr_cts; - unsigned int fr_ri; unsigned int lcrh_tx; unsigned int lcrh_rx; - u16 *reg_lut; bool oversampling; bool dma_threshold; bool cts_event_workaround; @@ -90,48 +85,6 @@ struct vendor_data { unsigned int (*get_fifosize)(struct amba_device *dev); }; -/* Max address offset of register in use is 0x48 */ -#define REG_NR (0x48 >> 2) -#define IDX(x) (x >> 2) -enum reg_idx { - REG_DR = IDX(UART01x_DR), - REG_RSR = IDX(UART01x_RSR), - REG_ST_DMAWM = IDX(ST_UART011_DMAWM), - REG_FR = IDX(UART01x_FR), - REG_ST_LCRH_RX = IDX(ST_UART011_LCRH_RX), - REG_ILPR = IDX(UART01x_ILPR), - REG_IBRD = IDX(UART011_IBRD), - REG_FBRD = IDX(UART011_FBRD), - REG_LCRH = IDX(UART011_LCRH), - REG_CR = IDX(UART011_CR), - REG_IFLS = IDX(UART011_IFLS), - REG_IMSC = IDX(UART011_IMSC), - REG_RIS = IDX(UART011_RIS), - REG_MIS = IDX(UART011_MIS), - REG_ICR = IDX(UART011_ICR), - REG_DMACR = IDX(UART011_DMACR), -}; - -static u16 arm_reg[] = { - [REG_DR] = UART01x_DR, - [REG_RSR] = UART01x_RSR, - [REG_ST_DMAWM] = ~0, - [REG_FR] = UART01x_FR, - [REG_ST_LCRH_RX] = ~0, - [REG_ILPR] = UART01x_ILPR, - [REG_IBRD] = UART011_IBRD, - [REG_FBRD] = UART011_FBRD, - [REG_LCRH] = UART011_LCRH, - [REG_CR] = UART011_CR, - [REG_IFLS] = UART011_IFLS, - [REG_IMSC] = UART011_IMSC, - [REG_RIS] = UART011_RIS, - [REG_MIS] = UART011_MIS, - [REG_ICR] = UART011_ICR, - [REG_DMACR] = UART011_DMACR, -}; - -#ifdef CONFIG_ARM_AMBA static unsigned int get_fifosize_arm(struct amba_device *dev) { return amba_rev(dev) < 3 ? 16 : 32; @@ -139,13 +92,8 @@ static unsigned int get_fifosize_arm(struct amba_device *dev) static struct vendor_data vendor_arm = { .ifls = UART011_IFLS_RX4_8|UART011_IFLS_TX4_8, - .fr_busy = UART01x_FR_BUSY, - .fr_dsr = UART01x_FR_DSR, - .fr_cts = UART01x_FR_CTS, - .fr_ri = UART011_FR_RI, - .lcrh_tx = REG_LCRH, - .lcrh_rx = REG_LCRH, - .reg_lut = arm_reg, + .lcrh_tx = UART011_LCRH, + .lcrh_rx = UART011_LCRH, .oversampling = false, .dma_threshold = false, .cts_event_workaround = false, @@ -153,14 +101,8 @@ static struct vendor_data vendor_arm = { .fixed_options = false, .get_fifosize = get_fifosize_arm, }; -#endif static struct vendor_data vendor_sbsa = { - .fr_busy = UART01x_FR_BUSY, - .fr_dsr = UART01x_FR_DSR, - .fr_cts = UART01x_FR_CTS, - .fr_ri = UART011_FR_RI, - .reg_lut = arm_reg, .oversampling = false, .dma_threshold = false, .cts_event_workaround = false, @@ -168,26 +110,6 @@ static struct vendor_data vendor_sbsa = { .fixed_options = true, }; -#ifdef CONFIG_ARM_AMBA -static u16 st_reg[] = { - [REG_DR] = UART01x_DR, - [REG_RSR] = UART01x_RSR, - [REG_ST_DMAWM] = ST_UART011_DMAWM, - [REG_FR] = UART01x_FR, - [REG_ST_LCRH_RX] = ST_UART011_LCRH_RX, - [REG_ILPR] = UART01x_ILPR, - [REG_IBRD] = UART011_IBRD, - [REG_FBRD] = UART011_FBRD, - [REG_LCRH] = UART011_LCRH, - [REG_CR] = UART011_CR, - [REG_IFLS] = UART011_IFLS, - [REG_IMSC] = UART011_IMSC, - [REG_RIS] = UART011_RIS, - [REG_MIS] = UART011_MIS, - [REG_ICR] = UART011_ICR, - [REG_DMACR] = UART011_DMACR, -}; - static unsigned int get_fifosize_st(struct amba_device *dev) { return 64; @@ -195,13 +117,8 @@ static unsigned int get_fifosize_st(struct amba_device *dev) static struct vendor_data vendor_st = { .ifls = UART011_IFLS_RX_HALF|UART011_IFLS_TX_HALF, - .fr_busy = UART01x_FR_BUSY, - .fr_dsr = UART01x_FR_DSR, - .fr_cts = UART01x_FR_CTS, - .fr_ri = UART011_FR_RI, - .lcrh_tx = REG_LCRH, - .lcrh_rx = REG_ST_LCRH_RX, - .reg_lut = st_reg, + .lcrh_tx = ST_UART011_LCRH_TX, + .lcrh_rx = ST_UART011_LCRH_RX, .oversampling = true, .dma_threshold = true, .cts_event_workaround = true, @@ -209,43 +126,6 @@ static struct vendor_data vendor_st = { .fixed_options = false, .get_fifosize = get_fifosize_st, }; -#endif - -#ifdef CONFIG_SOC_ZX296702 -static u16 zte_reg[] = { - [REG_DR] = ZX_UART01x_DR, - [REG_RSR] = UART01x_RSR, - [REG_ST_DMAWM] = ST_UART011_DMAWM, - [REG_FR] = ZX_UART01x_FR, - [REG_ST_LCRH_RX] = ST_UART011_LCRH_RX, - [REG_ILPR] = UART01x_ILPR, - [REG_IBRD] = UART011_IBRD, - [REG_FBRD] = UART011_FBRD, - [REG_LCRH] = ZX_UART011_LCRH_TX, - [REG_CR] = ZX_UART011_CR, - [REG_IFLS] = ZX_UART011_IFLS, - [REG_IMSC] = ZX_UART011_IMSC, - [REG_RIS] = ZX_UART011_RIS, - [REG_MIS] = ZX_UART011_MIS, - [REG_ICR] = ZX_UART011_ICR, - [REG_DMACR] = ZX_UART011_DMACR, -}; - -static struct vendor_data vendor_zte = { - .ifls = UART011_IFLS_RX4_8|UART011_IFLS_TX4_8, - .fr_busy = ZX_UART01x_FR_BUSY, - .fr_dsr = ZX_UART01x_FR_DSR, - .fr_cts = ZX_UART01x_FR_CTS, - .fr_ri = ZX_UART011_FR_RI, - .lcrh_tx = REG_LCRH, - .lcrh_rx = REG_ST_LCRH_RX, - .reg_lut = zte_reg, - .oversampling = false, - .dma_threshold = false, - .cts_event_workaround = false, - .fixed_options = false, -}; -#endif /* Deals with DMA transactions */ @@ -284,15 +164,10 @@ struct uart_amba_port { struct uart_port port; struct clk *clk; const struct vendor_data *vendor; - u16 *reg_lut; unsigned int dmacr; /* dma control reg */ unsigned int im; /* interrupt mask */ unsigned int old_status; unsigned int fifosize; /* vendor-specific */ - unsigned int fr_busy; /* vendor-specific */ - unsigned int fr_dsr; /* vendor-specific */ - unsigned int fr_cts; /* vendor-specific */ - unsigned int fr_ri; /* vendor-specific */ unsigned int lcrh_tx; /* vendor-specific */ unsigned int lcrh_rx; /* vendor-specific */ unsigned int old_cr; /* state during shutdown */ @@ -309,29 +184,6 @@ struct uart_amba_port { #endif }; -static bool is_implemented(struct uart_amba_port *uap, unsigned int reg) -{ - return uap->reg_lut[reg] != (u16)~0; -} - -static unsigned int pl011_readw(struct uart_amba_port *uap, int index) -{ - WARN_ON(index > REG_NR); - return readw_relaxed(uap->port.membase + uap->reg_lut[index]); -} - -static void pl011_writew(struct uart_amba_port *uap, int val, int index) -{ - WARN_ON(index > REG_NR); - writew_relaxed(val, uap->port.membase + uap->reg_lut[index]); -} - -static void pl011_writeb(struct uart_amba_port *uap, u8 val, int index) -{ - WARN_ON(index > REG_NR); - writeb_relaxed(val, uap->port.membase + uap->reg_lut[index]); -} - /* * Reads up to 256 characters from the FIFO or until it's empty and * inserts them into the TTY layer. Returns the number of characters @@ -344,12 +196,12 @@ static int pl011_fifo_to_tty(struct uart_amba_port *uap) int fifotaken = 0; while (max_count--) { - status = pl011_readw(uap, REG_FR); + status = readw(uap->port.membase + UART01x_FR); if (status & UART01x_FR_RXFE) break; /* Take chars from the FIFO and update status */ - ch = pl011_readw(uap, REG_DR) | + ch = readw(uap->port.membase + UART01x_DR) | UART_DUMMY_DR_RX; flag = TTY_NORMAL; uap->port.icount.rx++; @@ -432,7 +284,7 @@ static void pl011_dma_probe(struct uart_amba_port *uap) struct amba_pl011_data *plat = dev_get_platdata(uap->port.dev); struct device *dev = uap->port.dev; struct dma_slave_config tx_conf = { - .dst_addr = uap->port.mapbase + uap->reg_lut[REG_DR], + .dst_addr = uap->port.mapbase + UART01x_DR, .dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE, .direction = DMA_MEM_TO_DEV, .dst_maxburst = uap->fifosize >> 1, @@ -487,7 +339,7 @@ static void pl011_dma_probe(struct uart_amba_port *uap) if (chan) { struct dma_slave_config rx_conf = { - .src_addr = uap->port.mapbase + uap->reg_lut[REG_DR], + .src_addr = uap->port.mapbase + UART01x_DR, .src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE, .direction = DMA_DEV_TO_MEM, .src_maxburst = uap->fifosize >> 2, @@ -586,7 +438,7 @@ static void pl011_dma_tx_callback(void *data) dmacr = uap->dmacr; uap->dmacr = dmacr & ~UART011_TXDMAE; - pl011_writew(uap, uap->dmacr, REG_DMACR); + writew(uap->dmacr, uap->port.membase + UART011_DMACR); /* * If TX DMA was disabled, it means that we've stopped the DMA for @@ -700,7 +552,7 @@ static int pl011_dma_tx_refill(struct uart_amba_port *uap) dma_dev->device_issue_pending(chan); uap->dmacr |= UART011_TXDMAE; - pl011_writew(uap, uap->dmacr, REG_DMACR); + writew(uap->dmacr, uap->port.membase + UART011_DMACR); uap->dmatx.queued = true; /* @@ -736,9 +588,9 @@ static bool pl011_dma_tx_irq(struct uart_amba_port *uap) */ if (uap->dmatx.queued) { uap->dmacr |= UART011_TXDMAE; - pl011_writew(uap, uap->dmacr, REG_DMACR); + writew(uap->dmacr, uap->port.membase + UART011_DMACR); uap->im &= ~UART011_TXIM; - pl011_writew(uap, uap->im, REG_IMSC); + writew(uap->im, uap->port.membase + UART011_IMSC); return true; } @@ -748,7 +600,7 @@ static bool pl011_dma_tx_irq(struct uart_amba_port *uap) */ if (pl011_dma_tx_refill(uap) > 0) { uap->im &= ~UART011_TXIM; - pl011_writew(uap, uap->im, REG_IMSC); + writew(uap->im, uap->port.membase + UART011_IMSC); return true; } return false; @@ -762,7 +614,7 @@ static inline void pl011_dma_tx_stop(struct uart_amba_port *uap) { if (uap->dmatx.queued) { uap->dmacr &= ~UART011_TXDMAE; - pl011_writew(uap, uap->dmacr, REG_DMACR); + writew(uap->dmacr, uap->port.membase + UART011_DMACR); } } @@ -788,12 +640,14 @@ static inline bool pl011_dma_tx_start(struct uart_amba_port *uap) if (!uap->dmatx.queued) { if (pl011_dma_tx_refill(uap) > 0) { uap->im &= ~UART011_TXIM; - pl011_writew(uap, uap->im, REG_IMSC); + writew(uap->im, uap->port.membase + + UART011_IMSC); } else ret = false; } else if (!(uap->dmacr & UART011_TXDMAE)) { uap->dmacr |= UART011_TXDMAE; - pl011_writew(uap, uap->dmacr, REG_DMACR); + writew(uap->dmacr, + uap->port.membase + UART011_DMACR); } return ret; } @@ -804,9 +658,9 @@ static inline bool pl011_dma_tx_start(struct uart_amba_port *uap) */ dmacr = uap->dmacr; uap->dmacr &= ~UART011_TXDMAE; - pl011_writew(uap, uap->dmacr, REG_DMACR); + writew(uap->dmacr, uap->port.membase + UART011_DMACR); - if (pl011_readw(uap, REG_FR) & UART01x_FR_TXFF) { + if (readw(uap->port.membase + UART01x_FR) & UART01x_FR_TXFF) { /* * No space in the FIFO, so enable the transmit interrupt * so we know when there is space. Note that once we've @@ -815,13 +669,13 @@ static inline bool pl011_dma_tx_start(struct uart_amba_port *uap) return false; } - pl011_writew(uap, uap->port.x_char, REG_DR); + writew(uap->port.x_char, uap->port.membase + UART01x_DR); uap->port.icount.tx++; uap->port.x_char = 0; /* Success - restore the DMA state */ uap->dmacr = dmacr; - pl011_writew(uap, dmacr, REG_DMACR); + writew(dmacr, uap->port.membase + UART011_DMACR); return true; } @@ -849,7 +703,7 @@ __acquires(&uap->port.lock) DMA_TO_DEVICE); uap->dmatx.queued = false; uap->dmacr &= ~UART011_TXDMAE; - pl011_writew(uap, uap->dmacr, REG_DMACR); + writew(uap->dmacr, uap->port.membase + UART011_DMACR); } } @@ -889,11 +743,11 @@ static int pl011_dma_rx_trigger_dma(struct uart_amba_port *uap) dma_async_issue_pending(rxchan); uap->dmacr |= UART011_RXDMAE; - pl011_writew(uap, uap->dmacr, REG_DMACR); + writew(uap->dmacr, uap->port.membase + UART011_DMACR); uap->dmarx.running = true; uap->im &= ~UART011_RXIM; - pl011_writew(uap, uap->im, REG_IMSC); + writew(uap->im, uap->port.membase + UART011_IMSC); return 0; } @@ -951,9 +805,8 @@ static void pl011_dma_rx_chars(struct uart_amba_port *uap, */ if (dma_count == pending && readfifo) { /* Clear any error flags */ - pl011_writew(uap, - UART011_OEIS | UART011_BEIS | UART011_PEIS - | UART011_FEIS, REG_ICR); + writew(UART011_OEIS | UART011_BEIS | UART011_PEIS | UART011_FEIS, + uap->port.membase + UART011_ICR); /* * If we read all the DMA'd characters, and we had an @@ -1001,7 +854,7 @@ static void pl011_dma_rx_irq(struct uart_amba_port *uap) /* Disable RX DMA - incoming data will wait in the FIFO */ uap->dmacr &= ~UART011_RXDMAE; - pl011_writew(uap, uap->dmacr, REG_DMACR); + writew(uap->dmacr, uap->port.membase + UART011_DMACR); uap->dmarx.running = false; pending = sgbuf->sg.length - state.residue; @@ -1021,7 +874,7 @@ static void pl011_dma_rx_irq(struct uart_amba_port *uap) dev_dbg(uap->port.dev, "could not retrigger RX DMA job " "fall back to interrupt mode\n"); uap->im |= UART011_RXIM; - pl011_writew(uap, uap->im, REG_IMSC); + writew(uap->im, uap->port.membase + UART011_IMSC); } } @@ -1069,7 +922,7 @@ static void pl011_dma_rx_callback(void *data) dev_dbg(uap->port.dev, "could not retrigger RX DMA job " "fall back to interrupt mode\n"); uap->im |= UART011_RXIM; - pl011_writew(uap, uap->im, REG_IMSC); + writew(uap->im, uap->port.membase + UART011_IMSC); } } @@ -1082,7 +935,7 @@ static inline void pl011_dma_rx_stop(struct uart_amba_port *uap) { /* FIXME. Just disable the DMA enable */ uap->dmacr &= ~UART011_RXDMAE; - pl011_writew(uap, uap->dmacr, REG_DMACR); + writew(uap->dmacr, uap->port.membase + UART011_DMACR); } /* @@ -1126,7 +979,7 @@ static void pl011_dma_rx_poll(unsigned long args) spin_lock_irqsave(&uap->port.lock, flags); pl011_dma_rx_stop(uap); uap->im |= UART011_RXIM; - pl011_writew(uap, uap->im, REG_IMSC); + writew(uap->im, uap->port.membase + UART011_IMSC); spin_unlock_irqrestore(&uap->port.lock, flags); uap->dmarx.running = false; @@ -1188,7 +1041,7 @@ static void pl011_dma_startup(struct uart_amba_port *uap) skip_rx: /* Turn on DMA error (RX/TX will be enabled on demand) */ uap->dmacr |= UART011_DMAONERR; - pl011_writew(uap, uap->dmacr, REG_DMACR); + writew(uap->dmacr, uap->port.membase + UART011_DMACR); /* * ST Micro variants has some specific dma burst threshold @@ -1196,9 +1049,8 @@ skip_rx: * be issued above/below 16 bytes. */ if (uap->vendor->dma_threshold) - pl011_writew(uap, - ST_UART011_DMAWM_RX_16 | ST_UART011_DMAWM_TX_16, - REG_ST_DMAWM); + writew(ST_UART011_DMAWM_RX_16 | ST_UART011_DMAWM_TX_16, + uap->port.membase + ST_UART011_DMAWM); if (uap->using_rx_dma) { if (pl011_dma_rx_trigger_dma(uap)) @@ -1223,12 +1075,12 @@ static void pl011_dma_shutdown(struct uart_amba_port *uap) return; /* Disable RX and TX DMA */ - while (pl011_readw(uap, REG_FR) & uap->fr_busy) + while (readw(uap->port.membase + UART01x_FR) & UART01x_FR_BUSY) barrier(); spin_lock_irq(&uap->port.lock); uap->dmacr &= ~(UART011_DMAONERR | UART011_RXDMAE | UART011_TXDMAE); - pl011_writew(uap, uap->dmacr, REG_DMACR); + writew(uap->dmacr, uap->port.membase + UART011_DMACR); spin_unlock_irq(&uap->port.lock); if (uap->using_tx_dma) { @@ -1329,7 +1181,7 @@ static void pl011_stop_tx(struct uart_port *port) container_of(port, struct uart_amba_port, port); uap->im &= ~UART011_TXIM; - pl011_writew(uap, uap->im, REG_IMSC); + writew(uap->im, uap->port.membase + UART011_IMSC); pl011_dma_tx_stop(uap); } @@ -1339,7 +1191,7 @@ static void pl011_tx_chars(struct uart_amba_port *uap, bool from_irq); static void pl011_start_tx_pio(struct uart_amba_port *uap) { uap->im |= UART011_TXIM; - pl011_writew(uap, uap->im, REG_IMSC); + writew(uap->im, uap->port.membase + UART011_IMSC); pl011_tx_chars(uap, false); } @@ -1359,7 +1211,7 @@ static void pl011_stop_rx(struct uart_port *port) uap->im &= ~(UART011_RXIM|UART011_RTIM|UART011_FEIM| UART011_PEIM|UART011_BEIM|UART011_OEIM); - pl011_writew(uap, uap->im, REG_IMSC); + writew(uap->im, uap->port.membase + UART011_IMSC); pl011_dma_rx_stop(uap); } @@ -1370,7 +1222,7 @@ static void pl011_enable_ms(struct uart_port *port) container_of(port, struct uart_amba_port, port); uap->im |= UART011_RIMIM|UART011_CTSMIM|UART011_DCDMIM|UART011_DSRMIM; - pl011_writew(uap, uap->im, REG_IMSC); + writew(uap->im, uap->port.membase + UART011_IMSC); } static void pl011_rx_chars(struct uart_amba_port *uap) @@ -1390,7 +1242,7 @@ __acquires(&uap->port.lock) dev_dbg(uap->port.dev, "could not trigger RX DMA job " "fall back to interrupt mode again\n"); uap->im |= UART011_RXIM; - pl011_writew(uap, uap->im, REG_IMSC); + writew(uap->im, uap->port.membase + UART011_IMSC); } else { #ifdef CONFIG_DMA_ENGINE /* Start Rx DMA poll */ @@ -1411,10 +1263,10 @@ static bool pl011_tx_char(struct uart_amba_port *uap, unsigned char c, bool from_irq) { if (unlikely(!from_irq) && - pl011_readw(uap, REG_FR) & UART01x_FR_TXFF) + readw(uap->port.membase + UART01x_FR) & UART01x_FR_TXFF) return false; /* unable to transmit character */ - pl011_writew(uap, c, REG_DR); + writew(c, uap->port.membase + UART01x_DR); uap->port.icount.tx++; return true; @@ -1461,7 +1313,7 @@ static void pl011_modem_status(struct uart_amba_port *uap) { unsigned int status, delta; - status = pl011_readw(uap, REG_FR) & UART01x_FR_MODEM_ANY; + status = readw(uap->port.membase + UART01x_FR) & UART01x_FR_MODEM_ANY; delta = status ^ uap->old_status; uap->old_status = status; @@ -1472,11 +1324,11 @@ static void pl011_modem_status(struct uart_amba_port *uap) if (delta & UART01x_FR_DCD) uart_handle_dcd_change(&uap->port, status & UART01x_FR_DCD); - if (delta & uap->fr_dsr) + if (delta & UART01x_FR_DSR) uap->port.icount.dsr++; - if (delta & uap->fr_cts) - uart_handle_cts_change(&uap->port, status & uap->fr_cts); + if (delta & UART01x_FR_CTS) + uart_handle_cts_change(&uap->port, status & UART01x_FR_CTS); wake_up_interruptible(&uap->port.state->port.delta_msr_wait); } @@ -1489,15 +1341,15 @@ static void check_apply_cts_event_workaround(struct uart_amba_port *uap) return; /* workaround to make sure that all bits are unlocked.. */ - pl011_writew(uap, 0x00, REG_ICR); + writew(0x00, uap->port.membase + UART011_ICR); /* * WA: introduce 26ns(1 uart clk) delay before W1C; * single apb access will incur 2 pclk(133.12Mhz) delay, * so add 2 dummy reads */ - dummy_read = pl011_readw(uap, REG_ICR); - dummy_read = pl011_readw(uap, REG_ICR); + dummy_read = readw(uap->port.membase + UART011_ICR); + dummy_read = readw(uap->port.membase + UART011_ICR); } static irqreturn_t pl011_int(int irq, void *dev_id) @@ -1509,13 +1361,15 @@ static irqreturn_t pl011_int(int irq, void *dev_id) int handled = 0; spin_lock_irqsave(&uap->port.lock, flags); - imsc = pl011_readw(uap, REG_IMSC); - status = pl011_readw(uap, REG_RIS) & imsc; + imsc = readw(uap->port.membase + UART011_IMSC); + status = readw(uap->port.membase + UART011_RIS) & imsc; if (status) { do { check_apply_cts_event_workaround(uap); - pl011_writew(uap, status & ~(UART011_TXIS|UART011_RTIS| - UART011_RXIS), REG_ICR); + + writew(status & ~(UART011_TXIS|UART011_RTIS| + UART011_RXIS), + uap->port.membase + UART011_ICR); if (status & (UART011_RTIS|UART011_RXIS)) { if (pl011_dma_rx_running(uap)) @@ -1532,7 +1386,7 @@ static irqreturn_t pl011_int(int irq, void *dev_id) if (pass_counter-- == 0) break; - status = pl011_readw(uap, REG_RIS) & imsc; + status = readw(uap->port.membase + UART011_RIS) & imsc; } while (status != 0); handled = 1; } @@ -1546,8 +1400,8 @@ static unsigned int pl011_tx_empty(struct uart_port *port) { struct uart_amba_port *uap = container_of(port, struct uart_amba_port, port); - unsigned int status = pl011_readw(uap, REG_FR); - return status & (uap->fr_busy|UART01x_FR_TXFF) ? 0 : TIOCSER_TEMT; + unsigned int status = readw(uap->port.membase + UART01x_FR); + return status & (UART01x_FR_BUSY|UART01x_FR_TXFF) ? 0 : TIOCSER_TEMT; } static unsigned int pl011_get_mctrl(struct uart_port *port) @@ -1555,16 +1409,16 @@ static unsigned int pl011_get_mctrl(struct uart_port *port) struct uart_amba_port *uap = container_of(port, struct uart_amba_port, port); unsigned int result = 0; - unsigned int status = pl011_readw(uap, REG_FR); + unsigned int status = readw(uap->port.membase + UART01x_FR); #define TIOCMBIT(uartbit, tiocmbit) \ if (status & uartbit) \ result |= tiocmbit TIOCMBIT(UART01x_FR_DCD, TIOCM_CAR); - TIOCMBIT(uap->fr_dsr, TIOCM_DSR); - TIOCMBIT(uap->fr_cts, TIOCM_CTS); - TIOCMBIT(uap->fr_ri, TIOCM_RNG); + TIOCMBIT(UART01x_FR_DSR, TIOCM_DSR); + TIOCMBIT(UART01x_FR_CTS, TIOCM_CTS); + TIOCMBIT(UART011_FR_RI, TIOCM_RNG); #undef TIOCMBIT return result; } @@ -1575,7 +1429,7 @@ static void pl011_set_mctrl(struct uart_port *port, unsigned int mctrl) container_of(port, struct uart_amba_port, port); unsigned int cr; - cr = pl011_readw(uap, REG_CR); + cr = readw(uap->port.membase + UART011_CR); #define TIOCMBIT(tiocmbit, uartbit) \ if (mctrl & tiocmbit) \ @@ -1595,7 +1449,7 @@ static void pl011_set_mctrl(struct uart_port *port, unsigned int mctrl) } #undef TIOCMBIT - pl011_writew(uap, cr, REG_CR); + writew(cr, uap->port.membase + UART011_CR); } static void pl011_break_ctl(struct uart_port *port, int break_state) @@ -1606,12 +1460,12 @@ static void pl011_break_ctl(struct uart_port *port, int break_state) unsigned int lcr_h; spin_lock_irqsave(&uap->port.lock, flags); - lcr_h = pl011_readw(uap, uap->lcrh_tx); + lcr_h = readw(uap->port.membase + uap->lcrh_tx); if (break_state == -1) lcr_h |= UART01x_LCRH_BRK; else lcr_h &= ~UART01x_LCRH_BRK; - pl011_writew(uap, lcr_h, uap->lcrh_tx); + writew(lcr_h, uap->port.membase + uap->lcrh_tx); spin_unlock_irqrestore(&uap->port.lock, flags); } @@ -1621,8 +1475,9 @@ static void pl011_quiesce_irqs(struct uart_port *port) { struct uart_amba_port *uap = container_of(port, struct uart_amba_port, port); + unsigned char __iomem *regs = uap->port.membase; - pl011_writew(uap, pl011_readw(uap, REG_MIS), REG_ICR); + writew(readw(regs + UART011_MIS), regs + UART011_ICR); /* * There is no way to clear TXIM as this is "ready to transmit IRQ", so * we simply mask it. start_tx() will unmask it. @@ -1636,7 +1491,7 @@ static void pl011_quiesce_irqs(struct uart_port *port) * (including tx queue), so we're also fine with start_tx()'s caller * side. */ - pl011_writew(uap, pl011_readw(uap, REG_IMSC) & ~UART011_TXIM, REG_IMSC); + writew(readw(regs + UART011_IMSC) & ~UART011_TXIM, regs + UART011_IMSC); } static int pl011_get_poll_char(struct uart_port *port) @@ -1651,11 +1506,11 @@ static int pl011_get_poll_char(struct uart_port *port) */ pl011_quiesce_irqs(port); - status = pl011_readw(uap, REG_FR); + status = readw(uap->port.membase + UART01x_FR); if (status & UART01x_FR_RXFE) return NO_POLL_CHAR; - return pl011_readw(uap, REG_DR); + return readw(uap->port.membase + UART01x_DR); } static void pl011_put_poll_char(struct uart_port *port, @@ -1664,10 +1519,10 @@ static void pl011_put_poll_char(struct uart_port *port, struct uart_amba_port *uap = container_of(port, struct uart_amba_port, port); - while (pl011_readw(uap, REG_FR) & UART01x_FR_TXFF) + while (readw(uap->port.membase + UART01x_FR) & UART01x_FR_TXFF) barrier(); - pl011_writew(uap, ch, REG_DR); + writew(ch, uap->port.membase + UART01x_DR); } #endif /* CONFIG_CONSOLE_POLL */ @@ -1691,15 +1546,15 @@ static int pl011_hwinit(struct uart_port *port) uap->port.uartclk = clk_get_rate(uap->clk); /* Clear pending error and receive interrupts */ - pl011_writew(uap, UART011_OEIS | UART011_BEIS | UART011_PEIS | - UART011_FEIS | UART011_RTIS | UART011_RXIS, REG_ICR); + writew(UART011_OEIS | UART011_BEIS | UART011_PEIS | UART011_FEIS | + UART011_RTIS | UART011_RXIS, uap->port.membase + UART011_ICR); /* * Save interrupts enable mask, and enable RX interrupts in case if * the interrupt is used for NMI entry. */ - uap->im = pl011_readw(uap, REG_IMSC); - pl011_writew(uap, UART011_RTIM | UART011_RXIM, REG_IMSC); + uap->im = readw(uap->port.membase + UART011_IMSC); + writew(UART011_RTIM | UART011_RXIM, uap->port.membase + UART011_IMSC); if (dev_get_platdata(uap->port.dev)) { struct amba_pl011_data *plat; @@ -1713,22 +1568,22 @@ static int pl011_hwinit(struct uart_port *port) static void pl011_write_lcr_h(struct uart_amba_port *uap, unsigned int lcr_h) { - pl011_writew(uap, lcr_h, uap->lcrh_rx); - if (is_implemented(uap, REG_ST_LCRH_RX)) { + writew(lcr_h, uap->port.membase + uap->lcrh_rx); + if (uap->lcrh_rx != uap->lcrh_tx) { int i; /* * Wait 10 PCLKs before writing LCRH_TX register, * to get this delay write read only register 10 times */ for (i = 0; i < 10; ++i) - pl011_writew(uap, 0xff, REG_MIS); - pl011_writew(uap, lcr_h, uap->lcrh_tx); + writew(0xff, uap->port.membase + UART011_MIS); + writew(lcr_h, uap->port.membase + uap->lcrh_tx); } } static int pl011_allocate_irq(struct uart_amba_port *uap) { - pl011_writew(uap, uap->im, REG_IMSC); + writew(uap->im, uap->port.membase + UART011_IMSC); return request_irq(uap->port.irq, pl011_int, 0, "uart-pl011", uap); } @@ -1743,11 +1598,12 @@ static void pl011_enable_interrupts(struct uart_amba_port *uap) spin_lock_irq(&uap->port.lock); /* Clear out any spuriously appearing RX interrupts */ - pl011_writew(uap, UART011_RTIS | UART011_RXIS, REG_ICR); + writew(UART011_RTIS | UART011_RXIS, + uap->port.membase + UART011_ICR); uap->im = UART011_RTIM; if (!pl011_dma_rx_running(uap)) uap->im |= UART011_RXIM; - pl011_writew(uap, uap->im, REG_IMSC); + writew(uap->im, uap->port.membase + UART011_IMSC); spin_unlock_irq(&uap->port.lock); } @@ -1766,21 +1622,21 @@ static int pl011_startup(struct uart_port *port) if (retval) goto clk_dis; - pl011_writew(uap, uap->vendor->ifls, REG_IFLS); + writew(uap->vendor->ifls, uap->port.membase + UART011_IFLS); spin_lock_irq(&uap->port.lock); /* restore RTS and DTR */ cr = uap->old_cr & (UART011_CR_RTS | UART011_CR_DTR); cr |= UART01x_CR_UARTEN | UART011_CR_RXE | UART011_CR_TXE; - pl011_writew(uap, cr, REG_CR); + writew(cr, uap->port.membase + UART011_CR); spin_unlock_irq(&uap->port.lock); /* * initialise the old status of the modem signals */ - uap->old_status = pl011_readw(uap, REG_FR) & UART01x_FR_MODEM_ANY; + uap->old_status = readw(uap->port.membase + UART01x_FR) & UART01x_FR_MODEM_ANY; /* Startup DMA */ pl011_dma_startup(uap); @@ -1819,11 +1675,11 @@ static int sbsa_uart_startup(struct uart_port *port) static void pl011_shutdown_channel(struct uart_amba_port *uap, unsigned int lcrh) { - unsigned long val; + unsigned long val; - val = pl011_readw(uap, lcrh); - val &= ~(UART01x_LCRH_BRK | UART01x_LCRH_FEN); - pl011_writew(uap, val, lcrh); + val = readw(uap->port.membase + lcrh); + val &= ~(UART01x_LCRH_BRK | UART01x_LCRH_FEN); + writew(val, uap->port.membase + lcrh); } /* @@ -1837,18 +1693,18 @@ static void pl011_disable_uart(struct uart_amba_port *uap) uap->autorts = false; spin_lock_irq(&uap->port.lock); - cr = pl011_readw(uap, REG_CR); + cr = readw(uap->port.membase + UART011_CR); uap->old_cr = cr; cr &= UART011_CR_RTS | UART011_CR_DTR; cr |= UART01x_CR_UARTEN | UART011_CR_TXE; - pl011_writew(uap, cr, REG_CR); + writew(cr, uap->port.membase + UART011_CR); spin_unlock_irq(&uap->port.lock); /* * disable break condition and fifos */ pl011_shutdown_channel(uap, uap->lcrh_rx); - if (is_implemented(uap, REG_ST_LCRH_RX)) + if (uap->lcrh_rx != uap->lcrh_tx) pl011_shutdown_channel(uap, uap->lcrh_tx); } @@ -1858,8 +1714,8 @@ static void pl011_disable_interrupts(struct uart_amba_port *uap) /* mask all interrupts and clear all pending ones */ uap->im = 0; - pl011_writew(uap, uap->im, REG_IMSC); - pl011_writew(uap, 0xffff, REG_ICR); + writew(uap->im, uap->port.membase + UART011_IMSC); + writew(0xffff, uap->port.membase + UART011_ICR); spin_unlock_irq(&uap->port.lock); } @@ -2011,8 +1867,8 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios, pl011_enable_ms(port); /* first, disable everything */ - old_cr = pl011_readw(uap, REG_CR); - pl011_writew(uap, 0, REG_CR); + old_cr = readw(port->membase + UART011_CR); + writew(0, port->membase + UART011_CR); if (termios->c_cflag & CRTSCTS) { if (old_cr & UART011_CR_RTS) @@ -2045,17 +1901,17 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios, quot -= 2; } /* Set baud rate */ - pl011_writew(uap, quot & 0x3f, REG_FBRD); - pl011_writew(uap, quot >> 6, REG_IBRD); + writew(quot & 0x3f, port->membase + UART011_FBRD); + writew(quot >> 6, port->membase + UART011_IBRD); /* * ----------v----------v----------v----------v----- * NOTE: lcrh_tx and lcrh_rx MUST BE WRITTEN AFTER - * REG_FBRD & REG_IBRD. + * UART011_FBRD & UART011_IBRD. * ----------^----------^----------^----------^----- */ pl011_write_lcr_h(uap, lcr_h); - pl011_writew(uap, old_cr, REG_CR); + writew(old_cr, port->membase + UART011_CR); spin_unlock_irqrestore(&port->lock, flags); } @@ -2196,9 +2052,9 @@ static void pl011_console_putchar(struct uart_port *port, int ch) struct uart_amba_port *uap = container_of(port, struct uart_amba_port, port); - while (pl011_readw(uap, REG_FR) & UART01x_FR_TXFF) + while (readw(uap->port.membase + UART01x_FR) & UART01x_FR_TXFF) barrier(); - pl011_writew(uap, ch, REG_DR); + writew(ch, uap->port.membase + UART01x_DR); } static void @@ -2223,10 +2079,10 @@ pl011_console_write(struct console *co, const char *s, unsigned int count) * First save the CR then disable the interrupts */ if (!uap->vendor->always_enabled) { - old_cr = pl011_readw(uap, REG_CR); + old_cr = readw(uap->port.membase + UART011_CR); new_cr = old_cr & ~UART011_CR_CTSEN; new_cr |= UART01x_CR_UARTEN | UART011_CR_TXE; - pl011_writew(uap, new_cr, REG_CR); + writew(new_cr, uap->port.membase + UART011_CR); } uart_console_write(&uap->port, s, count, pl011_console_putchar); @@ -2236,10 +2092,10 @@ pl011_console_write(struct console *co, const char *s, unsigned int count) * and restore the TCR */ do { - status = pl011_readw(uap, REG_FR); - } while (status & uap->fr_busy); + status = readw(uap->port.membase + UART01x_FR); + } while (status & UART01x_FR_BUSY); if (!uap->vendor->always_enabled) - pl011_writew(uap, old_cr, REG_CR); + writew(old_cr, uap->port.membase + UART011_CR); if (locked) spin_unlock(&uap->port.lock); @@ -2252,10 +2108,10 @@ static void __init pl011_console_get_options(struct uart_amba_port *uap, int *baud, int *parity, int *bits) { - if (pl011_readw(uap, REG_CR) & UART01x_CR_UARTEN) { + if (readw(uap->port.membase + UART011_CR) & UART01x_CR_UARTEN) { unsigned int lcr_h, ibrd, fbrd; - lcr_h = pl011_readw(uap, uap->lcrh_tx); + lcr_h = readw(uap->port.membase + uap->lcrh_tx); *parity = 'n'; if (lcr_h & UART01x_LCRH_PEN) { @@ -2270,13 +2126,13 @@ pl011_console_get_options(struct uart_amba_port *uap, int *baud, else *bits = 8; - ibrd = pl011_readw(uap, REG_IBRD); - fbrd = pl011_readw(uap, REG_FBRD); + ibrd = readw(uap->port.membase + UART011_IBRD); + fbrd = readw(uap->port.membase + UART011_FBRD); *baud = uap->port.uartclk * 4 / (64 * ibrd + fbrd); if (uap->vendor->oversampling) { - if (pl011_readw(uap, REG_CR) + if (readw(uap->port.membase + UART011_CR) & ST_UART011_CR_OVSFACT) *baud *= 2; } @@ -2348,13 +2204,10 @@ static struct console amba_console = { static void pl011_putc(struct uart_port *port, int c) { - struct uart_amba_port *uap = - container_of(port, struct uart_amba_port, port); - - while (pl011_readw(uap, REG_FR) & UART01x_FR_TXFF) + while (readl(port->membase + UART01x_FR) & UART01x_FR_TXFF) ; - pl011_writeb(uap, c, REG_DR); - while (pl011_readw(uap, REG_FR) & uap->fr_busy) + writeb(c, port->membase + UART01x_DR); + while (readl(port->membase + UART01x_FR) & UART01x_FR_BUSY) ; } @@ -2481,8 +2334,8 @@ static int pl011_register_port(struct uart_amba_port *uap) int ret; /* Ensure interrupts from this UART are masked and cleared */ - pl011_writew(uap, 0, REG_IMSC); - pl011_writew(uap, 0xffff, REG_ICR); + writew(0, uap->port.membase + UART011_IMSC); + writew(0xffff, uap->port.membase + UART011_ICR); if (!amba_reg.state) { ret = uart_register_driver(&amba_reg); @@ -2500,7 +2353,6 @@ static int pl011_register_port(struct uart_amba_port *uap) return ret; } -#ifdef CONFIG_ARM_AMBA static int pl011_probe(struct amba_device *dev, const struct amba_id *id) { struct uart_amba_port *uap; @@ -2521,13 +2373,8 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id) return PTR_ERR(uap->clk); uap->vendor = vendor; - uap->reg_lut = vendor->reg_lut; uap->lcrh_rx = vendor->lcrh_rx; uap->lcrh_tx = vendor->lcrh_tx; - uap->fr_busy = vendor->fr_busy; - uap->fr_dsr = vendor->fr_dsr; - uap->fr_cts = vendor->fr_cts; - uap->fr_ri = vendor->fr_ri; uap->fifosize = vendor->get_fifosize(dev); uap->port.irq = dev->irq[0]; uap->port.ops = &amba_pl011_pops; @@ -2551,67 +2398,6 @@ static int pl011_remove(struct amba_device *dev) pl011_unregister_port(uap); return 0; } -#endif - -#ifdef CONFIG_SOC_ZX296702 -static int zx_uart_probe(struct platform_device *pdev) -{ - struct uart_amba_port *uap; - struct vendor_data *vendor = &vendor_zte; - struct resource *res; - int portnr, ret; - - portnr = pl011_find_free_port(); - if (portnr < 0) - return portnr; - - uap = devm_kzalloc(&pdev->dev, sizeof(struct uart_amba_port), - GFP_KERNEL); - if (!uap) { - ret = -ENOMEM; - goto out; - } - - uap->clk = devm_clk_get(&pdev->dev, NULL); - if (IS_ERR(uap->clk)) { - ret = PTR_ERR(uap->clk); - goto out; - } - - uap->vendor = vendor; - uap->reg_lut = vendor->reg_lut; - uap->lcrh_rx = vendor->lcrh_rx; - uap->lcrh_tx = vendor->lcrh_tx; - uap->fr_busy = vendor->fr_busy; - uap->fr_dsr = vendor->fr_dsr; - uap->fr_cts = vendor->fr_cts; - uap->fr_ri = vendor->fr_ri; - uap->fifosize = 16; - uap->port.irq = platform_get_irq(pdev, 0); - uap->port.ops = &amba_pl011_pops; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - - ret = pl011_setup_port(&pdev->dev, uap, res, portnr); - if (ret) - return ret; - - platform_set_drvdata(pdev, uap); - - return pl011_register_port(uap); -out: - return ret; -} - -static int zx_uart_remove(struct platform_device *pdev) -{ - struct uart_amba_port *uap = platform_get_drvdata(pdev); - - uart_remove_one_port(&amba_reg, &uap->port); - pl011_unregister_port(uap); - return 0; -} -#endif #ifdef CONFIG_PM_SLEEP static int pl011_suspend(struct device *dev) @@ -2668,11 +2454,6 @@ static int sbsa_uart_probe(struct platform_device *pdev) return -ENOMEM; uap->vendor = &vendor_sbsa; - uap->reg_lut = vendor_sbsa.reg_lut; - uap->fr_busy = vendor_sbsa.fr_busy; - uap->fr_dsr = vendor_sbsa.fr_dsr; - uap->fr_cts = vendor_sbsa.fr_cts; - uap->fr_ri = vendor_sbsa.fr_ri; uap->fifosize = 32; uap->port.irq = platform_get_irq(pdev, 0); uap->port.ops = &sbsa_uart_pops; @@ -2722,7 +2503,6 @@ static struct platform_driver arm_sbsa_uart_platform_driver = { }, }; -#ifdef CONFIG_ARM_AMBA static struct amba_id pl011_ids[] = { { .id = 0x00041011, @@ -2748,57 +2528,20 @@ static struct amba_driver pl011_driver = { .probe = pl011_probe, .remove = pl011_remove, }; -#endif - -#ifdef CONFIG_SOC_ZX296702 -static const struct of_device_id zx_uart_dt_ids[] = { - { .compatible = "zte,zx296702-uart", }, - { /* sentinel */ } -}; -MODULE_DEVICE_TABLE(of, zx_uart_dt_ids); - -static struct platform_driver zx_uart_driver = { - .driver = { - .name = "zx-uart", - .owner = THIS_MODULE, - .pm = &pl011_dev_pm_ops, - .of_match_table = zx_uart_dt_ids, - }, - .probe = zx_uart_probe, - .remove = zx_uart_remove, -}; -#endif - static int __init pl011_init(void) { - int ret; printk(KERN_INFO "Serial: AMBA PL011 UART driver\n"); if (platform_driver_register(&arm_sbsa_uart_platform_driver)) pr_warn("could not register SBSA UART platform driver\n"); - -#ifdef CONFIG_SOC_ZX296702 - ret = platform_driver_register(&zx_uart_driver); - if (ret) - pr_warn("could not register ZX UART platform driver\n"); -#endif - -#ifdef CONFIG_ARM_AMBA - ret = amba_driver_register(&pl011_driver); -#endif - return ret; + return amba_driver_register(&pl011_driver); } static void __exit pl011_exit(void) { platform_driver_unregister(&arm_sbsa_uart_platform_driver); -#ifdef CONFIG_SOC_ZX296702 - platform_driver_unregister(&zx_uart_driver); -#endif -#ifdef CONFIG_ARM_AMBA amba_driver_unregister(&pl011_driver); -#endif } /* diff --git a/drivers/video/fbdev/xen-fbfront.c b/drivers/video/fbdev/xen-fbfront.c index 09dc44736c1a..0567d517eed3 100644 --- a/drivers/video/fbdev/xen-fbfront.c +++ b/drivers/video/fbdev/xen-fbfront.c @@ -46,7 +46,7 @@ struct xenfb_info { int nr_pages; int irq; struct xenfb_page *page; - unsigned long *mfns; + unsigned long *gfns; int update_wanted; /* XENFB_TYPE_UPDATE wanted */ int feature_resize; /* XENFB_TYPE_RESIZE ok */ struct xenfb_resize resize; /* protected by resize_lock */ @@ -402,8 +402,8 @@ static int xenfb_probe(struct xenbus_device *dev, info->nr_pages = (fb_size + PAGE_SIZE - 1) >> PAGE_SHIFT; - info->mfns = vmalloc(sizeof(unsigned long) * info->nr_pages); - if (!info->mfns) + info->gfns = vmalloc(sizeof(unsigned long) * info->nr_pages); + if (!info->gfns) goto error_nomem; /* set up shared page */ @@ -530,29 +530,29 @@ static int xenfb_remove(struct xenbus_device *dev) framebuffer_release(info->fb_info); } free_page((unsigned long)info->page); - vfree(info->mfns); + vfree(info->gfns); vfree(info->fb); kfree(info); return 0; } -static unsigned long vmalloc_to_mfn(void *address) +static unsigned long vmalloc_to_gfn(void *address) { - return pfn_to_mfn(vmalloc_to_pfn(address)); + return xen_page_to_gfn(vmalloc_to_page(address)); } static void xenfb_init_shared_page(struct xenfb_info *info, struct fb_info *fb_info) { int i; - int epd = PAGE_SIZE / sizeof(info->mfns[0]); + int epd = PAGE_SIZE / sizeof(info->gfns[0]); for (i = 0; i < info->nr_pages; i++) - info->mfns[i] = vmalloc_to_mfn(info->fb + i * PAGE_SIZE); + info->gfns[i] = vmalloc_to_gfn(info->fb + i * PAGE_SIZE); for (i = 0; i * epd < info->nr_pages; i++) - info->page->pd[i] = vmalloc_to_mfn(&info->mfns[i * epd]); + info->page->pd[i] = vmalloc_to_gfn(&info->gfns[i * epd]); info->page->width = fb_info->var.xres; info->page->height = fb_info->var.yres; @@ -586,7 +586,7 @@ static int xenfb_connect_backend(struct xenbus_device *dev, goto unbind_irq; } ret = xenbus_printf(xbt, dev->nodename, "page-ref", "%lu", - virt_to_mfn(info->page)); + virt_to_gfn(info->page)); if (ret) goto error_xenbus; ret = xenbus_printf(xbt, dev->nodename, "event-channel", "%u", diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c index 82e80e034f25..7efc32945810 100644 --- a/drivers/virtio/virtio_balloon.c +++ b/drivers/virtio/virtio_balloon.c @@ -157,7 +157,9 @@ static void fill_balloon(struct virtio_balloon *vb, size_t num) } set_page_pfns(vb->pfns + vb->num_pfns, page); vb->num_pages += VIRTIO_BALLOON_PAGES_PER_PAGE; - adjust_managed_page_count(page, -1); + if (!virtio_has_feature(vb->vdev, + VIRTIO_BALLOON_F_DEFLATE_ON_OOM)) + adjust_managed_page_count(page, -1); } /* Did we get any? */ @@ -166,14 +168,16 @@ static void fill_balloon(struct virtio_balloon *vb, size_t num) mutex_unlock(&vb->balloon_lock); } -static void release_pages_by_pfn(const u32 pfns[], unsigned int num) +static void release_pages_balloon(struct virtio_balloon *vb) { unsigned int i; /* Find pfns pointing at start of each page, get pages and free them. */ - for (i = 0; i < num; i += VIRTIO_BALLOON_PAGES_PER_PAGE) { - struct page *page = balloon_pfn_to_page(pfns[i]); - adjust_managed_page_count(page, 1); + for (i = 0; i < vb->num_pfns; i += VIRTIO_BALLOON_PAGES_PER_PAGE) { + struct page *page = balloon_pfn_to_page(vb->pfns[i]); + if (!virtio_has_feature(vb->vdev, + VIRTIO_BALLOON_F_DEFLATE_ON_OOM)) + adjust_managed_page_count(page, 1); put_page(page); /* balloon reference */ } } @@ -206,7 +210,7 @@ static unsigned leak_balloon(struct virtio_balloon *vb, size_t num) if (vb->num_pfns != 0) tell_host(vb, vb->deflate_vq); mutex_unlock(&vb->balloon_lock); - release_pages_by_pfn(vb->pfns, vb->num_pfns); + release_pages_balloon(vb); return num_freed_pages; } diff --git a/drivers/virtio/virtio_mmio.c b/drivers/virtio/virtio_mmio.c index 10189b5b627f..f499d9da7237 100644 --- a/drivers/virtio/virtio_mmio.c +++ b/drivers/virtio/virtio_mmio.c @@ -58,6 +58,7 @@ #define pr_fmt(fmt) "virtio-mmio: " fmt +#include <linux/acpi.h> #include <linux/highmem.h> #include <linux/interrupt.h> #include <linux/io.h> @@ -732,12 +733,21 @@ static struct of_device_id virtio_mmio_match[] = { }; MODULE_DEVICE_TABLE(of, virtio_mmio_match); +#ifdef CONFIG_ACPI +static const struct acpi_device_id virtio_mmio_acpi_match[] = { + { "LNRO0005", }, + { } +}; +MODULE_DEVICE_TABLE(acpi, virtio_mmio_acpi_match); +#endif + static struct platform_driver virtio_mmio_driver = { .probe = virtio_mmio_probe, .remove = virtio_mmio_remove, .driver = { .name = "virtio-mmio", .of_match_table = virtio_mmio_match, + .acpi_match_table = ACPI_PTR(virtio_mmio_acpi_match), }, }; diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c index 1fa633b2d556..c79329fcfa78 100644 --- a/drivers/xen/balloon.c +++ b/drivers/xen/balloon.c @@ -441,7 +441,7 @@ static enum bp_state decrease_reservation(unsigned long nr_pages, gfp_t gfp) /* Update direct mapping, invalidate P2M, and add to balloon. */ for (i = 0; i < nr_pages; i++) { pfn = frame_list[i]; - frame_list[i] = pfn_to_mfn(pfn); + frame_list[i] = pfn_to_gfn(pfn); page = pfn_to_page(pfn); #ifdef CONFIG_XEN_HAVE_PVMMU diff --git a/drivers/xen/biomerge.c b/drivers/xen/biomerge.c index 0edb91c0de6b..8ae2fc90e1ea 100644 --- a/drivers/xen/biomerge.c +++ b/drivers/xen/biomerge.c @@ -6,10 +6,10 @@ bool xen_biovec_phys_mergeable(const struct bio_vec *vec1, const struct bio_vec *vec2) { - unsigned long mfn1 = pfn_to_mfn(page_to_pfn(vec1->bv_page)); - unsigned long mfn2 = pfn_to_mfn(page_to_pfn(vec2->bv_page)); + unsigned long bfn1 = pfn_to_bfn(page_to_pfn(vec1->bv_page)); + unsigned long bfn2 = pfn_to_bfn(page_to_pfn(vec2->bv_page)); return __BIOVEC_PHYS_MERGEABLE(vec1, vec2) && - ((mfn1 == mfn2) || ((mfn1+1) == mfn2)); + ((bfn1 == bfn2) || ((bfn1+1) == bfn2)); } EXPORT_SYMBOL(xen_biovec_phys_mergeable); diff --git a/drivers/xen/events/events_base.c b/drivers/xen/events/events_base.c index 68d129019e8f..6cd5e65c4aff 100644 --- a/drivers/xen/events/events_base.c +++ b/drivers/xen/events/events_base.c @@ -1688,7 +1688,7 @@ void __init xen_init_IRQ(void) struct physdev_pirq_eoi_gmfn eoi_gmfn; pirq_eoi_map = (void *)__get_free_page(GFP_KERNEL|__GFP_ZERO); - eoi_gmfn.gmfn = virt_to_mfn(pirq_eoi_map); + eoi_gmfn.gmfn = virt_to_gfn(pirq_eoi_map); rc = HYPERVISOR_physdev_op(PHYSDEVOP_pirq_eoi_gmfn_v2, &eoi_gmfn); /* TODO: No PVH support for PIRQ EOI */ if (rc != 0) { diff --git a/drivers/xen/events/events_fifo.c b/drivers/xen/events/events_fifo.c index ed673e1acd61..1d4baf56c36b 100644 --- a/drivers/xen/events/events_fifo.c +++ b/drivers/xen/events/events_fifo.c @@ -111,7 +111,7 @@ static int init_control_block(int cpu, for (i = 0; i < EVTCHN_FIFO_MAX_QUEUES; i++) q->head[i] = 0; - init_control.control_gfn = virt_to_mfn(control_block); + init_control.control_gfn = virt_to_gfn(control_block); init_control.offset = 0; init_control.vcpu = cpu; @@ -167,7 +167,7 @@ static int evtchn_fifo_setup(struct irq_info *info) /* Mask all events in this page before adding it. */ init_array_page(array_page); - expand_array.array_gfn = virt_to_mfn(array_page); + expand_array.array_gfn = virt_to_gfn(array_page); ret = HYPERVISOR_event_channel_op(EVTCHNOP_expand_array, &expand_array); if (ret < 0) diff --git a/drivers/xen/gntalloc.c b/drivers/xen/gntalloc.c index 696301d9dc91..4547a91bca67 100644 --- a/drivers/xen/gntalloc.c +++ b/drivers/xen/gntalloc.c @@ -142,7 +142,8 @@ static int add_grefs(struct ioctl_gntalloc_alloc_gref *op, /* Grant foreign access to the page. */ rc = gnttab_grant_foreign_access(op->domid, - pfn_to_mfn(page_to_pfn(gref->page)), readonly); + xen_page_to_gfn(gref->page), + readonly); if (rc < 0) goto undo; gref_ids[i] = gref->gref_id = rc; diff --git a/drivers/xen/manage.c b/drivers/xen/manage.c index d10effee9b9e..e12bd3635f83 100644 --- a/drivers/xen/manage.c +++ b/drivers/xen/manage.c @@ -80,7 +80,7 @@ static int xen_suspend(void *data) * is resuming in a new domain. */ si->cancelled = HYPERVISOR_suspend(xen_pv_domain() - ? virt_to_mfn(xen_start_info) + ? virt_to_gfn(xen_start_info) : 0); xen_arch_post_suspend(si->cancelled); diff --git a/drivers/xen/privcmd.c b/drivers/xen/privcmd.c index 56cb13fcbd0e..5e9adac928e6 100644 --- a/drivers/xen/privcmd.c +++ b/drivers/xen/privcmd.c @@ -193,16 +193,16 @@ static int traverse_pages_block(unsigned nelem, size_t size, return ret; } -struct mmap_mfn_state { +struct mmap_gfn_state { unsigned long va; struct vm_area_struct *vma; domid_t domain; }; -static int mmap_mfn_range(void *data, void *state) +static int mmap_gfn_range(void *data, void *state) { struct privcmd_mmap_entry *msg = data; - struct mmap_mfn_state *st = state; + struct mmap_gfn_state *st = state; struct vm_area_struct *vma = st->vma; int rc; @@ -216,7 +216,7 @@ static int mmap_mfn_range(void *data, void *state) ((msg->va+(msg->npages<<PAGE_SHIFT)) > vma->vm_end)) return -EINVAL; - rc = xen_remap_domain_mfn_range(vma, + rc = xen_remap_domain_gfn_range(vma, msg->va & PAGE_MASK, msg->mfn, msg->npages, vma->vm_page_prot, @@ -236,7 +236,7 @@ static long privcmd_ioctl_mmap(void __user *udata) struct vm_area_struct *vma; int rc; LIST_HEAD(pagelist); - struct mmap_mfn_state state; + struct mmap_gfn_state state; /* We only support privcmd_ioctl_mmap_batch for auto translated. */ if (xen_feature(XENFEAT_auto_translated_physmap)) @@ -273,7 +273,7 @@ static long privcmd_ioctl_mmap(void __user *udata) rc = traverse_pages(mmapcmd.num, sizeof(struct privcmd_mmap_entry), &pagelist, - mmap_mfn_range, &state); + mmap_gfn_range, &state); out_up: @@ -299,18 +299,18 @@ struct mmap_batch_state { int global_error; int version; - /* User-space mfn array to store errors in the second pass for V1. */ - xen_pfn_t __user *user_mfn; + /* User-space gfn array to store errors in the second pass for V1. */ + xen_pfn_t __user *user_gfn; /* User-space int array to store errors in the second pass for V2. */ int __user *user_err; }; -/* auto translated dom0 note: if domU being created is PV, then mfn is - * mfn(addr on bus). If it's auto xlated, then mfn is pfn (input to HAP). +/* auto translated dom0 note: if domU being created is PV, then gfn is + * mfn(addr on bus). If it's auto xlated, then gfn is pfn (input to HAP). */ static int mmap_batch_fn(void *data, int nr, void *state) { - xen_pfn_t *mfnp = data; + xen_pfn_t *gfnp = data; struct mmap_batch_state *st = state; struct vm_area_struct *vma = st->vma; struct page **pages = vma->vm_private_data; @@ -321,8 +321,8 @@ static int mmap_batch_fn(void *data, int nr, void *state) cur_pages = &pages[st->index]; BUG_ON(nr < 0); - ret = xen_remap_domain_mfn_array(st->vma, st->va & PAGE_MASK, mfnp, nr, - (int *)mfnp, st->vma->vm_page_prot, + ret = xen_remap_domain_gfn_array(st->vma, st->va & PAGE_MASK, gfnp, nr, + (int *)gfnp, st->vma->vm_page_prot, st->domain, cur_pages); /* Adjust the global_error? */ @@ -347,22 +347,22 @@ static int mmap_return_error(int err, struct mmap_batch_state *st) if (st->version == 1) { if (err) { - xen_pfn_t mfn; + xen_pfn_t gfn; - ret = get_user(mfn, st->user_mfn); + ret = get_user(gfn, st->user_gfn); if (ret < 0) return ret; /* * V1 encodes the error codes in the 32bit top - * nibble of the mfn (with its known + * nibble of the gfn (with its known * limitations vis-a-vis 64 bit callers). */ - mfn |= (err == -ENOENT) ? + gfn |= (err == -ENOENT) ? PRIVCMD_MMAPBATCH_PAGED_ERROR : PRIVCMD_MMAPBATCH_MFN_ERROR; - return __put_user(mfn, st->user_mfn++); + return __put_user(gfn, st->user_gfn++); } else - st->user_mfn++; + st->user_gfn++; } else { /* st->version == 2 */ if (err) return __put_user(err, st->user_err++); @@ -388,7 +388,7 @@ static int mmap_return_errors(void *data, int nr, void *state) return 0; } -/* Allocate pfns that are then mapped with gmfns from foreign domid. Update +/* Allocate pfns that are then mapped with gfns from foreign domid. Update * the vma with the page info to use later. * Returns: 0 if success, otherwise -errno */ @@ -526,7 +526,7 @@ static long privcmd_ioctl_mmap_batch(void __user *udata, int version) if (state.global_error) { /* Write back errors in second pass. */ - state.user_mfn = (xen_pfn_t *)m.arr; + state.user_gfn = (xen_pfn_t *)m.arr; state.user_err = m.err; ret = traverse_pages_block(m.num, sizeof(xen_pfn_t), &pagelist, mmap_return_errors, &state); @@ -587,7 +587,7 @@ static void privcmd_close(struct vm_area_struct *vma) if (!xen_feature(XENFEAT_auto_translated_physmap) || !numpgs || !pages) return; - rc = xen_unmap_domain_mfn_range(vma, numpgs, pages); + rc = xen_unmap_domain_gfn_range(vma, numpgs, pages); if (rc == 0) free_xenballooned_pages(numpgs, pages); else diff --git a/drivers/xen/swiotlb-xen.c b/drivers/xen/swiotlb-xen.c index da1029ef8159..79bc4933b13e 100644 --- a/drivers/xen/swiotlb-xen.c +++ b/drivers/xen/swiotlb-xen.c @@ -82,8 +82,8 @@ static u64 start_dma_addr; */ static inline dma_addr_t xen_phys_to_bus(phys_addr_t paddr) { - unsigned long mfn = pfn_to_mfn(PFN_DOWN(paddr)); - dma_addr_t dma = (dma_addr_t)mfn << PAGE_SHIFT; + unsigned long bfn = pfn_to_bfn(PFN_DOWN(paddr)); + dma_addr_t dma = (dma_addr_t)bfn << PAGE_SHIFT; dma |= paddr & ~PAGE_MASK; @@ -92,7 +92,7 @@ static inline dma_addr_t xen_phys_to_bus(phys_addr_t paddr) static inline phys_addr_t xen_bus_to_phys(dma_addr_t baddr) { - unsigned long pfn = mfn_to_pfn(PFN_DOWN(baddr)); + unsigned long pfn = bfn_to_pfn(PFN_DOWN(baddr)); dma_addr_t dma = (dma_addr_t)pfn << PAGE_SHIFT; phys_addr_t paddr = dma; @@ -110,15 +110,15 @@ static int check_pages_physically_contiguous(unsigned long pfn, unsigned int offset, size_t length) { - unsigned long next_mfn; + unsigned long next_bfn; int i; int nr_pages; - next_mfn = pfn_to_mfn(pfn); + next_bfn = pfn_to_bfn(pfn); nr_pages = (offset + length + PAGE_SIZE-1) >> PAGE_SHIFT; for (i = 1; i < nr_pages; i++) { - if (pfn_to_mfn(++pfn) != ++next_mfn) + if (pfn_to_bfn(++pfn) != ++next_bfn) return 0; } return 1; @@ -138,8 +138,8 @@ static inline int range_straddles_page_boundary(phys_addr_t p, size_t size) static int is_xen_swiotlb_buffer(dma_addr_t dma_addr) { - unsigned long mfn = PFN_DOWN(dma_addr); - unsigned long pfn = mfn_to_local_pfn(mfn); + unsigned long bfn = PFN_DOWN(dma_addr); + unsigned long pfn = bfn_to_local_pfn(bfn); phys_addr_t paddr; /* If the address is outside our domain, it CAN diff --git a/drivers/xen/tmem.c b/drivers/xen/tmem.c index 239738f944ba..945fc4327201 100644 --- a/drivers/xen/tmem.c +++ b/drivers/xen/tmem.c @@ -129,21 +129,17 @@ static int xen_tmem_new_pool(struct tmem_pool_uuid uuid, /* xen generic tmem ops */ static int xen_tmem_put_page(u32 pool_id, struct tmem_oid oid, - u32 index, unsigned long pfn) + u32 index, struct page *page) { - unsigned long gmfn = xen_pv_domain() ? pfn_to_mfn(pfn) : pfn; - return xen_tmem_op(TMEM_PUT_PAGE, pool_id, oid, index, - gmfn, 0, 0, 0); + xen_page_to_gfn(page), 0, 0, 0); } static int xen_tmem_get_page(u32 pool_id, struct tmem_oid oid, - u32 index, unsigned long pfn) + u32 index, struct page *page) { - unsigned long gmfn = xen_pv_domain() ? pfn_to_mfn(pfn) : pfn; - return xen_tmem_op(TMEM_GET_PAGE, pool_id, oid, index, - gmfn, 0, 0, 0); + xen_page_to_gfn(page), 0, 0, 0); } static int xen_tmem_flush_page(u32 pool_id, struct tmem_oid oid, u32 index) @@ -173,14 +169,13 @@ static void tmem_cleancache_put_page(int pool, struct cleancache_filekey key, { u32 ind = (u32) index; struct tmem_oid oid = *(struct tmem_oid *)&key; - unsigned long pfn = page_to_pfn(page); if (pool < 0) return; if (ind != index) return; mb(); /* ensure page is quiescent; tmem may address it with an alias */ - (void)xen_tmem_put_page((u32)pool, oid, ind, pfn); + (void)xen_tmem_put_page((u32)pool, oid, ind, page); } static int tmem_cleancache_get_page(int pool, struct cleancache_filekey key, @@ -188,7 +183,6 @@ static int tmem_cleancache_get_page(int pool, struct cleancache_filekey key, { u32 ind = (u32) index; struct tmem_oid oid = *(struct tmem_oid *)&key; - unsigned long pfn = page_to_pfn(page); int ret; /* translate return values to linux semantics */ @@ -196,7 +190,7 @@ static int tmem_cleancache_get_page(int pool, struct cleancache_filekey key, return -1; if (ind != index) return -1; - ret = xen_tmem_get_page((u32)pool, oid, ind, pfn); + ret = xen_tmem_get_page((u32)pool, oid, ind, page); if (ret == 1) return 0; else @@ -287,7 +281,6 @@ static int tmem_frontswap_store(unsigned type, pgoff_t offset, { u64 ind64 = (u64)offset; u32 ind = (u32)offset; - unsigned long pfn = page_to_pfn(page); int pool = tmem_frontswap_poolid; int ret; @@ -296,7 +289,7 @@ static int tmem_frontswap_store(unsigned type, pgoff_t offset, if (ind64 != ind) return -1; mb(); /* ensure page is quiescent; tmem may address it with an alias */ - ret = xen_tmem_put_page(pool, oswiz(type, ind), iswiz(ind), pfn); + ret = xen_tmem_put_page(pool, oswiz(type, ind), iswiz(ind), page); /* translate Xen tmem return values to linux semantics */ if (ret == 1) return 0; @@ -313,7 +306,6 @@ static int tmem_frontswap_load(unsigned type, pgoff_t offset, { u64 ind64 = (u64)offset; u32 ind = (u32)offset; - unsigned long pfn = page_to_pfn(page); int pool = tmem_frontswap_poolid; int ret; @@ -321,7 +313,7 @@ static int tmem_frontswap_load(unsigned type, pgoff_t offset, return -1; if (ind64 != ind) return -1; - ret = xen_tmem_get_page(pool, oswiz(type, ind), iswiz(ind), pfn); + ret = xen_tmem_get_page(pool, oswiz(type, ind), iswiz(ind), page); /* translate Xen tmem return values to linux semantics */ if (ret == 1) return 0; diff --git a/drivers/xen/xenbus/xenbus_client.c b/drivers/xen/xenbus/xenbus_client.c index e30353575d5d..2ba09c1195c8 100644 --- a/drivers/xen/xenbus/xenbus_client.c +++ b/drivers/xen/xenbus/xenbus_client.c @@ -380,7 +380,7 @@ int xenbus_grant_ring(struct xenbus_device *dev, void *vaddr, for (i = 0; i < nr_pages; i++) { err = gnttab_grant_foreign_access(dev->otherend_id, - virt_to_mfn(vaddr), 0); + virt_to_gfn(vaddr), 0); if (err < 0) { xenbus_dev_fatal(dev, err, "granting access to ring page"); diff --git a/drivers/xen/xenbus/xenbus_dev_backend.c b/drivers/xen/xenbus/xenbus_dev_backend.c index b17707ee07d4..ee6d9efd7b76 100644 --- a/drivers/xen/xenbus/xenbus_dev_backend.c +++ b/drivers/xen/xenbus/xenbus_dev_backend.c @@ -49,7 +49,7 @@ static long xenbus_alloc(domid_t domid) goto out_err; gnttab_grant_foreign_access_ref(GNTTAB_RESERVED_XENSTORE, domid, - virt_to_mfn(xen_store_interface), 0 /* writable */); + virt_to_gfn(xen_store_interface), 0 /* writable */); arg.dom = DOMID_SELF; arg.remote_dom = domid; diff --git a/drivers/xen/xenbus/xenbus_probe.c b/drivers/xen/xenbus/xenbus_probe.c index 4308fb3cf7c2..3cbe0556de26 100644 --- a/drivers/xen/xenbus/xenbus_probe.c +++ b/drivers/xen/xenbus/xenbus_probe.c @@ -75,7 +75,7 @@ EXPORT_SYMBOL_GPL(xen_store_interface); enum xenstore_init xen_store_domain_type; EXPORT_SYMBOL_GPL(xen_store_domain_type); -static unsigned long xen_store_mfn; +static unsigned long xen_store_gfn; static BLOCKING_NOTIFIER_HEAD(xenstore_chain); @@ -711,9 +711,7 @@ static int __init xenstored_local_init(void) if (!page) goto out_err; - xen_store_mfn = xen_start_info->store_mfn = - pfn_to_mfn(virt_to_phys((void *)page) >> - PAGE_SHIFT); + xen_store_gfn = xen_start_info->store_mfn = virt_to_gfn((void *)page); /* Next allocate a local port which xenstored can bind to */ alloc_unbound.dom = DOMID_SELF; @@ -787,12 +785,12 @@ static int __init xenbus_init(void) err = xenstored_local_init(); if (err) goto out_error; - xen_store_interface = mfn_to_virt(xen_store_mfn); + xen_store_interface = gfn_to_virt(xen_store_gfn); break; case XS_PV: xen_store_evtchn = xen_start_info->store_evtchn; - xen_store_mfn = xen_start_info->store_mfn; - xen_store_interface = mfn_to_virt(xen_store_mfn); + xen_store_gfn = xen_start_info->store_mfn; + xen_store_interface = gfn_to_virt(xen_store_gfn); break; case XS_HVM: err = hvm_get_parameter(HVM_PARAM_STORE_EVTCHN, &v); @@ -802,9 +800,9 @@ static int __init xenbus_init(void) err = hvm_get_parameter(HVM_PARAM_STORE_PFN, &v); if (err) goto out_error; - xen_store_mfn = (unsigned long)v; + xen_store_gfn = (unsigned long)v; xen_store_interface = - xen_remap(xen_store_mfn << PAGE_SHIFT, PAGE_SIZE); + xen_remap(xen_store_gfn << PAGE_SHIFT, PAGE_SIZE); break; default: pr_warn("Xenstore state unknown\n"); diff --git a/drivers/xen/xlate_mmu.c b/drivers/xen/xlate_mmu.c index 58a5389aec89..cff23872c5a9 100644 --- a/drivers/xen/xlate_mmu.c +++ b/drivers/xen/xlate_mmu.c @@ -38,8 +38,8 @@ #include <xen/interface/xen.h> #include <xen/interface/memory.h> -/* map fgmfn of domid to lpfn in the current domain */ -static int map_foreign_page(unsigned long lpfn, unsigned long fgmfn, +/* map fgfn of domid to lpfn in the current domain */ +static int map_foreign_page(unsigned long lpfn, unsigned long fgfn, unsigned int domid) { int rc; @@ -49,7 +49,7 @@ static int map_foreign_page(unsigned long lpfn, unsigned long fgmfn, .size = 1, .space = XENMAPSPACE_gmfn_foreign, }; - xen_ulong_t idx = fgmfn; + xen_ulong_t idx = fgfn; xen_pfn_t gpfn = lpfn; int err = 0; @@ -62,13 +62,13 @@ static int map_foreign_page(unsigned long lpfn, unsigned long fgmfn, } struct remap_data { - xen_pfn_t *fgmfn; /* foreign domain's gmfn */ + xen_pfn_t *fgfn; /* foreign domain's gfn */ pgprot_t prot; domid_t domid; struct vm_area_struct *vma; int index; struct page **pages; - struct xen_remap_mfn_info *info; + struct xen_remap_gfn_info *info; int *err_ptr; int mapped; }; @@ -82,20 +82,20 @@ static int remap_pte_fn(pte_t *ptep, pgtable_t token, unsigned long addr, pte_t pte = pte_mkspecial(pfn_pte(pfn, info->prot)); int rc; - rc = map_foreign_page(pfn, *info->fgmfn, info->domid); + rc = map_foreign_page(pfn, *info->fgfn, info->domid); *info->err_ptr++ = rc; if (!rc) { set_pte_at(info->vma->vm_mm, addr, ptep, pte); info->mapped++; } - info->fgmfn++; + info->fgfn++; return 0; } int xen_xlate_remap_gfn_array(struct vm_area_struct *vma, unsigned long addr, - xen_pfn_t *mfn, int nr, + xen_pfn_t *gfn, int nr, int *err_ptr, pgprot_t prot, unsigned domid, struct page **pages) @@ -108,7 +108,7 @@ int xen_xlate_remap_gfn_array(struct vm_area_struct *vma, x86 PVOPS */ BUG_ON(!((vma->vm_flags & (VM_PFNMAP | VM_IO)) == (VM_PFNMAP | VM_IO))); - data.fgmfn = mfn; + data.fgfn = gfn; data.prot = prot; data.domid = domid; data.vma = vma; |