* [PATCH 1/1] arm64: Correcting format specifier for printing 64 bit addresses
From: Maninder Singh @ 2016-12-05 8:09 UTC (permalink / raw)
To: linux-arm-kernel
This patch corrects format specifier for printing 64 bit addresses.
Signed-off-by: Maninder Singh <maninder1.s@samsung.com>
Signed-off-by: Vaneet Narang <v.narang@samsung.com>
---
arch/arm64/kernel/signal.c | 2 +-
arch/arm64/kvm/sys_regs.c | 8 ++++++--
arch/arm64/mm/fault.c | 15 ++++++++++-----
arch/arm64/mm/mmu.c | 4 ++--
4 files changed, 19 insertions(+), 10 deletions(-)
diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c
index c7b6de6..c89d5fd 100644
--- a/arch/arm64/kernel/signal.c
+++ b/arch/arm64/kernel/signal.c
@@ -155,7 +155,7 @@ asmlinkage long sys_rt_sigreturn(struct pt_regs *regs)
badframe:
if (show_unhandled_signals)
- pr_info_ratelimited("%s[%d]: bad frame in %s: pc=%08llx sp=%08llx\n",
+ pr_info_ratelimited("%s[%d]: bad frame in %s: pc=%016llx sp=%016llx\n",
current->comm, task_pid_nr(current), __func__,
regs->pc, regs->sp);
force_sig(SIGSEGV, current);
diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index 87e7e66..89bf5c1 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -1554,8 +1554,12 @@ static void unhandled_cp_access(struct kvm_vcpu *vcpu,
WARN_ON(1);
}
- kvm_err("Unsupported guest CP%d access at: %08lx\n",
- cp, *vcpu_pc(vcpu));
+ if (params->is_32bit)
+ kvm_err("Unsupported guest CP%d access at: %08lx\n",
+ cp, *vcpu_pc(vcpu));
+ else
+ kvm_err("Unsupported guest CP%d access at: %016lx\n",
+ cp, *vcpu_pc(vcpu));
print_sys_reg_instr(params);
kvm_inject_undefined(vcpu);
}
diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
index a78a5c4..d96a42a 100644
--- a/arch/arm64/mm/fault.c
+++ b/arch/arm64/mm/fault.c
@@ -77,7 +77,7 @@ void show_pte(struct mm_struct *mm, unsigned long addr)
pr_alert("pgd = %p\n", mm->pgd);
pgd = pgd_offset(mm, addr);
- pr_alert("[%08lx] *pgd=%016llx", addr, pgd_val(*pgd));
+ pr_alert("[%016lx] *pgd=%016llx", addr, pgd_val(*pgd));
do {
pud_t *pud;
@@ -177,7 +177,7 @@ static void __do_kernel_fault(struct mm_struct *mm, unsigned long addr,
* No handler, we'll have to terminate things with extreme prejudice.
*/
bust_spinlocks(1);
- pr_alert("Unable to handle kernel %s at virtual address %08lx\n",
+ pr_alert("Unable to handle kernel %s at virtual address %016lx\n",
(addr < PAGE_SIZE) ? "NULL pointer dereference" :
"paging request", addr);
@@ -198,9 +198,14 @@ static void __do_user_fault(struct task_struct *tsk, unsigned long addr,
struct siginfo si;
if (unhandled_signal(tsk, sig) && show_unhandled_signals_ratelimited()) {
- pr_info("%s[%d]: unhandled %s (%d)@0x%08lx, esr 0x%03x\n",
- tsk->comm, task_pid_nr(tsk), fault_name(esr), sig,
- addr, esr);
+ if (compat_user_mode(regs))
+ pr_info("%s[%d]: unhandled %s (%d) at 0x%08lx, esr 0x%03x\n",
+ tsk->comm, task_pid_nr(tsk), fault_name(esr), sig,
+ addr, esr);
+ else
+ pr_info("%s[%d]: unhandled %s (%d) at 0x%016lx, esr 0x%03x\n",
+ tsk->comm, task_pid_nr(tsk), fault_name(esr), sig,
+ addr, esr);
show_pte(tsk->mm, addr);
show_regs(regs);
}
diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
index 17243e4..cbf444c 100644
--- a/arch/arm64/mm/mmu.c
+++ b/arch/arm64/mm/mmu.c
@@ -683,9 +683,9 @@ void __init early_fixmap_init(void)
pr_warn("pmd %p != %p, %p\n",
pmd, fixmap_pmd(fix_to_virt(FIX_BTMAP_BEGIN)),
fixmap_pmd(fix_to_virt(FIX_BTMAP_END)));
- pr_warn("fix_to_virt(FIX_BTMAP_BEGIN): %08lx\n",
+ pr_warn("fix_to_virt(FIX_BTMAP_BEGIN): %016lx\n",
fix_to_virt(FIX_BTMAP_BEGIN));
- pr_warn("fix_to_virt(FIX_BTMAP_END): %08lx\n",
+ pr_warn("fix_to_virt(FIX_BTMAP_END): %016lx\n",
fix_to_virt(FIX_BTMAP_END));
pr_warn("FIX_BTMAP_END: %d\n", FIX_BTMAP_END);
--
1.9.1
^ permalink raw reply related
* [PATCH v2] arm64: dts: zx: add pcu_domain node for zx296718
From: Baoyou Xie @ 2016-12-05 8:17 UTC (permalink / raw)
To: linux-arm-kernel
This patch adds the pcu_domain node, so it can be used
by zte-soc's power domain driver.
Signed-off-by: Baoyou Xie <baoyou.xie@linaro.org>
---
arch/arm64/boot/dts/zte/zx296718.dtsi | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/arch/arm64/boot/dts/zte/zx296718.dtsi b/arch/arm64/boot/dts/zte/zx296718.dtsi
index b44d1d1..1aa0587 100644
--- a/arch/arm64/boot/dts/zte/zx296718.dtsi
+++ b/arch/arm64/boot/dts/zte/zx296718.dtsi
@@ -302,6 +302,11 @@
reg = <0x116000 0x1000>;
};
+ pcu_domain: pcu at 117000 {
+ compatible = "zte,zx296718-pcu";
+ reg = <0x00117000 0x1000>;
+ };
+
uart0: uart at 11f000 {
compatible = "arm,pl011", "arm,primecell";
arm,primecell-periphid = <0x001feffe>;
--
2.7.4
^ permalink raw reply related
* RE: Re: [PATCH 1/2] arm64: Correcting format specifier for printin 64 bit addresses
From: Maninder Singh @ 2016-12-05 8:18 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CGME20161130105054epcas2p2d8e6fbfc65564ff74c646e1ca00d3bf5@epcas2p2.samsung.com>
?
Hi Will,
>There are a bunch of these you haven't caught:
>
....
>arch/arm64/mm/mmu.c: pr_warn("fix_to_virt(FIX_BTMAP_END): %08lx\n",
>
>so it would probably make sense to fix these to be consistent.
>
>Will
All changes are sent in new patch except kvm changes, because for kvm we don't not much idea.
>arch/arm64/kernel/signal32.c: pr_info_ratelimited("%s[%d]: bad frame in %s: pc=%08llx sp=%08llx\n",
>arch/arm64/kernel/signal32.c: pr_info_ratelimited("%s[%d]: bad frame in %s: pc=%08llx sp=%08llx\n",
and signal32 fiel changes are not required, because it meant only for 32 bit.
--------------------
Thanks and Regards,
Maninder Singh
^ permalink raw reply
* XHCI controller does not detect USB key insertion
From: Neil Armstrong @ 2016-12-05 8:26 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <5841B6D1.4070507@free.fr>
Hi Mason,
On 12/02/2016 07:00 PM, Mason wrote:
> [ Fix incorrect address for Felipe ]
>
> On 02/12/2016 14:46, Neil Armstrong wrote:
>
>> On 12/02/2016 11:24 AM, Mason wrote:
>>
>>> (Sad face) All the documentation I have is in front of me, and nothing
>>> is ringing a bell. This is a Sigma Designs SoC, with a Pravega XHCI
>>> controller + Synopsys PHY.
>>>
>>> The documentation I have:
>>>
>>> Pravega_Dual_Mode_Datasheet_v10c.pdf (documents IP signals)
>>> Pravega_Dual_Mode_Controller_Programmers_Reference_manual_v1.pdf (documents IP registers)
>>> PHY databook (very low-level stuff)
>>> SoC register mapping (for how the SoC maps the IP signals to registers)
>>
>> You should have all the necessary bits to enable and configure the Embedded Synopsys PHY !
>>
>> You should have some register mapping of the PHY signals, or at least a way to write those registers.
>>
>> You should have a reset, clock gate and eventually a power regulator to enable in order to have the PHY running.
>
> I'll dump all the non-0 non-standard registers. Maybe someone
> more experienced than me will spot an obvious mistake.
>
> host_usb30_0_config: 0x2e800
> - host_usb30_0_fladj 0x20
> - host_usb30_0_usb30_controller_cg_disable 0x0
> - host_usb30_0_mode_select 0x1
> - host_usb30_0_device_reset_mode 0x0
>
> host_usb30_0_control: 0x2e804
> - host_usb30_0_app_lfps_u3_wp 0x0
> - host_usb30_0_link_up 0x1
> - host_usb30_0_msi_msg_sent 0x0
> - host_usb30_0_usb3_p0_over_current 0x0
> - host_usb30_0_usb2_p0_over_current 0x0
>
> host_usb30_0_test: 0x2e808
> - host_usb30_0_test_powerdown_hsp 0x0
> - host_usb30_0_test_powerdown_ssp 0x0
> - host_usb30_0_test_burnin 0x0
> - host_usb30_0_acjt_level 0x14
> - host_usb30_0_lane0_tx2rx_loopbk 0x0
> - host_usb30_0_rtune_req 0x0
>
> host_usb30_0_status: 0x2e80c
> - host_usb30_0_phystatus 0x0
> - host_usb30_0_usb2_p0_pp 0x1
> - host_usb30_0_usb3_p0_pp 0x1
> - host_usb30_0_usb3_sleep 0x0
> - host_usb30_0_rtune_ack 0x0
>
> host_usb30_0_clk_rst_0: 0x2e810
> - host_usb30_0_commononn 0x1
> - host_usb30_0_portreset 0x0
> - host_usb30_0_refclksel 0x2
> - host_usb30_0_teneable 0x1
> - host_usb30_0_fsel 0x27
> - host_usb30_0_mpll_multiplier 0x19
> - host_usb30_0_ref_clkdiv2 0x0
> - host_usb30_0_ref_ssp_en 0x1
> - host_usb30_0_ref_use_pad 0x0
> - host_usb30_0_ssc_en 0x1
> - host_usb30_0_ssc_range 0x0
>
> host_usb30_0_clk_rst_1: 0x2e814
> - host_usb30_0_ssc_ref_clk_sel 0x88
> - host_usb30_0_sleepm 0x1
> - host_usb30_0_vbusvldext 0x1
>
> host_usb30_0_param_0: 0x2e818
> - host_usb30_0_compdistune 0x4
> - host_usb30_0_otgtune 0x4
> - host_usb30_0_sqrxtune 0x3
> - host_usb30_0_txfsltune 0x3
> - host_usb30_0_txhsxvtune 0x3
> - host_usb30_0_txpreempltune 0x0
> - host_usb30_0_txpreemppulsetune 0x0
> - host_usb30_0_txrestune 0x1
> - host_usb30_0_txrisetune 0x2
> - host_usb30_0_txvreftune 0x4
>
> host_usb30_0_param_1: 0x2e81c
> - host_usb30_0_los_bias 0x5
> - host_usb30_0_los_level 0xc
> - host_usb30_0_pcs_rx_los_mask_val 0xf0
> - host_usb30_0_pcs_tx_deemph_3p5db 0x18
> - host_usb30_0_pcs_tx_deemph_6db 0x21
>
> host_usb30_0_param_2: 0x2e820
> - host_usb30_0_pcs_tx_swing_full 0x73
> - host_usb30_0_lane0_tx_term_offset 0x0
> - host_usb30_0_tx_vboost_lvl 0x4
>
> host_usb30_0_SNPS_CR_ADD: 0x2e880
> - host_usb30_0_snps_cr_add 0xe03c
This is obviously the PHY registers.
Commonly, the PHY from Synopsys does not have a register interface given by Synopsys, but it's in charge
of the SoC integrator to add a register set to program all the PHY signals.
Typically, those signal will contain some Clock selection, Enable Reset, Tunings and VBUS mode selection.
commononn seems top be an enable, but active low
portreset seems to be used to reset the port
refclksel seem to select the clock source (you should have either an external Xtal, SoX Xtal or a PLL output)
And so on.
Please look at your "PHY databook" how these signals should be configured.
Be aware that some "tune" register should have been calibrated in fab somehow, so you should make sure the reset values are correct.
Neil
>
> DEVICE_AND_PORT_000: 0x70050000
> - sw_reset 0x0
> - gen_resume 0x0
> - ss_support 0x0
> - revision_id 0x0
> - vendor_id 0x3
>
> DEVICE_AND_PORT_00C: 0x7005000c
> - set_isoc_delay 0x0
> - utmi_vstatus 0x0
> - utmi_vcontrolloadm 0x1
> - utmi_vcontrol 0x0
> - config_dev_speed 0x1
>
> ENDP_CONFIG_020: 0x70050020
> - burst_size 0x1
> - max_packet_size_7_0 0x0
> - rst_seq_num 0x0
> - iso_xact_type 0x0
> - stall 0x0
> - max_pkt_size_10_8 0x2
> - setup_reenable 0x0
> - endp_enable 0x1
> - endp_type 0x0
> - endp_no 0x0
>
> LTSSM_STATE_REGISTER: 0x70050220
> - ltssm_state_status 0x4
> - u1_enable 0x0
> - u2_enable 0x0
> - disable_scramble_lb 0x1
> - lfps_ux_exit 0x0
> - disable_scramble_request 0x0
> - self_powered_device 0x0
> - host_device 0x1
> - send_warm_reseti 0x0
> - send_hot_reset 0x0
> - reg_lgo_u3 0x0
>
> PHY_TIMER_REGISTER: 0x70050410
> - u2_inactivity_timeout 0x0
> - pending_hp_time_out 0x2a
> - recv_resume 0x0
> - auto_resume 0x0
> - credit_hp_timer 0x46
> - usb3_clk_pulse_256us 0x100
>
> PM_LC_TIMER_REGISTER: 0x70050418
> - cntr_pulse_pm_lc_timer 0x2a
> - cntr_pulse_pm_entry_timer 0x54
> - lup_timeout_value 0xa
> - no_link_commands_timeout_value 0xe
> - pm_lc_timer_register_reserved 0x6e
>
> LTSSM_TIMER_REGISTER1: 0x7005041c
> - u1_exit_timeout 0x54
> - u2_exit_timeout 0x54
> - reg_12_ms_timeout 0xa8
>
> LTSSM_TIMER_REGISTER2: 0x70050420
> - reg_360_ms_timeout 0x34
> - pipe_width 0x3
> - reg_2_ms_timeout 0x3c
> - rxeq_timeout 0xffff
>
> LTSSM_TIMER_REGISTER3: 0x70050424
> - reg_6_ms_timeout 0x54
> - reg_300_ms_timeout 0x149
> - reg_100_ms_timeout 0x8c
> - ltssm_timer_reg3_undef 0x0
>
> LOW_POWER_LFPS_SIGNALING_REGISTER: 0x70050434
> - low_power_lfps_signaling_register_value 0x4e030303
> - low_power_lfps_undef 0x0
>
> PING_POLLING_LFPS_SIGNALING_REGISTER: 0x70050440
> - ping_polling_lfps_signaling_register 0x9f5beebc
>
> WARM_RESET_LFPS_SIGNALING_REGISTER: 0x70050444
> - lfps_rx_trepeat_polling 0x5
> - lfps_wr_undef 0x0
> - lfps_wr_tresetdelay_min 0x12
> - lfps_wr_tresetdelay_max 0x0
> - lfps_wr_treset_total 0x76
>
> LOW_POWER_LFPS_SIGNALING_REGISTER1: 0x70050448
> - lfp_rx_undef 0x0
> - lfps_rx_u2_t13_t11 0x12
> - lfps_rx_u3_t13_t11 0x62
> - lfps_rx_u1_t13_t11 0x7
> - lfps_tx_u1_t11_t10 0xe
> - lfps_tx_u1_t12_t11 0x8
> - lfps_tx_u1_t11_t10_7_4 0x1
>
> LOW_POWER_LFPS_SIGNALING_REGISTER2: 0x7005044c
> - low_power_lfps_signaling_register2 0xc34f07d0
>
> LOW_POWER_LFPS_SIGNALING_REGISTER3: 0x70050450
> - low_power_lfps_signaling_register3 0xc34f07d0
>
> TIMER_ENABLE_REGISTERS: 0x70050454
> - pravega_counter_pulse_1us 0x9
> - pravega_counter_pulse_10us 0x9
> - pravega_counter_pulse_1ms 0x9
> - pravega_counter_pulse_100us 0x9
> - pravega_counter_pulse_10ms 0x9
> - counter_pulse_100ns 0x14
>
These seems to be non-standard Prevaga XHCI registers.
>
> I'll take a closer look on Monday.
>
> Regards.
>
^ permalink raw reply
* [PATCH v3 4/7] PWM: add pwm driver for stm32 plaftorm
From: Lee Jones @ 2016-12-05 8:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161205072357.GB18069@ulmo.ba.sec>
On Mon, 05 Dec 2016, Thierry Reding wrote:
> On Fri, Dec 02, 2016 at 11:17:19AM +0100, Benjamin Gaignard wrote:
> > This driver add support for pwm driver on stm32 platform.
>
> "adds". Also please use PWM in prose because it's an abbreviation.
>
> > The SoC have multiple instances of the hardware IP and each
> > of them could have small differences: number of channels,
> > complementary output, counter register size...
> > Use DT parameters to handle those differentes configuration
>
> "different configurations"
>
> >
> > version 2:
> > - only keep one comptatible
> > - use DT paramaters to discover hardware block configuration
>
> "parameters"
>
> >
> > Signed-off-by: Benjamin Gaignard <benjamin.gaignard@st.com>
> > ---
> > drivers/pwm/Kconfig | 8 ++
> > drivers/pwm/Makefile | 1 +
> > drivers/pwm/pwm-stm32.c | 285 ++++++++++++++++++++++++++++++++++++++++++++++++
> > 3 files changed, 294 insertions(+)
> > create mode 100644 drivers/pwm/pwm-stm32.c
> >
> > diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
> > index bf01288..a89fdba 100644
> > --- a/drivers/pwm/Kconfig
> > +++ b/drivers/pwm/Kconfig
> > @@ -388,6 +388,14 @@ config PWM_STI
> > To compile this driver as a module, choose M here: the module
> > will be called pwm-sti.
> >
> > +config PWM_STM32
> > + bool "STMicroelectronics STM32 PWM"
> > + depends on ARCH_STM32
> > + depends on OF
> > + select MFD_STM32_GP_TIMER
>
> Should that be a "depends on"?
>
> > + help
> > + Generic PWM framework driver for STM32 SoCs.
> > +
> > config PWM_STMPE
> > bool "STMPE expander PWM export"
> > depends on MFD_STMPE
> > diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile
> > index 1194c54..5aa9308 100644
> > --- a/drivers/pwm/Makefile
> > +++ b/drivers/pwm/Makefile
> > @@ -37,6 +37,7 @@ obj-$(CONFIG_PWM_ROCKCHIP) += pwm-rockchip.o
> > obj-$(CONFIG_PWM_SAMSUNG) += pwm-samsung.o
> > obj-$(CONFIG_PWM_SPEAR) += pwm-spear.o
> > obj-$(CONFIG_PWM_STI) += pwm-sti.o
> > +obj-$(CONFIG_PWM_STM32) += pwm-stm32.o
> > obj-$(CONFIG_PWM_STMPE) += pwm-stmpe.o
> > obj-$(CONFIG_PWM_SUN4I) += pwm-sun4i.o
> > obj-$(CONFIG_PWM_TEGRA) += pwm-tegra.o
> > diff --git a/drivers/pwm/pwm-stm32.c b/drivers/pwm/pwm-stm32.c
> > new file mode 100644
> > index 0000000..a362f63
> > --- /dev/null
> > +++ b/drivers/pwm/pwm-stm32.c
> > @@ -0,0 +1,285 @@
> > +/*
> > + * Copyright (C) STMicroelectronics 2016
> > + * Author: Gerald Baeza <gerald.baeza@st.com>
>
> Could use a blank line between the above. Also, please use a single
> space after : for consistency.
>
> > + * License terms: GNU General Public License (GPL), version 2
>
> Here too.
>
> > + *
> > + * Inspired by timer-stm32.c from Maxime Coquelin
> > + * pwm-atmel.c from Bo Shen
> > + */
> > +
> > +#include <linux/of.h>
> > +#include <linux/module.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/pwm.h>
>
> Please sort these alphabetically.
>
> > +
> > +#include <linux/mfd/stm32-gptimer.h>
> > +
> > +#define DRIVER_NAME "stm32-pwm"
> > +
> > +#define CAP_COMPLEMENTARY BIT(0)
> > +#define CAP_32BITS_COUNTER BIT(1)
> > +#define CAP_BREAKINPUT BIT(2)
> > +#define CAP_BREAKINPUT_POLARITY BIT(3)
>
> Just make these boolean. Makes the conditionals a lot simpler to read.
>
> > +
> > +struct stm32_pwm_dev {
>
> No need for the _dev suffix.
I usually like ddata (short for device data, which is what it is).
I'll be asking for the same in the MFD driver too.
> > + struct device *dev;
> > + struct clk *clk;
> > + struct regmap *regmap;
> > + struct pwm_chip chip;
>
> It's slightly more efficient to put this as first field because then
> to_stm32_pwm() becomes a no-op.
Niiiice!
> > + int caps;
> > + int npwm;
>
> unsigned int, please.
>
> > + u32 polarity;
>
> Maybe use a prefix here to stress that it is the polarity of the
> complementary output. Otherwise one might take it for the PWM signal's
> polarity that's already part of the PWM state.
>
> > +};
> > +
> > +#define to_stm32_pwm_dev(x) container_of(chip, struct stm32_pwm_dev, chip)
>
> Please turn this into a static inline.
>
> > +
> > +static u32 __active_channels(struct stm32_pwm_dev *pwm_dev)
>
> No need for a __ prefix.
>
> > +{
> > + u32 ccer;
> > +
> > + regmap_read(pwm_dev->regmap, TIM_CCER, &ccer);
> > +
> > + return ccer & TIM_CCER_CCXE;
> > +}
> > +
> > +static int write_ccrx(struct stm32_pwm_dev *dev, struct pwm_device *pwm,
> > + u32 ccr)
>
> u32 value, perhaps? I first mistook this to be a register offset.
>
> > +{
> > + switch (pwm->hwpwm) {
> > + case 0:
> > + return regmap_write(dev->regmap, TIM_CCR1, ccr);
> > + case 1:
> > + return regmap_write(dev->regmap, TIM_CCR2, ccr);
> > + case 2:
> > + return regmap_write(dev->regmap, TIM_CCR3, ccr);
> > + case 3:
> > + return regmap_write(dev->regmap, TIM_CCR4, ccr);
> > + }
> > + return -EINVAL;
> > +}
> > +
> > +static int stm32_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
> > + int duty_ns, int period_ns)
>
> Please implement this as an atomic PWM driver, I don't want new drivers
> to use the legacy callbacks.
>
> > +{
> > + struct stm32_pwm_dev *dev = to_stm32_pwm_dev(chip);
>
> I think something like "stm", or "priv" would be more appropriate here.
> If you ever need access to a struct device, you'll be hard-pressed to
> find a good name for it.
See above.
> > + unsigned long long prd, div, dty;
> > + int prescaler = 0;
>
> If this can never be negative, please make it unsigned int.
>
> > + u32 max_arr = 0xFFFF, ccmr, mask, shift, bdtr;
> > +
> > + if (dev->caps & CAP_32BITS_COUNTER)
> > + max_arr = 0xFFFFFFFF;
>
> I prefer lower-case hexadecimal digits.
Even better to define the max values.
> > +
> > + /* Period and prescaler values depends of clock rate */
>
> "depend on"
>
> > + div = (unsigned long long)clk_get_rate(dev->clk) * period_ns;
> > +
> > + do_div(div, NSEC_PER_SEC);
> > + prd = div;
> > +
> > + while (div > max_arr) {
> > + prescaler++;
> > + div = prd;
> > + do_div(div, (prescaler + 1));
> > + }
> > + prd = div;
>
> Blank line after blocks, please.
... unless directly related to the block, which I think this is. It's
the '\n' *before* the block which confuses me.
> > + if (prescaler > MAX_TIM_PSC) {
> > + dev_err(chip->dev, "prescaler exceeds the maximum value\n");
> > + return -EINVAL;
> > + }
> > +
> > + /* All channels share the same prescaler and counter so
> > + * when two channels are active at the same we can't change them
> > + */
>
> This isn't proper block comment style. Also, please use all of the
> columns at your disposal.
>
> > + if (__active_channels(dev) & ~(1 << pwm->hwpwm * 4)) {
> > + u32 psc, arr;
> > +
> > + regmap_read(dev->regmap, TIM_PSC, &psc);
> > + regmap_read(dev->regmap, TIM_ARR, &arr);
> > +
> > + if ((psc != prescaler) || (arr != prd - 1))
> > + return -EINVAL;
>
> Maybe -EBUSY to differentiate from other error cases?
>
> > + }
> > +
> > + regmap_write(dev->regmap, TIM_PSC, prescaler);
> > + regmap_write(dev->regmap, TIM_ARR, prd - 1);
> > + regmap_update_bits(dev->regmap, TIM_CR1, TIM_CR1_ARPE, TIM_CR1_ARPE);
> > +
> > + /* Calculate the duty cycles */
> > + dty = prd * duty_ns;
> > + do_div(dty, period_ns);
> > +
> > + write_ccrx(dev, pwm, dty);
> > +
> > + /* Configure output mode */
> > + shift = (pwm->hwpwm & 0x1) * 8;
> > + ccmr = (TIM_CCMR_PE | TIM_CCMR_M1) << shift;
> > + mask = 0xFF << shift;
> > +
> > + if (pwm->hwpwm & 0x2)
>
> This looks as though TIM_CCMR1 is used for channels 0 and 1, while
> TIM_CCMR2 is used for channels 2 and 3. Wouldn't it be more natural to
> make the conditional above:
>
> if (pwm->hwpwm >= 2)
>
> ? Or perhaps better yet:
>
> if (pwm->hwpwm < 2)
> /* update TIM_CCMR1 */
> else
> /* update TIM_CCMR2 */
And please define the magic numbers.
*_MASK
*_SHIFT
> The other alternative, which might make the code slightly more readable,
> would be to get rid of all these conditionals by parameterizing the
> offsets per PWM channel. The PWM subsystem has a means of storing per-
> channel chip-specific data (see pwm_{set,get}_chip_data()). It might be
> a little overkill for this particular driver, given that the number of
> conditionals is fairly small.
>
> > + regmap_update_bits(dev->regmap, TIM_CCMR2, mask, ccmr);
> > + else
> > + regmap_update_bits(dev->regmap, TIM_CCMR1, mask, ccmr);
> > +
> > + if (!(dev->caps & CAP_BREAKINPUT))
> > + return 0;
>
> If you make these capabilities boolean, it becomes much more readable,
> especially for negations:
>
> if (!dev->has_breakinput)
+1
> > +
> > + bdtr = TIM_BDTR_MOE | TIM_BDTR_AOE;
> > +
> > + if (dev->caps & CAP_BREAKINPUT_POLARITY)
> > + bdtr |= TIM_BDTR_BKE;
> > +
> > + if (dev->polarity)
> > + bdtr |= TIM_BDTR_BKP;
> > +
> > + regmap_update_bits(dev->regmap, TIM_BDTR,
> > + TIM_BDTR_MOE | TIM_BDTR_AOE |
> > + TIM_BDTR_BKP | TIM_BDTR_BKE,
> > + bdtr);
> > +
> > + return 0;
> > +}
> > +
> > +static int stm32_pwm_set_polarity(struct pwm_chip *chip, struct pwm_device *pwm,
> > + enum pwm_polarity polarity)
> > +{
> > + u32 mask;
> > + struct stm32_pwm_dev *dev = to_stm32_pwm_dev(chip);
> > +
> > + mask = TIM_CCER_CC1P << (pwm->hwpwm * 4);
> > + if (dev->caps & CAP_COMPLEMENTARY)
> > + mask |= TIM_CCER_CC1NP << (pwm->hwpwm * 4);
> > +
> > + regmap_update_bits(dev->regmap, TIM_CCER, mask,
> > + polarity == PWM_POLARITY_NORMAL ? 0 : mask);
> > +
> > + return 0;
> > +}
> > +
> > +static int stm32_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
> > +{
> > + u32 mask;
> > + struct stm32_pwm_dev *dev = to_stm32_pwm_dev(chip);
> > +
> > + clk_enable(dev->clk);
> > +
> > + /* Enable channel */
> > + mask = TIM_CCER_CC1E << (pwm->hwpwm * 4);
> > + if (dev->caps & CAP_COMPLEMENTARY)
> > + mask |= TIM_CCER_CC1NE << (pwm->hwpwm * 4);
> > +
> > + regmap_update_bits(dev->regmap, TIM_CCER, mask, mask);
> > +
> > + /* Make sure that registers are updated */
> > + regmap_update_bits(dev->regmap, TIM_EGR, TIM_EGR_UG, TIM_EGR_UG);
> > +
> > + /* Enable controller */
> > + regmap_update_bits(dev->regmap, TIM_CR1, TIM_CR1_CEN, TIM_CR1_CEN);
> > +
> > + return 0;
> > +}
> > +
> > +static void stm32_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
> > +{
> > + u32 mask;
> > + struct stm32_pwm_dev *dev = to_stm32_pwm_dev(chip);
> > +
> > + /* Disable channel */
> > + mask = TIM_CCER_CC1E << (pwm->hwpwm * 4);
> > + if (dev->caps & CAP_COMPLEMENTARY)
> > + mask |= TIM_CCER_CC1NE << (pwm->hwpwm * 4);
> > +
> > + regmap_update_bits(dev->regmap, TIM_CCER, mask, 0);
> > +
> > + /* When all channels are disabled, we can disable the controller */
> > + if (!__active_channels(dev))
> > + regmap_update_bits(dev->regmap, TIM_CR1, TIM_CR1_CEN, 0);
> > +
> > + clk_disable(dev->clk);
> > +}
>
> All of the above can be folded into the ->apply() hook for atomic PWM
> support.
>
> Also, in the above you use clk_enable() in the ->enable() callback and
> clk_disable() in ->disable(). If you need the clock to access registers
> you'll have to enabled it in the others as well because there are no
> guarantees that configuration will only happen between ->enable() and
> ->disable(). Atomic PWM simplifies this a bit, but you still need to be
> careful about when to enable the clock in your ->apply() hook.
>
> > +
> > +static const struct pwm_ops stm32pwm_ops = {
> > + .config = stm32_pwm_config,
> > + .set_polarity = stm32_pwm_set_polarity,
> > + .enable = stm32_pwm_enable,
> > + .disable = stm32_pwm_disable,
> > +};
>
> You need to set the .owner field as well.
>
> > +
> > +static int stm32_pwm_probe(struct platform_device *pdev)
> > +{
> > + struct device *dev = &pdev->dev;
> > + struct device_node *np = dev->of_node;
> > + struct stm32_gptimer_dev *mfd = dev_get_drvdata(pdev->dev.parent);
> > + struct stm32_pwm_dev *pwm;
pwm is okay. Please also consider using ddata for consistency across
the driver-set.
> > + int ret;
> > +
> > + pwm = devm_kzalloc(dev, sizeof(*pwm), GFP_KERNEL);
> > + if (!pwm)
> > + return -ENOMEM;
> > +
> > + pwm->regmap = mfd->regmap;
> > + pwm->clk = mfd->clk;
> > +
> > + if (!pwm->regmap || !pwm->clk)
> > + return -EINVAL;
> > +
> > + if (of_property_read_bool(np, "st,complementary"))
> > + pwm->caps |= CAP_COMPLEMENTARY;
> > +
> > + if (of_property_read_bool(np, "st,32bits-counter"))
> > + pwm->caps |= CAP_32BITS_COUNTER;
> > +
> > + if (of_property_read_bool(np, "st,breakinput"))
> > + pwm->caps |= CAP_BREAKINPUT;
> > +
> > + if (!of_property_read_u32(np, "st,breakinput-polarity", &pwm->polarity))
> > + pwm->caps |= CAP_BREAKINPUT_POLARITY;
> > +
> > + of_property_read_u32(np, "st,pwm-num-chan", &pwm->npwm);
> > +
> > + pwm->chip.base = -1;
> > + pwm->chip.dev = dev;
> > + pwm->chip.ops = &stm32pwm_ops;
> > + pwm->chip.npwm = pwm->npwm;
> > +
> > + ret = pwmchip_add(&pwm->chip);
> > + if (ret < 0)
> > + return ret;
> > +
> > + platform_set_drvdata(pdev, pwm);
> > +
> > + return 0;
> > +}
> > +
> > +static int stm32_pwm_remove(struct platform_device *pdev)
> > +{
> > + struct stm32_pwm_dev *pwm = platform_get_drvdata(pdev);
> > + int i;
>
> unsigned int, please.
>
> > +
> > + for (i = 0; i < pwm->npwm; i++)
> > + pwm_disable(&pwm->chip.pwms[i]);
> > +
> > + pwmchip_remove(&pwm->chip);
> > +
> > + return 0;
> > +}
> > +
> > +static const struct of_device_id stm32_pwm_of_match[] = {
> > + {
> > + .compatible = "st,stm32-pwm",
> > + },
>
> The above can be collapsed into a single line.
+1
> > +};
> > +MODULE_DEVICE_TABLE(of, stm32_pwm_of_match);
> > +
> > +static struct platform_driver stm32_pwm_driver = {
> > + .probe = stm32_pwm_probe,
> > + .remove = stm32_pwm_remove,
> > + .driver = {
> > + .name = DRIVER_NAME,
> > + .of_match_table = stm32_pwm_of_match,
> > + },
> > +};
>
> Please don't use tabs for padding within the structure definition since
> it doesn't align properly anyway.
+1
> > +module_platform_driver(stm32_pwm_driver);
> > +
> > +MODULE_ALIAS("platform:" DRIVER_NAME);
> > +MODULE_DESCRIPTION("STMicroelectronics STM32 PWM driver");
> > +MODULE_LICENSE("GPL");
>
> According to the header comment this should be "GPL v2".
+1
--
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org ? Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
^ permalink raw reply
* [PATCH v3 3/7] PWM: add pwm-stm32 DT bindings
From: Lee Jones @ 2016-12-05 8:35 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161205065350.GA18069@ulmo.ba.sec>
On Mon, 05 Dec 2016, Thierry Reding wrote:
> On Fri, Dec 02, 2016 at 11:17:18AM +0100, Benjamin Gaignard wrote:
> > Define bindings for pwm-stm32
> >
> > version 2:
> > - use parameters instead of compatible of handle the hardware configuration
> >
> > Signed-off-by: Benjamin Gaignard <benjamin.gaignard@st.com>
> > ---
> > .../devicetree/bindings/pwm/pwm-stm32.txt | 38 ++++++++++++++++++++++
> > 1 file changed, 38 insertions(+)
> > create mode 100644 Documentation/devicetree/bindings/pwm/pwm-stm32.txt
> >
> > diff --git a/Documentation/devicetree/bindings/pwm/pwm-stm32.txt b/Documentation/devicetree/bindings/pwm/pwm-stm32.txt
> > new file mode 100644
> > index 0000000..575b9fb
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/pwm/pwm-stm32.txt
> > @@ -0,0 +1,38 @@
> > +STMicroelectronics PWM driver bindings for STM32
>
> Technically this bindings describe devices, so "driver binding" is a
> somewhat odd wording. Perhaps:
>
> STMicroelectronics STM32 General Purpose Timer PWM bindings
>
> ?
>
> > +
> > +Must be a sub-node of STM32 general purpose timer driver
> > +Parent node properties are describe in ../mfd/stm32-general-purpose-timer.txt
>
> Again, "driver parent node" is odd. Perhaps:
>
> Must be a sub-node of an STM32 General Purpose Timer device tree
> node. See ../mfd/stm32-general-purpose-timer.txt for details about
> the parent node.
>
> ?
>
> > +Required parameters:
> > +- compatible: Must be "st,stm32-pwm"
> > +- pinctrl-names: Set to "default".
> > +- pinctrl-0: List of phandles pointing to pin configuration nodes
> > + for PWM module.
> > + For Pinctrl properties, please refer to [1].
>
> Your indentation and capitalization are inconsistent. Also, please refer
> to the pinctrl bindings by relative path and inline, rather than as a
> footnote reference.
>
> > +
> > +Optional parameters:
> > +- st,breakinput: Set if the hardware have break input capabilities
> > +- st,breakinput-polarity: Set break input polarity. Default is 0
> > + The value define the active polarity:
> > + - 0 (active LOW)
> > + - 1 (active HIGH)
>
> Could we fold these into a single property? If st,breakinput-polarity is
> not present it could simply mean that there is no break input, and if it
> is present you don't have to rely on a default.
>
> > +- st,pwm-num-chan: Number of available PWM channels. Default is 0.
>
> The pwm- prefix is rather redundant since the node is already named pwm.
> Why not simply st,channels? Or simply channels, since it's not really
> anything specific to this hardware.
>
> Come to think of it, might be worth having a discussion with our DT
> gurus about what their stance is on using the # as prefix for numbers
> (such as in #address-cells or #size-cells). This could be #channels to
> mark it more explicitly as representing a count.
Unfortunately that ship has sailed.
st,pwm-num-chan already exists (with your blessing). It's usually
suggested to reuse exiting properties when writing new bindings.
> > +- st,32bits-counter: Set if the hardware have a 32 bits counter
> > +- st,complementary: Set if the hardware have complementary output channels
>
> "hardware has" and also maybe mention explicitly that this is a boolean
> property. Otherwise people might be left wondering what it should be set
> to. Or maybe word this differently to imply that it's boolean:
>
> - st,32bits-counter: if present, the hardware has a 32 bit counter
> - st,complementary: if present, the hardware has a complementary
> output channel
>
> Thierry
--
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org ? Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
^ permalink raw reply
* [PATCH v2 1/3] ARM: da850: fix infinite loop in clk_set_rate()
From: Sekhar Nori @ 2016-12-05 8:38 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1480693134-31324-2-git-send-email-bgolaszewski@baylibre.com>
On Friday 02 December 2016 09:08 PM, Bartosz Golaszewski wrote:
> The aemif clock is added twice to the lookup table in da850.c. This
> breaks the children list of pll0_sysclk3 as we're using the same list
> links in struct clk. When calling clk_set_rate(), we get stuck in
> propagate_rate().
>
> Create a separate clock for nand, inheriting the rate of the aemif
> clock and retrieve it in the davinci_nand module.
>
> Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
> ---
> arch/arm/mach-davinci/da850.c | 7 ++++++-
> drivers/mtd/nand/davinci_nand.c | 2 +-
> 2 files changed, 7 insertions(+), 2 deletions(-)
>
> diff --git a/arch/arm/mach-davinci/da850.c b/arch/arm/mach-davinci/da850.c
> index e770c97..1fcc986 100644
> --- a/arch/arm/mach-davinci/da850.c
> +++ b/arch/arm/mach-davinci/da850.c
> @@ -367,6 +367,11 @@ static struct clk aemif_clk = {
> .flags = ALWAYS_ENABLED,
> };
>
> +static struct clk nand_clk = {
> + .name = "nand",
> + .parent = &aemif_clk,
> +};
> +
> static struct clk usb11_clk = {
> .name = "usb11",
> .parent = &pll0_sysclk4,
> @@ -537,7 +542,7 @@ static struct clk_lookup da850_clks[] = {
> CLK("da830-mmc.0", NULL, &mmcsd0_clk),
> CLK("da830-mmc.1", NULL, &mmcsd1_clk),
> CLK("ti-aemif", NULL, &aemif_clk),
> - CLK(NULL, "aemif", &aemif_clk),
> + CLK(NULL, "nand", &nand_clk),
Why use a NULL device name here?
> CLK("ohci-da8xx", "usb11", &usb11_clk),
> CLK("musb-da8xx", "usb20", &usb20_clk),
> CLK("spi_davinci.0", NULL, &spi0_clk),
> diff --git a/drivers/mtd/nand/davinci_nand.c b/drivers/mtd/nand/davinci_nand.c
> index 27fa8b8..5857d06 100644
> --- a/drivers/mtd/nand/davinci_nand.c
> +++ b/drivers/mtd/nand/davinci_nand.c
> @@ -694,7 +694,7 @@ static int nand_davinci_probe(struct platform_device *pdev)
>
> ret = -EINVAL;
>
> - info->clk = devm_clk_get(&pdev->dev, "aemif");
> + info->clk = devm_clk_get(&pdev->dev, "nand");
This driver is used by keystone devices too. So just changing the
connection id will likely break them. Why do you need to change the
connection id?
Thanks,
Sekhar
^ permalink raw reply
* [PATCH v2 3/3] ARM: da850: fix da850_set_pll0rate()
From: Sekhar Nori @ 2016-12-05 8:45 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1480693134-31324-4-git-send-email-bgolaszewski@baylibre.com>
On Friday 02 December 2016 09:08 PM, Bartosz Golaszewski wrote:
> This function is broken - its second argument is an index to the freq
> table, not the requested clock rate in Hz. It leads to an oops when
> called from clk_set_rate() since this argument isn't bounds checked
> either.
>
> Fix it by iterating over the array of supported frequencies and
> selecting a one that matches or returning -EINVAL for unsupported
> rates.
>
> Also: update the davinci cpufreq driver. It's the only user of this
> clock and currently it passes the cpufreq table index to
> clk_set_rate(), which is confusing. Make it pass the requested clock
> rate in Hz.
>
> Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
> ---
> arch/arm/mach-davinci/da850.c | 22 ++++++++++++++++++----
> drivers/cpufreq/davinci-cpufreq.c | 2 +-
> 2 files changed, 19 insertions(+), 5 deletions(-)
>
> diff --git a/arch/arm/mach-davinci/da850.c b/arch/arm/mach-davinci/da850.c
> index a55101c..92e3303 100644
> --- a/arch/arm/mach-davinci/da850.c
> +++ b/arch/arm/mach-davinci/da850.c
> @@ -1179,14 +1179,28 @@ static int da850_set_armrate(struct clk *clk, unsigned long index)
> return clk_set_rate(pllclk, index);
> }
>
> -static int da850_set_pll0rate(struct clk *clk, unsigned long index)
> +static int da850_set_pll0rate(struct clk *clk, unsigned long rate)
> {
> - unsigned int prediv, mult, postdiv;
> - struct da850_opp *opp;
> struct pll_data *pll = clk->pll_data;
> + struct cpufreq_frequency_table *freq;
> + unsigned int prediv, mult, postdiv;
> + struct da850_opp *opp = NULL;
> int ret;
>
> - opp = (struct da850_opp *) cpufreq_info.freq_table[index].driver_data;
> + for (freq = da850_freq_table;
> + freq->frequency != CPUFREQ_TABLE_END; freq++) {
> + /* requested_rate is in Hz, freq->frequency is in KHz */
> + unsigned long freq_rate = freq->frequency * 1000;
A small optimization here. Instead of multiplying potentially every
frequency in the table by 1000, you could divide the incoming rate down
to KHz. This will also avoid the need for 'freq_rate'. Should have
noticed this earlier. Sorry about that.
Thanks,
Sekhar
^ permalink raw reply
* [PATCH 2/2] arm: dts: sun8i: reuse the uart1 node of iNet D978 rev2 board
From: Maxime Ripard @ 2016-12-05 8:50 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161202151913.38892-2-icenowy@aosc.xyz>
On Fri, Dec 02, 2016 at 11:19:13PM +0800, Icenowy Zheng wrote:
> As a uart1 node is added into sun8i-reference-design-tablet.dtsi, simply
> use it in iNet D978 rev2 device tree.
>
> Signed-off-by: Icenowy Zheng <icenowy@aosc.xyz>
I'd like to see more consolidation before that change is needed. If we
find more boards using that, it will make sense, but for a single
board it's not worth it.
Maxime
--
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 801 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20161205/4aa6d997/attachment.sig>
^ permalink raw reply
* [PATCH v1 1/2] Add crypto driver support for some MediaTek chips
From: Corentin Labbe @ 2016-12-05 8:52 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1480921284-45827-2-git-send-email-ryder.lee@mediatek.com>
Hello
I have two minor comment.
On Mon, Dec 05, 2016 at 03:01:23PM +0800, Ryder Lee wrote:
> This adds support for the MediaTek hardware accelerator on
> mt7623/mt2701/mt8521p SoC.
>
> This driver currently implement:
> - SHA1 and SHA2 family(HMAC) hash alogrithms.
There is a typo for algorithms.
[...]
> +/**
> + * struct mtk_desc - DMA descriptor
> + * @hdr: the descriptor control header
> + * @buf: DMA address of input buffer segment
> + * @ct: DMA address of command token that control operation flow
> + * @ct_hdr: the command token control header
> + * @tag: the user-defined field
> + * @tfm: DMA address of transform state
> + * @bound: align descriptors offset boundary
> + *
> + * Structure passed to the crypto engine to describe where source
> + * data needs to be fetched and how it needs to be processed.
> + */
> +struct mtk_desc {
> + u32 hdr;
> + u32 buf;
> + u32 ct;
> + u32 ct_hdr;
> + u32 tag;
> + u32 tfm;
> + u32 bound[2];
> +};
Do you have tested this descriptor with BE/LE kernel ?
Regards
Corentin Labbe
^ permalink raw reply
* [PATCH v2 2/3] ARM: dts: sunxi: add support for Orange Pi Zero board
From: Maxime Ripard @ 2016-12-05 8:52 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <11498641480688550@web2g.yandex.ru>
On Fri, Dec 02, 2016 at 10:22:30PM +0800, Icenowy Zheng wrote:
>
>
> 01.12.2016, 17:36, "Maxime Ripard" <maxime.ripard@free-electrons.com>:
> > On Mon, Nov 28, 2016 at 12:29:07AM +0000, Andr? Przywara wrote:
> >> ?> Something more interesting happened.
> >> ?>
> >> ?> Xunlong made a add-on board for Orange Pi Zero, which exposes the
> >> ?> two USB Controllers exported at expansion bus as USB Type-A
> >> ?> connectors.
> >> ?>
> >> ?> Also it exposes a analog A/V jack and a microphone.
> >> ?>
> >> ?> Should I enable {e,o}hci{2.3} in the device tree?
> >>
> >> ?Actually we should do this regardless of this extension board. The USB
> >> ?pins are not multiplexed and are exposed on user accessible pins (just
> >> ?not soldered, but that's a detail), so I think they qualify for DT
> >> ?enablement. And even if a user can't use them, it doesn't hurt to have
> >> ?them (since they are not multiplexed).
> >
> > My main concern about this is that we'll leave regulators enabled by
> > default, for a minority of users. And that minority will prevent to do
> > a proper power management when the times come since we'll have to keep
> > that behaviour forever.
>
> I think these users can add a 'fdt set /xxx/xxx status "disabled" ' .
You can't ask that from the majority of users. These users will take
debian or fedora, install it, and expect everything to work
properly. I would make the opposite argument actually. If someone is
knowledgeable enough to solder the USB pins a connector, then (s)he'll
be able to make that u-boot call.
Maxime
--
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 801 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20161205/41c61333/attachment.sig>
^ permalink raw reply
* [PATCH v2] arm64: dts: zx: add pcu_domain node for zx296718
From: Shawn Guo @ 2016-12-05 8:54 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1480925871-20855-1-git-send-email-baoyou.xie@linaro.org>
On Mon, Dec 05, 2016 at 04:17:51PM +0800, Baoyou Xie wrote:
> This patch adds the pcu_domain node, so it can be used
> by zte-soc's power domain driver.
>
> Signed-off-by: Baoyou Xie <baoyou.xie@linaro.org>
I'm fine with the patch itself, but I need to wait the driver and
bindings being accepted to apply it.
Shawn
> ---
> arch/arm64/boot/dts/zte/zx296718.dtsi | 5 +++++
> 1 file changed, 5 insertions(+)
>
> diff --git a/arch/arm64/boot/dts/zte/zx296718.dtsi b/arch/arm64/boot/dts/zte/zx296718.dtsi
> index b44d1d1..1aa0587 100644
> --- a/arch/arm64/boot/dts/zte/zx296718.dtsi
> +++ b/arch/arm64/boot/dts/zte/zx296718.dtsi
> @@ -302,6 +302,11 @@
> reg = <0x116000 0x1000>;
> };
>
> + pcu_domain: pcu at 117000 {
> + compatible = "zte,zx296718-pcu";
> + reg = <0x00117000 0x1000>;
> + };
> +
> uart0: uart at 11f000 {
> compatible = "arm,pl011", "arm,primecell";
> arm,primecell-periphid = <0x001feffe>;
> --
> 2.7.4
>
^ permalink raw reply
* [PATCH v3 7/7] ARM: dts: stm32: add stm32 general purpose timer driver in DT
From: Lee Jones @ 2016-12-05 8:54 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <14837e15-07bb-39e5-b5b6-39a7dfb9130f@kernel.org>
On Sat, 03 Dec 2016, Jonathan Cameron wrote:
> On 02/12/16 13:22, Lee Jones wrote:
> > On Fri, 02 Dec 2016, Benjamin Gaignard wrote:
> >
> >> Add general purpose timers and it sub-nodes into DT for stm32f4.
> >> Define and enable pwm1 and pwm3 for stm32f469 discovery board
> >>
> >> version 3:
> >> - use "st,stm32-timer-trigger" in DT
> >>
> >> version 2:
> >> - use parameters to describe hardware capabilities
> >> - do not use references for pwm and iio timer subnodes
> >>
> >> Signed-off-by: Benjamin Gaignard <benjamin.gaignard@st.com>
> >> ---
> >> arch/arm/boot/dts/stm32f429.dtsi | 333 +++++++++++++++++++++++++++++++++-
> >> arch/arm/boot/dts/stm32f469-disco.dts | 28 +++
> >> 2 files changed, 360 insertions(+), 1 deletion(-)
> >>
> >> diff --git a/arch/arm/boot/dts/stm32f429.dtsi b/arch/arm/boot/dts/stm32f429.dtsi
> >> index bca491d..8c50d03 100644
> >> --- a/arch/arm/boot/dts/stm32f429.dtsi
> >> +++ b/arch/arm/boot/dts/stm32f429.dtsi
> >> @@ -48,7 +48,7 @@
> >> #include "skeleton.dtsi"
> >> #include "armv7-m.dtsi"
> >> #include <dt-bindings/pinctrl/stm32f429-pinfunc.h>
> >> -
> >> +#include <dt-bindings/iio/timer/st,stm32-timer-triggers.h>
> >> / {
> >> clocks {
> >> clk_hse: clk-hse {
> >> @@ -355,6 +355,21 @@
> >> slew-rate = <2>;
> >> };
> >> };
> >> +
> >> + pwm1_pins: pwm at 1 {
> >> + pins {
> >> + pinmux = <STM32F429_PA8_FUNC_TIM1_CH1>,
> >> + <STM32F429_PB13_FUNC_TIM1_CH1N>,
> >> + <STM32F429_PB12_FUNC_TIM1_BKIN>;
> >> + };
> >> + };
> >> +
> >> + pwm3_pins: pwm at 3 {
> >> + pins {
> >> + pinmux = <STM32F429_PB4_FUNC_TIM3_CH1>,
> >> + <STM32F429_PB5_FUNC_TIM3_CH2>;
> >> + };
> >> + };
> >> };
> >>
> >> rcc: rcc at 40023810 {
> >> @@ -426,6 +441,322 @@
> >> interrupts = <80>;
> >> clocks = <&rcc 0 38>;
> >> };
> >> +
> >> + gptimer1: gptimer1 at 40010000 {
> >
> > timer at xxxxxxx
> >
> > Node names should be generic and not numbered.
> >
> > I suggest that this isn't actually a timer either. Is contains a
> > timer (and a PWM), but in it's completeness it is not a timer per
> > say.
> That's just mean ;) At least suggest an alternative?
>
> stm32-gptimerish-magic?
Perfect! ;)
I already did:
https://lkml.org/lkml/2016/11/23/131
> >> + compatible = "st,stm32-gptimer";
> >> + reg = <0x40010000 0x400>;
> >> + clocks = <&rcc 0 160>;
> >> + clock-names = "clk_int";
> >> + status = "disabled";
> >> +
> >> + pwm1 at 0 {
> >> + compatible = "st,stm32-pwm";
> >> + st,pwm-num-chan = <4>;
> >> + st,breakinput;
> >> + st,complementary;
> >> + status = "disabled";
> >> + };
> >> +
> >> + timer1 at 0 {
> >> + compatible = "st,stm32-timer-trigger";
> >> + interrupts = <27>;
> >> + st,input-triggers-names = TIM5_TRGO,
> >> + TIM2_TRGO,
> >> + TIM4_TRGO,
> >> + TIM3_TRGO;
> >
> > I'm still dubious with matching by strings.
> >
> > I'll take a look at the C code to see what the alternatives could be.
> >
> >> + st,output-triggers-names = TIM1_TRGO,
> >> + TIM1_CH1,
> >> + TIM1_CH2,
> >> + TIM1_CH3,
> >> + TIM1_CH4;
> >> + status = "disabled";
> >> + };
> >> + };
> >> +
> >> + gptimer2: gptimer2 at 40000000 {
> >> + compatible = "st,stm32-gptimer";
> >> + reg = <0x40000000 0x400>;
> >> + clocks = <&rcc 0 128>;
> >> + clock-names = "clk_int";
> >> + status = "disabled";
> >> +
> >> + pwm2 at 0 {
> >> + compatible = "st,stm32-pwm";
> >> + st,pwm-num-chan = <4>;
> >> + st,32bits-counter;
> >> + status = "disabled";
> >> + };
> >> +
> >> + timer2 at 0 {
> >> + compatible = "st,stm32-timer-trigger";
> >> + interrupts = <28>;
> >> + st,input-triggers-names = TIM1_TRGO,
> >> + TIM8_TRGO,
> >> + TIM3_TRGO,
> >> + TIM4_TRGO;
> >> + st,output-triggers-names = TIM2_TRGO,
> >> + TIM2_CH1,
> >> + TIM2_CH2,
> >> + TIM2_CH3,
> >> + TIM2_CH4;
> >> + status = "disabled";
> >> + };
> >> + };
> >> +
> >> + gptimer3: gptimer3 at 40000400 {
> >> + compatible = "st,stm32-gptimer";
> >> + reg = <0x40000400 0x400>;
> >> + clocks = <&rcc 0 129>;
> >> + clock-names = "clk_int";
> >> + status = "disabled";
> >> +
> >> + pwm3 at 0 {
> >> + compatible = "st,stm32-pwm";
> >> + st,pwm-num-chan = <4>;
> >> + status = "disabled";
> >> + };
> >> +
> >> + timer3 at 0 {
> >> + compatible = "st,stm32-timer-trigger";
> >> + interrupts = <29>;
> >> + st,input-triggers-names = TIM1_TRGO,
> >> + TIM8_TRGO,
> >> + TIM5_TRGO,
> >> + TIM4_TRGO;
> >> + st,output-triggers-names = TIM3_TRGO,
> >> + TIM3_CH1,
> >> + TIM3_CH2,
> >> + TIM3_CH3,
> >> + TIM3_CH4;
> >> + status = "disabled";
> >> + };
> >> + };
> >> +
> >> + gptimer4: gptimer4 at 40000800 {
> >> + compatible = "st,stm32-gptimer";
> >> + reg = <0x40000800 0x400>;
> >> + clocks = <&rcc 0 130>;
> >> + clock-names = "clk_int";
> >> + status = "disabled";
> >> +
> >> + pwm4 at 0 {
> >> + compatible = "st,stm32-pwm";
> >> + st,pwm-num-chan = <4>;
> >> + status = "disabled";
> >> + };
> >> +
> >> + timer4 at 0 {
> >> + compatible = "st,stm32-timer-trigger";
> >> + interrupts = <30>;
> >> + st,input-triggers-names = TIM1_TRGO,
> >> + TIM2_TRGO,
> >> + TIM3_TRGO,
> >> + TIM8_TRGO;
> >> + st,output-triggers-names = TIM4_TRGO,
> >> + TIM4_CH1,
> >> + TIM4_CH2,
> >> + TIM4_CH3,
> >> + TIM4_CH4;
> >> + status = "disabled";
> >> + };
> >> + };
> >> +
> >> + gptimer5: gptimer5 at 40000C00 {
> >> + compatible = "st,stm32-gptimer";
> >> + reg = <0x40000C00 0x400>;
> >> + clocks = <&rcc 0 131>;
> >> + clock-names = "clk_int";
> >> + status = "disabled";
> >> +
> >> + pwm5 at 0 {
> >> + compatible = "st,stm32-pwm";
> >> + st,pwm-num-chan = <4>;
> >> + st,32bits-counter;
> >> + status = "disabled";
> >> + };
> >> +
> >> + timer5 at 0 {
> >> + compatible = "st,stm32-timer-trigger";
> >> + interrupts = <50>;
> >> + st,input-triggers-names = TIM2_TRGO,
> >> + TIM3_TRGO,
> >> + TIM4_TRGO,
> >> + TIM8_TRGO;
> >> + st,output-triggers-names = TIM5_TRGO,
> >> + TIM5_CH1,
> >> + TIM5_CH2,
> >> + TIM5_CH3,
> >> + TIM5_CH4;
> >> + status = "disabled";
> >> + };
> >> + };
> >> +
> >> + gptimer6: gptimer6 at 40001000 {
> >> + compatible = "st,stm32-gptimer";
> >> + reg = <0x40001000 0x400>;
> >> + clocks = <&rcc 0 132>;
> >> + clock-names = "clk_int";
> >> + status = "disabled";
> >> +
> >> + timer6 at 0 {
> >> + compatible = "st,stm32-timer-trigger";
> >> + interrupts = <54>;
> >> + st,output-triggers-names = TIM6_TRGO;
> >> + status = "disabled";
> >> + };
> >> + };
> >> +
> >> + gptimer7: gptimer7 at 40001400 {
> >> + compatible = "st,stm32-gptimer";
> >> + reg = <0x40001400 0x400>;
> >> + clocks = <&rcc 0 133>;
> >> + clock-names = "clk_int";
> >> + status = "disabled";
> >> +
> >> + timer7 at 0 {
> >> + compatible = "st,stm32-timer-trigger";
> >> + interrupts = <55>;
> >> + st,output-triggers-names = TIM7_TRGO;
> >> + status = "disabled";
> >> + };
> >> + };
> >> +
> >> + gptimer8: gptimer8 at 40010400 {
> >> + compatible = "st,stm32-gptimer";
> >> + reg = <0x40010400 0x400>;
> >> + clocks = <&rcc 0 161>;
> >> + clock-names = "clk_int";
> >> + status = "disabled";
> >> +
> >> + pwm8 at 0 {
> >> + compatible = "st,stm32-pwm";
> >> + st,pwm-num-chan = <4>;
> >> + st,complementary;
> >> + st,breakinput;
> >> + status = "disabled";
> >> + };
> >> +
> >> + timer8 at 0 {
> >> + compatible = "st,stm32-timer-trigger";
> >> + interrupts = <46>;
> >> + st,input-triggers-names = TIM1_TRGO,
> >> + TIM2_TRGO,
> >> + TIM4_TRGO,
> >> + TIM5_TRGO;
> >> + st,output-triggers-names = TIM8_TRGO,
> >> + TIM8_CH1,
> >> + TIM8_CH2,
> >> + TIM8_CH3,
> >> + TIM8_CH4;
> >> + status = "disabled";
> >> + };
> >> + };
> >> +
> >> + gptimer9: gptimer9 at 40014000 {
> >> + compatible = "st,stm32-gptimer";
> >> + reg = <0x40014000 0x400>;
> >> + clocks = <&rcc 0 176>;
> >> + clock-names = "clk_int";
> >> + status = "disabled";
> >> +
> >> + pwm9 at 0 {
> >> + compatible = "st,stm32-pwm";
> >> + st,pwm-num-chan = <2>;
> >> + status = "disabled";
> >> + };
> >> +
> >> + timer9 at 0 {
> >> + compatible = "st,stm32-timer-trigger";
> >> + interrupts = <24>;
> >> + st,input-triggers-names = TIM2_TRGO,
> >> + TIM3_TRGO;
> >> + st,output-triggers-names = TIM9_TRGO,
> >> + TIM9_CH1,
> >> + TIM9_CH2;
> >> + status = "disabled";
> >> + };
> >> + };
> >> +
> >> + gptimer10: gptimer10 at 40014400 {
> >> + compatible = "st,stm32-gptimer";
> >> + reg = <0x40014400 0x400>;
> >> + clocks = <&rcc 0 177>;
> >> + clock-names = "clk_int";
> >> + status = "disabled";
> >> +
> >> + pwm10 at 0 {
> >> + compatible = "st,stm32-pwm";
> >> + st,pwm-num-chan = <1>;
> >> + status = "disabled";
> >> + };
> >> + };
> >> +
> >> + gptimer11: gptimer11 at 40014800 {
> >> + compatible = "st,stm32-gptimer";
> >> + reg = <0x40014800 0x400>;
> >> + clocks = <&rcc 0 178>;
> >> + clock-names = "clk_int";
> >> + status = "disabled";
> >> +
> >> + pwm11 at 0 {
> >> + compatible = "st,stm32-pwm";
> >> + st,pwm-num-chan = <1>;
> >> + status = "disabled";
> >> + };
> >> + };
> >> +
> >> + gptimer12: gptimer12 at 40001800 {
> >> + compatible = "st,stm32-gptimer";
> >> + reg = <0x40001800 0x400>;
> >> + clocks = <&rcc 0 134>;
> >> + clock-names = "clk_int";
> >> + status = "disabled";
> >> +
> >> + pwm12 at 0 {
> >> + compatible = "st,stm32-pwm";
> >> + st,pwm-num-chan = <2>;
> >> + status = "disabled";
> >> + };
> >> +
> >> + timer12 at 0 {
> >> + compatible = "st,stm32-timer-trigger";
> >> + interrupts = <43>;
> >> + st,input-triggers-names = TIM4_TRGO,
> >> + TIM5_TRGO;
> >> + st,output-triggers-names = TIM12_TRGO,
> >> + TIM12_CH1,
> >> + TIM12_CH2;
> >> + status = "disabled";
> >> + };
> >> + };
> >> +
> >> + gptimer13: gptimer13 at 40001C00 {
> >> + compatible = "st,stm32-gptimer";
> >> + reg = <0x40001C00 0x400>;
> >> + clocks = <&rcc 0 135>;
> >> + clock-names = "clk_int";
> >> + status = "disabled";
> >> +
> >> + pwm13 at 0 {
> >> + compatible = "st,stm32-pwm";
> >> + st,pwm-num-chan = <1>;
> >> + status = "disabled";
> >> + };
> >> + };
> >> +
> >> + gptimer14: gptimer14 at 40002000 {
> >> + compatible = "st,stm32-gptimer";
> >> + reg = <0x40002000 0x400>;
> >> + clocks = <&rcc 0 136>;
> >> + clock-names = "clk_int";
> >> + status = "disabled";
> >> +
> >> + pwm14 at 0 {
> >> + compatible = "st,stm32-pwm";
> >> + st,pwm-num-chan = <1>;
> >> + status = "disabled";
> >> + };
> >> + };
> >> };
> >> };
> >>
> >> diff --git a/arch/arm/boot/dts/stm32f469-disco.dts b/arch/arm/boot/dts/stm32f469-disco.dts
> >> index 8a163d7..df4ca7e 100644
> >> --- a/arch/arm/boot/dts/stm32f469-disco.dts
> >> +++ b/arch/arm/boot/dts/stm32f469-disco.dts
> >> @@ -81,3 +81,31 @@
> >> &usart3 {
> >> status = "okay";
> >> };
> >> +
> >> +&gptimer1 {
> >> + status = "okay";
> >> +
> >> + pwm1 at 0 {
> >> + pinctrl-0 = <&pwm1_pins>;
> >> + pinctrl-names = "default";
> >> + status = "okay";
> >> + };
> >> +
> >> + timer1 at 0 {
> >> + status = "okay";
> >> + };
> >> +};
> >
> > This is a much *better* format than before.
> >
> > I still don't like the '&' syntax though.
> >
> >> +&gptimer3 {
> >> + status = "okay";
> >> +
> >> + pwm3 at 0 {
> >> + pinctrl-0 = <&pwm3_pins>;
> >> + pinctrl-names = "default";
> >> + status = "okay";
> >> + };
> >> +
> >> + timer3 at 0 {
> >> + status = "okay";
> >> + };
> >> +};
> >
>
--
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org ? Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
^ permalink raw reply
* [PATCH v2 2/3] ARM: dts: sunxi: add support for Orange Pi Zero board
From: Maxime Ripard @ 2016-12-05 9:05 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <324c8820-aeea-3fad-0e02-1bdb8f675677@arm.com>
On Fri, Dec 02, 2016 at 04:10:46PM +0000, Andre Przywara wrote:
> Hi,
>
> On 02/12/16 14:32, Icenowy Zheng wrote:
> >
> >
> > 02.12.2016, 22:30, "Hans de Goede" <hdegoede@redhat.com>:
> >> Hi,
> >>
> >> On 02-12-16 15:22, Icenowy Zheng wrote:
> >>> 01.12.2016, 17:36, "Maxime Ripard" <maxime.ripard@free-electrons.com>:
> >>>> On Mon, Nov 28, 2016 at 12:29:07AM +0000, Andr? Przywara wrote:
> >>>>> > Something more interesting happened.
> >>>>> >
> >>>>> > Xunlong made a add-on board for Orange Pi Zero, which exposes the
> >>>>> > two USB Controllers exported at expansion bus as USB Type-A
> >>>>> > connectors.
> >>>>> >
> >>>>> > Also it exposes a analog A/V jack and a microphone.
> >>>>> >
> >>>>> > Should I enable {e,o}hci{2.3} in the device tree?
> >>>>>
> >>>>> Actually we should do this regardless of this extension board. The USB
> >>>>> pins are not multiplexed and are exposed on user accessible pins (just
> >>>>> not soldered, but that's a detail), so I think they qualify for DT
> >>>>> enablement. And even if a user can't use them, it doesn't hurt to have
> >>>>> them (since they are not multiplexed).
> >>>>
> >>>> My main concern about this is that we'll leave regulators enabled by
> >>>> default, for a minority of users. And that minority will prevent to do
> >>>> a proper power management when the times come since we'll have to keep
> >>>> that behaviour forever.
> >>>
> >>> I think these users can add a 'fdt set /xxx/xxx status "disabled" ' .
> >>
> >> I don't think that will be necessary I'm pretty sure these extra usb
> >> ports do not have a regulator for the Vbus, they just hook directly
> >> to the 5V rail, can someone with a schematic check ?
> >
> > We seems to have still no schematics for the add-on board.
>
> From looking at the picture of that expansion board on the Aliexpress
> page and chasing the tracks, there is clearly no voltage regulator on
> there, it's just passive components. The 5V pin from the headers is
> routed forth and back between the two layers via some vias directly to
> the 5V pins of the USB sockets.
>
> > But something is sure is that there's no any regulator-related pins
> > on the add-on pinout. There's only USB DM and DP pins.
> >
> > So the Vbus must be directly connected to +5V.
>
> So yes, it is.
>
> But I think the question is moot anyways, since we don't provide DT
> support for that add-on board at that point anyways.
> One could imagine another board, though, which has regulators switched
> by GPIOs, but that would be their problem and they would have regulators
> specified in their specific DT snippet, then.
>
> So to summarize:
> - For that specific Orange Pi Zero board which we discuss the DT for
> there is no regulator support for the additional USB ports. Thus nothing
> we could turn off to save power.
> - A user could just take these USB brackets with pin headers that are so
> common in PCs to connect additional USB ports to the back of the box.
> One just needs to re-sort the pins, which is a matter of a minute.
> - As long as we don't provide any easy way of handling DT changes, we
> should enable the USB ports for the sake of the users of either those
> brackets or the expansion board. Any more sophisticated USB expansion
> board with regulators would need to amend the DT anyway.
I disagree with this. We already have different ways of changing the
DT at runtime, and even if we didn't I'd still disagree. Once you add
that, there's simply no going back. Saying "let's enable it and we'll
figure it out later" doesn't work, and is essentially a "enable it".
So what you're suggesting is to have those regulators enabled forever,
which might be the case on that board anyway, but definitely shouldn't
be policy.
Maxime
--
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 801 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20161205/d728f143/attachment.sig>
^ permalink raw reply
* [PATCH v2 1/3] ARM: da850: fix infinite loop in clk_set_rate()
From: Bartosz Golaszewski @ 2016-12-05 9:06 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <34f9e4c4-917e-0472-72af-96fbc7e0c6db@ti.com>
2016-12-05 9:38 GMT+01:00 Sekhar Nori <nsekhar@ti.com>:
> On Friday 02 December 2016 09:08 PM, Bartosz Golaszewski wrote:
>> The aemif clock is added twice to the lookup table in da850.c. This
>> breaks the children list of pll0_sysclk3 as we're using the same list
>> links in struct clk. When calling clk_set_rate(), we get stuck in
>> propagate_rate().
>>
>> Create a separate clock for nand, inheriting the rate of the aemif
>> clock and retrieve it in the davinci_nand module.
>>
>> Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
>> ---
>> arch/arm/mach-davinci/da850.c | 7 ++++++-
>> drivers/mtd/nand/davinci_nand.c | 2 +-
>> 2 files changed, 7 insertions(+), 2 deletions(-)
>>
>> diff --git a/arch/arm/mach-davinci/da850.c b/arch/arm/mach-davinci/da850.c
>> index e770c97..1fcc986 100644
>> --- a/arch/arm/mach-davinci/da850.c
>> +++ b/arch/arm/mach-davinci/da850.c
>> @@ -367,6 +367,11 @@ static struct clk aemif_clk = {
>> .flags = ALWAYS_ENABLED,
>> };
>>
>> +static struct clk nand_clk = {
>> + .name = "nand",
>> + .parent = &aemif_clk,
>> +};
>> +
>> static struct clk usb11_clk = {
>> .name = "usb11",
>> .parent = &pll0_sysclk4,
>> @@ -537,7 +542,7 @@ static struct clk_lookup da850_clks[] = {
>> CLK("da830-mmc.0", NULL, &mmcsd0_clk),
>> CLK("da830-mmc.1", NULL, &mmcsd1_clk),
>> CLK("ti-aemif", NULL, &aemif_clk),
>> - CLK(NULL, "aemif", &aemif_clk),
>> + CLK(NULL, "nand", &nand_clk),
>
> Why use a NULL device name here?
>
>> CLK("ohci-da8xx", "usb11", &usb11_clk),
>> CLK("musb-da8xx", "usb20", &usb20_clk),
>> CLK("spi_davinci.0", NULL, &spi0_clk),
>> diff --git a/drivers/mtd/nand/davinci_nand.c b/drivers/mtd/nand/davinci_nand.c
>> index 27fa8b8..5857d06 100644
>> --- a/drivers/mtd/nand/davinci_nand.c
>> +++ b/drivers/mtd/nand/davinci_nand.c
>> @@ -694,7 +694,7 @@ static int nand_davinci_probe(struct platform_device *pdev)
>>
>> ret = -EINVAL;
>>
>> - info->clk = devm_clk_get(&pdev->dev, "aemif");
>> + info->clk = devm_clk_get(&pdev->dev, "nand");
>
> This driver is used by keystone devices too. So just changing the
> connection id will likely break them. Why do you need to change the
> connection id?
>
> Thanks,
> Sekhar
Thanks, I didn't know it.
I thought it would make the purpose of the clock more obvious. I'll
change it back to "aemif".
Best regards,
Bartosz Golaszewski
^ permalink raw reply
* [PATCH v2 3/3] ARM: da850: fix da850_set_pll0rate()
From: Bartosz Golaszewski @ 2016-12-05 9:07 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <130825f1-5c8f-f6bc-1f27-929ff591a9c3@ti.com>
2016-12-05 9:45 GMT+01:00 Sekhar Nori <nsekhar@ti.com>:
> On Friday 02 December 2016 09:08 PM, Bartosz Golaszewski wrote:
>> This function is broken - its second argument is an index to the freq
>> table, not the requested clock rate in Hz. It leads to an oops when
>> called from clk_set_rate() since this argument isn't bounds checked
>> either.
>>
>> Fix it by iterating over the array of supported frequencies and
>> selecting a one that matches or returning -EINVAL for unsupported
>> rates.
>>
>> Also: update the davinci cpufreq driver. It's the only user of this
>> clock and currently it passes the cpufreq table index to
>> clk_set_rate(), which is confusing. Make it pass the requested clock
>> rate in Hz.
>>
>> Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
>> ---
>> arch/arm/mach-davinci/da850.c | 22 ++++++++++++++++++----
>> drivers/cpufreq/davinci-cpufreq.c | 2 +-
>> 2 files changed, 19 insertions(+), 5 deletions(-)
>>
>> diff --git a/arch/arm/mach-davinci/da850.c b/arch/arm/mach-davinci/da850.c
>> index a55101c..92e3303 100644
>> --- a/arch/arm/mach-davinci/da850.c
>> +++ b/arch/arm/mach-davinci/da850.c
>> @@ -1179,14 +1179,28 @@ static int da850_set_armrate(struct clk *clk, unsigned long index)
>> return clk_set_rate(pllclk, index);
>> }
>>
>> -static int da850_set_pll0rate(struct clk *clk, unsigned long index)
>> +static int da850_set_pll0rate(struct clk *clk, unsigned long rate)
>> {
>> - unsigned int prediv, mult, postdiv;
>> - struct da850_opp *opp;
>> struct pll_data *pll = clk->pll_data;
>> + struct cpufreq_frequency_table *freq;
>> + unsigned int prediv, mult, postdiv;
>> + struct da850_opp *opp = NULL;
>> int ret;
>>
>> - opp = (struct da850_opp *) cpufreq_info.freq_table[index].driver_data;
>> + for (freq = da850_freq_table;
>> + freq->frequency != CPUFREQ_TABLE_END; freq++) {
>> + /* requested_rate is in Hz, freq->frequency is in KHz */
>> + unsigned long freq_rate = freq->frequency * 1000;
>
> A small optimization here. Instead of multiplying potentially every
> frequency in the table by 1000, you could divide the incoming rate down
> to KHz. This will also avoid the need for 'freq_rate'. Should have
> noticed this earlier. Sorry about that.
>
> Thanks,
> Sekhar
I thought about it, but figured the multiplication would be safer. I
will change it if you prefer this version.
Best regards,
Bartosz Golaszewski
^ permalink raw reply
* [linux-sunxi] [PATCH v3 -next 2/2] ARM: dts: sunxi: add support for Orange Pi Zero board
From: Maxime Ripard @ 2016-12-05 9:12 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161203162455.OlDm27ch@smtp3m.mail.yandex.net>
Hi Icenowy,
On Sat, Dec 03, 2016 at 09:24:19PM +0800, Icenowy Zheng wrote:
> <p dir="ltr"><br>
> 2016年12月3日 下午5:43于 Jernej Skrabec <jernej.skrabec at gmail.com>写道:<br>
> ><br>
> > Hi,<br>
> ><br>
> > Dne petek, 02. december 2016 17.42.04 UTC+1 je oseba Chen-Yu Tsai napisala:<br>
> >><br>
> >> Hi, <br>
> >><br>
> >> On Fri, Dec 2, 2016 at 11:05 PM, Icenowy Zheng <ice... at aosc.xyz> wrote: <br>
> >> > Orange Pi Zero is a board that came with the new Allwinner H2+ SoC and a <br>
> >> > SDIO Wi-Fi chip by Allwinner (XR819). <br>
> >> > <br>
> >> > Add a device tree file for it. <br>
> >> > <br>
> >> > Signed-off-by: Icenowy Zheng <ice... at aosc.xyz> <br>
Please make sure to disable the HTML replies, this is what your mail
looks like on a !HTML MUA :)
Maxime
--
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 801 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20161205/8617213b/attachment.sig>
^ permalink raw reply
* [PATCH v3 0/4] mm: fix the "counter.sh" failure for libhugetlbfs
From: Huang Shijie @ 2016-12-05 9:17 UTC (permalink / raw)
To: linux-arm-kernel
(1) Background
For the arm64, the hugetlb page size can be 32M (PMD + Contiguous bit).
In the 4K page environment, the max page order is 10 (max_order - 1),
so 32M page is the gigantic page.
The arm64 MMU supports a Contiguous bit which is a hint that the TTE
is one of a set of contiguous entries which can be cached in a single
TLB entry. Please refer to the arm64v8 mannul :
DDI0487A_f_armv8_arm.pdf (in page D4-1811)
(2) The bug
After I tested the libhugetlbfs, I found the test case "counter.sh"
will fail with the gigantic page (32M page in arm64 board).
The counter.sh is just a wrapper for counter.c.
You can find them in:
https://github.com/libhugetlbfs/libhugetlbfs/blob/master/tests/counters.c
https://github.com/libhugetlbfs/libhugetlbfs/blob/master/tests/counters.sh
The error log shows below:
----------------------------------------------------------
...........................................
LD_PRELOAD=libhugetlbfs.so shmoverride_unlinked (32M: 64): PASS
LD_PRELOAD=libhugetlbfs.so HUGETLB_SHM=yes shmoverride_unlinked (32M: 64): PASS
quota.sh (32M: 64): PASS
counters.sh (32M: 64): FAIL mmap failed: Invalid argument
********** TEST SUMMARY
* 32M
* 32-bit 64-bit
* Total testcases: 0 87
* Skipped: 0 0
* PASS: 0 86
* FAIL: 0 1
* Killed by signal: 0 0
* Bad configuration: 0 0
* Expected FAIL: 0 0
* Unexpected PASS: 0 0
* Strange test result: 0 0
**********
----------------------------------------------------------
The failure is caused by:
1) kernel fails to allocate a gigantic page for the surplus case.
And the gather_surplus_pages() will return NULL in the end.
2) The condition checks for some functions are wrong:
return_unused_surplus_pages()
nr_overcommit_hugepages_store()
hugetlb_overcommit_handler()
This patch set adds support for gigantic surplus hugetlb pages,
allowing the counter.sh unit test to pass.
Test this patch set with Juno-r1 board.
v2 -- > v3:
1.) In patch 2, change argument "no_init" to "do_prep"
2.) In patch 3, also change alloc_fresh_huge_page().
In the v2, this patch only changes the alloc_fresh_gigantic_page().
3.) Merge old patch #4,#5 into the last one.
4.) Follow Babka's suggestion, do the NULL check for @mask.
5.) others.
v1 -- > v2:
1.) fix the compiler error in X86.
2.) add new patches for NUMA.
The patch #2 ~ #5 are new patches.
Huang Shijie (4):
mm: hugetlb: rename some allocation functions
mm: hugetlb: add a new parameter for some functions
mm: hugetlb: change the return type for some functions
mm: hugetlb: support gigantic surplus pages
include/linux/mempolicy.h | 8 +++
mm/hugetlb.c | 146 +++++++++++++++++++++++++++++++++++-----------
mm/mempolicy.c | 44 ++++++++++++++
3 files changed, 163 insertions(+), 35 deletions(-)
--
2.5.5
^ permalink raw reply
* [PATCH v3 1/4] mm: hugetlb: rename some allocation functions
From: Huang Shijie @ 2016-12-05 9:17 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1480929431-22348-1-git-send-email-shijie.huang@arm.com>
After a future patch, the __alloc_buddy_huge_page() will not necessarily
use the buddy allocator.
So this patch removes the "buddy" from these functions:
__alloc_buddy_huge_page -> __alloc_huge_page
__alloc_buddy_huge_page_no_mpol -> __alloc_huge_page_no_mpol
__alloc_buddy_huge_page_with_mpol -> __alloc_huge_page_with_mpol
This patch also adds the description for alloc_gigantic_page().
This patch makes preparation for the later patch.
Signed-off-by: Huang Shijie <shijie.huang@arm.com>
---
mm/hugetlb.c | 30 ++++++++++++++++++++----------
1 file changed, 20 insertions(+), 10 deletions(-)
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index 5f228cd..5f4213d 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -1089,6 +1089,12 @@ static bool zone_spans_last_pfn(const struct zone *zone,
return zone_spans_pfn(zone, last_pfn);
}
+/*
+ * Allocate a gigantic page from @nid node.
+ *
+ * Scan the zones of @nid node, and try to allocate a number of contiguous
+ * pages (1 << order).
+ */
static struct page *alloc_gigantic_page(int nid, unsigned int order)
{
unsigned long nr_pages = 1 << order;
@@ -1157,6 +1163,10 @@ static int alloc_fresh_gigantic_page(struct hstate *h,
static inline bool gigantic_page_supported(void) { return true; }
#else
+static inline struct page *alloc_gigantic_page(int nid, unsigned int order)
+{
+ return NULL;
+}
static inline bool gigantic_page_supported(void) { return false; }
static inline void free_gigantic_page(struct page *page, unsigned int order) { }
static inline void destroy_compound_gigantic_page(struct page *page,
@@ -1568,7 +1578,7 @@ static struct page *__hugetlb_alloc_buddy_huge_page(struct hstate *h,
* For (2), we ignore 'vma' and 'addr' and use 'nid' exclusively. This
* implies that memory policies will not be taken in to account.
*/
-static struct page *__alloc_buddy_huge_page(struct hstate *h,
+static struct page *__alloc_huge_page(struct hstate *h,
struct vm_area_struct *vma, unsigned long addr, int nid)
{
struct page *page;
@@ -1649,21 +1659,21 @@ static struct page *__alloc_buddy_huge_page(struct hstate *h,
* anywhere.
*/
static
-struct page *__alloc_buddy_huge_page_no_mpol(struct hstate *h, int nid)
+struct page *__alloc_huge_page_no_mpol(struct hstate *h, int nid)
{
unsigned long addr = -1;
- return __alloc_buddy_huge_page(h, NULL, addr, nid);
+ return __alloc_huge_page(h, NULL, addr, nid);
}
/*
* Use the VMA's mpolicy to allocate a huge page from the buddy.
*/
static
-struct page *__alloc_buddy_huge_page_with_mpol(struct hstate *h,
+struct page *__alloc_huge_page_with_mpol(struct hstate *h,
struct vm_area_struct *vma, unsigned long addr)
{
- return __alloc_buddy_huge_page(h, vma, addr, NUMA_NO_NODE);
+ return __alloc_huge_page(h, vma, addr, NUMA_NO_NODE);
}
/*
@@ -1681,7 +1691,7 @@ struct page *alloc_huge_page_node(struct hstate *h, int nid)
spin_unlock(&hugetlb_lock);
if (!page)
- page = __alloc_buddy_huge_page_no_mpol(h, nid);
+ page = __alloc_huge_page_no_mpol(h, nid);
return page;
}
@@ -1711,7 +1721,7 @@ static int gather_surplus_pages(struct hstate *h, int delta)
retry:
spin_unlock(&hugetlb_lock);
for (i = 0; i < needed; i++) {
- page = __alloc_buddy_huge_page_no_mpol(h, NUMA_NO_NODE);
+ page = __alloc_huge_page_no_mpol(h, NUMA_NO_NODE);
if (!page) {
alloc_ok = false;
break;
@@ -2027,7 +2037,7 @@ struct page *alloc_huge_page(struct vm_area_struct *vma,
page = dequeue_huge_page_vma(h, vma, addr, avoid_reserve, gbl_chg);
if (!page) {
spin_unlock(&hugetlb_lock);
- page = __alloc_buddy_huge_page_with_mpol(h, vma, addr);
+ page = __alloc_huge_page_with_mpol(h, vma, addr);
if (!page)
goto out_uncharge_cgroup;
if (!avoid_reserve && vma_has_reserves(vma, gbl_chg)) {
@@ -2285,7 +2295,7 @@ static unsigned long set_max_huge_pages(struct hstate *h, unsigned long count,
* First take pages out of surplus state. Then make up the
* remaining difference by allocating fresh huge pages.
*
- * We might race with __alloc_buddy_huge_page() here and be unable
+ * We might race with __alloc_huge_page() here and be unable
* to convert a surplus huge page to a normal huge page. That is
* not critical, though, it just means the overall size of the
* pool might be one hugepage larger than it needs to be, but
@@ -2331,7 +2341,7 @@ static unsigned long set_max_huge_pages(struct hstate *h, unsigned long count,
* By placing pages into the surplus state independent of the
* overcommit value, we are allowing the surplus pool size to
* exceed overcommit. There are few sane options here. Since
- * __alloc_buddy_huge_page() is checking the global counter,
+ * __alloc_huge_page() is checking the global counter,
* though, we'll note that we're not allowed to exceed surplus
* and won't grow the pool anywhere else. Not until one of the
* sysctls are changed, or the surplus pages go out of use.
--
2.5.5
^ permalink raw reply related
* [PATCH v3 2/4] mm: hugetlb: add a new parameter for some functions
From: Huang Shijie @ 2016-12-05 9:17 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1480929431-22348-1-git-send-email-shijie.huang@arm.com>
This patch adds a new parameter, the "do_prep", for these functions:
alloc_fresh_gigantic_page_node()
alloc_fresh_gigantic_page()
The prep_new_huge_page() does some initialization for the new page.
But sometime, we do not need it to do so, such as in the surplus case
in later patch.
With this parameter, the prep_new_huge_page() can be called by needed:
If the "do_prep" is true, calls the prep_new_huge_page() in
the alloc_fresh_gigantic_page_node();
This patch makes preparation for the later patches.
Signed-off-by: Huang Shijie <shijie.huang@arm.com>
---
mm/hugetlb.c | 14 ++++++++------
1 file changed, 8 insertions(+), 6 deletions(-)
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index 5f4213d..b7c73a1 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -1133,27 +1133,29 @@ static struct page *alloc_gigantic_page(int nid, unsigned int order)
static void prep_new_huge_page(struct hstate *h, struct page *page, int nid);
static void prep_compound_gigantic_page(struct page *page, unsigned int order);
-static struct page *alloc_fresh_gigantic_page_node(struct hstate *h, int nid)
+static struct page *alloc_fresh_gigantic_page_node(struct hstate *h,
+ int nid, bool do_prep)
{
struct page *page;
page = alloc_gigantic_page(nid, huge_page_order(h));
if (page) {
prep_compound_gigantic_page(page, huge_page_order(h));
- prep_new_huge_page(h, page, nid);
+ if (do_prep)
+ prep_new_huge_page(h, page, nid);
}
return page;
}
static int alloc_fresh_gigantic_page(struct hstate *h,
- nodemask_t *nodes_allowed)
+ nodemask_t *nodes_allowed, bool do_prep)
{
struct page *page = NULL;
int nr_nodes, node;
for_each_node_mask_to_alloc(h, nr_nodes, node, nodes_allowed) {
- page = alloc_fresh_gigantic_page_node(h, node);
+ page = alloc_fresh_gigantic_page_node(h, node, do_prep);
if (page)
return 1;
}
@@ -1172,7 +1174,7 @@ static inline void free_gigantic_page(struct page *page, unsigned int order) { }
static inline void destroy_compound_gigantic_page(struct page *page,
unsigned int order) { }
static inline int alloc_fresh_gigantic_page(struct hstate *h,
- nodemask_t *nodes_allowed) { return 0; }
+ nodemask_t *nodes_allowed, bool do_prep) { return 0; }
#endif
static void update_and_free_page(struct hstate *h, struct page *page)
@@ -2319,7 +2321,7 @@ static unsigned long set_max_huge_pages(struct hstate *h, unsigned long count,
cond_resched();
if (hstate_is_gigantic(h))
- ret = alloc_fresh_gigantic_page(h, nodes_allowed);
+ ret = alloc_fresh_gigantic_page(h, nodes_allowed, true);
else
ret = alloc_fresh_huge_page(h, nodes_allowed);
spin_lock(&hugetlb_lock);
--
2.5.5
^ permalink raw reply related
* [PATCH v3 3/4] mm: hugetlb: change the return type for some functions
From: Huang Shijie @ 2016-12-05 9:17 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1480929431-22348-1-git-send-email-shijie.huang@arm.com>
This patch changes the return type to "struct page*" for
alloc_fresh_gigantic_page()/alloc_fresh_huge_page().
This patch makes preparation for later patch.
Signed-off-by: Huang Shijie <shijie.huang@arm.com>
---
mm/hugetlb.c | 29 ++++++++++++++---------------
1 file changed, 14 insertions(+), 15 deletions(-)
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index b7c73a1..1395bef 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -1148,7 +1148,7 @@ static struct page *alloc_fresh_gigantic_page_node(struct hstate *h,
return page;
}
-static int alloc_fresh_gigantic_page(struct hstate *h,
+static struct page *alloc_fresh_gigantic_page(struct hstate *h,
nodemask_t *nodes_allowed, bool do_prep)
{
struct page *page = NULL;
@@ -1157,10 +1157,10 @@ static int alloc_fresh_gigantic_page(struct hstate *h,
for_each_node_mask_to_alloc(h, nr_nodes, node, nodes_allowed) {
page = alloc_fresh_gigantic_page_node(h, node, do_prep);
if (page)
- return 1;
+ return page;
}
- return 0;
+ return NULL;
}
static inline bool gigantic_page_supported(void) { return true; }
@@ -1173,8 +1173,8 @@ static inline bool gigantic_page_supported(void) { return false; }
static inline void free_gigantic_page(struct page *page, unsigned int order) { }
static inline void destroy_compound_gigantic_page(struct page *page,
unsigned int order) { }
-static inline int alloc_fresh_gigantic_page(struct hstate *h,
- nodemask_t *nodes_allowed, bool do_prep) { return 0; }
+static inline struct page *alloc_fresh_gigantic_page(struct hstate *h,
+ nodemask_t *nodes_allowed, bool do_prep) { return NULL; }
#endif
static void update_and_free_page(struct hstate *h, struct page *page)
@@ -1387,26 +1387,24 @@ static struct page *alloc_fresh_huge_page_node(struct hstate *h, int nid)
return page;
}
-static int alloc_fresh_huge_page(struct hstate *h, nodemask_t *nodes_allowed)
+static struct page *alloc_fresh_huge_page(struct hstate *h,
+ nodemask_t *nodes_allowed)
{
- struct page *page;
+ struct page *page = NULL;
int nr_nodes, node;
- int ret = 0;
for_each_node_mask_to_alloc(h, nr_nodes, node, nodes_allowed) {
page = alloc_fresh_huge_page_node(h, node);
- if (page) {
- ret = 1;
+ if (page)
break;
- }
}
- if (ret)
+ if (page)
count_vm_event(HTLB_BUDDY_PGALLOC);
else
count_vm_event(HTLB_BUDDY_PGALLOC_FAIL);
- return ret;
+ return page;
}
/*
@@ -2321,9 +2319,10 @@ static unsigned long set_max_huge_pages(struct hstate *h, unsigned long count,
cond_resched();
if (hstate_is_gigantic(h))
- ret = alloc_fresh_gigantic_page(h, nodes_allowed, true);
+ ret = !!alloc_fresh_gigantic_page(h, nodes_allowed,
+ true);
else
- ret = alloc_fresh_huge_page(h, nodes_allowed);
+ ret = !!alloc_fresh_huge_page(h, nodes_allowed);
spin_lock(&hugetlb_lock);
if (!ret)
goto out;
--
2.5.5
^ permalink raw reply related
* [PATCH v3 4/4] mm: hugetlb: support gigantic surplus pages
From: Huang Shijie @ 2016-12-05 9:17 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1480929431-22348-1-git-send-email-shijie.huang@arm.com>
When testing the gigantic page whose order is too large for the buddy
allocator, the libhugetlbfs test case "counter.sh" will fail.
The counter.sh is just a wrapper for counter.c, you can find them in:
https://github.com/libhugetlbfs/libhugetlbfs/blob/master/tests/counters.c
https://github.com/libhugetlbfs/libhugetlbfs/blob/master/tests/counters.sh
Please see the error log below:
............................................
........
quota.sh (32M: 64): PASS
counters.sh (32M: 64): FAIL mmap failed: Invalid argument
********** TEST SUMMARY
* 32M
* 32-bit 64-bit
* Total testcases: 0 87
* Skipped: 0 0
* PASS: 0 86
* FAIL: 0 1
* Killed by signal: 0 0
* Bad configuration: 0 0
* Expected FAIL: 0 0
* Unexpected PASS: 0 0
* Strange test result: 0 0
**********
............................................
The failure is caused by:
1) kernel fails to allocate a gigantic page for the surplus case.
And the gather_surplus_pages() will return NULL in the end.
2) The condition checks for "over-commit" is wrong.
This patch does following things:
1) This patch changes the condition checks for:
return_unused_surplus_pages()
nr_overcommit_hugepages_store()
hugetlb_overcommit_handler()
2) This patch introduces two helper functions:
huge_nodemask() and __hugetlb_alloc_gigantic_page().
Please see the descritions in the two functions.
3) This patch uses __hugetlb_alloc_gigantic_page() to allocate the
gigantic page in the __alloc_huge_page(). After this patch,
gather_surplus_pages() can return a gigantic page for the surplus case.
After this patch, the counter.sh can pass for the gigantic page.
Signed-off-by: Huang Shijie <shijie.huang@arm.com>
---
include/linux/mempolicy.h | 8 +++++
mm/hugetlb.c | 77 +++++++++++++++++++++++++++++++++++++++++++----
mm/mempolicy.c | 44 +++++++++++++++++++++++++++
3 files changed, 123 insertions(+), 6 deletions(-)
diff --git a/include/linux/mempolicy.h b/include/linux/mempolicy.h
index 5f4d828..6539fbb 100644
--- a/include/linux/mempolicy.h
+++ b/include/linux/mempolicy.h
@@ -146,6 +146,8 @@ extern void mpol_rebind_task(struct task_struct *tsk, const nodemask_t *new,
enum mpol_rebind_step step);
extern void mpol_rebind_mm(struct mm_struct *mm, nodemask_t *new);
+extern bool huge_nodemask(struct vm_area_struct *vma,
+ unsigned long addr, nodemask_t *mask);
extern struct zonelist *huge_zonelist(struct vm_area_struct *vma,
unsigned long addr, gfp_t gfp_flags,
struct mempolicy **mpol, nodemask_t **nodemask);
@@ -269,6 +271,12 @@ static inline void mpol_rebind_mm(struct mm_struct *mm, nodemask_t *new)
{
}
+static inline bool huge_nodemask(struct vm_area_struct *vma,
+ unsigned long addr, nodemask_t *mask)
+{
+ return false;
+}
+
static inline struct zonelist *huge_zonelist(struct vm_area_struct *vma,
unsigned long addr, gfp_t gfp_flags,
struct mempolicy **mpol, nodemask_t **nodemask)
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index 1395bef..04440b8 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -1506,6 +1506,69 @@ int dissolve_free_huge_pages(unsigned long start_pfn, unsigned long end_pfn)
/*
* There are 3 ways this can get called:
+ *
+ * 1. When the NUMA is not enabled, use alloc_gigantic_page() to get
+ * the gigantic page.
+ *
+ * 2. The NUMA is enabled, but the vma is NULL.
+ * Initialize the @mask, and use alloc_fresh_gigantic_page() to get
+ * the gigantic page.
+ *
+ * 3. The NUMA is enabled, and the vma is valid.
+ * Use the @vma's memory policy.
+ * Get @mask by huge_nodemask(), and use alloc_fresh_gigantic_page()
+ * to get the gigantic page.
+ */
+static struct page *__hugetlb_alloc_gigantic_page(struct hstate *h,
+ struct vm_area_struct *vma, unsigned long addr, int nid)
+{
+ NODEMASK_ALLOC(nodemask_t, mask, GFP_KERNEL | __GFP_NORETRY);
+ struct page *page = NULL;
+
+ /* Not NUMA */
+ if (!IS_ENABLED(CONFIG_NUMA)) {
+ if (nid == NUMA_NO_NODE)
+ nid = numa_mem_id();
+
+ page = alloc_gigantic_page(nid, huge_page_order(h));
+ if (page)
+ prep_compound_gigantic_page(page, huge_page_order(h));
+ goto got_page;
+ }
+
+ /* NUMA && !vma */
+ if (!vma) {
+ /* First, check the mask */
+ if (!mask) {
+ mask = &node_states[N_MEMORY];
+ } else {
+ if (nid == NUMA_NO_NODE) {
+ if (!init_nodemask_of_mempolicy(mask)) {
+ NODEMASK_FREE(mask);
+ mask = &node_states[N_MEMORY];
+ }
+ } else {
+ init_nodemask_of_node(mask, nid);
+ }
+ }
+
+ page = alloc_fresh_gigantic_page(h, mask, false);
+ goto got_page;
+ }
+
+ /* NUMA && vma */
+ if (mask && huge_nodemask(vma, addr, mask))
+ page = alloc_fresh_gigantic_page(h, mask, false);
+
+got_page:
+ if (mask != &node_states[N_MEMORY])
+ NODEMASK_FREE(mask);
+
+ return page;
+}
+
+/*
+ * There are 3 ways this can get called:
* 1. With vma+addr: we use the VMA's memory policy
* 2. With !vma, but nid=NUMA_NO_NODE: We try to allocate a huge
* page from any node, and let the buddy allocator itself figure
@@ -1584,7 +1647,7 @@ static struct page *__alloc_huge_page(struct hstate *h,
struct page *page;
unsigned int r_nid;
- if (hstate_is_gigantic(h))
+ if (hstate_is_gigantic(h) && !gigantic_page_supported())
return NULL;
/*
@@ -1629,7 +1692,10 @@ static struct page *__alloc_huge_page(struct hstate *h,
}
spin_unlock(&hugetlb_lock);
- page = __hugetlb_alloc_buddy_huge_page(h, vma, addr, nid);
+ if (hstate_is_gigantic(h))
+ page = __hugetlb_alloc_gigantic_page(h, vma, addr, nid);
+ else
+ page = __hugetlb_alloc_buddy_huge_page(h, vma, addr, nid);
spin_lock(&hugetlb_lock);
if (page) {
@@ -1796,8 +1862,7 @@ static void return_unused_surplus_pages(struct hstate *h,
/* Uncommit the reservation */
h->resv_huge_pages -= unused_resv_pages;
- /* Cannot return gigantic pages currently */
- if (hstate_is_gigantic(h))
+ if (hstate_is_gigantic(h) && !gigantic_page_supported())
return;
nr_pages = min(unused_resv_pages, h->surplus_huge_pages);
@@ -2514,7 +2579,7 @@ static ssize_t nr_overcommit_hugepages_store(struct kobject *kobj,
unsigned long input;
struct hstate *h = kobj_to_hstate(kobj, NULL);
- if (hstate_is_gigantic(h))
+ if (hstate_is_gigantic(h) && !gigantic_page_supported())
return -EINVAL;
err = kstrtoul(buf, 10, &input);
@@ -2966,7 +3031,7 @@ int hugetlb_overcommit_handler(struct ctl_table *table, int write,
tmp = h->nr_overcommit_huge_pages;
- if (write && hstate_is_gigantic(h))
+ if (write && hstate_is_gigantic(h) && !gigantic_page_supported())
return -EINVAL;
table->data = &tmp;
diff --git a/mm/mempolicy.c b/mm/mempolicy.c
index 6d3639e..3550a29 100644
--- a/mm/mempolicy.c
+++ b/mm/mempolicy.c
@@ -1800,6 +1800,50 @@ static inline unsigned interleave_nid(struct mempolicy *pol,
#ifdef CONFIG_HUGETLBFS
/*
+ * huge_nodemask(@vma, @addr, @mask)
+ * @vma: virtual memory area whose policy is sought
+ * @addr: address in @vma
+ * @mask: should be a valid nodemask pointer, not NULL
+ *
+ * Return true if we can succeed in extracting the policy nodemask
+ * for 'bind' or 'interleave' policy into the argument @mask, or
+ * initializing the argument @mask to contain the single node for
+ * 'preferred' or 'local' policy.
+ */
+bool huge_nodemask(struct vm_area_struct *vma, unsigned long addr,
+ nodemask_t *mask)
+{
+ struct mempolicy *mpol;
+ bool ret = true;
+ int nid;
+
+ mpol = get_vma_policy(vma, addr);
+
+ switch (mpol->mode) {
+ case MPOL_PREFERRED:
+ if (mpol->flags & MPOL_F_LOCAL)
+ nid = numa_node_id();
+ else
+ nid = mpol->v.preferred_node;
+ init_nodemask_of_node(mask, nid);
+ break;
+
+ case MPOL_BIND:
+ /* Fall through */
+ case MPOL_INTERLEAVE:
+ *mask = mpol->v.nodes;
+ break;
+
+ default:
+ ret = false;
+ break;
+ }
+ mpol_cond_put(mpol);
+
+ return ret;
+}
+
+/*
* huge_zonelist(@vma, @addr, @gfp_flags, @mpol)
* @vma: virtual memory area whose policy is sought
* @addr: address in @vma for shared policy lookup and interleave policy
--
2.5.5
^ permalink raw reply related
* [crypto] [marvell-cesa] Possible regression after Linux 4.7
From: Romain Perier @ 2016-12-05 9:19 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <4573998d-6c5b-03e4-e1fa-7516d5a9e276@free-electrons.com>
Hello,
The issue is reproducible in STD mode too. We have found fixes.
Could you test these patches in STD mode please ?
cover letter:
https://www.mail-archive.com/linux-crypto at vger.kernel.org/msg22143.html
1/2: https://www.mail-archive.com/linux-crypto at vger.kernel.org/msg22142.html
2/2: https://www.mail-archive.com/linux-crypto at vger.kernel.org/msg22141.html
If you want to turn off DMA, open drivers/crypto/marvell/cesa.c and in
armada_xp_caps, change .has_tdma to false. (assuming that you test on a
armada 38x).
We're still investigating for regressions in DMA mode.
Have a nice day,
Romain
--
Romain Perier, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
^ permalink raw reply
* [PATCH v3 -next 1/2] ARM: sunxi: add support for H2+ SoC
From: Maxime Ripard @ 2016-12-05 9:19 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161202150513.34691-1-icenowy@aosc.xyz>
On Fri, Dec 02, 2016 at 11:05:12PM +0800, Icenowy Zheng wrote:
> Allwinner H2+ is a quad-core Cortex-A7 SoC.
>
> It is very like H3, that they share the same SoC ID (0x1680), and H3
> memory maps as well as drivers works well on the SoC.
>
> Signed-off-by: Icenowy Zheng <icenowy@aosc.xyz>
Fixed the alphabetical order in the bindings doc, and applied.
Thanks!
Maxime
--
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 801 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20161205/364dbd55/attachment.sig>
^ permalink raw reply
* [PATCH] ARM: dts: sunxi: Add num-cs for A20 spi nodes
From: Maxime Ripard @ 2016-12-05 9:28 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161201112414.62f9b351186115f62c8998a9@bidouilliste.com>
On Thu, Dec 01, 2016 at 11:24:14AM +0100, Emmanuel Vadot wrote:
> > > > > If num-cs isn't present nothing prevent to start a transfer
> > > > > with a non-valid CS pin, resulting in an error. num-cs are
> > > > > default property especially made for this and a SPI driver
> > > > > should try to get the property at probe/attach time.
> > > >
> > > > Yes, but as far as I know, our driver doesn't. I'm all in for
> > > > having support for that in our driver, but without it, that
> > > > patch is kind of useless.
> > >
> > > Yes the Linux driver doesn't use it but my upcoming one for FreeBSD
> > > uses it. So it is not useless for downstream user of DTS.
> >
> > Ah, I didn't know this was for FreeBSD. So you started to use our DTs,
> > or do you have some modifications to it? How does that work?
>
> Yes we use the DTS from linux from quite some times now. We're
> currently synced with 4.7-ish. We either use them directly or
> modify them according to our needs and driver support.
Do you have a link to those modifications?
Thanks,
Maxime
--
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 801 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20161205/7f666e1b/attachment-0001.sig>
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox