提交 e30aee9e 编写于 作者: L Linus Torvalds

Merge tag 'char-misc-4.11-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc

Pull char/misc driver updates from Greg KH:
 "Here is the big char/misc driver patchset for 4.11-rc1.

  Lots of different driver subsystems updated here: rework for the
  hyperv subsystem to handle new platforms better, mei and w1 and extcon
  driver updates, as well as a number of other "minor" driver updates.

  All of these have been in linux-next for a while with no reported
  issues"

* tag 'char-misc-4.11-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc: (169 commits)
  goldfish: Sanitize the broken interrupt handler
  x86/platform/goldfish: Prevent unconditional loading
  vmbus: replace modulus operation with subtraction
  vmbus: constify parameters where possible
  vmbus: expose hv_begin/end_read
  vmbus: remove conditional locking of vmbus_write
  vmbus: add direct isr callback mode
  vmbus: change to per channel tasklet
  vmbus: put related per-cpu variable together
  vmbus: callback is in softirq not workqueue
  binder: Add support for file-descriptor arrays
  binder: Add support for scatter-gather
  binder: Add extra size to allocator
  binder: Refactor binder_transact()
  binder: Support multiple /dev instances
  binder: Deal with contexts in debugfs
  binder: Support multiple context managers
  binder: Split flat_binder_object
  auxdisplay: ht16k33: remove private workqueue
  auxdisplay: ht16k33: rework input device initialization
  ...
