* [PATCH 2/2] arm64: dts: renesas: condor: add I2C0 support
From: Sergei Shtylyov @ 2018-05-28 20:14 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <e9c94553-be9d-0eec-a1ee-1713bb97fbab@cogentembedded.com>
Define the Condor board dependent part of the I2C0 device node.
The I2C0 bus is populated by 2 ON Semiconductor PCA9654 I/O expanders
and Analog Devices ADV7511W HDMI transmitter (but we're only describing
the former chips now).
Signed-off-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
---
arch/arm64/boot/dts/renesas/r8a77980-condor.dts | 27 ++++++++++++++++++++++++
1 file changed, 27 insertions(+)
Index: renesas/arch/arm64/boot/dts/renesas/r8a77980-condor.dts
===================================================================
--- renesas.orig/arch/arm64/boot/dts/renesas/r8a77980-condor.dts
+++ renesas/arch/arm64/boot/dts/renesas/r8a77980-condor.dts
@@ -80,6 +80,28 @@
clock-frequency = <32768>;
};
+&i2c0 {
+ pinctrl-0 = <&i2c0_pins>;
+ pinctrl-names = "default";
+
+ status = "okay";
+ clock-frequency = <400000>;
+
+ io_expander0: gpio at 20 {
+ compatible = "onnn,pca9654";
+ reg = <0x20>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ io_expander1: gpio at 21 {
+ compatible = "onnn,pca9654";
+ reg = <0x21>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+};
+
&mmc0 {
pinctrl-0 = <&mmc_pins>;
pinctrl-1 = <&mmc_pins_uhs>;
@@ -104,6 +126,11 @@
function = "canfd0";
};
+ i2c0_pins: i2c0 {
+ groups = "i2c0";
+ function = "i2c0";
+ };
+
mmc_pins: mmc {
groups = "mmc_data8", "mmc_ctrl", "mmc_ds";
function = "mmc";
^ permalink raw reply
* [PATCH v3 0/2] Add R8A77980/Condor I2C support
From: Sergei Shtylyov @ 2018-05-28 20:16 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <e9c94553-be9d-0eec-a1ee-1713bb97fbab@cogentembedded.com>
Sorry, "v3" shouldn't be there in the subject...
^ permalink raw reply
* [patch v22 4/4] Documentation: jtag: Add ABI documentation
From: Randy Dunlap @ 2018-05-28 20:32 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1527508827-30724-5-git-send-email-oleksandrs@mellanox.com>
On 05/28/2018 05:00 AM, Oleksandr Shamray wrote:
> Added document that describe the ABI for JTAG class drivrer
>
> Signed-off-by: Oleksandr Shamray <oleksandrs@mellanox.com>
> Acked-by: Arnd Bergmann <arnd@arndb.de>
> ---
> ---
> Documentation/ABI/testing/jtag-dev | 27 +++++++++
> Documentation/jtag/overview | 28 +++++++++
> Documentation/jtag/transactions | 109 ++++++++++++++++++++++++++++++++++++
> MAINTAINERS | 1 +
> 4 files changed, 165 insertions(+), 0 deletions(-)
> create mode 100644 Documentation/ABI/testing/jtag-dev
> create mode 100644 Documentation/jtag/overview
> create mode 100644 Documentation/jtag/transactions
>
> diff --git a/Documentation/jtag/overview b/Documentation/jtag/overview
> new file mode 100644
> index 0000000..42b487a
> --- /dev/null
> +++ b/Documentation/jtag/overview
> @@ -0,0 +1,28 @@
> +Linux kernel JTAG support
> +=========================
> +
> +The JTAG is an industry standard for verifying hardware.
JTAG is an
> +JTAG provides access to many logic signals of a complex integrated circuit,
> +including the device pins.
> +
> +A JTAG interface is a special interface added to a chip.
> +Depending on the version of JTAG, two, four, or five pins are added.
> +
> +The connector pins are:
> + TDI (Test Data In)
> + TDO (Test Data Out)
> + TCK (Test Clock)
> + TMS (Test Mode Select)
> + TRST (Test Reset) optional
> +
> +JTAG interface is designed to have two parts - basic core driver and
> +hardware specific driver. The basic driver introduces a general interface
> +which is not dependent of specific hardware. It provides communication
> +between user space and hardware specific driver.
> +Each JTAG device is represented as a char device from (jtag0, jtag1, ...).
> +Access to a JTAG device is performed through IOCTL calls.
> +
> +Call flow example:
> +User: open -> /dev/jatgX
> +User: ioctl -> /dev/jtagX -> JTAG core driver -> JTAG hardware specific driver
> +User: close -> /dev/jatgX
> diff --git a/Documentation/jtag/transactions b/Documentation/jtag/transactions
> new file mode 100644
> index 0000000..2abf833
> --- /dev/null
> +++ b/Documentation/jtag/transactions
> @@ -0,0 +1,109 @@
> +The JTAG API
> +=============
> +
> +JTAG master devices can be accessed through a character misc-device.
> +Each JTAG master interface can be accessed by using /dev/jtagN.
> +
> +JTAG system calls set:
> +- SIR (Scan Instruction Register, IEEE 1149.1 Instruction Register scan);
> +- SDR (Scan Data Register, IEEE 1149.1 Data Register scan);
> +- RUNTEST (Forces the IEEE 1149.1 bus to a run state for a specified
> +number of clocks.
> +
> +open(), close()
> +-------
> +open() opens JTAG device. Only one open operation per JTAG device
> +can be performed. Two or more open for one device will return error.
> +
> +Open/Close device:
> +- jtag_fd = open("/dev/jtag0", O_RDWR);
> +- close(jtag_fd);
> +
> +ioctl()
> +-------
> +All access operations to JTAG devices performed through ioctl interface.
to JTAG devices are performed through
> +The IOCTL interface supports these requests:
> + JTAG_IOCRUNTEST - Force JTAG state machine to RUN_TEST/IDLE state
> + JTAG_SIOCFREQ - Set JTAG TCK frequency
> + JTAG_GIOCFREQ - Get JTAG TCK frequency
> + JTAG_IOCXFER - send JTAG data Xfer
> + JTAG_GIOCSTATUS - get current JTAG TAP status
> + JTAG_SIOCMODE - set JTAG mode flags.
> +
> +JTAG_SIOCFREQ, JTAG_GIOCFREQ
> +------
> +Set/Get JTAG clock speed:
> +
> + unsigned int jtag_fd;
> + ioctl(jtag_fd, JTAG_SIOCFREQ, &frq);
> + ioctl(jtag_fd, JTAG_GIOCFREQ, &frq);
> +
> +JTAG_IOCRUNTEST
> +------
> +Force JTAG state machine to RUN_TEST/IDLE state
> +
> +struct jtag_run_test_idle {
> + __u8 reset;
> + __u8 endstate;
> + __u8 tck;
> +};
> +
> +reset: 0 - run IDLE/PAUSE from current state
> + 1 - go through TEST_LOGIC/RESET state before IDLE/PAUSE
before IDLE/PAUSE
> +endstate: completion flag
> +tck: clock counter
> +
> +Example:
> + struct jtag_run_test_idle runtest;
> +
> + runtest.endstate = JTAG_STATE_IDLE;
> + runtest.reset = 0;
> + runtest.tck = data_p->tck;
> + usleep(25 * 1000);
> + ioctl(jtag_fd, JTAG_IOCRUNTEST, &runtest);
> +
> +JTAG_IOCXFER
> +------
> +Send SDR/SIR transaction
> +
> +struct jtag_xfer {
> + __u8 type;
> + __u8 direction;
> + __u8 endstate;
> + __u8 padding;
> + __u32 length;
> + __u64 tdio;
> +};
> +
> +type: transfer type - JTAG_SIR_XFER/JTAG_SDR_XFER
> +direction: xfer direction - JTAG_SIR_XFER/JTAG_SDR_XFER,
drop ending comma ^
> +length: xfer data len in bits
s/len/length/
> +tdio : xfer data array
> +endstate: xfer end state after transaction finish
> + can be: JTAG_STATE_IDLE/JTAG_STATE_PAUSEIR/JTAG_STATE_PAUSEDR
> +
> +Example:
> + struct jtag_xfer xfer;
> + static char buf[64];
> + static unsigned int buf_len = 0;
> + [...]
> + xfer.type = JTAG_SDR_XFER;
> + xfer.tdio = (__u64)buf;
> + xfer.length = buf_len;
> + xfer.endstate = JTAG_STATE_IDLE;
> +
> + if (is_read)
> + xfer.direction = JTAG_READ_XFER;
> + else
> + xfer.direction = JTAG_WRITE_XFER;
> +
> + ioctl(jtag_fd, JTAG_IOCXFER, &xfer);
> +
> +JTAG_SIOCMODE
> +------
> +If hardware driver can support different running modes you can change it.
> +
> +Example:
> + unsigned int mode;
> + mode = JTAG_XFER_HW_MODE;
> + ioctl(jtag_fd, JTAG_SIOCMODE, &mode);
--
~Randy
^ permalink raw reply
* [PATCH V3 1/2] PCI: Try to clean up resources via remove if shutdown doesn't exist
From: Sinan Kaya @ 2018-05-28 21:21 UTC (permalink / raw)
To: linux-arm-kernel
It is up to a driver to implement shutdown() callback. If shutdown()
callback is not implemented, PCI device can have pending interrupt and
even do DMA transactions while the system is going down.
If kexec is in use, this can damage the newly booting kexec kernel
or even prevent it from booting altogether. Fallback to calling the
remove() callback if shutdown() isn't implemented for a given driver.
Signed-off-by: Sinan Kaya <okaya@codeaurora.org>
Link: https://bugzilla.kernel.org/show_bug.cgi?id=199779
Fixes: cc27b735ad3a ("PCI/portdrv: Turn off PCIe services during shutdown")
Cc: stable at vger.kernel.org
Reported-by: Ryan Finnie <ryan@finnie.org>
---
drivers/pci/pci-driver.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index cbda0e6..75a00fe 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -477,8 +477,17 @@ static void pci_device_shutdown(struct device *dev)
pm_runtime_resume(dev);
+ /*
+ * Try shutdown callback if it exists, otherwise fallback to remove
+ * callback. PCI drivers can do DMA and have pending interrupts.
+ * Leaving the DMA and interrupts pending could damage the newly
+ * booting kexec kernel as well as prevent it from booting altogether
+ * if the pending interrupt is level.
+ */
if (drv && drv->shutdown)
drv->shutdown(pci_dev);
+ else if (drv && drv->remove)
+ drv->remove(pci_dev);
/*
* If this is a kexec reboot, turn off Bus Master bit on the
--
2.7.4
^ permalink raw reply related
* [PATCH V3 2/2] scsi: hpsa: drop shutdown callback
From: Sinan Kaya @ 2018-05-28 21:21 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1527542471-10316-1-git-send-email-okaya@codeaurora.org>
'Commit cc27b735ad3a ("PCI/portdrv: Turn off PCIe services during
shutdown")' has been added to kernel to shutdown pending PCIe port
service interrupts during reboot so that a newly started kexec kernel
wouldn't observe pending interrupts.
pcie_port_device_remove() is disabling the root port and switches by
calling pci_disable_device() after all PCIe service drivers are shutdown.
This has been found to cause crashes on HP DL360 Gen9 machines during
reboot due to hpsa driver not clearing the bus master bit during the
shutdown procedure by calling pci_disable_device().
Drop the shutdown API and do an orderly clean up by using the remove.
Signed-off-by: Sinan Kaya <okaya@codeaurora.org>
Link: https://bugzilla.kernel.org/show_bug.cgi?id=199779
Fixes: cc27b735ad3a ("PCI/portdrv: Turn off PCIe services during shutdown")
Cc: stable at vger.kernel.org
Reported-by: Ryan Finnie <ryan@finnie.org>
---
drivers/scsi/hpsa.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index 3a9eca1..3dbef28 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -8970,7 +8970,6 @@ static struct pci_driver hpsa_pci_driver = {
.probe = hpsa_init_one,
.remove = hpsa_remove_one,
.id_table = hpsa_pci_device_id, /* id_table */
- .shutdown = hpsa_shutdown,
.suspend = hpsa_suspend,
.resume = hpsa_resume,
};
--
2.7.4
^ permalink raw reply related
* [PATCH V2] PCI/portdrv: do not disable device on reboot/shutdown
From: Sinan Kaya @ 2018-05-28 21:25 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <36b790d3fb4c43349cfa560283c03ab5@microsemi.com>
On 5/24/2018 6:37 AM, Don Brace wrote:
>> But we really need guidance from an hpsa expert. I don't know the
>> filesystem/SCSI/hpsa details.
>>
>> Bjorn
> It's most likely OCSD traffic that will stop when bus mastering is turned off.
> So, I'll run some tests on my end before ACKing your patch.
Can you test V3 instead of this?
I don't think adding pci_disable_device() to shutdown() is enough to put
the HW into safe state. I moved clean up responsibility to remove() instead
of shutdown().
--
Sinan Kaya
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project.
^ permalink raw reply
* [RFT v3 0/4] Perf script: Add python script for CoreSight trace disassembler
From: Mathieu Poirier @ 2018-05-28 21:53 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180528200326.GJ25467@kernel.org>
On 28 May 2018 at 14:03, Arnaldo Carvalho de Melo <acme@kernel.org> wrote:
> Em Mon, May 28, 2018 at 04:44:59PM +0800, Leo Yan escreveu:
>> This patch series is to support for using 'perf script' for CoreSight
>> trace disassembler, for this purpose this patch series adds a new
>> python script to parse CoreSight tracing event and use command 'objdump'
>> for disassembled lines, finally this can generate readable program
>> execution flow for reviewing tracing data.
>>
>> Patch 0001 is one fixing patch to generate samples for the start packet
>> and exception packets.
>>
>> Patch 0002 is the prerequisite to add addr into sample dict, so this
>> value can be used by python script to analyze instruction range.
>>
>> Patch 0003 is to add python script for trace disassembler.
>>
>> Patch 0004 is to add doc to explain python script usage and give
>> example for it.
>>
>> This patch series has been rebased on acme git tree [1] with the commit
>> 19422a9f2a3b ("perf tools: Fix kernel_start for PTI on x86") and tested
>> on Hikey (ARM64 octa CA53 cores).
>
> Thanks, applied to perf/core.
Please hold off on that Arnaldo - I'm currently reviewing the set and
I think some things can be improved.
Thanks,
Mathieu
>
> - Arnaldo
^ permalink raw reply
* [RFT v3 1/4] perf cs-etm: Generate branch sample for missed packets
From: Mathieu Poirier @ 2018-05-28 22:13 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1527497103-3593-2-git-send-email-leo.yan@linaro.org>
Leo and/or Robert,
On Mon, May 28, 2018 at 04:45:00PM +0800, Leo Yan wrote:
> Commit e573e978fb12 ("perf cs-etm: Inject capabilitity for CoreSight
> traces") reworks the samples generation flow from CoreSight trace to
> match the correct format so Perf report tool can display the samples
> properly.
>
> But the change has side effect for branch packet handling, it only
> generate branch samples by checking previous packet flag
> 'last_instr_taken_branch' is true, this results in below three kinds
> packets are missed to generate branch samples:
>
> - The start tracing packet at the beginning of tracing data;
> - The exception handling packet;
> - If one CS_ETM_TRACE_ON packet is inserted, we also miss to handle it
> for branch samples. CS_ETM_TRACE_ON packet itself can give the info
> that there have a discontinuity in the trace, on the other hand we
> also miss to generate proper branch sample for packets before and
> after CS_ETM_TRACE_ON packet.
>
> This patch is to add branch sample handling for up three kinds packets:
>
> - In function cs_etm__sample(), check if 'prev_packet->sample_type' is
> zero and in this case it generates branch sample for the start tracing
> packet; furthermore, we also need to handle the condition for
> prev_packet::end_addr is zero in the cs_etm__last_executed_instr();
>
> - In function cs_etm__sample(), check if 'prev_packet->exc' is true and
> generate branch sample for exception handling packet;
>
> - If there has one CS_ETM_TRACE_ON packet is coming, we firstly generate
> branch sample in the function cs_etm__flush(), this can save complete
> info for the previous CS_ETM_RANGE packet just before CS_ETM_TRACE_ON
> packet. We also generate branch sample for the new CS_ETM_RANGE
> packet after CS_ETM_TRACE_ON packet, this have two purposes, the
> first one purpose is to save the info for the new CS_ETM_RANGE packet,
> the second purpose is to save CS_ETM_TRACE_ON packet info so we can
> have hint for a discontinuity in the trace.
>
> For CS_ETM_TRACE_ON packet, its fields 'packet->start_addr' and
> 'packet->end_addr' equal to 0xdeadbeefdeadbeefUL which are emitted in
> the decoder layer as dummy value. This patch is to convert these
> values to zeros for more readable; this is accomplished by functions
> cs_etm__last_executed_instr() and cs_etm__first_executed_instr(). The
> later one is a new function introduced by this patch.
>
> Reviewed-by: Robert Walker <robert.walker@arm.com>
> Fixes: e573e978fb12 ("perf cs-etm: Inject capabilitity for CoreSight traces")
> Signed-off-by: Leo Yan <leo.yan@linaro.org>
> ---
> tools/perf/util/cs-etm.c | 93 +++++++++++++++++++++++++++++++++++++-----------
> 1 file changed, 73 insertions(+), 20 deletions(-)
>
> diff --git a/tools/perf/util/cs-etm.c b/tools/perf/util/cs-etm.c
> index 822ba91..8418173 100644
> --- a/tools/perf/util/cs-etm.c
> +++ b/tools/perf/util/cs-etm.c
> @@ -495,6 +495,20 @@ static inline void cs_etm__reset_last_branch_rb(struct cs_etm_queue *etmq)
> static inline u64 cs_etm__last_executed_instr(struct cs_etm_packet *packet)
> {
> /*
> + * The packet is the start tracing packet if the end_addr is zero,
> + * returns 0 for this case.
> + */
> + if (!packet->end_addr)
> + return 0;
What is considered to be the "start tracing packet"? Right now the only two
kind of packets inserted in the decoder packet buffer queue are INST_RANGE and
TRACE_ON. How can we hit a condition where packet->end-addr == 0?
> +
> + /*
> + * The packet is the CS_ETM_TRACE_ON packet if the end_addr is
> + * magic number 0xdeadbeefdeadbeefUL, returns 0 for this case.
> + */
> + if (packet->end_addr == 0xdeadbeefdeadbeefUL)
> + return 0;
As it is with the above, I find triggering on addresses to be brittle and hard
to maintain on the long run. Packets all have a sample_type field that should
be used in cases like this one. That way we know exactly the condition that is
targeted.
While working on this set, please spin-off another patch that defines
CS_ETM_INVAL_ADDR 0xdeadbeefdeadbeefUL and replace all the cases where the
numeral is used. That way we stop using the hard coded value.
> +
> + /*
> * The packet records the execution range with an exclusive end address
> *
> * A64 instructions are constant size, so the last executed
> @@ -505,6 +519,18 @@ static inline u64 cs_etm__last_executed_instr(struct cs_etm_packet *packet)
> return packet->end_addr - A64_INSTR_SIZE;
> }
>
> +static inline u64 cs_etm__first_executed_instr(struct cs_etm_packet *packet)
> +{
> + /*
> + * The packet is the CS_ETM_TRACE_ON packet if the start_addr is
> + * magic number 0xdeadbeefdeadbeefUL, returns 0 for this case.
> + */
> + if (packet->start_addr == 0xdeadbeefdeadbeefUL)
> + return 0;
Same comment as above.
> +
> + return packet->start_addr;
> +}
> +
> static inline u64 cs_etm__instr_count(const struct cs_etm_packet *packet)
> {
> /*
> @@ -546,7 +572,7 @@ static void cs_etm__update_last_branch_rb(struct cs_etm_queue *etmq)
>
> be = &bs->entries[etmq->last_branch_pos];
> be->from = cs_etm__last_executed_instr(etmq->prev_packet);
> - be->to = etmq->packet->start_addr;
> + be->to = cs_etm__first_executed_instr(etmq->packet);
> /* No support for mispredict */
> be->flags.mispred = 0;
> be->flags.predicted = 1;
> @@ -701,7 +727,7 @@ static int cs_etm__synth_branch_sample(struct cs_etm_queue *etmq)
> sample.ip = cs_etm__last_executed_instr(etmq->prev_packet);
> sample.pid = etmq->pid;
> sample.tid = etmq->tid;
> - sample.addr = etmq->packet->start_addr;
> + sample.addr = cs_etm__first_executed_instr(etmq->packet);
> sample.id = etmq->etm->branches_id;
> sample.stream_id = etmq->etm->branches_id;
> sample.period = 1;
> @@ -897,13 +923,28 @@ static int cs_etm__sample(struct cs_etm_queue *etmq)
> etmq->period_instructions = instrs_over;
> }
>
> - if (etm->sample_branches &&
> - etmq->prev_packet &&
> - etmq->prev_packet->sample_type == CS_ETM_RANGE &&
> - etmq->prev_packet->last_instr_taken_branch) {
> - ret = cs_etm__synth_branch_sample(etmq);
> - if (ret)
> - return ret;
> + if (etm->sample_branches && etmq->prev_packet) {
> + bool generate_sample = false;
> +
> + /* Generate sample for start tracing packet */
> + if (etmq->prev_packet->sample_type == 0 ||
What kind of packet is sample_type == 0 ?
> + etmq->prev_packet->sample_type == CS_ETM_TRACE_ON)
> + generate_sample = true;
> +
> + /* Generate sample for exception packet */
> + if (etmq->prev_packet->exc == true)
> + generate_sample = true;
Please don't do that. Exception packets have a type of their own and can be
added to the decoder packet queue the same way INST_RANGE and TRACE_ON packets
are. Moreover exception packet containt an address that, if I'm reading the
documenation properly, can be used to keep track of instructions that were
executed between the last address of the previous range packet and the address
executed just before the exception occurred. Mike and Rob will have to confirm
this as the decoder may be doing all that hard work for us.
> +
> + /* Generate sample for normal branch packet */
> + if (etmq->prev_packet->sample_type == CS_ETM_RANGE &&
> + etmq->prev_packet->last_instr_taken_branch)
> + generate_sample = true;
> +
> + if (generate_sample) {
> + ret = cs_etm__synth_branch_sample(etmq);
> + if (ret)
> + return ret;
> + }
> }
>
> if (etm->sample_branches || etm->synth_opts.last_branch) {
> @@ -922,11 +963,16 @@ static int cs_etm__sample(struct cs_etm_queue *etmq)
> static int cs_etm__flush(struct cs_etm_queue *etmq)
> {
> int err = 0;
> + struct cs_etm_auxtrace *etm = etmq->etm;
> struct cs_etm_packet *tmp;
>
> - if (etmq->etm->synth_opts.last_branch &&
> - etmq->prev_packet &&
> - etmq->prev_packet->sample_type == CS_ETM_RANGE) {
> + if (!etmq->prev_packet)
> + return 0;
> +
> + if (etmq->prev_packet->sample_type != CS_ETM_RANGE)
> + return 0;
> +
> + if (etmq->etm->synth_opts.last_branch) {
If you add:
if (!etmq->etm->synth_opts.last_branch)
return 0;
You can avoid indenting the whole block.
> /*
> * Generate a last branch event for the branches left in the
> * circular buffer at the end of the trace.
> @@ -939,18 +985,25 @@ static int cs_etm__flush(struct cs_etm_queue *etmq)
> err = cs_etm__synth_instruction_sample(
> etmq, addr,
> etmq->period_instructions);
> + if (err)
> + return err;
> etmq->period_instructions = 0;
> + }
>
> - /*
> - * Swap PACKET with PREV_PACKET: PACKET becomes PREV_PACKET for
> - * the next incoming packet.
> - */
> - tmp = etmq->packet;
> - etmq->packet = etmq->prev_packet;
> - etmq->prev_packet = tmp;
> + if (etm->sample_branches) {
> + err = cs_etm__synth_branch_sample(etmq);
> + if (err)
> + return err;
> }
>
> - return err;
> + /*
> + * Swap PACKET with PREV_PACKET: PACKET becomes PREV_PACKET for
> + * the next incoming packet.
> + */
> + tmp = etmq->packet;
> + etmq->packet = etmq->prev_packet;
> + etmq->prev_packet = tmp;
Robert, I remember noticing that when you first submitted the code but forgot to
go back to it. What is the point of swapping the packets? I understand
etmq->prev_packet = etmq->packet;
But not
etmq->packet = tmp;
After all etmq->packet will be clobbered as soon as cs_etm_decoder__get_packet()
is called, which is alwasy right after either cs_etm__sample() or
cs_etm__flush().
Thanks,
Mathieu
> + return 0;
> }
>
> static int cs_etm__run_decoder(struct cs_etm_queue *etmq)
> --
> 2.7.4
>
^ permalink raw reply
* [PATCH] usb/gadget: aspeed-vhub: add USB_LIBCOMPOSITE dependency
From: Benjamin Herrenschmidt @ 2018-05-28 23:49 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180525160729.92026-1-arnd@arndb.de>
On Fri, 2018-05-25 at 18:07 +0200, Arnd Bergmann wrote:
> Without that option, we run into a link failure:
>
> drivers/usb/gadget/udc/aspeed-vhub/hub.o: In function `ast_vhub_std_hub_request':
> hub.c:(.text+0x5b0): undefined reference to `usb_gadget_get_string'
Thanks ! I hadn't realized these functions were part of an optional
library.
> Fixes: 7ecca2a4080c ("usb/gadget: Add driver for Aspeed SoC virtual hub")
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> ---
> drivers/usb/gadget/udc/aspeed-vhub/Kconfig | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/drivers/usb/gadget/udc/aspeed-vhub/Kconfig b/drivers/usb/gadget/udc/aspeed-vhub/Kconfig
> index f0cdf89b8503..83ba8a2eb6af 100644
> --- a/drivers/usb/gadget/udc/aspeed-vhub/Kconfig
> +++ b/drivers/usb/gadget/udc/aspeed-vhub/Kconfig
> @@ -2,6 +2,7 @@
> config USB_ASPEED_VHUB
> tristate "Aspeed vHub UDC driver"
> depends on ARCH_ASPEED || COMPILE_TEST
> + depends on USB_LIBCOMPOSITE
> help
> USB peripheral controller for the Aspeed AST2500 family
> SoCs supporting the "vHub" functionality and USB2.0
^ permalink raw reply
* [RFT v3 1/4] perf cs-etm: Generate branch sample for missed packets
From: Leo Yan @ 2018-05-29 0:25 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180528221347.GA4109@xps15>
Hi Mathieu,
On Mon, May 28, 2018 at 04:13:47PM -0600, Mathieu Poirier wrote:
> Leo and/or Robert,
>
> On Mon, May 28, 2018 at 04:45:00PM +0800, Leo Yan wrote:
> > Commit e573e978fb12 ("perf cs-etm: Inject capabilitity for CoreSight
> > traces") reworks the samples generation flow from CoreSight trace to
> > match the correct format so Perf report tool can display the samples
> > properly.
> >
> > But the change has side effect for branch packet handling, it only
> > generate branch samples by checking previous packet flag
> > 'last_instr_taken_branch' is true, this results in below three kinds
> > packets are missed to generate branch samples:
> >
> > - The start tracing packet at the beginning of tracing data;
> > - The exception handling packet;
> > - If one CS_ETM_TRACE_ON packet is inserted, we also miss to handle it
> > for branch samples. CS_ETM_TRACE_ON packet itself can give the info
> > that there have a discontinuity in the trace, on the other hand we
> > also miss to generate proper branch sample for packets before and
> > after CS_ETM_TRACE_ON packet.
> >
> > This patch is to add branch sample handling for up three kinds packets:
> >
> > - In function cs_etm__sample(), check if 'prev_packet->sample_type' is
> > zero and in this case it generates branch sample for the start tracing
> > packet; furthermore, we also need to handle the condition for
> > prev_packet::end_addr is zero in the cs_etm__last_executed_instr();
> >
> > - In function cs_etm__sample(), check if 'prev_packet->exc' is true and
> > generate branch sample for exception handling packet;
> >
> > - If there has one CS_ETM_TRACE_ON packet is coming, we firstly generate
> > branch sample in the function cs_etm__flush(), this can save complete
> > info for the previous CS_ETM_RANGE packet just before CS_ETM_TRACE_ON
> > packet. We also generate branch sample for the new CS_ETM_RANGE
> > packet after CS_ETM_TRACE_ON packet, this have two purposes, the
> > first one purpose is to save the info for the new CS_ETM_RANGE packet,
> > the second purpose is to save CS_ETM_TRACE_ON packet info so we can
> > have hint for a discontinuity in the trace.
> >
> > For CS_ETM_TRACE_ON packet, its fields 'packet->start_addr' and
> > 'packet->end_addr' equal to 0xdeadbeefdeadbeefUL which are emitted in
> > the decoder layer as dummy value. This patch is to convert these
> > values to zeros for more readable; this is accomplished by functions
> > cs_etm__last_executed_instr() and cs_etm__first_executed_instr(). The
> > later one is a new function introduced by this patch.
> >
> > Reviewed-by: Robert Walker <robert.walker@arm.com>
> > Fixes: e573e978fb12 ("perf cs-etm: Inject capabilitity for CoreSight traces")
> > Signed-off-by: Leo Yan <leo.yan@linaro.org>
> > ---
> > tools/perf/util/cs-etm.c | 93 +++++++++++++++++++++++++++++++++++++-----------
> > 1 file changed, 73 insertions(+), 20 deletions(-)
> >
> > diff --git a/tools/perf/util/cs-etm.c b/tools/perf/util/cs-etm.c
> > index 822ba91..8418173 100644
> > --- a/tools/perf/util/cs-etm.c
> > +++ b/tools/perf/util/cs-etm.c
> > @@ -495,6 +495,20 @@ static inline void cs_etm__reset_last_branch_rb(struct cs_etm_queue *etmq)
> > static inline u64 cs_etm__last_executed_instr(struct cs_etm_packet *packet)
> > {
> > /*
> > + * The packet is the start tracing packet if the end_addr is zero,
> > + * returns 0 for this case.
> > + */
> > + if (!packet->end_addr)
> > + return 0;
>
> What is considered to be the "start tracing packet"? Right now the only two
> kind of packets inserted in the decoder packet buffer queue are INST_RANGE and
> TRACE_ON. How can we hit a condition where packet->end-addr == 0?
When the first CS_ETM_RANGE packet is coming, etmq->prev_packet is
initialized by the function cs_etm__alloc_queue(), so
etmq->prev_packet->end_addr is zero:
etmq->prev_packet = zalloc(szp);
As you mentioned, we should only have two kind of packets for
CS_ETM_RANGE and CS_ETM_TRACE_ON. Currently we skip to handle the
first CS_ETM_TRACE_ON packet in function cs_etm__flush(), we also can
refine the function cs_etm__flush() to handle the first coming
CS_ETM_TRACE_ON packet, after that all packets will be CS_ETM_RANGE
and CS_ETM_TRACE_ON and have no chance to hit 'packet->end_addr = 0'.
Does this make sense for you?
--- Packet dumping when first packet coming ---
cs_etm__flush: prev_packet: sample_type=0 exc=0 exc_ret=0 cpu=0 start_addr=0x0 end_addr=0x0 last_instr_taken_branch=0
cs_etm__flush: packet: sample_type=2 exc=0 exc_ret=0 cpu=1 start_addr=0xdeadbeefdeadbeef end_addr=0xdeadbeefdeadbeef last_instr_taken_branch=0
> > +
> > + /*
> > + * The packet is the CS_ETM_TRACE_ON packet if the end_addr is
> > + * magic number 0xdeadbeefdeadbeefUL, returns 0 for this case.
> > + */
> > + if (packet->end_addr == 0xdeadbeefdeadbeefUL)
> > + return 0;
>
> As it is with the above, I find triggering on addresses to be brittle and hard
> to maintain on the long run. Packets all have a sample_type field that should
> be used in cases like this one. That way we know exactly the condition that is
> targeted.
Will do this.
> While working on this set, please spin-off another patch that defines
> CS_ETM_INVAL_ADDR 0xdeadbeefdeadbeefUL and replace all the cases where the
> numeral is used. That way we stop using the hard coded value.
Will do this.
As now this patch is big with more complex logic, so I consider to
split it into small patches:
- Define CS_ETM_INVAL_ADDR;
- Fix for CS_ETM_TRACE_ON packet;
- Fix for exception packet;
Does this make sense for you? I have concern that this patch is a
fixing patch, so not sure after spliting patches will introduce
trouble for applying them for other stable kernels ...
> > +
> > + /*
> > * The packet records the execution range with an exclusive end address
> > *
> > * A64 instructions are constant size, so the last executed
> > @@ -505,6 +519,18 @@ static inline u64 cs_etm__last_executed_instr(struct cs_etm_packet *packet)
> > return packet->end_addr - A64_INSTR_SIZE;
> > }
> >
> > +static inline u64 cs_etm__first_executed_instr(struct cs_etm_packet *packet)
> > +{
> > + /*
> > + * The packet is the CS_ETM_TRACE_ON packet if the start_addr is
> > + * magic number 0xdeadbeefdeadbeefUL, returns 0 for this case.
> > + */
> > + if (packet->start_addr == 0xdeadbeefdeadbeefUL)
> > + return 0;
>
> Same comment as above.
Will do this.
> > +
> > + return packet->start_addr;
> > +}
> > +
> > static inline u64 cs_etm__instr_count(const struct cs_etm_packet *packet)
> > {
> > /*
> > @@ -546,7 +572,7 @@ static void cs_etm__update_last_branch_rb(struct cs_etm_queue *etmq)
> >
> > be = &bs->entries[etmq->last_branch_pos];
> > be->from = cs_etm__last_executed_instr(etmq->prev_packet);
> > - be->to = etmq->packet->start_addr;
> > + be->to = cs_etm__first_executed_instr(etmq->packet);
> > /* No support for mispredict */
> > be->flags.mispred = 0;
> > be->flags.predicted = 1;
> > @@ -701,7 +727,7 @@ static int cs_etm__synth_branch_sample(struct cs_etm_queue *etmq)
> > sample.ip = cs_etm__last_executed_instr(etmq->prev_packet);
> > sample.pid = etmq->pid;
> > sample.tid = etmq->tid;
> > - sample.addr = etmq->packet->start_addr;
> > + sample.addr = cs_etm__first_executed_instr(etmq->packet);
> > sample.id = etmq->etm->branches_id;
> > sample.stream_id = etmq->etm->branches_id;
> > sample.period = 1;
> > @@ -897,13 +923,28 @@ static int cs_etm__sample(struct cs_etm_queue *etmq)
> > etmq->period_instructions = instrs_over;
> > }
> >
> > - if (etm->sample_branches &&
> > - etmq->prev_packet &&
> > - etmq->prev_packet->sample_type == CS_ETM_RANGE &&
> > - etmq->prev_packet->last_instr_taken_branch) {
> > - ret = cs_etm__synth_branch_sample(etmq);
> > - if (ret)
> > - return ret;
> > + if (etm->sample_branches && etmq->prev_packet) {
> > + bool generate_sample = false;
> > +
> > + /* Generate sample for start tracing packet */
> > + if (etmq->prev_packet->sample_type == 0 ||
>
> What kind of packet is sample_type == 0 ?
Just as explained above, sample_type == 0 is the packet which
initialized in the function cs_etm__alloc_queue().
> > + etmq->prev_packet->sample_type == CS_ETM_TRACE_ON)
> > + generate_sample = true;
> > +
> > + /* Generate sample for exception packet */
> > + if (etmq->prev_packet->exc == true)
> > + generate_sample = true;
>
> Please don't do that. Exception packets have a type of their own and can be
> added to the decoder packet queue the same way INST_RANGE and TRACE_ON packets
> are. Moreover exception packet containt an address that, if I'm reading the
> documenation properly, can be used to keep track of instructions that were
> executed between the last address of the previous range packet and the address
> executed just before the exception occurred. Mike and Rob will have to confirm
> this as the decoder may be doing all that hard work for us.
Sure, will wait for Rob and Mike to confirm for this.
At my side, I dump the packet, the exception packet isn't passed to
cs-etm.c layer, the decoder layer only sets the flag
'packet->exc = true' when exception packet is coming [1].
[1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/tools/perf/util/cs-etm-decoder/cs-etm-decoder.c#n364
> > +
> > + /* Generate sample for normal branch packet */
> > + if (etmq->prev_packet->sample_type == CS_ETM_RANGE &&
> > + etmq->prev_packet->last_instr_taken_branch)
> > + generate_sample = true;
> > +
> > + if (generate_sample) {
> > + ret = cs_etm__synth_branch_sample(etmq);
> > + if (ret)
> > + return ret;
> > + }
> > }
> >
> > if (etm->sample_branches || etm->synth_opts.last_branch) {
> > @@ -922,11 +963,16 @@ static int cs_etm__sample(struct cs_etm_queue *etmq)
> > static int cs_etm__flush(struct cs_etm_queue *etmq)
> > {
> > int err = 0;
> > + struct cs_etm_auxtrace *etm = etmq->etm;
> > struct cs_etm_packet *tmp;
> >
> > - if (etmq->etm->synth_opts.last_branch &&
> > - etmq->prev_packet &&
> > - etmq->prev_packet->sample_type == CS_ETM_RANGE) {
> > + if (!etmq->prev_packet)
> > + return 0;
> > +
> > + if (etmq->prev_packet->sample_type != CS_ETM_RANGE)
> > + return 0;
> > +
> > + if (etmq->etm->synth_opts.last_branch) {
>
> If you add:
>
> if (!etmq->etm->synth_opts.last_branch)
> return 0;
>
> You can avoid indenting the whole block.
No, here we cannot do like this. Except we need to handle the
condition for 'etmq->etm->synth_opts.last_branch', we also need to
handle 'etm->sample_branches'. These two conditions are saperate and
decide by different command parameters from 'perf script'.
> > /*
> > * Generate a last branch event for the branches left in the
> > * circular buffer at the end of the trace.
> > @@ -939,18 +985,25 @@ static int cs_etm__flush(struct cs_etm_queue *etmq)
> > err = cs_etm__synth_instruction_sample(
> > etmq, addr,
> > etmq->period_instructions);
> > + if (err)
> > + return err;
> > etmq->period_instructions = 0;
> > + }
> >
> > - /*
> > - * Swap PACKET with PREV_PACKET: PACKET becomes PREV_PACKET for
> > - * the next incoming packet.
> > - */
> > - tmp = etmq->packet;
> > - etmq->packet = etmq->prev_packet;
> > - etmq->prev_packet = tmp;
> > + if (etm->sample_branches) {
> > + err = cs_etm__synth_branch_sample(etmq);
> > + if (err)
> > + return err;
> > }
> >
> > - return err;
> > + /*
> > + * Swap PACKET with PREV_PACKET: PACKET becomes PREV_PACKET for
> > + * the next incoming packet.
> > + */
> > + tmp = etmq->packet;
> > + etmq->packet = etmq->prev_packet;
> > + etmq->prev_packet = tmp;
>
> Robert, I remember noticing that when you first submitted the code but forgot to
> go back to it. What is the point of swapping the packets? I understand
>
> etmq->prev_packet = etmq->packet;
>
> But not
>
> etmq->packet = tmp;
>
> After all etmq->packet will be clobbered as soon as cs_etm_decoder__get_packet()
> is called, which is alwasy right after either cs_etm__sample() or
> cs_etm__flush().
Yeah, I have the same question for this :)
Thanks for suggestions and reviewing.
> Thanks,
> Mathieu
>
>
>
> > + return 0;
> > }
> >
> > static int cs_etm__run_decoder(struct cs_etm_queue *etmq)
> > --
> > 2.7.4
> >
^ permalink raw reply
* [RESEND PATCH] media: helene: fix tuning frequency of satellite
From: Katsuhiro Suzuki @ 2018-05-29 1:06 UTC (permalink / raw)
To: linux-arm-kernel
This patch fixes tuning frequency of satellite to kHz. That as same
as terrestrial one.
Signed-off-by: Katsuhiro Suzuki <suzuki.katsuhiro@socionext.com>
---
drivers/media/dvb-frontends/helene.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/media/dvb-frontends/helene.c b/drivers/media/dvb-frontends/helene.c
index 04033f0c278b..0a4f312c4368 100644
--- a/drivers/media/dvb-frontends/helene.c
+++ b/drivers/media/dvb-frontends/helene.c
@@ -523,7 +523,7 @@ static int helene_set_params_s(struct dvb_frontend *fe)
enum helene_tv_system_t tv_system;
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct helene_priv *priv = fe->tuner_priv;
- int frequencykHz = p->frequency;
+ int frequencykHz = p->frequency / 1000;
uint32_t frequency4kHz = 0;
u32 symbol_rate = p->symbol_rate/1000;
--
2.17.0
^ permalink raw reply related
* [RESEND PATCH] media: helene: fix xtal frequency setting at power on
From: Katsuhiro Suzuki @ 2018-05-29 1:09 UTC (permalink / raw)
To: linux-arm-kernel
This patch fixes crystal frequency setting when power on this device.
Signed-off-by: Katsuhiro Suzuki <suzuki.katsuhiro@socionext.com>
Acked-by: Abylay Ospan <aospan@netup.ru>
---
Changes from before:
- Add Abylay's Ack
---
drivers/media/dvb-frontends/helene.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/drivers/media/dvb-frontends/helene.c b/drivers/media/dvb-frontends/helene.c
index 0a4f312c4368..8fcf7a00782a 100644
--- a/drivers/media/dvb-frontends/helene.c
+++ b/drivers/media/dvb-frontends/helene.c
@@ -924,7 +924,10 @@ static int helene_x_pon(struct helene_priv *priv)
helene_write_regs(priv, 0x99, cdata, sizeof(cdata));
/* 0x81 - 0x94 */
- data[0] = 0x18; /* xtal 24 MHz */
+ if (priv->xtal == SONY_HELENE_XTAL_16000)
+ data[0] = 0x10; /* xtal 16 MHz */
+ else
+ data[0] = 0x18; /* xtal 24 MHz */
data[1] = (uint8_t)(0x80 | (0x04 & 0x1F)); /* 4 x 25 = 100uA */
data[2] = (uint8_t)(0x80 | (0x26 & 0x7F)); /* 38 x 0.25 = 9.5pF */
data[3] = 0x80; /* REFOUT signal output 500mVpp */
--
2.17.0
^ permalink raw reply related
* [RESEND PATCH v2] media: dvb-frontends: add Socionext SC1501A ISDB-S/T demodulator driver
From: Katsuhiro Suzuki @ 2018-05-29 1:11 UTC (permalink / raw)
To: linux-arm-kernel
This patch adds a frontend driver for the Socionext SC1501A series
and Socionext MN88443x ISDB-S/T demodulators.
Signed-off-by: Katsuhiro Suzuki <suzuki.katsuhiro@socionext.com>
---
Changes since v1:
- Fix sparse warning about type of constant
- Use div_s64() instead of divide operator
---
drivers/media/dvb-frontends/Kconfig | 10 +
drivers/media/dvb-frontends/Makefile | 1 +
drivers/media/dvb-frontends/sc1501a.c | 802 ++++++++++++++++++++++++++
drivers/media/dvb-frontends/sc1501a.h | 27 +
4 files changed, 840 insertions(+)
create mode 100644 drivers/media/dvb-frontends/sc1501a.c
create mode 100644 drivers/media/dvb-frontends/sc1501a.h
diff --git a/drivers/media/dvb-frontends/Kconfig b/drivers/media/dvb-frontends/Kconfig
index 55e36a4f5215..e9d2c94b290e 100644
--- a/drivers/media/dvb-frontends/Kconfig
+++ b/drivers/media/dvb-frontends/Kconfig
@@ -739,6 +739,16 @@ config DVB_TC90522
Toshiba TC90522 2xISDB-S 8PSK + 2xISDB-T OFDM demodulator.
Say Y when you want to support this frontend.
+config DVB_SC1501A
+ tristate "Socionext SC1501A"
+ depends on DVB_CORE && I2C
+ select REGMAP_I2C
+ default m if !MEDIA_SUBDRV_AUTOSELECT
+ help
+ A driver for Socionext SC1501A and Panasonic MN88443x
+ ISDB-S + ISDB-T demodulator.
+ Say Y when you want to support this frontend.
+
comment "Digital terrestrial only tuners/PLL"
depends on DVB_CORE
diff --git a/drivers/media/dvb-frontends/Makefile b/drivers/media/dvb-frontends/Makefile
index 67a783fd5ed0..e204502347ed 100644
--- a/drivers/media/dvb-frontends/Makefile
+++ b/drivers/media/dvb-frontends/Makefile
@@ -125,6 +125,7 @@ obj-$(CONFIG_DVB_AF9033) += af9033.o
obj-$(CONFIG_DVB_AS102_FE) += as102_fe.o
obj-$(CONFIG_DVB_GP8PSK_FE) += gp8psk-fe.o
obj-$(CONFIG_DVB_TC90522) += tc90522.o
+obj-$(CONFIG_DVB_SC1501A) += sc1501a.o
obj-$(CONFIG_DVB_HORUS3A) += horus3a.o
obj-$(CONFIG_DVB_ASCOT2E) += ascot2e.o
obj-$(CONFIG_DVB_HELENE) += helene.o
diff --git a/drivers/media/dvb-frontends/sc1501a.c b/drivers/media/dvb-frontends/sc1501a.c
new file mode 100644
index 000000000000..c3d0369a9448
--- /dev/null
+++ b/drivers/media/dvb-frontends/sc1501a.c
@@ -0,0 +1,802 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Socionext SC1501A series demodulator driver for ISDB-S/ISDB-T.
+//
+// Copyright (c) 2018 Socionext Inc.
+
+#include <linux/bitfield.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/of_device.h>
+#include <linux/regmap.h>
+#include <media/dvb_math.h>
+
+#include "sc1501a.h"
+
+/* ISDB-S registers */
+#define ATSIDU_S 0x2f
+#define ATSIDL_S 0x30
+#define TSSET_S 0x31
+#define AGCREAD_S 0x5a
+#define CPMON1_S 0x5e
+#define CPMON1_S_FSYNC BIT(5)
+#define CPMON1_S_ERRMON BIT(4)
+#define CPMON1_S_SIGOFF BIT(3)
+#define CPMON1_S_W2LOCK BIT(2)
+#define CPMON1_S_W1LOCK BIT(1)
+#define CPMON1_S_DW1LOCK BIT(0)
+#define TRMON_S 0x60
+#define BERCNFLG_S 0x68
+#define BERCNFLG_S_BERVRDY BIT(5)
+#define BERCNFLG_S_BERVCHK BIT(4)
+#define BERCNFLG_S_BERDRDY BIT(3)
+#define BERCNFLG_S_BERDCHK BIT(2)
+#define CNRDXU_S 0x69
+#define CNRDXL_S 0x6a
+#define CNRDYU_S 0x6b
+#define CNRDYL_S 0x6c
+#define BERVRDU_S 0x71
+#define BERVRDL_S 0x72
+#define DOSET1_S 0x73
+
+/* Primary ISDB-T */
+#define PLLASET1 0x00
+#define PLLASET2 0x01
+#define PLLBSET1 0x02
+#define PLLBSET2 0x03
+#define PLLSET 0x04
+#define OUTCSET 0x08
+#define OUTCSET_CHDRV_8MA 0xff
+#define OUTCSET_CHDRV_4MA 0x00
+#define PLDWSET 0x09
+#define PLDWSET_NORMAL 0x00
+#define PLDWSET_PULLDOWN 0xff
+#define HIZSET1 0x0a
+#define HIZSET2 0x0b
+
+/* Secondary ISDB-T (for MN884434 only) */
+#define RCVSET 0x00
+#define TSSET1_M 0x01
+#define TSSET2_M 0x02
+#define TSSET3_M 0x03
+#define INTACSET 0x08
+#define HIZSET3 0x0b
+
+/* ISDB-T registers */
+#define TSSET1 0x05
+#define TSSET1_TSASEL_MASK GENMASK(4, 3)
+#define TSSET1_TSASEL_ISDBT (0x0 << 3)
+#define TSSET1_TSASEL_ISDBS (0x1 << 3)
+#define TSSET1_TSASEL_NONE (0x2 << 3)
+#define TSSET1_TSBSEL_MASK GENMASK(2, 1)
+#define TSSET1_TSBSEL_ISDBS (0x0 << 1)
+#define TSSET1_TSBSEL_ISDBT (0x1 << 1)
+#define TSSET1_TSBSEL_NONE (0x2 << 1)
+#define TSSET2 0x06
+#define TSSET3 0x07
+#define TSSET3_INTASEL_MASK GENMASK(7, 6)
+#define TSSET3_INTASEL_T (0x0 << 6)
+#define TSSET3_INTASEL_S (0x1 << 6)
+#define TSSET3_INTASEL_NONE (0x2 << 6)
+#define TSSET3_INTBSEL_MASK GENMASK(5, 4)
+#define TSSET3_INTBSEL_S (0x0 << 4)
+#define TSSET3_INTBSEL_T (0x1 << 4)
+#define TSSET3_INTBSEL_NONE (0x2 << 4)
+#define OUTSET2 0x0d
+#define PWDSET 0x0f
+#define PWDSET_OFDMPD_MASK GENMASK(3, 2)
+#define PWDSET_OFDMPD_DOWN BIT(3)
+#define PWDSET_PSKPD_MASK GENMASK(1, 0)
+#define PWDSET_PSKPD_DOWN BIT(1)
+#define CLKSET1_T 0x11
+#define MDSET_T 0x13
+#define MDSET_T_MDAUTO_MASK GENMASK(7, 4)
+#define MDSET_T_MDAUTO_AUTO (0xf << 4)
+#define MDSET_T_MDAUTO_MANUAL (0x0 << 4)
+#define MDSET_T_FFTS_MASK GENMASK(3, 2)
+#define MDSET_T_FFTS_MODE1 (0x0 << 2)
+#define MDSET_T_FFTS_MODE2 (0x1 << 2)
+#define MDSET_T_FFTS_MODE3 (0x2 << 2)
+#define MDSET_T_GI_MASK GENMASK(1, 0)
+#define MDSET_T_GI_1_32 (0x0 << 0)
+#define MDSET_T_GI_1_16 (0x1 << 0)
+#define MDSET_T_GI_1_8 (0x2 << 0)
+#define MDSET_T_GI_1_4 (0x3 << 0)
+#define MDASET_T 0x14
+#define ADCSET1_T 0x20
+#define ADCSET1_T_REFSEL_MASK GENMASK(1, 0)
+#define ADCSET1_T_REFSEL_2V (0x3 << 0)
+#define ADCSET1_T_REFSEL_1_5V (0x2 << 0)
+#define ADCSET1_T_REFSEL_1V (0x1 << 0)
+#define NCOFREQU_T 0x24
+#define NCOFREQM_T 0x25
+#define NCOFREQL_T 0x26
+#define FADU_T 0x27
+#define FADM_T 0x28
+#define FADL_T 0x29
+#define AGCSET2_T 0x2c
+#define AGCSET2_T_IFPOLINV_INC BIT(0)
+#define AGCSET2_T_RFPOLINV_INC BIT(1)
+#define AGCV3_T 0x3e
+#define MDRD_T 0xa2
+#define MDRD_T_SEGID_MASK GENMASK(5, 4)
+#define MDRD_T_SEGID_13 (0x0 << 4)
+#define MDRD_T_SEGID_1 (0x1 << 4)
+#define MDRD_T_SEGID_3 (0x2 << 4)
+#define MDRD_T_FFTS_MASK GENMASK(3, 2)
+#define MDRD_T_FFTS_MODE1 (0x0 << 2)
+#define MDRD_T_FFTS_MODE2 (0x1 << 2)
+#define MDRD_T_FFTS_MODE3 (0x2 << 2)
+#define MDRD_T_GI_MASK GENMASK(1, 0)
+#define MDRD_T_GI_1_32 (0x0 << 0)
+#define MDRD_T_GI_1_16 (0x1 << 0)
+#define MDRD_T_GI_1_8 (0x2 << 0)
+#define MDRD_T_GI_1_4 (0x3 << 0)
+#define SSEQRD_T 0xa3
+#define SSEQRD_T_SSEQSTRD_MASK GENMASK(3, 0)
+#define SSEQRD_T_SSEQSTRD_RESET (0x0 << 0)
+#define SSEQRD_T_SSEQSTRD_TUNING (0x1 << 0)
+#define SSEQRD_T_SSEQSTRD_AGC (0x2 << 0)
+#define SSEQRD_T_SSEQSTRD_SEARCH (0x3 << 0)
+#define SSEQRD_T_SSEQSTRD_CLOCK_SYNC (0x4 << 0)
+#define SSEQRD_T_SSEQSTRD_FREQ_SYNC (0x8 << 0)
+#define SSEQRD_T_SSEQSTRD_FRAME_SYNC (0x9 << 0)
+#define SSEQRD_T_SSEQSTRD_SYNC (0xa << 0)
+#define SSEQRD_T_SSEQSTRD_LOCK (0xb << 0)
+#define AGCRDU_T 0xa8
+#define AGCRDL_T 0xa9
+#define CNRDU_T 0xbe
+#define CNRDL_T 0xbf
+#define BERFLG_T 0xc0
+#define BERFLG_T_BERDRDY BIT(7)
+#define BERFLG_T_BERDCHK BIT(6)
+#define BERFLG_T_BERVRDYA BIT(5)
+#define BERFLG_T_BERVCHKA BIT(4)
+#define BERFLG_T_BERVRDYB BIT(3)
+#define BERFLG_T_BERVCHKB BIT(2)
+#define BERFLG_T_BERVRDYC BIT(1)
+#define BERFLG_T_BERVCHKC BIT(0)
+#define BERRDU_T 0xc1
+#define BERRDM_T 0xc2
+#define BERRDL_T 0xc3
+#define BERLENRDU_T 0xc4
+#define BERLENRDL_T 0xc5
+#define ERRFLG_T 0xc6
+#define ERRFLG_T_BERDOVF BIT(7)
+#define ERRFLG_T_BERVOVFA BIT(6)
+#define ERRFLG_T_BERVOVFB BIT(5)
+#define ERRFLG_T_BERVOVFC BIT(4)
+#define ERRFLG_T_NERRFA BIT(3)
+#define ERRFLG_T_NERRFB BIT(2)
+#define ERRFLG_T_NERRFC BIT(1)
+#define ERRFLG_T_NERRF BIT(0)
+#define DOSET1_T 0xcf
+
+#define CLK_LOW 4000000
+#define CLK_DIRECT 20200000
+#define CLK_MAX 25410000
+
+#define S_T_FREQ 8126984 /* 512 / 63 MHz */
+
+struct sc1501a_spec {
+ bool primary;
+};
+
+struct sc1501a_priv {
+ const struct sc1501a_spec *spec;
+
+ struct dvb_frontend fe;
+ struct clk *mclk;
+ struct gpio_desc *reset_gpio;
+ u32 clk_freq;
+ u32 if_freq;
+
+ /* Common */
+ bool use_clkbuf;
+
+ /* ISDB-S */
+ struct i2c_client *client_s;
+ struct regmap *regmap_s;
+
+ /* ISDB-T */
+ struct i2c_client *client_t;
+ struct regmap *regmap_t;
+};
+
+static void sc1501a_cmn_power_on(struct sc1501a_priv *chip)
+{
+ struct regmap *r_t = chip->regmap_t;
+
+ clk_prepare_enable(chip->mclk);
+
+ gpiod_set_value_cansleep(chip->reset_gpio, 1);
+ usleep_range(100, 1000);
+ gpiod_set_value_cansleep(chip->reset_gpio, 0);
+
+ if (chip->spec->primary) {
+ regmap_write(r_t, OUTCSET, OUTCSET_CHDRV_8MA);
+ regmap_write(r_t, PLDWSET, PLDWSET_NORMAL);
+ regmap_write(r_t, HIZSET1, 0x80);
+ regmap_write(r_t, HIZSET2, 0xe0);
+ } else {
+ regmap_write(r_t, HIZSET3, 0x8f);
+ }
+}
+
+static void sc1501a_cmn_power_off(struct sc1501a_priv *chip)
+{
+ gpiod_set_value_cansleep(chip->reset_gpio, 1);
+
+ clk_disable_unprepare(chip->mclk);
+}
+
+static void sc1501a_s_sleep(struct sc1501a_priv *chip)
+{
+ struct regmap *r_t = chip->regmap_t;
+
+ regmap_update_bits(r_t, PWDSET, PWDSET_PSKPD_MASK,
+ PWDSET_PSKPD_DOWN);
+}
+
+static void sc1501a_s_wake(struct sc1501a_priv *chip)
+{
+ struct regmap *r_t = chip->regmap_t;
+
+ regmap_update_bits(r_t, PWDSET, PWDSET_PSKPD_MASK, 0);
+}
+
+static void sc1501a_s_tune(struct sc1501a_priv *chip,
+ struct dtv_frontend_properties *c)
+{
+ struct regmap *r_s = chip->regmap_s;
+
+ regmap_write(r_s, ATSIDU_S, c->stream_id >> 8);
+ regmap_write(r_s, ATSIDL_S, c->stream_id);
+ regmap_write(r_s, TSSET_S, 0);
+}
+
+static int sc1501a_s_read_status(struct sc1501a_priv *chip,
+ struct dtv_frontend_properties *c,
+ enum fe_status *status)
+{
+ struct regmap *r_s = chip->regmap_s;
+ u32 cpmon, tmpu, tmpl, flg;
+ u64 tmp;
+
+ /* Sync detection */
+ regmap_read(r_s, CPMON1_S, &cpmon);
+
+ *status = 0;
+ if (cpmon & CPMON1_S_FSYNC)
+ *status |= FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
+ if (cpmon & CPMON1_S_W2LOCK)
+ *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER;
+
+ /* Signal strength */
+ c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+
+ if (*status & FE_HAS_SIGNAL) {
+ u32 agc;
+
+ regmap_read(r_s, AGCREAD_S, &tmpu);
+ agc = tmpu << 8;
+
+ c->strength.len = 1;
+ c->strength.stat[0].scale = FE_SCALE_RELATIVE;
+ c->strength.stat[0].uvalue = agc;
+ }
+
+ /* C/N rate */
+ c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+
+ if (*status & FE_HAS_VITERBI) {
+ u32 cnr = 0, x, y, d;
+ u64 d_3 = 0;
+
+ regmap_read(r_s, CNRDXU_S, &tmpu);
+ regmap_read(r_s, CNRDXL_S, &tmpl);
+ x = (tmpu << 8) | tmpl;
+ regmap_read(r_s, CNRDYU_S, &tmpu);
+ regmap_read(r_s, CNRDYL_S, &tmpl);
+ y = (tmpu << 8) | tmpl;
+
+ /* CNR[dB]: 10 * log10(D) - 30.74 / D^3 - 3 */
+ /* D = x^2 / (2^15 * y - x^2) */
+ d = (y << 15) - x * x;
+ if (d > 0) {
+ /* (2^4 * D)^3 = 2^12 * D^3 */
+ /* 3.074 * 2^(12 + 24) = 211243671486 */
+ d_3 = div_u64(16 * x * x, d);
+ d_3 = d_3 * d_3 * d_3;
+ if (d_3)
+ d_3 = div_u64(211243671486ULL, d_3);
+ }
+
+ if (d_3) {
+ /* 0.3 * 2^24 = 5033164 */
+ tmp = (s64)2 * intlog10(x) - intlog10(abs(d)) - d_3
+ - 5033164;
+ cnr = div_u64(tmp * 10000, 1 << 24);
+ }
+
+ if (cnr) {
+ c->cnr.len = 1;
+ c->cnr.stat[0].scale = FE_SCALE_DECIBEL;
+ c->cnr.stat[0].uvalue = cnr;
+ }
+ }
+
+ /* BER */
+ c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+ c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+
+ regmap_read(r_s, BERCNFLG_S, &flg);
+
+ if ((*status & FE_HAS_VITERBI) && (flg & BERCNFLG_S_BERVRDY)) {
+ u32 bit_err, bit_cnt;
+
+ regmap_read(r_s, BERVRDU_S, &tmpu);
+ regmap_read(r_s, BERVRDL_S, &tmpl);
+ bit_err = (tmpu << 8) | tmpl;
+ bit_cnt = (1 << 13) * 204;
+
+ if (bit_cnt) {
+ c->post_bit_error.len = 1;
+ c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER;
+ c->post_bit_error.stat[0].uvalue = bit_err;
+ c->post_bit_count.len = 1;
+ c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER;
+ c->post_bit_count.stat[0].uvalue = bit_cnt;
+ }
+ }
+
+ return 0;
+}
+
+static void sc1501a_t_sleep(struct sc1501a_priv *chip)
+{
+ struct regmap *r_t = chip->regmap_t;
+
+ regmap_update_bits(r_t, PWDSET, PWDSET_OFDMPD_MASK,
+ PWDSET_OFDMPD_DOWN);
+}
+
+static void sc1501a_t_wake(struct sc1501a_priv *chip)
+{
+ struct regmap *r_t = chip->regmap_t;
+
+ regmap_update_bits(r_t, PWDSET, PWDSET_OFDMPD_MASK, 0);
+}
+
+static bool sc1501a_t_is_valid_clk(u32 adckt, u32 if_freq)
+{
+ if (if_freq == DIRECT_IF_57MHZ) {
+ if (adckt >= CLK_DIRECT && adckt <= 21000000)
+ return true;
+ if (adckt >= 25300000 && adckt <= CLK_MAX)
+ return true;
+ } else if (if_freq == DIRECT_IF_44MHZ) {
+ if (adckt >= 25000000 && adckt <= CLK_MAX)
+ return true;
+ } else if (if_freq >= LOW_IF_4MHZ && if_freq < DIRECT_IF_44MHZ) {
+ if (adckt >= CLK_DIRECT && adckt <= CLK_MAX)
+ return true;
+ }
+
+ return false;
+}
+
+static int sc1501a_t_set_freq(struct sc1501a_priv *chip)
+{
+ struct device *dev = &chip->client_s->dev;
+ struct regmap *r_t = chip->regmap_t;
+ s64 adckt, nco, ad_t;
+ u32 m, v;
+
+ /* Clock buffer (but not supported) or XTAL */
+ if (chip->clk_freq >= CLK_LOW && chip->clk_freq < CLK_DIRECT) {
+ chip->use_clkbuf = true;
+ regmap_write(r_t, CLKSET1_T, 0x07);
+
+ adckt = 0;
+ } else {
+ chip->use_clkbuf = false;
+ regmap_write(r_t, CLKSET1_T, 0x00);
+
+ adckt = chip->clk_freq;
+ }
+ if (!sc1501a_t_is_valid_clk(adckt, chip->if_freq)) {
+ dev_err(dev, "Invalid clock, CLK:%d, ADCKT:%lld, IF:%d\n",
+ chip->clk_freq, adckt, chip->if_freq);
+ return -EINVAL;
+ }
+
+ /* Direct IF or Low IF */
+ if (chip->if_freq == DIRECT_IF_57MHZ ||
+ chip->if_freq == DIRECT_IF_44MHZ)
+ nco = adckt * 2 - chip->if_freq;
+ else
+ nco = -((s64)chip->if_freq);
+ nco = div_s64(nco << 24, adckt);
+ ad_t = div_s64(adckt << 22, S_T_FREQ);
+
+ regmap_write(r_t, NCOFREQU_T, nco >> 16);
+ regmap_write(r_t, NCOFREQM_T, nco >> 8);
+ regmap_write(r_t, NCOFREQL_T, nco);
+ regmap_write(r_t, FADU_T, ad_t >> 16);
+ regmap_write(r_t, FADM_T, ad_t >> 8);
+ regmap_write(r_t, FADL_T, ad_t);
+
+ /* Level of IF */
+ m = ADCSET1_T_REFSEL_MASK;
+ v = ADCSET1_T_REFSEL_1_5V;
+ regmap_update_bits(r_t, ADCSET1_T, m, v);
+
+ /* Polarity of AGC */
+ v = AGCSET2_T_IFPOLINV_INC | AGCSET2_T_RFPOLINV_INC;
+ regmap_update_bits(r_t, AGCSET2_T, v, v);
+
+ /* Lower output level of AGC */
+ regmap_write(r_t, AGCV3_T, 0x00);
+
+ regmap_write(r_t, MDSET_T, 0xfa);
+
+ return 0;
+}
+
+static void sc1501a_t_tune(struct sc1501a_priv *chip,
+ struct dtv_frontend_properties *c)
+{
+ struct regmap *r_t = chip->regmap_t;
+ u32 m, v;
+
+ m = MDSET_T_MDAUTO_MASK | MDSET_T_FFTS_MASK | MDSET_T_GI_MASK;
+ v = MDSET_T_MDAUTO_AUTO | MDSET_T_FFTS_MODE3 | MDSET_T_GI_1_8;
+ regmap_update_bits(r_t, MDSET_T, m, v);
+
+ regmap_write(r_t, MDASET_T, 0);
+}
+
+static int sc1501a_t_read_status(struct sc1501a_priv *chip,
+ struct dtv_frontend_properties *c,
+ enum fe_status *status)
+{
+ struct regmap *r_t = chip->regmap_t;
+ u32 seqrd, st, flg, tmpu, tmpm, tmpl;
+ u64 tmp;
+
+ /* Sync detection */
+ regmap_read(r_t, SSEQRD_T, &seqrd);
+ st = seqrd & SSEQRD_T_SSEQSTRD_MASK;
+
+ *status = 0;
+ if (st >= SSEQRD_T_SSEQSTRD_SYNC)
+ *status |= FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
+ if (st >= SSEQRD_T_SSEQSTRD_FRAME_SYNC)
+ *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER;
+
+ /* Signal strength */
+ c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+
+ if (*status & FE_HAS_SIGNAL) {
+ u32 agc;
+
+ regmap_read(r_t, AGCRDU_T, &tmpu);
+ regmap_read(r_t, AGCRDL_T, &tmpl);
+ agc = (tmpu << 8) | tmpl;
+
+ c->strength.len = 1;
+ c->strength.stat[0].scale = FE_SCALE_RELATIVE;
+ c->strength.stat[0].uvalue = agc;
+ }
+
+ /* C/N rate */
+ c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+
+ if (*status & FE_HAS_VITERBI) {
+ u32 cnr;
+
+ regmap_read(r_t, CNRDU_T, &tmpu);
+ regmap_read(r_t, CNRDL_T, &tmpl);
+
+ if (tmpu || tmpl) {
+ /* CNR[dB]: 10 * (log10(65536 / value) + 0.2) */
+ /* intlog10(65536) = 80807124, 0.2 * 2^24 = 3355443 */
+ tmp = (u64)80807124 - intlog10((tmpu << 8) | tmpl)
+ + 3355443;
+ cnr = div_u64(tmp * 10000, 1 << 24);
+ } else {
+ cnr = 0;
+ }
+
+ c->cnr.len = 1;
+ c->cnr.stat[0].scale = FE_SCALE_DECIBEL;
+ c->cnr.stat[0].uvalue = cnr;
+ }
+
+ /* BER */
+ c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+ c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+
+ regmap_read(r_t, BERFLG_T, &flg);
+
+ if ((*status & FE_HAS_VITERBI) && (flg & BERFLG_T_BERVRDYA)) {
+ u32 bit_err, bit_cnt;
+
+ regmap_read(r_t, BERRDU_T, &tmpu);
+ regmap_read(r_t, BERRDM_T, &tmpm);
+ regmap_read(r_t, BERRDL_T, &tmpl);
+ bit_err = (tmpu << 16) | (tmpm << 8) | tmpl;
+
+ regmap_read(r_t, BERLENRDU_T, &tmpu);
+ regmap_read(r_t, BERLENRDL_T, &tmpl);
+ bit_cnt = ((tmpu << 8) | tmpl) * 203 * 8;
+
+ if (bit_cnt) {
+ c->post_bit_error.len = 1;
+ c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER;
+ c->post_bit_error.stat[0].uvalue = bit_err;
+ c->post_bit_count.len = 1;
+ c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER;
+ c->post_bit_count.stat[0].uvalue = bit_cnt;
+ }
+ }
+
+ return 0;
+}
+
+static int sc1501a_sleep(struct dvb_frontend *fe)
+{
+ struct sc1501a_priv *chip = fe->demodulator_priv;
+
+ sc1501a_s_sleep(chip);
+ sc1501a_t_sleep(chip);
+
+ return 0;
+}
+
+static int sc1501a_set_frontend(struct dvb_frontend *fe)
+{
+ struct sc1501a_priv *chip = fe->demodulator_priv;
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+ struct regmap *r_s = chip->regmap_s;
+ struct regmap *r_t = chip->regmap_t;
+ u8 tssel = 0, intsel = 0;
+
+ if (c->delivery_system == SYS_ISDBS) {
+ sc1501a_s_wake(chip);
+ sc1501a_t_sleep(chip);
+
+ tssel = TSSET1_TSASEL_ISDBS;
+ intsel = TSSET3_INTASEL_S;
+ } else if (c->delivery_system == SYS_ISDBT) {
+ sc1501a_s_sleep(chip);
+ sc1501a_t_wake(chip);
+
+ sc1501a_t_set_freq(chip);
+
+ tssel = TSSET1_TSASEL_ISDBT;
+ intsel = TSSET3_INTASEL_T;
+ }
+
+ regmap_update_bits(r_t, TSSET1,
+ TSSET1_TSASEL_MASK | TSSET1_TSBSEL_MASK,
+ tssel | TSSET1_TSBSEL_NONE);
+ regmap_write(r_t, TSSET2, 0);
+ regmap_update_bits(r_t, TSSET3,
+ TSSET3_INTASEL_MASK | TSSET3_INTBSEL_MASK,
+ intsel | TSSET3_INTBSEL_NONE);
+
+ regmap_write(r_t, DOSET1_T, 0x95);
+ regmap_write(r_s, DOSET1_S, 0x80);
+
+ if (c->delivery_system == SYS_ISDBS)
+ sc1501a_s_tune(chip, c);
+ else if (c->delivery_system == SYS_ISDBT)
+ sc1501a_t_tune(chip, c);
+
+ if (fe->ops.tuner_ops.set_params) {
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
+ fe->ops.tuner_ops.set_params(fe);
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 0);
+ }
+
+ return 0;
+}
+
+static int sc1501a_get_tune_settings(struct dvb_frontend *fe,
+ struct dvb_frontend_tune_settings *s)
+{
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+
+ s->min_delay_ms = 850;
+
+ if (c->delivery_system == SYS_ISDBS) {
+ s->max_drift = 30000 * 2 + 1;
+ s->step_size = 30000;
+ } else if (c->delivery_system == SYS_ISDBT) {
+ s->max_drift = 142857 * 2 + 1;
+ s->step_size = 142857 * 2;
+ }
+
+ return 0;
+}
+
+static int sc1501a_read_status(struct dvb_frontend *fe, enum fe_status *status)
+{
+ struct sc1501a_priv *chip = fe->demodulator_priv;
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+
+ if (c->delivery_system == SYS_ISDBS)
+ return sc1501a_s_read_status(chip, c, status);
+
+ if (c->delivery_system == SYS_ISDBT)
+ return sc1501a_t_read_status(chip, c, status);
+
+ return -EINVAL;
+}
+
+static const struct dvb_frontend_ops sc1501a_ops = {
+ .delsys = { SYS_ISDBS, SYS_ISDBT },
+ .info = {
+ .name = "Socionext SC1501A",
+ .frequency_min = 90000000,
+ .frequency_max = 2100000000,
+ .caps = FE_CAN_INVERSION_AUTO | FE_CAN_FEC_AUTO |
+ FE_CAN_QAM_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO |
+ FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO,
+ },
+
+ .sleep = sc1501a_sleep,
+ .set_frontend = sc1501a_set_frontend,
+ .get_tune_settings = sc1501a_get_tune_settings,
+ .read_status = sc1501a_read_status,
+};
+
+static const struct regmap_config regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .cache_type = REGCACHE_NONE,
+};
+
+static int sc1501a_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct sc1501a_config *conf = client->dev.platform_data;
+ struct sc1501a_priv *chip;
+ struct device *dev = &client->dev;
+ int ret;
+
+ chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
+ if (!chip)
+ return -ENOMEM;
+
+ if (dev->of_node)
+ chip->spec = of_device_get_match_data(dev);
+ else
+ chip->spec = (struct sc1501a_spec *)id->driver_data;
+ if (!chip->spec)
+ return -EINVAL;
+
+ chip->mclk = devm_clk_get(dev, "mclk");
+ if (IS_ERR(chip->mclk) && !conf) {
+ dev_err(dev, "Failed to request mclk: %ld\n",
+ PTR_ERR(chip->mclk));
+ return PTR_ERR(chip->mclk);
+ }
+
+ ret = of_property_read_u32(dev->of_node, "if-frequency",
+ &chip->if_freq);
+ if (ret && !conf) {
+ dev_err(dev, "Failed to load IF frequency: %d.\n", ret);
+ return ret;
+ }
+
+ chip->reset_gpio = devm_gpiod_get_optional(dev, "reset",
+ GPIOD_OUT_HIGH);
+ if (IS_ERR(chip->reset_gpio)) {
+ dev_err(dev, "Failed to request reset_gpio: %ld\n",
+ PTR_ERR(chip->reset_gpio));
+ return PTR_ERR(chip->reset_gpio);
+ }
+
+ if (conf) {
+ chip->mclk = conf->mclk;
+ chip->if_freq = conf->if_freq;
+ chip->reset_gpio = conf->reset_gpio;
+
+ *conf->fe = &chip->fe;
+ }
+
+ chip->client_s = client;
+ chip->regmap_s = devm_regmap_init_i2c(chip->client_s, ®map_config);
+ if (IS_ERR(chip->regmap_s))
+ return PTR_ERR(chip->regmap_s);
+
+ /*
+ * Chip has two I2C addresses for each satellite/terrestrial system.
+ * ISDB-T uses address ISDB-S + 4, so we register a dummy client.
+ */
+ chip->client_t = i2c_new_dummy(client->adapter, client->addr + 4);
+ if (!chip->client_t)
+ return -ENODEV;
+
+ chip->regmap_t = devm_regmap_init_i2c(chip->client_t, ®map_config);
+ if (IS_ERR(chip->regmap_t)) {
+ ret = PTR_ERR(chip->regmap_t);
+ goto err_i2c_t;
+ }
+
+ chip->clk_freq = clk_get_rate(chip->mclk);
+
+ memcpy(&chip->fe.ops, &sc1501a_ops, sizeof(sc1501a_ops));
+ chip->fe.demodulator_priv = chip;
+ i2c_set_clientdata(client, chip);
+
+ sc1501a_cmn_power_on(chip);
+ sc1501a_s_sleep(chip);
+ sc1501a_t_sleep(chip);
+
+ return 0;
+
+err_i2c_t:
+ i2c_unregister_device(chip->client_t);
+
+ return ret;
+}
+
+static int sc1501a_remove(struct i2c_client *client)
+{
+ struct sc1501a_priv *chip = i2c_get_clientdata(client);
+
+ sc1501a_cmn_power_off(chip);
+
+ i2c_unregister_device(chip->client_t);
+
+ return 0;
+}
+
+static const struct sc1501a_spec sc1501a_spec_pri = {
+ .primary = true,
+};
+
+static const struct sc1501a_spec sc1501a_spec_sec = {
+ .primary = false,
+};
+
+static const struct of_device_id sc1501a_of_match[] = {
+ { .compatible = "socionext,mn884433", .data = &sc1501a_spec_pri, },
+ { .compatible = "socionext,mn884434-0", .data = &sc1501a_spec_pri, },
+ { .compatible = "socionext,mn884434-1", .data = &sc1501a_spec_sec, },
+ { .compatible = "socionext,sc1501a", .data = &sc1501a_spec_pri, },
+ {}
+};
+MODULE_DEVICE_TABLE(of, sc1501a_of_match);
+
+static const struct i2c_device_id sc1501a_i2c_id[] = {
+ { "mn884433", (kernel_ulong_t)&sc1501a_spec_pri },
+ { "mn884434-0", (kernel_ulong_t)&sc1501a_spec_pri },
+ { "mn884434-1", (kernel_ulong_t)&sc1501a_spec_sec },
+ { "sc1501a", (kernel_ulong_t)&sc1501a_spec_pri },
+ {}
+};
+MODULE_DEVICE_TABLE(i2c, sc1501a_i2c_id);
+
+static struct i2c_driver sc1501a_driver = {
+ .driver = {
+ .name = "sc1501a",
+ .of_match_table = of_match_ptr(sc1501a_of_match),
+ },
+ .probe = sc1501a_probe,
+ .remove = sc1501a_remove,
+ .id_table = sc1501a_i2c_id,
+};
+
+module_i2c_driver(sc1501a_driver);
+
+MODULE_AUTHOR("Katsuhiro Suzuki <suzuki.katsuhiro@socionext.com>");
+MODULE_DESCRIPTION("Socionext SC1501A series demodulator driver.");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/dvb-frontends/sc1501a.h b/drivers/media/dvb-frontends/sc1501a.h
new file mode 100644
index 000000000000..7e247d44e4ac
--- /dev/null
+++ b/drivers/media/dvb-frontends/sc1501a.h
@@ -0,0 +1,27 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Socionext SC1501A series demodulator driver for ISDB-S/ISDB-T.
+ *
+ * Copyright (c) 2018 Socionext Inc.
+ */
+
+#ifndef SC1501A_H
+#define SC1501A_H
+
+#include <media/dvb_frontend.h>
+
+/* ISDB-T IF frequency */
+#define DIRECT_IF_57MHZ 57000000
+#define DIRECT_IF_44MHZ 44000000
+#define LOW_IF_4MHZ 4000000
+
+struct sc1501a_config {
+ struct clk *mclk;
+ u32 if_freq;
+ struct gpio_desc *reset_gpio;
+
+ /* Everything after that is returned by the driver. */
+ struct dvb_frontend **fe;
+};
+
+#endif /* SC1501A_H */
--
2.17.0
^ permalink raw reply related
* [PATCH v2 10/11] arm64: dts: r8a77965-salvator-x: Enable DU external clocks and HDMI
From: Kuninori Morimoto @ 2018-05-29 1:44 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAMuHMdW6HeWMwRDcn6PLnwzgxvYz-h=jx=1qvYEK9okwqY0itg@mail.gmail.com>
Hi Geert
> > +&hdmi0_con {
> > + remote-endpoint = <&rcar_dw_hdmi0_out>;
> > +};
>
> I think the hdmi0 and hdmi0_con parts can be moved to salvator-common.dtsi.
> Can we do that now (with stubs?), or does this have to wait until r8a77965 has
> received HDMI sound support?
HDMI sound doesn't use hdmi0_con.
You can do it now, thanks
Best regards
---
Kuninori Morimoto
^ permalink raw reply
* [PATCH V0:net-next 0/4] net: ethernet: stmmac: add support for stm32mp1
From: David Miller @ 2018-05-29 3:08 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1527234401-15812-1-git-send-email-christophe.roullier@st.com>
From: Christophe Roullier <christophe.roullier@st.com>
Date: Fri, 25 May 2018 09:46:37 +0200
> Patches to have Ethernet support on stm32mp1
Series applied.
^ permalink raw reply
* [PATCH 0/2] Add Mediatek X20 Development Board support
From: Manivannan Sadhasivam @ 2018-05-29 4:52 UTC (permalink / raw)
To: linux-arm-kernel
Add devicetree support for Mediatek X20 Development Board by Archermind.
This board is based on the Deca-Core MT6797 SoC from Mediatek and is
one of the 96Boards Consumer Edition platform.
With this devicetree change, board can boot into initramfs.
More information about this board can be found in 96Boards product page:
https://www.96boards.org/product/mediatek-x20/
Manivannan Sadhasivam (2):
dt-bindings: Add vendor prefix for ArcherMind
arm64: dts: Add Mediatek X20 Development Board support
.../devicetree/bindings/vendor-prefixes.txt | 1 +
arch/arm64/boot/dts/mediatek/Makefile | 1 +
.../boot/dts/mediatek/mt6797-x20-dev.dts | 33 +++++++++++++++++++
3 files changed, 35 insertions(+)
create mode 100644 arch/arm64/boot/dts/mediatek/mt6797-x20-dev.dts
--
2.17.0
^ permalink raw reply
* [PATCH 1/2] dt-bindings: Add vendor prefix for ArcherMind
From: Manivannan Sadhasivam @ 2018-05-29 4:52 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180529045258.1415-1-manivannan.sadhasivam@linaro.org>
Add vendor prefix for ArcherMind Technology (Nanjing) Co., Ltd.
Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
---
Documentation/devicetree/bindings/vendor-prefixes.txt | 1 +
1 file changed, 1 insertion(+)
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index a38d8bfae19c..f601acb5a0b4 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -32,6 +32,7 @@ andestech Andes Technology Corporation
apm Applied Micro Circuits Corporation (APM)
aptina Aptina Imaging
arasan Arasan Chip Systems
+archermind ArcherMind Technology (Nanjing) Co., Ltd.
arctic Arctic Sand
aries Aries Embedded GmbH
arm ARM Ltd.
--
2.17.0
^ permalink raw reply related
* [PATCH 2/2] arm64: dts: Add Mediatek X20 Development Board support
From: Manivannan Sadhasivam @ 2018-05-29 4:52 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180529045258.1415-1-manivannan.sadhasivam@linaro.org>
Add initial device tree support for Mediatek X20 Development Board
based on MT6797 Deca core SoC. This board is one of the 96Boards
Consumer Edition platform.
Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
---
arch/arm64/boot/dts/mediatek/Makefile | 1 +
.../boot/dts/mediatek/mt6797-x20-dev.dts | 33 +++++++++++++++++++
2 files changed, 34 insertions(+)
create mode 100644 arch/arm64/boot/dts/mediatek/mt6797-x20-dev.dts
diff --git a/arch/arm64/boot/dts/mediatek/Makefile b/arch/arm64/boot/dts/mediatek/Makefile
index ac17f60f998c..5b7fd6ad96e4 100644
--- a/arch/arm64/boot/dts/mediatek/Makefile
+++ b/arch/arm64/boot/dts/mediatek/Makefile
@@ -3,5 +3,6 @@ dtb-$(CONFIG_ARCH_MEDIATEK) += mt2712-evb.dtb
dtb-$(CONFIG_ARCH_MEDIATEK) += mt6755-evb.dtb
dtb-$(CONFIG_ARCH_MEDIATEK) += mt6795-evb.dtb
dtb-$(CONFIG_ARCH_MEDIATEK) += mt6797-evb.dtb
+dtb-$(CONFIG_ARCH_MEDIATEK) += mt6797-x20-dev.dtb
dtb-$(CONFIG_ARCH_MEDIATEK) += mt7622-rfb1.dtb
dtb-$(CONFIG_ARCH_MEDIATEK) += mt8173-evb.dtb
diff --git a/arch/arm64/boot/dts/mediatek/mt6797-x20-dev.dts b/arch/arm64/boot/dts/mediatek/mt6797-x20-dev.dts
new file mode 100644
index 000000000000..2c09ca95d9e2
--- /dev/null
+++ b/arch/arm64/boot/dts/mediatek/mt6797-x20-dev.dts
@@ -0,0 +1,33 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Device Tree Source for MediaTek X20 Development Board
+ *
+ * Copyright (C) 2018, Linaro Ltd.
+ *
+ */
+
+/dts-v1/;
+
+#include "mt6797.dtsi"
+
+/ {
+ model = "Mediatek X20 Development Board";
+ compatible = "archermind,mt6797-x20-dev", "mediatek,mt6797";
+
+ aliases {
+ serial0 = &uart1;
+ };
+
+ memory at 40000000 {
+ device_type = "memory";
+ reg = <0 0x40000000 0 0x1e605000>;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+};
+
+&uart1 {
+ status = "okay";
+};
--
2.17.0
^ permalink raw reply related
* [PATCH v2 1/8] driver core: make deferring probe after init optional
From: Frank Rowand @ 2018-05-29 5:12 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180524181834.GF4828@sirena.org.uk>
On 05/24/18 11:18, Mark Brown wrote:
> On Thu, May 24, 2018 at 12:50:17PM -0500, Rob Herring wrote:
>
>> Subsystems or drivers may opt-in to this behavior by calling
>> driver_deferred_probe_check_init_done() instead of just returning
>> -EPROBE_DEFER. They may use additional information from DT or kernel's
>> config to decide whether to continue to defer probe or not.
>
> Should userspace have some involvement in this decision? It knows if
> it's got any intention of loading modules for example. Kernel config
> checks might be good enough, though it's going to be a pain to work out
> if the relevant driver is built as a module for example.
>
A parallel issue is that loading an overlay could provide the resource
that will allow the deferred probe to complete. (That is, once we
finish implementing the run time overlays feature.)
-Frank
^ permalink raw reply
* linux-next: manual merge of the irqchip tree with the arm-soc tree
From: Stephen Rothwell @ 2018-05-29 5:52 UTC (permalink / raw)
To: linux-arm-kernel
Hi all,
Today's linux-next merge of the irqchip tree got a conflict in:
arch/arm/boot/dts/stm32mp157c.dtsi
between commit:
3c00436fdb20 ("ARM: dts: stm32: add USBPHYC support to stm32mp157c")
from the arm-soc tree and commit:
5f0e9d2557d7 ("ARM: dts: stm32: Add exti support for stm32mp157c")
from the irqchip tree.
I fixed it up (see below) and can carry the fix as necessary. This
is now fixed as far as linux-next is concerned, but any non trivial
conflicts should be mentioned to your upstream maintainer when your tree
is submitted for merging. You may also want to consider cooperating
with the maintainer of the conflicting tree to minimise any particularly
complex conflicts.
--
Cheers,
Stephen Rothwell
diff --cc arch/arm/boot/dts/stm32mp157c.dtsi
index b66f673b5038,4fa0df853c8a..000000000000
--- a/arch/arm/boot/dts/stm32mp157c.dtsi
+++ b/arch/arm/boot/dts/stm32mp157c.dtsi
@@@ -777,26 -183,13 +777,33 @@@
status = "disabled";
};
+ usbphyc: usbphyc at 5a006000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "st,stm32mp1-usbphyc";
+ reg = <0x5a006000 0x1000>;
+ clocks = <&rcc USBPHY_K>;
+ resets = <&rcc USBPHY_R>;
+ status = "disabled";
+
+ usbphyc_port0: usb-phy at 0 {
+ #phy-cells = <0>;
+ reg = <0>;
+ };
+
+ usbphyc_port1: usb-phy at 1 {
+ #phy-cells = <1>;
+ reg = <1>;
+ };
+ };
+
+ exti: interrupt-controller at 5000d000 {
+ compatible = "st,stm32mp1-exti", "syscon";
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ reg = <0x5000d000 0x400>;
+ };
+
usart1: serial at 5c000000 {
compatible = "st,stm32h7-uart";
reg = <0x5c000000 0x400>;
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 488 bytes
Desc: OpenPGP digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20180529/5a2ead38/attachment.sig>
^ permalink raw reply
* enable OTG on wandboard and riotboard
From: Alexander Kurz @ 2018-05-29 6:20 UTC (permalink / raw)
To: linux-arm-kernel
Both boards wandboard and riotboard feature an USB OTG connector.
Change the DT regulator nodes to match the convention, fix the
GPIO regulator polatity for the riotboard and add enable OTG
including the regulator infrastructure on the riotboard.
Changes since v2:
* split patch 0001 into two board specific patches
* use GPIO_ACTIVE_HIGH instead of literal numbers in patch v1-0001 (now v2-0002)
^ permalink raw reply
* [PATCH v2 1/4] ARM: dts: imx6qdl-wandboard: remove regulators bus node
From: Alexander Kurz @ 2018-05-29 6:20 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180529062021.3154-1-akurz@blala.de>
To match the convention, move all regulator-fixed nodes directly into
the root node.
Signed-off-by: Alexander Kurz <akurz@blala.de>
---
arch/arm/boot/dts/imx6qdl-wandboard.dtsi | 40 +++++++++++++-------------------
1 file changed, 16 insertions(+), 24 deletions(-)
diff --git a/arch/arm/boot/dts/imx6qdl-wandboard.dtsi b/arch/arm/boot/dts/imx6qdl-wandboard.dtsi
index ed96d7b5feab..b9c6c9d5d357 100644
--- a/arch/arm/boot/dts/imx6qdl-wandboard.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-wandboard.dtsi
@@ -12,30 +12,6 @@
#include <dt-bindings/gpio/gpio.h>
/ {
- regulators {
- compatible = "simple-bus";
- #address-cells = <1>;
- #size-cells = <0>;
-
- reg_2p5v: regulator at 0 {
- compatible = "regulator-fixed";
- reg = <0>;
- regulator-name = "2P5V";
- regulator-min-microvolt = <2500000>;
- regulator-max-microvolt = <2500000>;
- regulator-always-on;
- };
-
- reg_3p3v: regulator at 1 {
- compatible = "regulator-fixed";
- reg = <1>;
- regulator-name = "3P3V";
- regulator-min-microvolt = <3300000>;
- regulator-max-microvolt = <3300000>;
- regulator-always-on;
- };
- };
-
sound {
compatible = "fsl,imx6-wandboard-sgtl5000",
"fsl,imx-audio-sgtl5000";
@@ -56,6 +32,22 @@
spdif-controller = <&spdif>;
spdif-out;
};
+
+ reg_2p5v: regulator-2p5v {
+ compatible = "regulator-fixed";
+ regulator-name = "2P5V";
+ regulator-min-microvolt = <2500000>;
+ regulator-max-microvolt = <2500000>;
+ regulator-always-on;
+ };
+
+ reg_3p3v: regulator-3p3v {
+ compatible = "regulator-fixed";
+ regulator-name = "3P3V";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
};
&audmux {
--
2.11.0
^ permalink raw reply related
* [PATCH v2 2/4] ARM: dts: imx6dl-riotboard: remove regulators bus node
From: Alexander Kurz @ 2018-05-29 6:20 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180529062021.3154-1-akurz@blala.de>
To match the convention, move regulator-fixed nodes directly into
the root node.
Signed-off-by: Alexander Kurz <akurz@blala.de>
---
arch/arm/boot/dts/imx6dl-riotboard.dts | 55 ++++++++++++++--------------------
1 file changed, 23 insertions(+), 32 deletions(-)
diff --git a/arch/arm/boot/dts/imx6dl-riotboard.dts b/arch/arm/boot/dts/imx6dl-riotboard.dts
index 2e98c92adff7..a6851bfebbdb 100644
--- a/arch/arm/boot/dts/imx6dl-riotboard.dts
+++ b/arch/arm/boot/dts/imx6dl-riotboard.dts
@@ -19,38 +19,6 @@
reg = <0x10000000 0x40000000>;
};
- regulators {
- compatible = "simple-bus";
- #address-cells = <1>;
- #size-cells = <0>;
-
- reg_2p5v: regulator at 0 {
- compatible = "regulator-fixed";
- reg = <0>;
- regulator-name = "2P5V";
- regulator-min-microvolt = <2500000>;
- regulator-max-microvolt = <2500000>;
- };
-
- reg_3p3v: regulator at 1 {
- compatible = "regulator-fixed";
- reg = <1>;
- regulator-name = "3P3V";
- regulator-min-microvolt = <3300000>;
- regulator-max-microvolt = <3300000>;
- };
-
- reg_usb_otg_vbus: regulator at 2 {
- compatible = "regulator-fixed";
- reg = <2>;
- regulator-name = "usb_otg_vbus";
- regulator-min-microvolt = <5000000>;
- regulator-max-microvolt = <5000000>;
- gpio = <&gpio3 22 0>;
- enable-active-high;
- };
- };
-
leds {
compatible = "gpio-leds";
pinctrl-names = "default";
@@ -82,6 +50,29 @@
mux-int-port = <1>;
mux-ext-port = <3>;
};
+
+ reg_2p5v: regulator-2p5v {
+ compatible = "regulator-fixed";
+ regulator-name = "2P5V";
+ regulator-min-microvolt = <2500000>;
+ regulator-max-microvolt = <2500000>;
+ };
+
+ reg_3p3v: regulator-3p3v {
+ compatible = "regulator-fixed";
+ regulator-name = "3P3V";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ reg_usb_otg_vbus: regulator-usbotgvbus {
+ compatible = "regulator-fixed";
+ regulator-name = "usb_otg_vbus";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ gpio = <&gpio3 22 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
};
&audmux {
--
2.11.0
^ permalink raw reply related
* [PATCH v2 3/4] ARM: dts: imx6qdl-wandboard: enable USB OTG
From: Alexander Kurz @ 2018-05-29 6:20 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180529062021.3154-1-akurz@blala.de>
Enable USB OTG (dual-role) on the Wandboard.
Note, that the USB_OTG_VBUS current is quite limited due to a 22R resistor
in the power line. Hence, the overcurrent signal of 1A will never be
triggered on this board.
Signed-off-by: Alexander Kurz <akurz@blala.de>
---
arch/arm/boot/dts/imx6qdl-wandboard.dtsi | 19 ++++++++++++++++++-
1 file changed, 18 insertions(+), 1 deletion(-)
diff --git a/arch/arm/boot/dts/imx6qdl-wandboard.dtsi b/arch/arm/boot/dts/imx6qdl-wandboard.dtsi
index b9c6c9d5d357..01ee36af7ba4 100644
--- a/arch/arm/boot/dts/imx6qdl-wandboard.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-wandboard.dtsi
@@ -48,6 +48,16 @@
regulator-max-microvolt = <3300000>;
regulator-always-on;
};
+
+ reg_usb_otg_vbus: regulator-usbotgvbus {
+ compatible = "regulator-fixed";
+ regulator-name = "usb_otg_vbus";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usbotgvbus>;
+ gpio = <&gpio3 22 GPIO_ACTIVE_LOW>;
+ };
};
&audmux {
@@ -162,6 +172,12 @@
>;
};
+ pinctrl_usbotgvbus: usbotgvbusgrp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x130b0
+ >;
+ };
+
pinctrl_usdhc1: usdhc1grp {
fsl,pins = <
MX6QDL_PAD_SD1_CMD__SD1_CMD 0x17059
@@ -236,10 +252,11 @@
};
&usbotg {
+ vbus-supply = <®_usb_otg_vbus>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_usbotg>;
disable-over-current;
- dr_mode = "peripheral";
+ dr_mode = "otg";
status = "okay";
};
--
2.11.0
^ permalink raw reply related
* [PATCH v2 4/4] ARM: dts: imx6dl-riotboard: fix OTG regulator polarity
From: Alexander Kurz @ 2018-05-29 6:20 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180529062021.3154-1-akurz@blala.de>
USB OTG power is switched on when the GPIO is pulled low.
Signed-off-by: Alexander Kurz <akurz@blala.de>
---
arch/arm/boot/dts/imx6dl-riotboard.dts | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/arch/arm/boot/dts/imx6dl-riotboard.dts b/arch/arm/boot/dts/imx6dl-riotboard.dts
index a6851bfebbdb..89b06e20480d 100644
--- a/arch/arm/boot/dts/imx6dl-riotboard.dts
+++ b/arch/arm/boot/dts/imx6dl-riotboard.dts
@@ -70,8 +70,7 @@
regulator-name = "usb_otg_vbus";
regulator-min-microvolt = <5000000>;
regulator-max-microvolt = <5000000>;
- gpio = <&gpio3 22 GPIO_ACTIVE_HIGH>;
- enable-active-high;
+ gpio = <&gpio3 22 GPIO_ACTIVE_LOW>;
};
};
--
2.11.0
^ permalink raw reply related
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