acpi= [HW,ACPI,X86,ARM64,RISCV64,EARLY]
Advanced Configuration and Power Interface
Format: { force | on | off | strict | noirq | rsdt |
- copy_dsdt }
+ copy_dsdt | nospcr }
force -- enable ACPI if default was off
on -- enable ACPI but allow fallback to DT [arm64,riscv64]
off -- disable ACPI if default was on
strictly ACPI specification compliant.
rsdt -- prefer RSDT over (default) XSDT
copy_dsdt -- copy DSDT to memory
- For ARM64 and RISCV64, ONLY "acpi=off", "acpi=on" or
- "acpi=force" are available
+ nospcr -- disable console in ACPI SPCR table as
+ default _serial_ console on ARM64
+ For ARM64, ONLY "acpi=off", "acpi=on", "acpi=force" or
+ "acpi=nospcr" are available
+ For RISCV64, ONLY "acpi=off", "acpi=on" or "acpi=force"
+ are available
See also Documentation/power/runtime_pm.rst, pci=noacpi
Documentation/networking/netconsole.rst for an
alternative.
+ <DEVNAME>:<n>.<n>[,options]
+ Use the specified serial port on the serial core bus.
+ The addressing uses DEVNAME of the physical serial port
+ device, followed by the serial core controller instance,
+ and the serial port instance. The options are the same
+ as documented for the ttyS addressing above.
+
+ The mapping of the serial ports to the tty instances
+ can be viewed with:
+
+ $ ls -d /sys/bus/serial-base/devices/*:*.*/tty/*
+ /sys/bus/serial-base/devices/00:04:0.0/tty/ttyS0
+
+ In the above example, the console can be addressed with
+ console=00:04:0.0. Note that a console addressed this
+ way will only get added when the related device driver
+ is ready. The use of an earlycon parameter in addition to
+ the console may be desired for console output early on.
+
uart[8250],io,<addr>[,options]
uart[8250],mmio,<addr>[,options]
uart[8250],mmio16,<addr>[,options]
you are really sure that your UEFI does sane gc and
fulfills the spec otherwise your board may brick.
- efi_fake_mem= nn[KMG]@ss[KMG]:aa[,nn[KMG]@ss[KMG]:aa,..] [EFI,X86,EARLY]
- Add arbitrary attribute to specific memory range by
- updating original EFI memory map.
- Region of memory which aa attribute is added to is
- from ss to ss+nn.
-
- If efi_fake_mem=2G@4G:0x10000,2G@0x10a0000000:0x10000
- is specified, EFI_MEMORY_MORE_RELIABLE(0x10000)
- attribute is added to range 0x100000000-0x180000000 and
- 0x10a0000000-0x1120000000.
-
- If efi_fake_mem=8G@9G:0x40000 is specified, the
- EFI_MEMORY_SP(0x40000) attribute is added to
- range 0x240000000-0x43fffffff.
-
- Using this parameter you can do debugging of EFI memmap
- related features. For example, you can do debugging of
- Address Range Mirroring feature even if your box
- doesn't support it, or mark specific memory as
- "soft reserved".
-
efivar_ssdt= [EFI; X86] Name of an EFI variable that contains an SSDT
that is to be dynamically loaded by Linux. If there are
multiple variables with the same name but with different
for 64-bit NUMA, off otherwise.
Format: 0 | 1 (for off | on)
- hcl= [IA-64] SGI's Hardware Graph compatibility layer
-
hd= [EIDE] (E)IDE hard drive subsystem geometry
Format: <cyl>,<head>,<sect>
keepinitrd [HW,ARM] See retain_initrd.
- kernelcore= [KNL,X86,IA-64,PPC,EARLY]
+ kernelcore= [KNL,X86,PPC,EARLY]
Format: nn[KMGTPE] | nn% | "mirror"
This parameter specifies the amount of memory usable by
the kernel for non-movable allocations. The requested
unlikely, in the extreme case this might damage your
hardware.
- ltpc= [NET]
- Format: <io>,<irq>,<dma>
-
lsm.debug [SECURITY] Enable LSM initialization debugging output.
lsm=lsm1,...,lsmN
[SECURITY] Choose order of LSM initialization. This
overrides CONFIG_LSM, and the "security=" parameter.
- machvec= [IA-64] Force the use of a particular machine-vector
- (machvec) in a generic kernel.
- Example: machvec=hpzx1
-
machtype= [Loongson] Share the same kernel image file between
different yeeloong laptops.
Example: machtype=lemote-yeeloong-2f-7inch
- max_addr=nn[KMG] [KNL,BOOT,IA-64] All physical memory greater
- than or equal to this physical address is ignored.
-
maxcpus= [SMP,EARLY] Maximum number of processors that an SMP kernel
will bring up during bootup. maxcpus=n : n >= 0 limits
the kernel to bring up 'n' processors. Surely after
deep - Suspend-To-RAM or equivalent (if supported)
See Documentation/admin-guide/pm/sleep-states.rst.
- mfgpt_irq= [IA-32] Specify the IRQ to use for the
- Multi-Function General Purpose Timers on AMD Geode
- platforms.
-
mfgptfix [X86-32] Fix MFGPT timers on AMD Geode platforms when
the BIOS has incorrectly applied a workaround. TinyBIOS
version 0.98 is known to be affected, 0.99 fixes the
Enable or disable the microcode minimal revision
enforcement for the runtime microcode loader.
- min_addr=nn[KMG] [KNL,BOOT,IA-64] All physical memory below this
- physical address is ignored.
-
mini2440= [ARM,HW,KNL]
Format:[0..2][b][c][t]
Default: "0tb"
mousedev.yres= [MOUSE] Vertical screen resolution, used for devices
reporting absolute coordinates, such as tablets
- movablecore= [KNL,X86,IA-64,PPC,EARLY]
+ movablecore= [KNL,X86,PPC,EARLY]
Format: nn[KMGTPE] | nn%
This parameter is the complement to kernelcore=, it
specifies the amount of memory used for migratable
mtdparts= [MTD]
See drivers/mtd/parsers/cmdlinepart.c
- mtdset= [ARM]
- ARM/S3C2412 JIVE boot control
-
- See arch/arm/mach-s3c/mach-jive.c
-
mtouchusb.raw_coordinates=
[HW] Make the MicroTouch USB driver use raw coordinates
('y', default) or cooked coordinates ('n')
no_entry_flush [PPC,EARLY] Don't flush the L1-D cache when entering the kernel.
- noexec [IA-64]
-
noexec32 [X86-64]
This affects only 32-bit executables.
noexec32=on: enable non-executable mappings (default)
register save and restore. The kernel will only save
legacy floating-point registers on task switch.
- nohalt [IA-64] Tells the kernel not to use the power saving
- function PAL_HALT_LIGHT when idle. This increases
- power-consumption. On the positive side, it reduces
- interrupt wake-up latency, which may improve performance
- in certain environments such as networked servers or
- real-time systems.
-
no_hash_pointers
[KNL,EARLY]
Force pointers printed to the console or buffers to be
nohibernate [HIBERNATION] Disable hibernation and resume.
- nohlt [ARM,ARM64,MICROBLAZE,MIPS,PPC,SH] Forces the kernel to
+ nohlt [ARM,ARM64,MICROBLAZE,MIPS,PPC,RISCV,SH] Forces the kernel to
busy wait in do_idle() and not use the arch_cpu_idle()
implementation; requires CONFIG_GENERIC_IDLE_POLL_SETUP
to be effective. This is useful on platforms where the
remapping.
[Deprecated - use intremap=off]
- nointroute [IA-64]
-
noinvpcid [X86,EARLY] Disable the INVPCID cpu feature.
noiotrap [SH] Disables trapped I/O port accesses.
noisapnp [ISAPNP] Disables ISA PnP code.
- nojitter [IA-64] Disables jitter checking for ITC timers.
-
nokaslr [KNL,EARLY]
When CONFIG_RANDOMIZE_BASE is set, this disables
kernel and module base offset ASLR (Address Space
nolapic_timer [X86-32,APIC,EARLY] Do not use the local APIC timer.
- nomca [IA-64] Disable machine check abort handling
-
nomce [X86-32] Disable Machine Check Exception
nomfgpt [X86-32] Disable Multi-Function General Purpose
noresume [SWSUSP] Disables resume and restores original swap
space.
- nosbagart [IA-64]
-
no-scroll [VGA] Disables scrollback.
This is required for the Braillex ib80-piezo Braille
reader made by F.H. Papenmeier (Germany).
parameter, xsave area per process might occupy more
memory on xsaves enabled systems.
- nps_mtm_hs_ctr= [KNL,ARC]
- This parameter sets the maximum duration, in
- cycles, each HW thread of the CTOP can run
- without interruptions, before HW switches it.
- The actual maximum duration is 16 times this
- parameter's value.
- Format: integer between 1 and 255
- Default: 255
-
- nptcg= [IA-64] Override max number of concurrent global TLB
- purges which is reported from either PAL_VM_SUMMARY or
- SAL PALO.
-
nr_cpus= [SMP,EARLY] Maximum number of processors that an SMP kernel
could support. nr_cpus=n : n >= 1 limits the kernel to
support 'n' processors. It could be larger than the
none - Limited to cond_resched() calls
voluntary - Limited to cond_resched() and might_sleep() calls
full - Any section that isn't explicitly preempt disabled
- can be preempted anytime.
+ can be preempted anytime. Tasks will also yield
+ contended spinlocks (if the critical section isn't
+ explicitly preempt disabled beyond the lock itself).
print-fatal-signals=
[KNL] debug: print fatal signals
the ->nocb_bypass queue. The definition of "too
many" is supplied by this kernel boot parameter.
+ rcutree.nohz_full_patience_delay= [KNL]
+ On callback-offloaded (rcu_nocbs) CPUs, avoid
+ disturbing RCU unless the grace period has
+ reached the specified age in milliseconds.
+ Defaults to zero. Large values will be capped
+ at five seconds. All values will be rounded down
+ to the nearest value representable by jiffies.
+
rcutree.qhimark= [KNL]
Set threshold of queued RCU callbacks beyond which
batch limiting is disabled.
them. If <base> is less than 0x10000, the region
is assumed to be I/O ports; otherwise it is memory.
+ reserve_mem= [RAM]
+ Format: nn[KNG]:<align>:<label>
+ Reserve physical memory and label it with a name that
+ other subsystems can use to access it. This is typically
+ used for systems that do not wipe the RAM, and this command
+ line will try to reserve the same physical memory on
+ soft reboots. Note, it is not guaranteed to be the same
+ location. For example, if anything about the system changes
+ or if booting a different kernel. It can also fail if KASLR
+ places the kernel at the location of where the RAM reservation
+ was from a previous boot, the new reservation will be at a
+ different location.
+ Any subsystem using this feature must add a way to verify
+ that the contents of the physical memory is from a previous
+ boot, as there may be cases where the memory will not be
+ located at the same location.
+
+ The format is size:align:label for example, to request
+ 12 megabytes of 4096 alignment for ramoops:
+
+ reserve_mem=12M:4096:oops ramoops.mem_name=oops
+
reservetop= [X86-32,EARLY]
Format: nn[KMG]
Reserves a hole at the top of the kernel virtual
2 The "airplane mode" button toggles between everything
blocked and everything unblocked.
- rhash_entries= [KNL,NET]
- Set number of hash buckets for route cache
-
ring3mwait=disable
[KNL] Disable ring 3 MONITOR/MWAIT feature on supported
CPUs.
apic=verbose is specified.
Example: apic=debug show_lapic=all
- simeth= [IA-64]
- simscsi=
-
slab_debug[=options[,slabs][;[options[,slabs]]...] [MM]
Enabling slab_debug allows one to determine the
culprit if slab objects become corrupted. Enabling
deployment of the HW BHI control and the SW BHB
clearing sequence.
- on - (default) Enable the HW or SW mitigation
- as needed.
- off - Disable the mitigation.
+ on - (default) Enable the HW or SW mitigation as
+ needed. This protects the kernel from
+ both syscalls and VMs.
+ vmexit - On systems which don't have the HW mitigation
+ available, enable the SW mitigation on vmexit
+ ONLY. On such systems, the host kernel is
+ protected from VM-originated BHI attacks, but
+ may still be vulnerable to syscall attacks.
+ off - Disable the mitigation.
spectre_v2= [X86,EARLY] Control mitigation of Spectre variant 2
(indirect branch speculation) vulnerability.
Not specifying this option is equivalent to
spec_store_bypass_disable=auto.
- spia_io_base= [HW,MTD]
- spia_fio_base=
- spia_pedr=
- spia_peddr=
-
split_lock_detect=
[X86] Enable split lock detection or bus lock detection
This parameter controls use of the Protected
Execution Facility on pSeries.
- swiotlb= [ARM,IA-64,PPC,MIPS,X86,EARLY]
+ swiotlb= [ARM,PPC,MIPS,X86,S390,EARLY]
Format: { <int> [,<int>] | force | noforce }
<int> -- Number of I/O TLB slabs
<int> -- Second integer after comma. Number of swiotlb
e.g. base its process migration decisions on it.
Default is on.
- topology_updates= [KNL, PPC, NUMA]
- Format: {off}
- Specify if the kernel should ignore (off)
- topology updates sent by the hypervisor to this
- LPAR.
-
torture.disable_onoff_at_boot= [KNL]
Prevent the CPU-hotplug component of torturing
until after init has spawned.
torture.verbose_sleep_duration= [KNL]
Duration of each verbose-printk() sleep in jiffies.
- tp720= [HW,PS2]
-
tpm_suspend_pcr=[HW,TPM]
Format: integer pcr id
Specify that at suspend time, the tpm driver
Try vdso32=0 if you encounter an error that says:
dl_main: Assertion `(void *) ph->p_vaddr == _rtld_local._dl_sysinfo_dso' failed!
- vector= [IA-64,SMP]
- vector=percpu: enable percpu vector domain
-
video= [FB,EARLY] Frame buffer configuration
See Documentation/fb/modedb.rst.
Crash from Xen panic notifier, without executing late
panic() code such as dumping handler.
+ xen_mc_debug [X86,XEN,EARLY]
+ Enable multicall debugging when running as a Xen PV guest.
+ Enabling this feature will reduce performance a little
+ bit, so it should only be enabled for obtaining extended
+ debug data in case of multicall errors.
+
xen_msr_safe= [X86,XEN,EARLY]
Format: <bool>
Select whether to always use non-faulting (safe) MSR
access functions when running as Xen PV guest. The
default value is controlled by CONFIG_XEN_PV_MSR_SAFE.
- xen_nopvspin [X86,XEN,EARLY]
- Disables the qspinlock slowpath using Xen PV optimizations.
- This parameter is obsoleted by "nopvspin" parameter, which
- has equivalent effect for XEN platform.
-
xen_nopv [X86]
Disables the PV optimizations forcing the HVM guest to
run as generic HVM guest with no PV drivers.
};
uart0: serial@10000000 {
- compatible = "snps,dw-apb-uart";
+ compatible = "starfive,jh7110-uart", "snps,dw-apb-uart";
reg = <0x0 0x10000000 0x0 0x10000>;
clocks = <&syscrg JH7110_SYSCLK_UART0_CORE>,
<&syscrg JH7110_SYSCLK_UART0_APB>;
clock-names = "baudclk", "apb_pclk";
- resets = <&syscrg JH7110_SYSRST_UART0_APB>;
+ resets = <&syscrg JH7110_SYSRST_UART0_APB>,
+ <&syscrg JH7110_SYSRST_UART0_CORE>;
interrupts = <32>;
reg-io-width = <4>;
reg-shift = <2>;
};
uart1: serial@10010000 {
- compatible = "snps,dw-apb-uart";
+ compatible = "starfive,jh7110-uart", "snps,dw-apb-uart";
reg = <0x0 0x10010000 0x0 0x10000>;
clocks = <&syscrg JH7110_SYSCLK_UART1_CORE>,
<&syscrg JH7110_SYSCLK_UART1_APB>;
clock-names = "baudclk", "apb_pclk";
- resets = <&syscrg JH7110_SYSRST_UART1_APB>;
+ resets = <&syscrg JH7110_SYSRST_UART1_APB>,
+ <&syscrg JH7110_SYSRST_UART1_CORE>;
interrupts = <33>;
reg-io-width = <4>;
reg-shift = <2>;
};
uart2: serial@10020000 {
- compatible = "snps,dw-apb-uart";
+ compatible = "starfive,jh7110-uart", "snps,dw-apb-uart";
reg = <0x0 0x10020000 0x0 0x10000>;
clocks = <&syscrg JH7110_SYSCLK_UART2_CORE>,
<&syscrg JH7110_SYSCLK_UART2_APB>;
clock-names = "baudclk", "apb_pclk";
- resets = <&syscrg JH7110_SYSRST_UART2_APB>;
+ resets = <&syscrg JH7110_SYSRST_UART2_APB>,
+ <&syscrg JH7110_SYSRST_UART2_CORE>;
interrupts = <34>;
reg-io-width = <4>;
reg-shift = <2>;
};
uart3: serial@12000000 {
- compatible = "snps,dw-apb-uart";
+ compatible = "starfive,jh7110-uart", "snps,dw-apb-uart";
reg = <0x0 0x12000000 0x0 0x10000>;
clocks = <&syscrg JH7110_SYSCLK_UART3_CORE>,
<&syscrg JH7110_SYSCLK_UART3_APB>;
clock-names = "baudclk", "apb_pclk";
- resets = <&syscrg JH7110_SYSRST_UART3_APB>;
+ resets = <&syscrg JH7110_SYSRST_UART3_APB>,
+ <&syscrg JH7110_SYSRST_UART3_CORE>;
interrupts = <45>;
reg-io-width = <4>;
reg-shift = <2>;
};
uart4: serial@12010000 {
- compatible = "snps,dw-apb-uart";
+ compatible = "starfive,jh7110-uart", "snps,dw-apb-uart";
reg = <0x0 0x12010000 0x0 0x10000>;
clocks = <&syscrg JH7110_SYSCLK_UART4_CORE>,
<&syscrg JH7110_SYSCLK_UART4_APB>;
clock-names = "baudclk", "apb_pclk";
- resets = <&syscrg JH7110_SYSRST_UART4_APB>;
+ resets = <&syscrg JH7110_SYSRST_UART4_APB>,
+ <&syscrg JH7110_SYSRST_UART4_CORE>;
interrupts = <46>;
reg-io-width = <4>;
reg-shift = <2>;
};
uart5: serial@12020000 {
- compatible = "snps,dw-apb-uart";
+ compatible = "starfive,jh7110-uart", "snps,dw-apb-uart";
reg = <0x0 0x12020000 0x0 0x10000>;
clocks = <&syscrg JH7110_SYSCLK_UART5_CORE>,
<&syscrg JH7110_SYSCLK_UART5_APB>;
clock-names = "baudclk", "apb_pclk";
- resets = <&syscrg JH7110_SYSRST_UART5_APB>;
+ resets = <&syscrg JH7110_SYSRST_UART5_APB>,
+ <&syscrg JH7110_SYSRST_UART5_CORE>;
interrupts = <47>;
reg-io-width = <4>;
reg-shift = <2>;
#reset-cells = <1>;
power-domains = <&pwrc JH7110_PD_VOUT>;
};
+
+ pcie0: pcie@940000000 {
+ compatible = "starfive,jh7110-pcie";
+ reg = <0x9 0x40000000 0x0 0x1000000>,
+ <0x0 0x2b000000 0x0 0x100000>;
+ reg-names = "cfg", "apb";
+ linux,pci-domain = <0>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ #interrupt-cells = <1>;
+ ranges = <0x82000000 0x0 0x30000000 0x0 0x30000000 0x0 0x08000000>,
+ <0xc3000000 0x9 0x00000000 0x9 0x00000000 0x0 0x40000000>;
+ interrupts = <56>;
+ interrupt-map-mask = <0x0 0x0 0x0 0x7>;
+ interrupt-map = <0x0 0x0 0x0 0x1 &pcie_intc0 0x1>,
+ <0x0 0x0 0x0 0x2 &pcie_intc0 0x2>,
+ <0x0 0x0 0x0 0x3 &pcie_intc0 0x3>,
+ <0x0 0x0 0x0 0x4 &pcie_intc0 0x4>;
+ msi-controller;
+ device_type = "pci";
+ starfive,stg-syscon = <&stg_syscon>;
+ bus-range = <0x0 0xff>;
+ clocks = <&syscrg JH7110_SYSCLK_NOC_BUS_STG_AXI>,
+ <&stgcrg JH7110_STGCLK_PCIE0_TL>,
+ <&stgcrg JH7110_STGCLK_PCIE0_AXI_MST0>,
+ <&stgcrg JH7110_STGCLK_PCIE0_APB>;
+ clock-names = "noc", "tl", "axi_mst0", "apb";
+ resets = <&stgcrg JH7110_STGRST_PCIE0_AXI_MST0>,
+ <&stgcrg JH7110_STGRST_PCIE0_AXI_SLV0>,
+ <&stgcrg JH7110_STGRST_PCIE0_AXI_SLV>,
+ <&stgcrg JH7110_STGRST_PCIE0_BRG>,
+ <&stgcrg JH7110_STGRST_PCIE0_CORE>,
+ <&stgcrg JH7110_STGRST_PCIE0_APB>;
+ reset-names = "mst0", "slv0", "slv", "brg",
+ "core", "apb";
+ status = "disabled";
+
+ pcie_intc0: interrupt-controller {
+ #address-cells = <0>;
+ #interrupt-cells = <1>;
+ interrupt-controller;
+ };
+ };
+
+ pcie1: pcie@9c0000000 {
+ compatible = "starfive,jh7110-pcie";
+ reg = <0x9 0xc0000000 0x0 0x1000000>,
+ <0x0 0x2c000000 0x0 0x100000>;
+ reg-names = "cfg", "apb";
+ linux,pci-domain = <1>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ #interrupt-cells = <1>;
+ ranges = <0x82000000 0x0 0x38000000 0x0 0x38000000 0x0 0x08000000>,
+ <0xc3000000 0x9 0x80000000 0x9 0x80000000 0x0 0x40000000>;
+ interrupts = <57>;
+ interrupt-map-mask = <0x0 0x0 0x0 0x7>;
+ interrupt-map = <0x0 0x0 0x0 0x1 &pcie_intc1 0x1>,
+ <0x0 0x0 0x0 0x2 &pcie_intc1 0x2>,
+ <0x0 0x0 0x0 0x3 &pcie_intc1 0x3>,
+ <0x0 0x0 0x0 0x4 &pcie_intc1 0x4>;
+ msi-controller;
+ device_type = "pci";
+ starfive,stg-syscon = <&stg_syscon>;
+ bus-range = <0x0 0xff>;
+ clocks = <&syscrg JH7110_SYSCLK_NOC_BUS_STG_AXI>,
+ <&stgcrg JH7110_STGCLK_PCIE1_TL>,
+ <&stgcrg JH7110_STGCLK_PCIE1_AXI_MST0>,
+ <&stgcrg JH7110_STGCLK_PCIE1_APB>;
+ clock-names = "noc", "tl", "axi_mst0", "apb";
+ resets = <&stgcrg JH7110_STGRST_PCIE1_AXI_MST0>,
+ <&stgcrg JH7110_STGRST_PCIE1_AXI_SLV0>,
+ <&stgcrg JH7110_STGRST_PCIE1_AXI_SLV>,
+ <&stgcrg JH7110_STGRST_PCIE1_BRG>,
+ <&stgcrg JH7110_STGRST_PCIE1_CORE>,
+ <&stgcrg JH7110_STGRST_PCIE1_APB>;
+ reset-names = "mst0", "slv0", "slv", "brg",
+ "core", "apb";
+ status = "disabled";
+
+ pcie_intc1: interrupt-controller {
+ #address-cells = <0>;
+ #interrupt-cells = <1>;
+ interrupt-controller;
+ };
+ };
};
};
#define UCR4_OREN (1<<1) /* Receiver overrun interrupt enable */
#define UCR4_DREN (1<<0) /* Recv data ready interrupt enable */
#define UFCR_RXTL_SHF 0 /* Receiver trigger level shift */
+#define UFCR_RXTL_MASK 0x3F /* Receiver trigger 6 bits wide */
#define UFCR_DCEDTE (1<<6) /* DCE/DTE mode select */
#define UFCR_RFDIV (7<<7) /* Reference freq divider mask */
#define UFCR_RFDIV_REG(x) (((x) < 7 ? 6 - (x) : 6) << 7)
};
MODULE_DEVICE_TABLE(of, imx_uart_dt_ids);
+ static inline struct imx_port *to_imx_port(struct uart_port *port)
+ {
+ return container_of(port, struct imx_port, port);
+ }
+
static inline void imx_uart_writel(struct imx_port *sport, u32 val, u32 offset)
{
writel(val, sport->port.membase + offset);
/* called with port.lock taken and irqs off */
static void imx_uart_start_rx(struct uart_port *port)
{
- struct imx_port *sport = (struct imx_port *)port;
+ struct imx_port *sport = to_imx_port(port);
unsigned int ucr1, ucr2;
ucr1 = imx_uart_readl(sport, UCR1);
/* called with port.lock taken and irqs off */
static void imx_uart_stop_tx(struct uart_port *port)
{
- struct imx_port *sport = (struct imx_port *)port;
+ struct imx_port *sport = to_imx_port(port);
u32 ucr1, ucr4, usr2;
if (sport->tx_state == OFF)
static void imx_uart_stop_rx_with_loopback_ctrl(struct uart_port *port, bool loopback)
{
- struct imx_port *sport = (struct imx_port *)port;
+ struct imx_port *sport = to_imx_port(port);
u32 ucr1, ucr2, ucr4, uts;
ucr1 = imx_uart_readl(sport, UCR1);
/* called with port.lock taken and irqs off */
static void imx_uart_enable_ms(struct uart_port *port)
{
- struct imx_port *sport = (struct imx_port *)port;
+ struct imx_port *sport = to_imx_port(port);
mod_timer(&sport->timer, jiffies);
/* called with port.lock taken and irqs off */
static void imx_uart_start_tx(struct uart_port *port)
{
- struct imx_port *sport = (struct imx_port *)port;
+ struct imx_port *sport = to_imx_port(port);
struct tty_port *tport = &sport->port.state->port;
u32 ucr1;
*/
static unsigned int imx_uart_tx_empty(struct uart_port *port)
{
- struct imx_port *sport = (struct imx_port *)port;
+ struct imx_port *sport = to_imx_port(port);
unsigned int ret;
ret = (imx_uart_readl(sport, USR2) & USR2_TXDC) ? TIOCSER_TEMT : 0;
/* called with port.lock taken and irqs off */
static unsigned int imx_uart_get_mctrl(struct uart_port *port)
{
- struct imx_port *sport = (struct imx_port *)port;
+ struct imx_port *sport = to_imx_port(port);
unsigned int ret = imx_uart_get_hwmctrl(sport);
mctrl_gpio_get(sport->gpios, &ret);
/* called with port.lock taken and irqs off */
static void imx_uart_set_mctrl(struct uart_port *port, unsigned int mctrl)
{
- struct imx_port *sport = (struct imx_port *)port;
+ struct imx_port *sport = to_imx_port(port);
u32 ucr3, uts;
if (!(port->rs485.flags & SER_RS485_ENABLED)) {
*/
static void imx_uart_break_ctl(struct uart_port *port, int break_state)
{
- struct imx_port *sport = (struct imx_port *)port;
+ struct imx_port *sport = to_imx_port(port);
unsigned long flags;
u32 ucr1;
static int imx_uart_startup(struct uart_port *port)
{
- struct imx_port *sport = (struct imx_port *)port;
+ struct imx_port *sport = to_imx_port(port);
int retval;
unsigned long flags;
int dma_is_inited = 0;
static void imx_uart_shutdown(struct uart_port *port)
{
- struct imx_port *sport = (struct imx_port *)port;
+ struct imx_port *sport = to_imx_port(port);
unsigned long flags;
u32 ucr1, ucr2, ucr4, uts;
+ int loops;
if (sport->dma_is_enabled) {
dmaengine_terminate_sync(sport->dma_chan_tx);
ucr4 &= ~UCR4_TCEN;
imx_uart_writel(sport, ucr4, UCR4);
+ /*
+ * We have to ensure the tx state machine ends up in OFF. This
+ * is especially important for rs485 where we must not leave
+ * the RTS signal high, blocking the bus indefinitely.
+ *
+ * All interrupts are now disabled, so imx_uart_stop_tx() will
+ * no longer be called from imx_uart_transmit_buffer(). It may
+ * still be called via the hrtimers, and if those are in play,
+ * we have to honour the delays.
+ */
+ if (sport->tx_state == WAIT_AFTER_RTS || sport->tx_state == SEND)
+ imx_uart_stop_tx(port);
+
+ /*
+ * In many cases (rs232 mode, or if tx_state was
+ * WAIT_AFTER_RTS, or if tx_state was SEND and there is no
+ * delay_rts_after_send), this will have moved directly to
+ * OFF. In rs485 mode, tx_state might already have been
+ * WAIT_AFTER_SEND and the hrtimer thus already started, or
+ * the above imx_uart_stop_tx() call could have started it. In
+ * those cases, we have to wait for the hrtimer to fire and
+ * complete the transition to OFF.
+ */
+ loops = port->rs485.flags & SER_RS485_ENABLED ?
+ port->rs485.delay_rts_after_send : 0;
+ while (sport->tx_state != OFF && loops--) {
+ uart_port_unlock_irqrestore(&sport->port, flags);
+ msleep(1);
+ uart_port_lock_irqsave(&sport->port, &flags);
+ }
+
+ if (sport->tx_state != OFF) {
+ dev_warn(sport->port.dev, "unexpected tx_state %d\n",
+ sport->tx_state);
+ /*
+ * This machine may be busted, but ensure the RTS
+ * signal is inactive in order not to block other
+ * devices.
+ */
+ if (port->rs485.flags & SER_RS485_ENABLED) {
+ ucr2 = imx_uart_readl(sport, UCR2);
+ if (port->rs485.flags & SER_RS485_RTS_AFTER_SEND)
+ imx_uart_rts_active(sport, &ucr2);
+ else
+ imx_uart_rts_inactive(sport, &ucr2);
+ imx_uart_writel(sport, ucr2, UCR2);
+ }
+ sport->tx_state = OFF;
+ }
+
uart_port_unlock_irqrestore(&sport->port, flags);
clk_disable_unprepare(sport->clk_per);
/* called with port.lock taken and irqs off */
static void imx_uart_flush_buffer(struct uart_port *port)
{
- struct imx_port *sport = (struct imx_port *)port;
+ struct imx_port *sport = to_imx_port(port);
struct scatterlist *sgl = &sport->tx_sgl[0];
if (!sport->dma_chan_tx)
imx_uart_set_termios(struct uart_port *port, struct ktermios *termios,
const struct ktermios *old)
{
- struct imx_port *sport = (struct imx_port *)port;
+ struct imx_port *sport = to_imx_port(port);
unsigned long flags;
u32 ucr2, old_ucr2, ufcr;
unsigned int baud, quot;
static int imx_uart_poll_init(struct uart_port *port)
{
- struct imx_port *sport = (struct imx_port *)port;
+ struct imx_port *sport = to_imx_port(port);
unsigned long flags;
u32 ucr1, ucr2;
int retval;
static int imx_uart_poll_get_char(struct uart_port *port)
{
- struct imx_port *sport = (struct imx_port *)port;
+ struct imx_port *sport = to_imx_port(port);
if (!(imx_uart_readl(sport, USR2) & USR2_RDR))
return NO_POLL_CHAR;
static void imx_uart_poll_put_char(struct uart_port *port, unsigned char c)
{
- struct imx_port *sport = (struct imx_port *)port;
+ struct imx_port *sport = to_imx_port(port);
unsigned int status;
/* drain */
static int imx_uart_rs485_config(struct uart_port *port, struct ktermios *termios,
struct serial_rs485 *rs485conf)
{
- struct imx_port *sport = (struct imx_port *)port;
+ struct imx_port *sport = to_imx_port(port);
- u32 ucr2;
+ u32 ucr2, ufcr;
if (rs485conf->flags & SER_RS485_ENABLED) {
/* Enable receiver if low-active RTS signal is requested */
/* Make sure Rx is enabled in case Tx is active with Rx disabled */
if (!(rs485conf->flags & SER_RS485_ENABLED) ||
rs485conf->flags & SER_RS485_RX_DURING_TX) {
- imx_uart_setup_ufcr(sport, TXTL_DEFAULT, RXTL_DEFAULT);
+ /* If the receiver trigger is 0, set it to a default value */
+ ufcr = imx_uart_readl(sport, UFCR);
+ if ((ufcr & UFCR_RXTL_MASK) == 0)
+ imx_uart_setup_ufcr(sport, TXTL_DEFAULT, RXTL_DEFAULT);
imx_uart_start_rx(port);
}
#if IS_ENABLED(CONFIG_SERIAL_IMX_CONSOLE)
static void imx_uart_console_putchar(struct uart_port *port, unsigned char ch)
{
- struct imx_port *sport = (struct imx_port *)port;
+ struct imx_port *sport = to_imx_port(port);
while (imx_uart_readl(sport, imx_uart_uts_reg(sport)) & UTS_TXFULL)
barrier();