......@@ -11,7 +11,7 @@ DOCBOOKS := z8530book.xml \
writing_usb_driver.xml networking.xml \
kernel-api.xml filesystems.xml lsm.xml kgdb.xml \
gadget.xml libata.xml mtdnand.xml librs.xml rapidio.xml \
genericirq.xml s390-drivers.xml uio-howto.xml scsi.xml \
genericirq.xml s390-drivers.xml scsi.xml \
sh.xml regulator.xml w1.xml \
writing_musb_glue_layer.xml iio.xml
......
此差异已折叠。
......@@ -1195,6 +1195,10 @@
When zero, profiling data is discarded and associated
debugfs files are removed at module unload time.
goldfish [X86] Enable the goldfish android emulator platform.
Don't use this when you are not running on the
android emulator
gpt [EFI] Forces disk with valid GPT signature but
invalid Protective MBR to be treated as GPT. If the
primary GPT is corrupted, it enables the backup/alternate
......
EEPROM / CSR SMBus-slave interface of IDT 89HPESx devices
Required properties:
- compatible : should be "<manufacturer>,<type>"
Basically there is only one manufacturer: idt, but some
compatible devices may be produced in future. Following devices
are supported: 89hpes8nt2, 89hpes12nt3, 89hpes24nt6ag2,
89hpes32nt8ag2, 89hpes32nt8bg2, 89hpes12nt12g2, 89hpes16nt16g2,
89hpes24nt24g2, 89hpes32nt24ag2, 89hpes32nt24bg2;
89hpes12n3, 89hpes12n3a, 89hpes24n3, 89hpes24n3a;
89hpes32h8, 89hpes32h8g2, 89hpes48h12, 89hpes48h12g2,
89hpes48h12ag2, 89hpes16h16, 89hpes22h16, 89hpes22h16g2,
89hpes34h16, 89hpes34h16g2, 89hpes64h16, 89hpes64h16g2,
89hpes64h16ag2;
89hpes12t3g2, 89hpes24t3g2, 89hpes16t4, 89hpes4t4g2,
89hpes10t4g2, 89hpes16t4g2, 89hpes16t4ag2, 89hpes5t5,
89hpes6t5, 89hpes8t5, 89hpes8t5a, 89hpes24t6, 89hpes6t6g2,
89hpes24t6g2, 89hpes16t7, 89hpes32t8, 89hpes32t8g2,
89hpes48t12, 89hpes48t12g2.
- reg : I2C address of the IDT 89HPESx device.
Optionally there can be EEPROM-compatible subnode:
- compatible: There are five EEPROM devices supported: 24c32, 24c64, 24c128,
24c256 and 24c512 differed by size.
- reg: Custom address of EEPROM device (If not specified IDT 89HPESx
(optional) device will try to communicate with EEPROM sited by default
address - 0x50)
- read-only : Parameterless property disables writes to the EEPROM
(optional)
Example:
idt@60 {
compatible = "idt,89hpes32nt8ag2";
reg = <0x74>;
#address-cells = <1>;
#size-cells = <0>;
eeprom@50 {
compatible = "onsemi,24c64";
reg = <0x50>;
read-only;
};
};
Freescale i.MX6 On-Chip OTP Controller (OCOTP) device tree bindings
This binding represents the on-chip eFuse OTP controller found on
i.MX6Q/D, i.MX6DL/S, i.MX6SL, and i.MX6SX SoCs.
i.MX6Q/D, i.MX6DL/S, i.MX6SL, i.MX6SX and i.MX6UL SoCs.
Required properties:
- compatible: should be one of
"fsl,imx6q-ocotp" (i.MX6Q/D/DL/S),
"fsl,imx6sl-ocotp" (i.MX6SL), or
"fsl,imx6sx-ocotp" (i.MX6SX), followed by "syscon".
"fsl,imx6sx-ocotp" (i.MX6SX),
"fsl,imx6ul-ocotp" (i.MX6UL),
followed by "syscon".
- reg: Should contain the register base and length.
- clocks: Should contain a phandle pointing to the gated peripheral clock.
......
......@@ -42,6 +42,12 @@ Optional properties in the area nodes:
and in use by another device or devices
- export : indicates that the reserved SRAM area may be accessed outside
of the kernel, e.g. by bootloader or userspace
- protect-exec : Same as 'pool' above but with the additional
constraint that code wil be run from the region and
that the memory is maintained as read-only, executable
during code execution. NOTE: This region must be page
aligned on start and end in order to properly allow
manipulation of the page attributes.
- label : the name for the reserved partition, if omitted, the label
is taken from the node name excluding the unit address.
......
......@@ -30,6 +30,7 @@ available subsections can be seen below.
miscellaneous
vme
80211/index
uio-howto
.. only:: subproject and html
......
此差异已折叠。
Intel INT3496 ACPI device extcon driver documentation
-----------------------------------------------------
The Intel INT3496 ACPI device extcon driver is a driver for ACPI
devices with an acpi-id of INT3496, such as found for example on
Intel Baytrail and Cherrytrail tablets.
This ACPI device describes how the OS can read the id-pin of the devices'
USB-otg port, as well as how it optionally can enable Vbus output on the
otg port and how it can optionally control the muxing of the data pins
between an USB host and an USB peripheral controller.
The ACPI devices exposes this functionality by returning an array with up
to 3 gpio descriptors from its ACPI _CRS (Current Resource Settings) call:
Index 0: The input gpio for the id-pin, this is always present and valid
Index 1: The output gpio for enabling Vbus output from the device to the otg
port, write 1 to enable the Vbus output (this gpio descriptor may
be absent or invalid)
Index 2: The output gpio for muxing of the data pins between the USB host and
the USB peripheral controller, write 1 to mux to the peripheral
controller
......@@ -22,7 +22,16 @@ To program the FPGA from a file or from a buffer:
struct fpga_image_info *info,
const char *buf, size_t count);
Load the FPGA from an image which exists as a buffer in memory.
Load the FPGA from an image which exists as a contiguous buffer in
memory. Allocating contiguous kernel memory for the buffer should be avoided,
users are encouraged to use the _sg interface instead of this.
int fpga_mgr_buf_load_sg(struct fpga_manager *mgr,
struct fpga_image_info *info,
struct sg_table *sgt);
Load the FPGA from an image from non-contiguous in memory. Callers can
construct a sg_table using alloc_page backed memory.
int fpga_mgr_firmware_load(struct fpga_manager *mgr,
struct fpga_image_info *info,
......@@ -166,7 +175,7 @@ success or negative error codes otherwise.
The programming sequence is:
1. .write_init
2. .write (may be called once or multiple times)
2. .write or .write_sg (may be called once or multiple times)
3. .write_complete
The .write_init function will prepare the FPGA to receive the image data. The
......@@ -176,7 +185,11 @@ buffer up at least this much before starting.
The .write function writes a buffer to the FPGA. The buffer may be contain the
whole FPGA image or may be a smaller chunk of an FPGA image. In the latter
case, this function is called multiple times for successive chunks.
case, this function is called multiple times for successive chunks. This interface
is suitable for drivers which use PIO.
The .write_sg version behaves the same as .write except the input is a sg_table
scatter list. This interface is suitable for drivers which use DMA.
The .write_complete function is called after all the image has been written
to put the FPGA into operating mode.
......
......@@ -5993,6 +5993,7 @@ S: Maintained
F: arch/x86/include/asm/mshyperv.h
F: arch/x86/include/uapi/asm/hyperv.h
F: arch/x86/kernel/cpu/mshyperv.c
F: arch/x86/hyperv
F: drivers/hid/hid-hyperv.c
F: drivers/hv/
F: drivers/input/serio/hyperv-keyboard.c
......@@ -13071,7 +13072,7 @@ USERSPACE I/O (UIO)
M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
S: Maintained
T: git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc.git
F: Documentation/DocBook/uio-howto.tmpl
F: Documentation/driver-api/uio-howto.rst
F: drivers/uio/
F: include/linux/uio*.h
......
......@@ -557,15 +557,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),
/*
* The only user of this clock is davinci_nand and it get's it through
* con_id. The nand node itself is created from within the aemif
* driver to guarantee that it's probed after the aemif timing
* parameters are configured. of_dev_auxdata is not accessible from
* the aemif driver and can't be passed to of_platform_populate(). For
* that reason we're leaving the dev_id here as NULL.
*/
CLK(NULL, "aemif", &aemif_nand_clk),
CLK("davinci-nand.0", "aemif", &aemif_nand_clk),
CLK("ohci-da8xx", "usb11", &usb11_clk),
CLK("musb-da8xx", "usb20", &usb20_clk),
CLK("spi_davinci.0", NULL, &spi0_clk),
......
......@@ -11,6 +11,7 @@
#include <linux/of_irq.h>
#include <linux/of_platform.h>
#include <linux/irqdomain.h>
#include <linux/platform_data/ti-aemif.h>
#include <asm/mach/arch.h>
......@@ -18,6 +19,15 @@
#include "cp_intc.h"
#include <mach/da8xx.h>
static struct of_dev_auxdata da850_aemif_auxdata_lookup[] = {
OF_DEV_AUXDATA("ti,davinci-nand", 0x62000000, "davinci-nand.0", NULL),
{}
};
static struct aemif_platform_data aemif_data = {
.dev_lookup = da850_aemif_auxdata_lookup,
};
static struct of_dev_auxdata da850_auxdata_lookup[] __initdata = {
OF_DEV_AUXDATA("ti,davinci-i2c", 0x01c22000, "i2c_davinci.1", NULL),
OF_DEV_AUXDATA("ti,davinci-i2c", 0x01e28000, "i2c_davinci.2", NULL),
......@@ -37,7 +47,7 @@ static struct of_dev_auxdata da850_auxdata_lookup[] __initdata = {
OF_DEV_AUXDATA("ti,davinci-dm6467-emac", 0x01e20000, "davinci_emac.1",
NULL),
OF_DEV_AUXDATA("ti,da830-mcasp-audio", 0x01d00000, "davinci-mcasp.0", NULL),
OF_DEV_AUXDATA("ti,da850-aemif", 0x68000000, "ti-aemif", NULL),
OF_DEV_AUXDATA("ti,da850-aemif", 0x68000000, "ti-aemif", &aemif_data),
OF_DEV_AUXDATA("ti,da850-tilcdc", 0x01e13000, "da8xx_lcdc.0", NULL),
OF_DEV_AUXDATA("ti,da830-ohci", 0x01e25000, "ohci-da8xx", NULL),
OF_DEV_AUXDATA("ti,da830-musb", 0x01e00000, "musb-da8xx", NULL),
......
......@@ -7,6 +7,9 @@ obj-$(CONFIG_KVM) += kvm/
# Xen paravirtualization support
obj-$(CONFIG_XEN) += xen/
# Hyper-V paravirtualization support
obj-$(CONFIG_HYPERVISOR_GUEST) += hyperv/
# lguest paravirtualization support
obj-$(CONFIG_LGUEST_GUEST) += lguest/
......
/*
* X86 specific Hyper-V initialization code.
*
* Copyright (C) 2016, Microsoft, Inc.
*
* Author : K. Y. Srinivasan <kys@microsoft.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published
* by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
* NON INFRINGEMENT. See the GNU General Public License for more
* details.
*
*/
#include <linux/types.h>
#include <asm/hypervisor.h>
#include <asm/hyperv.h>
#include <asm/mshyperv.h>
#include <linux/version.h>
#include <linux/vmalloc.h>
#include <linux/mm.h>
#include <linux/clockchips.h>
#ifdef CONFIG_X86_64
static struct ms_hyperv_tsc_page *tsc_pg;
static u64 read_hv_clock_tsc(struct clocksource *arg)
{
u64 current_tick;
if (tsc_pg->tsc_sequence != 0) {
/*
* Use the tsc page to compute the value.
*/
while (1) {
u64 tmp;
u32 sequence = tsc_pg->tsc_sequence;
u64 cur_tsc;
u64 scale = tsc_pg->tsc_scale;
s64 offset = tsc_pg->tsc_offset;
rdtscll(cur_tsc);
/* current_tick = ((cur_tsc *scale) >> 64) + offset */
asm("mulq %3"
: "=d" (current_tick), "=a" (tmp)
: "a" (cur_tsc), "r" (scale));
current_tick += offset;
if (tsc_pg->tsc_sequence == sequence)
return current_tick;
if (tsc_pg->tsc_sequence != 0)
continue;
/*
* Fallback using MSR method.
*/
break;
}
}
rdmsrl(HV_X64_MSR_TIME_REF_COUNT, current_tick);
return current_tick;
}
static struct clocksource hyperv_cs_tsc = {
.name = "hyperv_clocksource_tsc_page",
.rating = 400,
.read = read_hv_clock_tsc,
.mask = CLOCKSOURCE_MASK(64),
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
};
#endif
static u64 read_hv_clock_msr(struct clocksource *arg)
{
u64 current_tick;
/*
* Read the partition counter to get the current tick count. This count
* is set to 0 when the partition is created and is incremented in
* 100 nanosecond units.
*/
rdmsrl(HV_X64_MSR_TIME_REF_COUNT, current_tick);
return current_tick;
}
static struct clocksource hyperv_cs_msr = {
.name = "hyperv_clocksource_msr",
.rating = 400,
.read = read_hv_clock_msr,
.mask = CLOCKSOURCE_MASK(64),
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
};
static void *hypercall_pg;
struct clocksource *hyperv_cs;
EXPORT_SYMBOL_GPL(hyperv_cs);
/*
* This function is to be invoked early in the boot sequence after the
* hypervisor has been detected.
*
* 1. Setup the hypercall page.
* 2. Register Hyper-V specific clocksource.
*/
void hyperv_init(void)
{
u64 guest_id;
union hv_x64_msr_hypercall_contents hypercall_msr;
if (x86_hyper != &x86_hyper_ms_hyperv)
return;
/*
* Setup the hypercall page and enable hypercalls.
* 1. Register the guest ID
* 2. Enable the hypercall and register the hypercall page
*/
guest_id = generate_guest_id(0, LINUX_VERSION_CODE, 0);
wrmsrl(HV_X64_MSR_GUEST_OS_ID, guest_id);
hypercall_pg = __vmalloc(PAGE_SIZE, GFP_KERNEL, PAGE_KERNEL_RX);
if (hypercall_pg == NULL) {
wrmsrl(HV_X64_MSR_GUEST_OS_ID, 0);
return;
}
rdmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
hypercall_msr.enable = 1;
hypercall_msr.guest_physical_address = vmalloc_to_pfn(hypercall_pg);
wrmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
/*
* Register Hyper-V specific clocksource.
*/
#ifdef CONFIG_X86_64
if (ms_hyperv.features & HV_X64_MSR_REFERENCE_TSC_AVAILABLE) {
union hv_x64_msr_hypercall_contents tsc_msr;
tsc_pg = __vmalloc(PAGE_SIZE, GFP_KERNEL, PAGE_KERNEL);
if (!tsc_pg)
goto register_msr_cs;
hyperv_cs = &hyperv_cs_tsc;
rdmsrl(HV_X64_MSR_REFERENCE_TSC, tsc_msr.as_uint64);
tsc_msr.enable = 1;
tsc_msr.guest_physical_address = vmalloc_to_pfn(tsc_pg);
wrmsrl(HV_X64_MSR_REFERENCE_TSC, tsc_msr.as_uint64);
clocksource_register_hz(&hyperv_cs_tsc, NSEC_PER_SEC/100);
return;
}
#endif
/*
* For 32 bit guests just use the MSR based mechanism for reading
* the partition counter.
*/
register_msr_cs:
hyperv_cs = &hyperv_cs_msr;
if (ms_hyperv.features & HV_X64_MSR_TIME_REF_COUNT_AVAILABLE)
clocksource_register_hz(&hyperv_cs_msr, NSEC_PER_SEC/100);
}
/*
* This routine is called before kexec/kdump, it does the required cleanup.
*/
void hyperv_cleanup(void)
{
union hv_x64_msr_hypercall_contents hypercall_msr;
/* Reset our OS id */
wrmsrl(HV_X64_MSR_GUEST_OS_ID, 0);
/* Reset the hypercall page */
hypercall_msr.as_uint64 = 0;
wrmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
/* Reset the TSC page */
hypercall_msr.as_uint64 = 0;
wrmsrl(HV_X64_MSR_REFERENCE_TSC, hypercall_msr.as_uint64);
}
EXPORT_SYMBOL_GPL(hyperv_cleanup);
/*
* hv_do_hypercall- Invoke the specified hypercall
*/
u64 hv_do_hypercall(u64 control, void *input, void *output)
{
u64 input_address = (input) ? virt_to_phys(input) : 0;
u64 output_address = (output) ? virt_to_phys(output) : 0;
#ifdef CONFIG_X86_64
u64 hv_status = 0;
if (!hypercall_pg)
return (u64)ULLONG_MAX;
__asm__ __volatile__("mov %0, %%r8" : : "r" (output_address) : "r8");
__asm__ __volatile__("call *%3" : "=a" (hv_status) :
"c" (control), "d" (input_address),
"m" (hypercall_pg));
return hv_status;
#else
u32 control_hi = control >> 32;
u32 control_lo = control & 0xFFFFFFFF;
u32 hv_status_hi = 1;
u32 hv_status_lo = 1;
u32 input_address_hi = input_address >> 32;
u32 input_address_lo = input_address & 0xFFFFFFFF;
u32 output_address_hi = output_address >> 32;
u32 output_address_lo = output_address & 0xFFFFFFFF;
if (!hypercall_pg)
return (u64)ULLONG_MAX;
__asm__ __volatile__ ("call *%8" : "=d"(hv_status_hi),
"=a"(hv_status_lo) : "d" (control_hi),
"a" (control_lo), "b" (input_address_hi),
"c" (input_address_lo), "D"(output_address_hi),
"S"(output_address_lo), "m" (hypercall_pg));
return hv_status_lo | ((u64)hv_status_hi << 32);
#endif /* !x86_64 */
}
EXPORT_SYMBOL_GPL(hv_do_hypercall);
void hyperv_report_panic(struct pt_regs *regs)
{
static bool panic_reported;
/*
* We prefer to report panic on 'die' chain as we have proper
* registers to report, but if we miss it (e.g. on BUG()) we need
* to report it on 'panic'.
*/
if (panic_reported)
return;
panic_reported = true;
wrmsrl(HV_X64_MSR_CRASH_P0, regs->ip);
wrmsrl(HV_X64_MSR_CRASH_P1, regs->ax);
wrmsrl(HV_X64_MSR_CRASH_P2, regs->bx);
wrmsrl(HV_X64_MSR_CRASH_P3, regs->cx);
wrmsrl(HV_X64_MSR_CRASH_P4, regs->dx);
/*
* Let Hyper-V know there is crash data available
*/
wrmsrl(HV_X64_MSR_CRASH_CTL, HV_CRASH_CTL_CRASH_NOTIFY);
}
EXPORT_SYMBOL_GPL(hyperv_report_panic);
bool hv_is_hypercall_page_setup(void)
{
union hv_x64_msr_hypercall_contents hypercall_msr;
/* Check if the hypercall page is setup */
hypercall_msr.as_uint64 = 0;
rdmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
if (!hypercall_msr.enable)
return false;
return true;
}
EXPORT_SYMBOL_GPL(hv_is_hypercall_page_setup);
......@@ -3,8 +3,28 @@
#include <linux/types.h>
#include <linux/interrupt.h>
#include <linux/clocksource.h>
#include <asm/hyperv.h>
/*
* The below CPUID leaves are present if VersionAndFeatures.HypervisorPresent
* is set by CPUID(HVCPUID_VERSION_FEATURES).
*/
enum hv_cpuid_function {
HVCPUID_VERSION_FEATURES = 0x00000001,
HVCPUID_VENDOR_MAXFUNCTION = 0x40000000,
HVCPUID_INTERFACE = 0x40000001,
/*
* The remaining functions depend on the value of
* HVCPUID_INTERFACE
*/
HVCPUID_VERSION = 0x40000002,
HVCPUID_FEATURES = 0x40000003,
HVCPUID_ENLIGHTENMENT_INFO = 0x40000004,
HVCPUID_IMPLEMENTATION_LIMITS = 0x40000005,
};
struct ms_hyperv_info {
u32 features;
u32 misc_features;
......@@ -13,6 +33,128 @@ struct ms_hyperv_info {
extern struct ms_hyperv_info ms_hyperv;
/*
* Declare the MSR used to setup pages used to communicate with the hypervisor.
*/
union hv_x64_msr_hypercall_contents {
u64 as_uint64;
struct {
u64 enable:1;
u64 reserved:11;
u64 guest_physical_address:52;
};
};
/*
* TSC page layout.
*/
struct ms_hyperv_tsc_page {
volatile u32 tsc_sequence;
u32 reserved1;
volatile u64 tsc_scale;
volatile s64 tsc_offset;
u64 reserved2[509];
};
/*
* The guest OS needs to register the guest ID with the hypervisor.
* The guest ID is a 64 bit entity and the structure of this ID is
* specified in the Hyper-V specification:
*
* msdn.microsoft.com/en-us/library/windows/hardware/ff542653%28v=vs.85%29.aspx
*
* While the current guideline does not specify how Linux guest ID(s)
* need to be generated, our plan is to publish the guidelines for
* Linux and other guest operating systems that currently are hosted
* on Hyper-V. The implementation here conforms to this yet
* unpublished guidelines.
*
*
* Bit(s)
* 63 - Indicates if the OS is Open Source or not; 1 is Open Source
* 62:56 - Os Type; Linux is 0x100
* 55:48 - Distro specific identification
* 47:16 - Linux kernel version number
* 15:0 - Distro specific identification
*
*
*/
#define HV_LINUX_VENDOR_ID 0x8100
/*
* Generate the guest ID based on the guideline described above.
*/
static inline __u64 generate_guest_id(__u64 d_info1, __u64 kernel_version,
__u64 d_info2)
{
__u64 guest_id = 0;
guest_id = (((__u64)HV_LINUX_VENDOR_ID) << 48);
guest_id |= (d_info1 << 48);
guest_id |= (kernel_version << 16);
guest_id |= d_info2;
return guest_id;
}
/* Free the message slot and signal end-of-message if required */
static inline void vmbus_signal_eom(struct hv_message *msg, u32 old_msg_type)
{
/*
* On crash we're reading some other CPU's message page and we need
* to be careful: this other CPU may already had cleared the header
* and the host may already had delivered some other message there.
* In case we blindly write msg->header.message_type we're going
* to lose it. We can still lose a message of the same type but
* we count on the fact that there can only be one
* CHANNELMSG_UNLOAD_RESPONSE and we don't care about other messages
* on crash.
*/
if (cmpxchg(&msg->header.message_type, old_msg_type,
HVMSG_NONE) != old_msg_type)
return;
/*
* Make sure the write to MessageType (ie set to
* HVMSG_NONE) happens before we read the
* MessagePending and EOMing. Otherwise, the EOMing
* will not deliver any more messages since there is
* no empty slot
*/
mb();
if (msg->header.message_flags.msg_pending) {
/*
* This will cause message queue rescan to
* possibly deliver another msg from the
* hypervisor
*/
wrmsrl(HV_X64_MSR_EOM, 0);
}
}
#define hv_get_current_tick(tick) rdmsrl(HV_X64_MSR_TIME_REF_COUNT, tick)
#define hv_init_timer(timer, tick) wrmsrl(timer, tick)
#define hv_init_timer_config(config, val) wrmsrl(config, val)
#define hv_get_simp(val) rdmsrl(HV_X64_MSR_SIMP, val)
#define hv_set_simp(val) wrmsrl(HV_X64_MSR_SIMP, val)
#define hv_get_siefp(val) rdmsrl(HV_X64_MSR_SIEFP, val)
#define hv_set_siefp(val) wrmsrl(HV_X64_MSR_SIEFP, val)
#define hv_get_synic_state(val) rdmsrl(HV_X64_MSR_SCONTROL, val)
#define hv_set_synic_state(val) wrmsrl(HV_X64_MSR_SCONTROL, val)
#define hv_get_vp_index(index) rdmsrl(HV_X64_MSR_VP_INDEX, index)
#define hv_get_synint_state(int_num, val) rdmsrl(int_num, val)
#define hv_set_synint_state(int_num, val) wrmsrl(int_num, val)
void hyperv_callback_vector(void);
#ifdef CONFIG_TRACING
#define trace_hyperv_callback_vector hyperv_callback_vector
......@@ -25,4 +167,13 @@ void hv_setup_kexec_handler(void (*handler)(void));
void hv_remove_kexec_handler(void);
void hv_setup_crash_handler(void (*handler)(struct pt_regs *regs));
void hv_remove_crash_handler(void);
#if IS_ENABLED(CONFIG_HYPERV)
extern struct clocksource *hyperv_cs;
void hyperv_init(void);
void hyperv_report_panic(struct pt_regs *regs);
bool hv_is_hypercall_page_setup(void);
void hyperv_cleanup(void);
#endif
#endif
......@@ -73,6 +73,9 @@
*/
#define HV_X64_MSR_STAT_PAGES_AVAILABLE (1 << 8)
/* Crash MSR available */
#define HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE (1 << 10)
/*
* Feature identification: EBX indicates which flags were specified at
* partition creation. The format is the same as the partition creation
......@@ -144,6 +147,11 @@
*/
#define HV_X64_RELAXED_TIMING_RECOMMENDED (1 << 5)
/*
* Crash notification flag.
*/
#define HV_CRASH_CTL_CRASH_NOTIFY (1ULL << 63)
/* MSR used to identify the guest OS. */
#define HV_X64_MSR_GUEST_OS_ID 0x40000000
......
......@@ -133,26 +133,6 @@ static uint32_t __init ms_hyperv_platform(void)
return 0;
}
static u64 read_hv_clock(struct clocksource *arg)
{
u64 current_tick;
/*
* Read the partition counter to get the current tick count. This count
* is set to 0 when the partition is created and is incremented in
* 100 nanosecond units.
*/
rdmsrl(HV_X64_MSR_TIME_REF_COUNT, current_tick);
return current_tick;
}
static struct clocksource hyperv_cs = {
.name = "hyperv_clocksource",
.rating = 400, /* use this when running on Hyperv*/
.read = read_hv_clock,
.mask = CLOCKSOURCE_MASK(64),
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
};
static unsigned char hv_get_nmi_reason(void)
{
return 0;
......@@ -180,6 +160,11 @@ static int hv_nmi_unknown(unsigned int val, struct pt_regs *regs)
static void __init ms_hyperv_init_platform(void)
{
int hv_host_info_eax;
int hv_host_info_ebx;
int hv_host_info_ecx;
int hv_host_info_edx;
/*
* Extract the features and hints
*/
......@@ -190,6 +175,21 @@ static void __init ms_hyperv_init_platform(void)
pr_info("HyperV: features 0x%x, hints 0x%x\n",
ms_hyperv.features, ms_hyperv.hints);
/*
* Extract host information.
*/
if (cpuid_eax(HVCPUID_VENDOR_MAXFUNCTION) >= HVCPUID_VERSION) {
hv_host_info_eax = cpuid_eax(HVCPUID_VERSION);
hv_host_info_ebx = cpuid_ebx(HVCPUID_VERSION);
hv_host_info_ecx = cpuid_ecx(HVCPUID_VERSION);
hv_host_info_edx = cpuid_edx(HVCPUID_VERSION);
pr_info("Hyper-V Host Build:%d-%d.%d-%d-%d.%d\n",
hv_host_info_eax, hv_host_info_ebx >> 16,
hv_host_info_ebx & 0xFFFF, hv_host_info_ecx,
hv_host_info_edx >> 24, hv_host_info_edx & 0xFFFFFF);
}
#ifdef CONFIG_X86_LOCAL_APIC
if (ms_hyperv.features & HV_X64_MSR_APIC_FREQUENCY_AVAILABLE) {
/*
......@@ -208,9 +208,6 @@ static void __init ms_hyperv_init_platform(void)
"hv_nmi_unknown");
#endif
if (ms_hyperv.features & HV_X64_MSR_TIME_REF_COUNT_AVAILABLE)
clocksource_register_hz(&hyperv_cs, NSEC_PER_SEC/100);
#ifdef CONFIG_X86_IO_APIC
no_timer_check = 1;
#endif
......@@ -227,6 +224,13 @@ static void __init ms_hyperv_init_platform(void)
*/
if (efi_enabled(EFI_BOOT))
x86_platform.get_nmi_reason = hv_get_nmi_reason;
#if IS_ENABLED(CONFIG_HYPERV)
/*
* Setup the hook to get control post apic initialization.
*/
x86_platform.apic_post_init = hyperv_init;
#endif
}
const __refconst struct hypervisor_x86 x86_hyper_ms_hyperv = {
......
......@@ -42,10 +42,22 @@ static struct resource goldfish_pdev_bus_resources[] = {
}
};
static bool goldfish_enable __initdata;
static int __init goldfish_setup(char *str)
{
goldfish_enable = true;
return 0;
}
__setup("goldfish", goldfish_setup);
static int __init goldfish_init(void)
{
if (!goldfish_enable)
return -ENODEV;
platform_device_register_simple("goldfish_pdev_bus", -1,
goldfish_pdev_bus_resources, 2);
goldfish_pdev_bus_resources, 2);
return 0;
}
device_initcall(goldfish_init);
......@@ -202,4 +202,6 @@ source "drivers/hwtracing/intel_th/Kconfig"
source "drivers/fpga/Kconfig"
source "drivers/fsi/Kconfig"
endmenu
......@@ -173,3 +173,4 @@ obj-$(CONFIG_STM) += hwtracing/stm/
obj-$(CONFIG_ANDROID) += android/
obj-$(CONFIG_NVMEM) += nvmem/
obj-$(CONFIG_FPGA) += fpga/
obj-$(CONFIG_FSI) += fsi/
......@@ -19,6 +19,18 @@ config ANDROID_BINDER_IPC
Android process, using Binder to identify, invoke and pass arguments
between said processes.
config ANDROID_BINDER_DEVICES
string "Android Binder devices"
depends on ANDROID_BINDER_IPC
default "binder"
---help---
Default value for the binder.devices parameter.
The binder.devices parameter is a comma-separated list of strings
that specifies the names of the binder device nodes that will be
created. Each binder device has its own context manager, and is
therefore logically separated from the other devices.
config ANDROID_BINDER_IPC_32BIT
bool
depends on !64BIT && ANDROID_BINDER_IPC
......
此差异已折叠。
......@@ -56,14 +56,16 @@
#define HT16K33_FB_SIZE (HT16K33_MATRIX_LED_MAX_COLS * BYTES_PER_ROW)
struct ht16k33_keypad {
struct i2c_client *client;
struct input_dev *dev;
spinlock_t lock;
struct delayed_work work;
uint32_t cols;
uint32_t rows;
uint32_t row_shift;
uint32_t debounce_ms;
uint16_t last_key_state[HT16K33_MATRIX_KEYPAD_MAX_COLS];
wait_queue_head_t wait;
bool stopped;
};
struct ht16k33_fbdev {
......@@ -78,7 +80,6 @@ struct ht16k33_priv {
struct i2c_client *client;
struct ht16k33_keypad keypad;
struct ht16k33_fbdev fbdev;
struct workqueue_struct *workqueue;
};
static struct fb_fix_screeninfo ht16k33_fb_fix = {
......@@ -124,16 +125,8 @@ static void ht16k33_fb_queue(struct ht16k33_priv *priv)
{
struct ht16k33_fbdev *fbdev = &priv->fbdev;
queue_delayed_work(priv->workqueue, &fbdev->work,
msecs_to_jiffies(HZ / fbdev->refresh_rate));
}
static void ht16k33_keypad_queue(struct ht16k33_priv *priv)
{
struct ht16k33_keypad *keypad = &priv->keypad;
queue_delayed_work(priv->workqueue, &keypad->work,
msecs_to_jiffies(keypad->debounce_ms));
schedule_delayed_work(&fbdev->work,
msecs_to_jiffies(HZ / fbdev->refresh_rate));
}
/*
......@@ -182,32 +175,6 @@ static void ht16k33_fb_update(struct work_struct *work)
ht16k33_fb_queue(priv);
}
static int ht16k33_keypad_start(struct input_dev *dev)
{
struct ht16k33_priv *priv = input_get_drvdata(dev);
struct ht16k33_keypad *keypad = &priv->keypad;
/*
* Schedule an immediate key scan to capture current key state;
* columns will be activated and IRQs be enabled after the scan.
*/
queue_delayed_work(priv->workqueue, &keypad->work, 0);
return 0;
}
static void ht16k33_keypad_stop(struct input_dev *dev)
{
struct ht16k33_priv *priv = input_get_drvdata(dev);
struct ht16k33_keypad *keypad = &priv->keypad;
cancel_delayed_work(&keypad->work);
/*
* ht16k33_keypad_scan() will leave IRQs enabled;
* we should disable them now.
*/
disable_irq_nosync(priv->client->irq);
}
static int ht16k33_initialize(struct ht16k33_priv *priv)
{
uint8_t byte;
......@@ -233,61 +200,6 @@ static int ht16k33_initialize(struct ht16k33_priv *priv)
return i2c_smbus_write_byte(priv->client, byte);
}
/*
* This gets the keys from keypad and reports it to input subsystem
*/
static void ht16k33_keypad_scan(struct work_struct *work)
{
struct ht16k33_keypad *keypad =
container_of(work, struct ht16k33_keypad, work.work);
struct ht16k33_priv *priv =
container_of(keypad, struct ht16k33_priv, keypad);
const unsigned short *keycodes = keypad->dev->keycode;
uint16_t bits_changed, new_state[HT16K33_MATRIX_KEYPAD_MAX_COLS];
uint8_t data[HT16K33_MATRIX_KEYPAD_MAX_COLS * 2];
int row, col, code;
bool reschedule = false;
if (i2c_smbus_read_i2c_block_data(priv->client, 0x40, 6, data) != 6) {
dev_err(&priv->client->dev, "Failed to read key data\n");
goto end;
}
for (col = 0; col < keypad->cols; col++) {
new_state[col] = (data[col * 2 + 1] << 8) | data[col * 2];
if (new_state[col])
reschedule = true;
bits_changed = keypad->last_key_state[col] ^ new_state[col];
while (bits_changed) {
row = ffs(bits_changed) - 1;
code = MATRIX_SCAN_CODE(row, col, keypad->row_shift);
input_event(keypad->dev, EV_MSC, MSC_SCAN, code);
input_report_key(keypad->dev, keycodes[code],
new_state[col] & BIT(row));
bits_changed &= ~BIT(row);
}
}
input_sync(keypad->dev);
memcpy(keypad->last_key_state, new_state, sizeof(new_state));
end:
if (reschedule)
ht16k33_keypad_queue(priv);
else
enable_irq(priv->client->irq);
}
static irqreturn_t ht16k33_irq_thread(int irq, void *dev)
{
struct ht16k33_priv *priv = dev;
disable_irq_nosync(priv->client->irq);
ht16k33_keypad_queue(priv);
return IRQ_HANDLED;
}
static int ht16k33_bl_update_status(struct backlight_device *bl)
{
int brightness = bl->props.brightness;
......@@ -334,15 +246,152 @@ static struct fb_ops ht16k33_fb_ops = {
.fb_mmap = ht16k33_mmap,
};
/*
* This gets the keys from keypad and reports it to input subsystem.
* Returns true if a key is pressed.
*/
static bool ht16k33_keypad_scan(struct ht16k33_keypad *keypad)
{
const unsigned short *keycodes = keypad->dev->keycode;
u16 new_state[HT16K33_MATRIX_KEYPAD_MAX_COLS];
u8 data[HT16K33_MATRIX_KEYPAD_MAX_COLS * 2];
unsigned long bits_changed;
int row, col, code;
bool pressed = false;
if (i2c_smbus_read_i2c_block_data(keypad->client, 0x40, 6, data) != 6) {
dev_err(&keypad->client->dev, "Failed to read key data\n");
return false;
}
for (col = 0; col < keypad->cols; col++) {
new_state[col] = (data[col * 2 + 1] << 8) | data[col * 2];
if (new_state[col])
pressed = true;
bits_changed = keypad->last_key_state[col] ^ new_state[col];
for_each_set_bit(row, &bits_changed, BITS_PER_LONG) {
code = MATRIX_SCAN_CODE(row, col, keypad->row_shift);
input_event(keypad->dev, EV_MSC, MSC_SCAN, code);
input_report_key(keypad->dev, keycodes[code],
new_state[col] & BIT(row));
}
}
input_sync(keypad->dev);
memcpy(keypad->last_key_state, new_state, sizeof(new_state));
return pressed;
}
static irqreturn_t ht16k33_keypad_irq_thread(int irq, void *dev)
{
struct ht16k33_keypad *keypad = dev;
do {
wait_event_timeout(keypad->wait, keypad->stopped,
msecs_to_jiffies(keypad->debounce_ms));
if (keypad->stopped)
break;
} while (ht16k33_keypad_scan(keypad));
return IRQ_HANDLED;
}
static int ht16k33_keypad_start(struct input_dev *dev)
{
struct ht16k33_keypad *keypad = input_get_drvdata(dev);
keypad->stopped = false;
mb();
enable_irq(keypad->client->irq);
return 0;
}
static void ht16k33_keypad_stop(struct input_dev *dev)
{
struct ht16k33_keypad *keypad = input_get_drvdata(dev);
keypad->stopped = true;
mb();
wake_up(&keypad->wait);
disable_irq(keypad->client->irq);
}
static int ht16k33_keypad_probe(struct i2c_client *client,
struct ht16k33_keypad *keypad)
{
struct device_node *node = client->dev.of_node;
u32 rows = HT16K33_MATRIX_KEYPAD_MAX_ROWS;
u32 cols = HT16K33_MATRIX_KEYPAD_MAX_COLS;
int err;
keypad->client = client;
init_waitqueue_head(&keypad->wait);
keypad->dev = devm_input_allocate_device(&client->dev);
if (!keypad->dev)
return -ENOMEM;
input_set_drvdata(keypad->dev, keypad);
keypad->dev->name = DRIVER_NAME"-keypad";
keypad->dev->id.bustype = BUS_I2C;
keypad->dev->open = ht16k33_keypad_start;
keypad->dev->close = ht16k33_keypad_stop;
if (!of_get_property(node, "linux,no-autorepeat", NULL))
__set_bit(EV_REP, keypad->dev->evbit);
err = of_property_read_u32(node, "debounce-delay-ms",
&keypad->debounce_ms);
if (err) {
dev_err(&client->dev, "key debounce delay not specified\n");
return err;
}
err = matrix_keypad_parse_of_params(&client->dev, &rows, &cols);
if (err)
return err;
keypad->rows = rows;
keypad->cols = cols;
keypad->row_shift = get_count_order(cols);
err = matrix_keypad_build_keymap(NULL, NULL, rows, cols, NULL,
keypad->dev);
if (err) {
dev_err(&client->dev, "failed to build keymap\n");
return err;
}
err = devm_request_threaded_irq(&client->dev, client->irq,
NULL, ht16k33_keypad_irq_thread,
IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
DRIVER_NAME, keypad);
if (err) {
dev_err(&client->dev, "irq request failed %d, error %d\n",
client->irq, err);
return err;
}
ht16k33_keypad_stop(keypad->dev);
err = input_register_device(keypad->dev);
if (err)
return err;
return 0;
}
static int ht16k33_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
int err;
uint32_t rows, cols, dft_brightness;
uint32_t dft_brightness;
struct backlight_device *bl;
struct backlight_properties bl_props;
struct ht16k33_priv *priv;
struct ht16k33_keypad *keypad;
struct ht16k33_fbdev *fbdev;
struct device_node *node = client->dev.of_node;
......@@ -363,23 +412,16 @@ static int ht16k33_probe(struct i2c_client *client,
priv->client = client;
i2c_set_clientdata(client, priv);
fbdev = &priv->fbdev;
keypad = &priv->keypad;
priv->workqueue = create_singlethread_workqueue(DRIVER_NAME "-wq");
if (priv->workqueue == NULL)
return -ENOMEM;
err = ht16k33_initialize(priv);
if (err)
goto err_destroy_wq;
return err;
/* Framebuffer (2 bytes per column) */
BUILD_BUG_ON(PAGE_SIZE < HT16K33_FB_SIZE);
fbdev->buffer = (unsigned char *) get_zeroed_page(GFP_KERNEL);
if (!fbdev->buffer) {
err = -ENOMEM;
goto err_free_fbdev;
}
if (!fbdev->buffer)
return -ENOMEM;
fbdev->cache = devm_kmalloc(&client->dev, HT16K33_FB_SIZE, GFP_KERNEL);
if (!fbdev->cache) {
......@@ -415,59 +457,7 @@ static int ht16k33_probe(struct i2c_client *client,
if (err)
goto err_fbdev_info;
/* Keypad */
keypad->dev = devm_input_allocate_device(&client->dev);
if (!keypad->dev) {
err = -ENOMEM;
goto err_fbdev_unregister;
}
keypad->dev->name = DRIVER_NAME"-keypad";
keypad->dev->id.bustype = BUS_I2C;
keypad->dev->open = ht16k33_keypad_start;
keypad->dev->close = ht16k33_keypad_stop;
if (!of_get_property(node, "linux,no-autorepeat", NULL))
__set_bit(EV_REP, keypad->dev->evbit);
err = of_property_read_u32(node, "debounce-delay-ms",
&keypad->debounce_ms);
if (err) {
dev_err(&client->dev, "key debounce delay not specified\n");
goto err_fbdev_unregister;
}
err = devm_request_threaded_irq(&client->dev, client->irq, NULL,
ht16k33_irq_thread,
IRQF_TRIGGER_RISING | IRQF_ONESHOT,
DRIVER_NAME, priv);
if (err) {
dev_err(&client->dev, "irq request failed %d, error %d\n",
client->irq, err);
goto err_fbdev_unregister;
}
disable_irq_nosync(client->irq);
rows = HT16K33_MATRIX_KEYPAD_MAX_ROWS;
cols = HT16K33_MATRIX_KEYPAD_MAX_COLS;
err = matrix_keypad_parse_of_params(&client->dev, &rows, &cols);
if (err)
goto err_fbdev_unregister;
err = matrix_keypad_build_keymap(NULL, NULL, rows, cols, NULL,
keypad->dev);
if (err) {
dev_err(&client->dev, "failed to build keymap\n");
goto err_fbdev_unregister;
}
input_set_drvdata(keypad->dev, priv);
keypad->rows = rows;
keypad->cols = cols;
keypad->row_shift = get_count_order(cols);
INIT_DELAYED_WORK(&keypad->work, ht16k33_keypad_scan);
err = input_register_device(keypad->dev);
err = ht16k33_keypad_probe(client, &priv->keypad);
if (err)
goto err_fbdev_unregister;
......@@ -482,7 +472,7 @@ static int ht16k33_probe(struct i2c_client *client,
if (IS_ERR(bl)) {
dev_err(&client->dev, "failed to register backlight\n");
err = PTR_ERR(bl);
goto err_keypad_unregister;
goto err_fbdev_unregister;
}
err = of_property_read_u32(node, "default-brightness-level",
......@@ -502,18 +492,12 @@ static int ht16k33_probe(struct i2c_client *client,
ht16k33_fb_queue(priv);
return 0;
err_keypad_unregister:
input_unregister_device(keypad->dev);
err_fbdev_unregister:
unregister_framebuffer(fbdev->info);
err_fbdev_info:
framebuffer_release(fbdev->info);
err_fbdev_buffer:
free_page((unsigned long) fbdev->buffer);
err_free_fbdev:
kfree(fbdev);
err_destroy_wq:
destroy_workqueue(priv->workqueue);
return err;
}
......@@ -521,17 +505,13 @@ static int ht16k33_probe(struct i2c_client *client,
static int ht16k33_remove(struct i2c_client *client)
{
struct ht16k33_priv *priv = i2c_get_clientdata(client);
struct ht16k33_keypad *keypad = &priv->keypad;
struct ht16k33_fbdev *fbdev = &priv->fbdev;
ht16k33_keypad_stop(keypad->dev);
cancel_delayed_work(&fbdev->work);
unregister_framebuffer(fbdev->info);
framebuffer_release(fbdev->info);
free_page((unsigned long) fbdev->buffer);
destroy_workqueue(priv->workqueue);
return 0;
}
......
......@@ -571,9 +571,12 @@ config TELCLOCK
controlling the behavior of this hardware.
config DEVPORT
bool
bool "/dev/port character device"
depends on ISA || PCI
default y
help
Say Y here if you want to support the /dev/port device. The /dev/port
device is similar to /dev/mem, but for I/O ports.
source "drivers/s390/char/Kconfig"
......
......@@ -31,13 +31,6 @@
#include <linux/kthread.h>
#include <linux/delay.h>
/*
* The apm_bios device is one of the misc char devices.
* This is its minor number.
*/
#define APM_MINOR_DEV 134
/*
* One option can be changed at boot time as follows:
* apm=on/off enable/disable APM
......
......@@ -17,7 +17,6 @@
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/miscdevice.h>
#include <linux/delay.h>
#include <linux/bcd.h>
#include <linux/mutex.h>
......
......@@ -463,9 +463,9 @@ static int mmtimer_mmap(struct file *file, struct vm_area_struct *vma)
}
static struct miscdevice mmtimer_miscdev = {
SGI_MMTIMER,
MMTIMER_NAME,
&mmtimer_fops
.minor = SGI_MMTIMER,
.name = MMTIMER_NAME,
.fops = &mmtimer_fops
};
static struct timespec sgi_clock_offset;
......
......@@ -269,7 +269,6 @@ int buffer_icap_set_configuration(struct hwicap_drvdata *drvdata, u32 *data,
{
int status;
s32 buffer_count = 0;
s32 num_writes = 0;
bool dirty = false;
u32 i;
void __iomem *base_address = drvdata->base_address;
......@@ -298,7 +297,6 @@ int buffer_icap_set_configuration(struct hwicap_drvdata *drvdata, u32 *data,
}
buffer_count = 0;
num_writes++;
dirty = false;
}
......@@ -328,7 +326,6 @@ int buffer_icap_get_configuration(struct hwicap_drvdata *drvdata, u32 *data,
{
int status;
s32 buffer_count = 0;
s32 read_count = 0;
u32 i;
void __iomem *base_address = drvdata->base_address;
......@@ -353,7 +350,6 @@ int buffer_icap_get_configuration(struct hwicap_drvdata *drvdata, u32 *data,
}
buffer_count = 0;
read_count++;
}
/* Copy data from bram */
......
......@@ -42,6 +42,16 @@ config EXTCON_GPIO
Say Y here to enable GPIO based extcon support. Note that GPIO
extcon supports single state per extcon instance.
config EXTCON_INTEL_INT3496
tristate "Intel INT3496 ACPI device extcon driver"
depends on GPIOLIB && ACPI
help
Say Y here to enable extcon support for USB OTG ports controlled by
an Intel INT3496 ACPI device.
This ACPI device is typically found on Intel Baytrail or Cherrytrail
based tablets, or other Baytrail / Cherrytrail devices.
config EXTCON_MAX14577
tristate "Maxim MAX14577/77836 EXTCON Support"
depends on MFD_MAX14577
......
......@@ -8,6 +8,7 @@ obj-$(CONFIG_EXTCON_ADC_JACK) += extcon-adc-jack.o
obj-$(CONFIG_EXTCON_ARIZONA) += extcon-arizona.o
obj-$(CONFIG_EXTCON_AXP288) += extcon-axp288.o
obj-$(CONFIG_EXTCON_GPIO) += extcon-gpio.o
obj-$(CONFIG_EXTCON_INTEL_INT3496) += extcon-intel-int3496.o
obj-$(CONFIG_EXTCON_MAX14577) += extcon-max14577.o
obj-$(CONFIG_EXTCON_MAX3355) += extcon-max3355.o
obj-$(CONFIG_EXTCON_MAX77693) += extcon-max77693.o
......
......@@ -14,7 +14,7 @@
* GNU General Public License for more details.
*/
#include <linux/extcon.h>
#include "extcon.h"
static int devm_extcon_dev_match(struct device *dev, void *res, void *data)
{
......
......@@ -67,7 +67,7 @@ static void adc_jack_handler(struct work_struct *work)
ret = iio_read_channel_raw(data->chan, &adc_val);
if (ret < 0) {
dev_err(&data->edev->dev, "read channel() error: %d\n", ret);
dev_err(data->dev, "read channel() error: %d\n", ret);
return;
}
......
......@@ -236,12 +236,8 @@ static void arizona_extcon_set_mode(struct arizona_extcon_info *info, int mode)
mode %= info->micd_num_modes;
if (arizona->pdata.micd_pol_gpio > 0)
gpio_set_value_cansleep(arizona->pdata.micd_pol_gpio,
info->micd_modes[mode].gpio);
else
gpiod_set_value_cansleep(info->micd_pol_gpio,
info->micd_modes[mode].gpio);
gpiod_set_value_cansleep(info->micd_pol_gpio,
info->micd_modes[mode].gpio);
regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1,
ARIZONA_MICD_BIAS_SRC_MASK,
......@@ -1412,21 +1408,21 @@ static int arizona_extcon_probe(struct platform_device *pdev)
regmap_update_bits(arizona->regmap, ARIZONA_GP_SWITCH_1,
ARIZONA_SW1_MODE_MASK, arizona->pdata.gpsw);
if (arizona->pdata.micd_pol_gpio > 0) {
if (pdata->micd_pol_gpio > 0) {
if (info->micd_modes[0].gpio)
mode = GPIOF_OUT_INIT_HIGH;
else
mode = GPIOF_OUT_INIT_LOW;
ret = devm_gpio_request_one(&pdev->dev,
arizona->pdata.micd_pol_gpio,
mode,
"MICD polarity");
ret = devm_gpio_request_one(&pdev->dev, pdata->micd_pol_gpio,
mode, "MICD polarity");
if (ret != 0) {
dev_err(arizona->dev, "Failed to request GPIO%d: %d\n",
arizona->pdata.micd_pol_gpio, ret);
pdata->micd_pol_gpio, ret);
goto err_register;
}
info->micd_pol_gpio = gpio_to_desc(pdata->micd_pol_gpio);
} else {
if (info->micd_modes[0].gpio)
mode = GPIOD_OUT_HIGH;
......
......@@ -21,7 +21,6 @@
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/property.h>
#include <linux/usb/phy.h>
#include <linux/notifier.h>
#include <linux/extcon.h>
#include <linux/regmap.h>
......@@ -71,12 +70,6 @@
#define DET_STAT_CDP 2
#define DET_STAT_DCP 3
/* IRQ enable-1 register */
#define PWRSRC_IRQ_CFG_MASK (BIT(4)|BIT(3)|BIT(2))
/* IRQ enable-6 register */
#define BC12_IRQ_CFG_MASK BIT(1)
enum axp288_extcon_reg {
AXP288_PS_STAT_REG = 0x00,
AXP288_PS_BOOT_REASON_REG = 0x02,
......@@ -84,8 +77,6 @@ enum axp288_extcon_reg {
AXP288_BC_VBUS_CNTL_REG = 0x2d,
AXP288_BC_USB_STAT_REG = 0x2e,
AXP288_BC_DET_STAT_REG = 0x2f,
AXP288_PWRSRC_IRQ_CFG_REG = 0x40,
AXP288_BC12_IRQ_CFG_REG = 0x45,
};
enum axp288_mux_select {
......@@ -105,6 +96,7 @@ static const unsigned int axp288_extcon_cables[] = {
EXTCON_CHG_USB_SDP,
EXTCON_CHG_USB_CDP,
EXTCON_CHG_USB_DCP,
EXTCON_USB,
EXTCON_NONE,
};
......@@ -112,11 +104,11 @@ struct axp288_extcon_info {
struct device *dev;
struct regmap *regmap;
struct regmap_irq_chip_data *regmap_irqc;
struct axp288_extcon_pdata *pdata;
struct gpio_desc *gpio_mux_cntl;
int irq[EXTCON_IRQ_END];
struct extcon_dev *edev;
struct notifier_block extcon_nb;
struct usb_phy *otg;
unsigned int previous_cable;
};
/* Power up/down reason string array */
......@@ -156,10 +148,9 @@ static void axp288_extcon_log_rsi(struct axp288_extcon_info *info)
static int axp288_handle_chrg_det_event(struct axp288_extcon_info *info)
{
static bool notify_otg, notify_charger;
static unsigned int cable;
int ret, stat, cfg, pwr_stat;
u8 chrg_type;
unsigned int cable = info->previous_cable;
bool vbus_attach = false;
ret = regmap_read(info->regmap, AXP288_PS_STAT_REG, &pwr_stat);
......@@ -168,9 +159,9 @@ static int axp288_handle_chrg_det_event(struct axp288_extcon_info *info)
return ret;
}
vbus_attach = (pwr_stat & PS_STAT_VBUS_PRESENT);
vbus_attach = (pwr_stat & PS_STAT_VBUS_VALID);
if (!vbus_attach)
goto notify_otg;
goto no_vbus;
/* Check charger detection completion status */
ret = regmap_read(info->regmap, AXP288_BC_GLOBAL_REG, &cfg);
......@@ -190,19 +181,14 @@ static int axp288_handle_chrg_det_event(struct axp288_extcon_info *info)
switch (chrg_type) {
case DET_STAT_SDP:
dev_dbg(info->dev, "sdp cable is connected\n");
notify_otg = true;
notify_charger = true;
cable = EXTCON_CHG_USB_SDP;
break;
case DET_STAT_CDP:
dev_dbg(info->dev, "cdp cable is connected\n");
notify_otg = true;
notify_charger = true;
cable = EXTCON_CHG_USB_CDP;
break;
case DET_STAT_DCP:
dev_dbg(info->dev, "dcp cable is connected\n");
notify_charger = true;
cable = EXTCON_CHG_USB_DCP;
break;
default:
......@@ -210,27 +196,28 @@ static int axp288_handle_chrg_det_event(struct axp288_extcon_info *info)
"disconnect or unknown or ID event\n");
}
notify_otg:
if (notify_otg) {
/*
* If VBUS is absent Connect D+/D- lines to PMIC for BC
* detection. Else connect them to SOC for USB communication.
*/
if (info->pdata->gpio_mux_cntl)
gpiod_set_value(info->pdata->gpio_mux_cntl,
vbus_attach ? EXTCON_GPIO_MUX_SEL_SOC
: EXTCON_GPIO_MUX_SEL_PMIC);
atomic_notifier_call_chain(&info->otg->notifier,
vbus_attach ? USB_EVENT_VBUS : USB_EVENT_NONE, NULL);
}
if (notify_charger)
no_vbus:
/*
* If VBUS is absent Connect D+/D- lines to PMIC for BC
* detection. Else connect them to SOC for USB communication.
*/
if (info->gpio_mux_cntl)
gpiod_set_value(info->gpio_mux_cntl,
vbus_attach ? EXTCON_GPIO_MUX_SEL_SOC
: EXTCON_GPIO_MUX_SEL_PMIC);
extcon_set_state_sync(info->edev, info->previous_cable, false);
if (info->previous_cable == EXTCON_CHG_USB_SDP)
extcon_set_state_sync(info->edev, EXTCON_USB, false);
if (vbus_attach) {
extcon_set_state_sync(info->edev, cable, vbus_attach);
if (cable == EXTCON_CHG_USB_SDP)
extcon_set_state_sync(info->edev, EXTCON_USB,
vbus_attach);
/* Clear the flags on disconnect event */
if (!vbus_attach)
notify_otg = notify_charger = false;
info->previous_cable = cable;
}
return 0;
......@@ -253,15 +240,10 @@ static irqreturn_t axp288_extcon_isr(int irq, void *data)
return IRQ_HANDLED;
}
static void axp288_extcon_enable_irq(struct axp288_extcon_info *info)
static void axp288_extcon_enable(struct axp288_extcon_info *info)
{
/* Unmask VBUS interrupt */
regmap_write(info->regmap, AXP288_PWRSRC_IRQ_CFG_REG,
PWRSRC_IRQ_CFG_MASK);
regmap_update_bits(info->regmap, AXP288_BC_GLOBAL_REG,
BC_GLOBAL_RUN, 0);
/* Unmask the BC1.2 complete interrupts */
regmap_write(info->regmap, AXP288_BC12_IRQ_CFG_REG, BC12_IRQ_CFG_MASK);
/* Enable the charger detection logic */
regmap_update_bits(info->regmap, AXP288_BC_GLOBAL_REG,
BC_GLOBAL_RUN, BC_GLOBAL_RUN);
......@@ -271,6 +253,7 @@ static int axp288_extcon_probe(struct platform_device *pdev)
{
struct axp288_extcon_info *info;
struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent);
struct axp288_extcon_pdata *pdata = pdev->dev.platform_data;
int ret, i, pirq, gpio;
info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
......@@ -280,15 +263,10 @@ static int axp288_extcon_probe(struct platform_device *pdev)
info->dev = &pdev->dev;
info->regmap = axp20x->regmap;
info->regmap_irqc = axp20x->regmap_irqc;
info->pdata = pdev->dev.platform_data;
if (!info->pdata) {
/* Try ACPI provided pdata via device properties */
if (!device_property_present(&pdev->dev,
"axp288_extcon_data\n"))
dev_err(&pdev->dev, "failed to get platform data\n");
return -ENODEV;
}
info->previous_cable = EXTCON_NONE;
if (pdata)
info->gpio_mux_cntl = pdata->gpio_mux_cntl;
platform_set_drvdata(pdev, info);
axp288_extcon_log_rsi(info);
......@@ -308,23 +286,16 @@ static int axp288_extcon_probe(struct platform_device *pdev)
return ret;
}
/* Get otg transceiver phy */
info->otg = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2);
if (IS_ERR(info->otg)) {
dev_err(&pdev->dev, "failed to get otg transceiver\n");
return PTR_ERR(info->otg);
}
/* Set up gpio control for USB Mux */
if (info->pdata->gpio_mux_cntl) {
gpio = desc_to_gpio(info->pdata->gpio_mux_cntl);
if (info->gpio_mux_cntl) {
gpio = desc_to_gpio(info->gpio_mux_cntl);
ret = devm_gpio_request(&pdev->dev, gpio, "USB_MUX");
if (ret < 0) {
dev_err(&pdev->dev,
"failed to request the gpio=%d\n", gpio);
return ret;
}
gpiod_direction_output(info->pdata->gpio_mux_cntl,
gpiod_direction_output(info->gpio_mux_cntl,
EXTCON_GPIO_MUX_SEL_PMIC);
}
......@@ -349,14 +320,21 @@ static int axp288_extcon_probe(struct platform_device *pdev)
}
}
/* Enable interrupts */
axp288_extcon_enable_irq(info);
/* Start charger cable type detection */
axp288_extcon_enable(info);
return 0;
}
static const struct platform_device_id axp288_extcon_table[] = {
{ .name = "axp288_extcon" },
{},
};
MODULE_DEVICE_TABLE(platform, axp288_extcon_table);
static struct platform_driver axp288_extcon_driver = {
.probe = axp288_extcon_probe,
.id_table = axp288_extcon_table,
.driver = {
.name = "axp288_extcon",
},
......
此差异已折叠。
......@@ -531,8 +531,10 @@ static int max14577_parse_irq(struct max14577_muic_info *info, int irq_type)
case MAX14577_IRQ_INT1_ADC:
case MAX14577_IRQ_INT1_ADCLOW:
case MAX14577_IRQ_INT1_ADCERR:
/* Handle all of accessory except for
type of charger accessory */
/*
* Handle all of accessory except for
* type of charger accessory.
*/
info->irq_adc = true;
return 1;
case MAX14577_IRQ_INT2_CHGTYP:
......
......@@ -188,8 +188,10 @@ enum max77693_muic_acc_type {
MAX77693_MUIC_ADC_AUDIO_MODE_REMOTE,
MAX77693_MUIC_ADC_OPEN,
/* The below accessories have same ADC value so ADCLow and
ADC1K bit is used to separate specific accessory */
/*
* The below accessories have same ADC value so ADCLow and
* ADC1K bit is used to separate specific accessory.
*/
/* ADC|VBVolot|ADCLow|ADC1K| */
MAX77693_MUIC_GND_USB_HOST = 0x100, /* 0x0| 0| 0| 0| */
MAX77693_MUIC_GND_USB_HOST_VB = 0x104, /* 0x0| 1| 0| 0| */
......@@ -970,8 +972,10 @@ static void max77693_muic_irq_work(struct work_struct *work)
case MAX77693_MUIC_IRQ_INT1_ADC_LOW:
case MAX77693_MUIC_IRQ_INT1_ADC_ERR:
case MAX77693_MUIC_IRQ_INT1_ADC1K:
/* Handle all of accessory except for
type of charger accessory */
/*
* Handle all of accessory except for
* type of charger accessory.
*/
ret = max77693_muic_adc_handler(info);
break;
case MAX77693_MUIC_IRQ_INT2_CHGTYP:
......
......@@ -97,8 +97,10 @@ enum max77843_muic_accessory_type {
MAX77843_MUIC_ADC_AUDIO_DEVICE_TYPE1,
MAX77843_MUIC_ADC_OPEN,
/* The blow accessories should check
not only ADC value but also ADC1K and VBVolt value. */
/*
* The below accessories should check
* not only ADC value but also ADC1K and VBVolt value.
*/
/* Offset|ADC1K|VBVolt| */
MAX77843_MUIC_GND_USB_HOST = 0x100, /* 0x1| 0| 0| */
MAX77843_MUIC_GND_USB_HOST_VB = 0x101, /* 0x1| 0| 1| */
......@@ -265,16 +267,20 @@ static int max77843_muic_get_cable_type(struct max77843_muic_info *info,
/* Check GROUND accessory with charger cable */
if (adc == MAX77843_MUIC_ADC_GROUND) {
if (chg_type == MAX77843_MUIC_CHG_NONE) {
/* The following state when charger cable is
/*
* The following state when charger cable is
* disconnected but the GROUND accessory still
* connected */
* connected.
*/
*attached = false;
cable_type = info->prev_chg_type;
info->prev_chg_type = MAX77843_MUIC_CHG_NONE;
} else {
/* The following state when charger cable is
* connected on the GROUND accessory */
/*
* The following state when charger cable is
* connected on the GROUND accessory.
*/
*attached = true;
cable_type = MAX77843_MUIC_CHG_GND;
info->prev_chg_type = MAX77843_MUIC_CHG_GND;
......@@ -299,11 +305,13 @@ static int max77843_muic_get_cable_type(struct max77843_muic_info *info,
} else {
*attached = true;
/* Offset|ADC1K|VBVolt|
/*
* Offset|ADC1K|VBVolt|
* 0x1| 0| 0| USB-HOST
* 0x1| 0| 1| USB-HOST with VB
* 0x1| 1| 0| MHL
* 0x1| 1| 1| MHL with VB */
* 0x1| 1| 1| MHL with VB
*/
/* Get ADC1K register bit */
gnd_type = (info->status[MAX77843_MUIC_STATUS1] &
MAX77843_MUIC_STATUS1_ADC1K_MASK);
......
此差异已折叠。
......@@ -142,8 +142,10 @@ enum rt8973a_muic_acc_type {
RT8973A_MUIC_ADC_UNKNOWN_ACC_5,
RT8973A_MUIC_ADC_OPEN = 0x1f,
/* The below accessories has same ADC value (0x1f).
So, Device type1 is used to separate specific accessory. */
/*
* The below accessories has same ADC value (0x1f).
* So, Device type1 is used to separate specific accessory.
*/
/* |---------|--ADC| */
/* | [7:5]|[4:0]| */
RT8973A_MUIC_ADC_USB = 0x3f, /* | 001|11111| */
......
......@@ -135,8 +135,10 @@ enum sm5502_muic_acc_type {
SM5502_MUIC_ADC_AUDIO_TYPE1,
SM5502_MUIC_ADC_OPEN = 0x1f,
/* The below accessories have same ADC value (0x1f or 0x1e).
So, Device type1 is used to separate specific accessory. */
/*
* The below accessories have same ADC value (0x1f or 0x1e).
* So, Device type1 is used to separate specific accessory.
*/
/* |---------|--ADC| */
/* | [7:5]|[4:0]| */
SM5502_MUIC_ADC_AUDIO_TYPE1_FULL_REMOTE = 0x3e, /* | 001|11110| */
......
......@@ -27,6 +27,7 @@
#include <linux/slab.h>
#include <linux/workqueue.h>
#include <linux/acpi.h>
#include <linux/pinctrl/consumer.h>
#define USB_GPIO_DEBOUNCE_MS 20 /* ms */
......@@ -245,6 +246,9 @@ static int usb_extcon_suspend(struct device *dev)
if (info->vbus_gpiod)
disable_irq(info->vbus_irq);
if (!device_may_wakeup(dev))
pinctrl_pm_select_sleep_state(dev);
return ret;
}
......@@ -253,6 +257,9 @@ static int usb_extcon_resume(struct device *dev)
struct usb_extcon_info *info = dev_get_drvdata(dev);
int ret = 0;
if (!device_may_wakeup(dev))
pinctrl_pm_select_default_state(dev);
if (device_may_wakeup(dev)) {
if (info->id_gpiod) {
ret = disable_irq_wake(info->id_irq);
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
obj-$(CONFIG_FSI) += fsi-core.o
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
......@@ -587,6 +587,7 @@ static int hv_memory_notifier(struct notifier_block *nb, unsigned long val,
spin_lock_irqsave(&dm_device.ha_lock, flags);
dm_device.num_pages_onlined += mem->nr_pages;
spin_unlock_irqrestore(&dm_device.ha_lock, flags);
/* Fall through */
case MEM_CANCEL_ONLINE:
if (dm_device.ha_waiting) {
dm_device.ha_waiting = false;
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册