* [PATCH 5/6] arm/arm64: vgic-new: Implement VGICv3 CPU interface access
From: Marc Zyngier @ 2016-09-17 11:37 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CALicx6ucEH3w58Rhb8Urk0V5kRcqtUdwDYDtSLXrkas-Jatv=A@mail.gmail.com>
On Sat, 17 Sep 2016 11:58:48 +0530
Vijay Kilari <vijay.kilari@gmail.com> wrote:
> On Fri, Sep 16, 2016 at 10:37 PM, Marc Zyngier <marc.zyngier@arm.com> wrote:
> > On 16/09/16 17:57, Vijay Kilari wrote:
> >> On Fri, Sep 16, 2016 at 8:06 PM, Marc Zyngier <marc.zyngier@arm.com> wrote:
> >>> On 16/09/16 13:20, vijay.kilari at gmail.com wrote:
> >>>> From: Vijaya Kumar K <Vijaya.Kumar@cavium.com>
> >>>>
> >>>> VGICv3 CPU interface registers are accessed using
> >>>> KVM_DEV_ARM_VGIC_CPU_SYSREGS ioctl. These registers are accessed
> >>>> as 64-bit. The cpu MPIDR value is passed along with register id.
> >>>> is used to identify the cpu for registers access.
> >>>>
> >>>> The version of VGIC v3 specification is define here
> >>>> http://lists.infradead.org/pipermail/linux-arm-kernel/2016-July/445611.html
> >>>>
> >>>> Signed-off-by: Pavel Fedin <p.fedin@samsung.com>
> >>>> Signed-off-by: Vijaya Kumar K <Vijaya.Kumar@cavium.com>
> >>>> ---
> >>>> arch/arm64/include/uapi/asm/kvm.h | 3 +
> >>>> arch/arm64/kvm/Makefile | 1 +
> >>>> include/linux/irqchip/arm-gic-v3.h | 30 ++++
> >>>> virt/kvm/arm/vgic/vgic-kvm-device.c | 27 ++++
> >>>> virt/kvm/arm/vgic/vgic-mmio-v3.c | 18 +++
> >>>> virt/kvm/arm/vgic/vgic-sys-reg-v3.c | 296 ++++++++++++++++++++++++++++++++++++
> >>>> virt/kvm/arm/vgic/vgic.h | 10 ++
> >>>> 7 files changed, 385 insertions(+)
> >
> > [...]
> >
> >>>> diff --git a/virt/kvm/arm/vgic/vgic-sys-reg-v3.c b/virt/kvm/arm/vgic/vgic-sys-reg-v3.c
> >>>> new file mode 100644
> >>>> index 0000000..8e4f403
> >>>> --- /dev/null
> >>>> +++ b/virt/kvm/arm/vgic/vgic-sys-reg-v3.c
> >>>> @@ -0,0 +1,296 @@
> >>>> +#include <linux/irqchip/arm-gic-v3.h>
> >>>> +#include <linux/kvm.h>
> >>>> +#include <linux/kvm_host.h>
> >>>> +#include <kvm/iodev.h>
> >>>> +#include <kvm/arm_vgic.h>
> >>>> +#include <asm/kvm_emulate.h>
> >>>> +#include <asm/kvm_arm.h>
> >>>> +#include <asm/kvm_mmu.h>
> >>>> +
> >>>> +#include "vgic.h"
> >>>> +#include "vgic-mmio.h"
> >>>> +#include "sys_regs.h"
> >>>> +
> >>>> +static bool access_gic_ctlr(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
> >>>> + const struct sys_reg_desc *r)
> >>>> +{
> >>>> + struct vgic_vmcr vmcr;
> >>>> + u64 val;
> >>>> + u32 ich_vtr;
> >>>> +
> >>>> + vgic_get_vmcr(vcpu, &vmcr);
> >>>> + if (p->is_write) {
> >>>> + val = p->regval;
> >>>> + vmcr.ctlr &= ~(ICH_VMCR_CBPR_MASK | ICH_VMCR_EOIM_MASK);
> >>>> + vmcr.ctlr |= ((val & ICC_CTLR_EL1_CBPR_MASK) >>
> >>>> + ICC_CTLR_EL1_CBPR_SHIFT) << ICH_VMCR_CBPR_SHIFT;
> >>>> + vmcr.ctlr |= ((val & ICC_CTLR_EL1_EOImode_MASK) >>
> >>>> + ICC_CTLR_EL1_EOImode_SHIFT) << ICH_VMCR_EOIM_SHIFT;
> >>>> + vgic_set_vmcr(vcpu, &vmcr);
> >>>
> >>> You've ignored my comments again: "What if userspace writes something
> >>> that is incompatible with the current configuration? Wrong number of ID
> >>> bits, or number of priorities?"
> >>
> >> IMO, In case of incompatibility,
> >> If ID bits and PRI bits are less than HW supported, it is ok.
> >
> > Yes. But you also need to track of what the guest has programmed in
> > order to be able to migrate it back to its original configuration.
>
> You mean the vgic has to track/store the ID and PRI bits that guest
> has programmed
> and return the same when guest reads back instead of
> returning HW supported value for ICC_CTLR_EL1 reg access?.
If you have two hosts (A and B), A having 5 bits of priority and B
having 7 bits, you should be able to migrate from A to B, and then from
B to A. Which means you have to preserve what the guest knows to be its
configuration, even if you run on a more capable system. Otherwise,
you're a bit stuck.
You probably won't be able to hide the discrepancy from inside the
guest though (the guest will be able to observe the change), but this
is better than nothing.
Thanks,
M.
--
Jazz is not dead. It just smells funny.
^ permalink raw reply
* [PATCH v2] input: touchscreen: Add support for Elan eKTF2127 touchscreen controller
From: Hans de Goede @ 2016-09-17 12:04 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20160916185654.GA14732@dtor-ws>
Hi,
On 16-09-16 20:56, Dmitry Torokhov wrote:
> On Fri, Sep 02, 2016 at 09:09:35AM -0500, Rob Herring wrote:
>> On Sun, Aug 28, 2016 at 06:00:05PM +0200, Hans de Goede wrote:
>>> From: Siebren Vroegindeweij <siebren.vroegindeweij@hotmail.com>
>>>
>>> This adds a driver for the Elan eKTF2127 touchscreen controller,
>>> which speaks an i2c protocol which is distinctly different from
>>> the already supported eKTH controllers.
>>>
>>> Signed-off-by: Michel Verlaan <michel.verl@gmail.com>
>>> Signed-off-by: Siebren Vroegindeweij <siebren.vroegindeweij@hotmail.com>
>>> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
>>> ---
>>> Changes in v2:
>>> -Improve devicetree bindings document
>>> -Use touchscreen_parse_properties and touchscreen_report_pos instead of DIY
>>> -Remove a bunch of unused defines (copy and paste leftover from chipone driver)
>>> -Some other minor cleanups and review comments addressed
>>> -Add defines for some command / address hex-values
>>> -Check packet header in interrupt handler
>>> ---
>>> .../bindings/input/touchscreen/ektf2127.txt | 27 ++
>>
>> Acked-by: Rob Herring <robh@kernel.org>
>
> I'd like to merge the version below (factored out querying dimensions
> and parsing/reporting touch), can you please give it a spin?
Just tested it, works as advertised. Nice cleanup, esp. the
refactoring of the dimension querying, I should have tought of
that myself.
Regards,
Hans
^ permalink raw reply
* [PATCH V5] perf tools: adding support for address filters
From: Masami Hiramatsu @ 2016-09-17 13:33 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CANLsYkwRUps0Mtc_yQfNOW+qsmOXT8yaGrDj4566LPPTrLsUxg@mail.gmail.com>
On Fri, 16 Sep 2016 09:32:43 -0600
Mathieu Poirier <mathieu.poirier@linaro.org> wrote:
> On 13 September 2016 at 17:25, Masami Hiramatsu <mhiramat@kernel.org> wrote:
> > On Tue, 13 Sep 2016 08:18:10 -0600
> > Mathieu Poirier <mathieu.poirier@linaro.org> wrote:
> >
> >> On 13 September 2016 at 04:01, Adrian Hunter <adrian.hunter@intel.com> wrote:
> >> > On 12/09/16 20:53, Mathieu Poirier wrote:
> >> >> This patch makes it possible to use the current filter
> >> >> framework with address filters. That way address filters for
> >> >> HW tracers such as CoreSight and IntelPT can be communicated
> >> >> to the kernel drivers.
> >> >>
> >> >> Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org>
> >> >>
> >> >> ---
> >> >> Changes for V5:
> >> >> - Modified perf_evsel__append_filter() to take a string format
> >> >> rather than an operation.
> >> >
> >> > Hope I'm not being a pain, but aren't there other places calling
> >> > perf_evsel__append_filter() that need to be changed. Might make
> >> > sense as a separate patch.
> >>
> >> No no, you're right - I completely overlooked that.
> >>
> >> But shouldn't it be in the same patch? That way a git bisect would
> >> stay consistent...
> >
> > You're right. Caller and callee should be changed in atomic.
> >
> > BTW, could you add document updates how the perf command line
> > will be changed, and also show the result in the patch description?
>
> This patch does not change anything on the perf command line. It
> simply allows current options to succeed (as they should) rather than
> fail.
Yes, and it will make perf acceptable to pass --filter to CoreSight or
Intel PT events, or am I misunderstand?
If it is correct, could you give us an example how to pass it, since
tools/perf/Documentation/perf-record.txt says it is only for tracepoints?
Thank you,
>
> Thanks,
> Mathieu
>
> >
> > Thank you,
> >
> >>
> >> >
> >> >>
> >> >> Changes for V4:
> >> >> - Added support for address filters over more than one
> >> >> nibble.
> >> >> - Removed Jiri's ack, this version is too different from
> >> >> what was reviewed.
> >> >>
> >> >> Changes for V3:
> >> >> - Added Jiri's ack.
> >> >> - Rebased to v4.8-rc5.
> >> >>
> >> >> Changes for V2:
> >> >> - Rebased to v4.8-rc4.
> >> >> - Revisited error path.
> >> >>
> >> >>
> >> >> tools/perf/util/evsel.c | 4 ++--
> >> >> tools/perf/util/evsel.h | 2 +-
> >> >> tools/perf/util/parse-events.c | 40 +++++++++++++++++++++++++++++++++++-----
> >> >> 3 files changed, 38 insertions(+), 8 deletions(-)
> >> >>
> >> >> diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
> >> >> index d40f852d2de2..a9bb277f221f 100644
> >> >> --- a/tools/perf/util/evsel.c
> >> >> +++ b/tools/perf/util/evsel.c
> >> >> @@ -1047,14 +1047,14 @@ int perf_evsel__set_filter(struct perf_evsel *evsel, const char *filter)
> >> >> }
> >> >>
> >> >> int perf_evsel__append_filter(struct perf_evsel *evsel,
> >> >> - const char *op, const char *filter)
> >> >> + const char *fmt, const char *filter)
> >> >> {
> >> >> char *new_filter;
> >> >>
> >> >> if (evsel->filter == NULL)
> >> >> return perf_evsel__set_filter(evsel, filter);
> >> >>
> >> >> - if (asprintf(&new_filter,"(%s) %s (%s)", evsel->filter, op, filter) > 0) {
> >> >> + if (asprintf(&new_filter, fmt, evsel->filter, filter) > 0) {
> >> >> free(evsel->filter);
> >> >> evsel->filter = new_filter;
> >> >> return 0;
> >> >> diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
> >> >> index 8ceb7ebb51f5..50595c8c7207 100644
> >> >> --- a/tools/perf/util/evsel.h
> >> >> +++ b/tools/perf/util/evsel.h
> >> >> @@ -236,7 +236,7 @@ void perf_evsel__set_sample_id(struct perf_evsel *evsel,
> >> >>
> >> >> int perf_evsel__set_filter(struct perf_evsel *evsel, const char *filter);
> >> >> int perf_evsel__append_filter(struct perf_evsel *evsel,
> >> >> - const char *op, const char *filter);
> >> >> + const char *fmt, const char *filter);
> >> >> int perf_evsel__apply_filter(struct perf_evsel *evsel, int ncpus, int nthreads,
> >> >> const char *filter);
> >> >> int perf_evsel__apply_drv_configs(struct perf_evsel *evsel,
> >> >> diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
> >> >> index 2eb8b1ed4cc8..8e683979ccd8 100644
> >> >> --- a/tools/perf/util/parse-events.c
> >> >> +++ b/tools/perf/util/parse-events.c
> >> >> @@ -1760,20 +1760,50 @@ foreach_evsel_in_last_glob(struct perf_evlist *evlist,
> >> >> static int set_filter(struct perf_evsel *evsel, const void *arg)
> >> >> {
> >> >> const char *str = arg;
> >> >> + bool found = false;
> >> >> + int nr_addr_filters = 0;
> >> >> + struct perf_pmu *pmu = NULL;
> >> >>
> >> >> - if (evsel == NULL || evsel->attr.type != PERF_TYPE_TRACEPOINT) {
> >> >> - fprintf(stderr,
> >> >> - "--filter option should follow a -e tracepoint option\n");
> >> >> - return -1;
> >> >> + if (evsel == NULL)
> >> >> + goto err;
> >> >> +
> >> >> + if (evsel->attr.type == PERF_TYPE_TRACEPOINT) {
> >> >> + if (perf_evsel__append_filter(evsel,
> >> >> + "(%s) && (%s)", str) < 0) {
> >> >> + fprintf(stderr,
> >> >> + "not enough memory to hold filter string\n");
> >> >> + return -1;
> >> >> + }
> >> >> +
> >> >> + return 0;
> >> >> }
> >> >>
> >> >> - if (perf_evsel__append_filter(evsel, "&&", str) < 0) {
> >> >> + while ((pmu = perf_pmu__scan(pmu)) != NULL)
> >> >> + if (pmu->type == evsel->attr.type) {
> >> >> + found = true;
> >> >> + break;
> >> >> + }
> >> >> +
> >> >> + if (found)
> >> >> + perf_pmu__scan_file(pmu, "nr_addr_filters",
> >> >> + "%d", &nr_addr_filters);
> >> >> +
> >> >> + if (!nr_addr_filters)
> >> >> + goto err;
> >> >> +
> >> >> + if (perf_evsel__append_filter(evsel, "%s,%s", str) < 0) {
> >> >> fprintf(stderr,
> >> >> "not enough memory to hold filter string\n");
> >> >> return -1;
> >> >> }
> >> >>
> >> >> return 0;
> >> >> +
> >> >> +err:
> >> >> + fprintf(stderr,
> >> >> + "--filter option should follow a -e tracepoint or HW tracer option\n");
> >> >> +
> >> >> + return -1;
> >> >> }
> >> >>
> >> >> int parse_filter(const struct option *opt, const char *str,
> >> >>
> >> >
> >
> >
> > --
> > Masami Hiramatsu <mhiramat@kernel.org>
--
Masami Hiramatsu <mhiramat@kernel.org>
^ permalink raw reply
* [RFC PATCH 9/9] ethernet: sun8i-emac: add pm_runtime support
From: Maxime Ripard @ 2016-09-17 13:40 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20160914140304.GA27639@Red>
On Wed, Sep 14, 2016 at 04:03:04PM +0200, LABBE Corentin wrote:
> > > +static int __maybe_unused sun8i_emac_suspend(struct platform_device *pdev, pm_message_t state)
> > > +{
> > > + struct net_device *ndev = platform_get_drvdata(pdev);
> > > + struct sun8i_emac_priv *priv = netdev_priv(ndev);
> > > +
> > > + napi_disable(&priv->napi);
> > > +
> > > + if (netif_running(ndev))
> > > + netif_device_detach(ndev);
> > > +
> > > + sun8i_emac_stop_tx(ndev);
> > > + sun8i_emac_stop_rx(ndev);
> > > +
> > > + sun8i_emac_rx_clean(ndev);
> > > + sun8i_emac_tx_clean(ndev);
> > > +
> > > + phy_stop(ndev->phydev);
> > > +
> > > + return 0;
> > > +}
> > > +
> > > +static int __maybe_unused sun8i_emac_resume(struct platform_device *pdev)
> > > +{
> > > + struct net_device *ndev = platform_get_drvdata(pdev);
> > > + struct sun8i_emac_priv *priv = netdev_priv(ndev);
> > > +
> > > + phy_start(ndev->phydev);
> > > +
> > > + sun8i_emac_start_tx(ndev);
> > > + sun8i_emac_start_rx(ndev);
> > > +
> > > + if (netif_running(ndev))
> > > + netif_device_attach(ndev);
> > > +
> > > + netif_start_queue(ndev);
> > > +
> > > + napi_enable(&priv->napi);
> > > +
> > > + return 0;
> > > +}
> >
> > The main idea behind the runtime PM hooks is that they bring the
> > device to a working state and shuts it down when it's not needed
> > anymore.
Indeed.
> I expect that the first part (all pm_runtime_xxx) of the patch bring that.
> When the interface is not opened:
> cat /sys/devices/platform/soc/1c30000.ethernet/power/runtime_status
> suspended
>
> > However, they shouldn't be called when the device is still in used, so
> > all the mangling with NAPI, the phy and so on is irrelevant here, but
> > the clocks, resets, for example, are.
> >
>
> I do the same as other ethernet driver for suspend/resume.
suspend / resume are used when you put the whole system into suspend,
and bring it back.
runtime_pm is only when the device is not used anymore. It makes sense
when you suspend to do whatever you're doing here. It doesn't make any
when the system is not suspended, but the device is.
> > > static const struct of_device_id sun8i_emac_of_match_table[] = {
> > > { .compatible = "allwinner,sun8i-a83t-emac",
> > > .data = &emac_variant_a83t },
> > > @@ -2246,6 +2302,8 @@ static struct platform_driver sun8i_emac_driver = {
> > > .name = "sun8i-emac",
> > > .of_match_table = sun8i_emac_of_match_table,
> > > },
> > > + .suspend = sun8i_emac_suspend,
> > > + .resume = sun8i_emac_resume,
> >
> > These are not the runtime PM hooks. How did you test that?
> >
>
> Anyway I didnt test suspend/resume so I will remove it until I
> successfully found how to hibernate my board.
So you submit code you never tested? That's usually a recipe for
disaster.
Maxime
--
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160917/c2f7dacb/attachment.sig>
^ permalink raw reply
* [PATCH v2 1/4] clk: sunxi-ng: Add A64 clocks
From: Maxime Ripard @ 2016-09-17 14:08 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAGb2v65fg_5j7RmiwHUSJfiZfR78Dmv7EOLEm9eDNtxMJ-MuFQ@mail.gmail.com>
Hi,
On Sat, Sep 10, 2016 at 11:24:48AM +0800, Chen-Yu Tsai wrote:
> > +static SUNXI_CCU_NK_WITH_GATE_LOCK_POSTDIV(pll_periph0_clk, "pll-periph0",
> > + "osc24M", 0x028,
> > + 8, 5, /* N */
> > + 4, 2, /* K */
>
> The manual says to give preference to K >= 2. I suggest swapping N/K and
> leaving a note about it, so the actual K is in the inner loop (see ccu_nk.c)
> of the factor calculation.
It also says that we should fix that frequency (and we don't), so we
don't really care.
> > +static SUNXI_CCU_NKM_WITH_GATE_LOCK(pll_mipi_clk, "pll-mipi",
> > + "pll-video0", 0x040,
> > + 8, 4, /* N */
> > + 4, 2, /* K */
>
> You need a table for K. (Manual says K >= 2).
Not really a table, but a minimum, like we have a maximum already.
> > +static SUNXI_CCU_DIV_TABLE_WITH_GATE(ths_clk, "ths", "osc24M",
> > + 0x074, 0, 2, ths_div_table, BIT(31), 0);
>
> Even though the mux has only one valid parent, I suggest you still implement it,
> in case some bogus value gets put in before the kernel loads.
Ack.
> > +static const char * const ts_parents[] = { "osc24M", "pll-periph0", };
> > +static SUNXI_CCU_MP_WITH_MUX_GATE(ts_clk, "ts", ts_parents, 0x098,
> > + 0, 4, /* M */
> > + 16, 2, /* P */
> > + 24, 2, /* mux */
>
> Manual says the mux is 4 bits wide.
Ack.
> > +static const char * const i2s_parents[] = { "pll-audio-8x", "pll-audio-4x",
> > + "pll-audio-2x", "pll-audio" };
> > +static SUNXI_CCU_MUX_WITH_GATE(i2s0_clk, "i2s0", i2s_parents,
> > + 0x0b0, 16, 2, BIT(31), 0);
> > +
> > +static SUNXI_CCU_MUX_WITH_GATE(i2s1_clk, "i2s1", i2s_parents,
> > + 0x0b4, 16, 2, BIT(31), 0);
> > +
> > +static SUNXI_CCU_MUX_WITH_GATE(i2s2_clk, "i2s2", i2s_parents,
> > + 0x0b8, 16, 2, BIT(31), 0);
> > +
> > +static SUNXI_CCU_M_WITH_GATE(spdif_clk, "spdif", "pll-audio",
> > + 0x0c0, 0, 4, BIT(31), 0);
>
> CLK_SET_PARENT_RATE for the above audio clocks?
Indeed.
> > +static SUNXI_CCU_GATE(usb_phy0_clk, "usb-phy0", "osc24M",
> > + 0x0cc, BIT(8), 0);
> > +static SUNXI_CCU_GATE(usb_phy1_clk, "usb-phy1", "osc24M",
> > + 0x0cc, BIT(9), 0);
> > +static SUNXI_CCU_GATE(usb_hsic_clk, "usb-hsic", "pll-hsic",
> > + 0x0cc, BIT(10), 0);
> > +static SUNXI_CCU_GATE(usb_hsic_12m_clk, "usb-hsic-12M", "osc12M",
> > + 0x0cc, BIT(11), 0);
> > +static SUNXI_CCU_GATE(usb_ohci0_clk, "usb-ohci0", "osc12M",
> > + 0x0cc, BIT(16), 0);
> > +static SUNXI_CCU_GATE(usb_ohci1_clk, "usb-ohci1", "usb-ohci0",
> > + 0x0cc, BIT(17), 0);
>
> I guess we aren't modeling the 2 OHCI 12M muxes?
To be honest, I can't even make sense of it. Which clocks are using it
is unclear to me, so yeah, I don't know. I can probably leave some ID
for it though, just in case.
> > +static const char * const tcon1_parents[] = { "pll-video0", "pll-video1" };
> > +static const u8 tcon1_table[] = { 0, 2, };
> > +struct ccu_div tcon1_clk = {
> > + .enable = BIT(31),
> > + .div = _SUNXI_CCU_DIV(0, 4),
> > + .mux = _SUNXI_CCU_MUX_TABLE(24, 3, tcon1_table),
> > + .common = {
> > + .reg = 0x11c,
> > + .hw.init = CLK_HW_INIT_PARENTS("tcon1",
> > + tcon1_parents,
> > + &ccu_div_ops,
> > + 0),
> > + },
> > +};
>
> CLK_SET_PARENT_RATE for the TCON clocks?
Yep
> > +static SUNXI_CCU_GATE(ac_dig_clk, "ac-dig", "pll-audio",
> > + 0x140, BIT(31), 0);
> > +
> > +static SUNXI_CCU_GATE(ac_dig_4x_clk, "ac-dig-4x", "pll-audio-4x",
> > + 0x140, BIT(30), 0);
>
> CLK_SET_PARENT_RATE for the above audio clocks?
Ack.
> > +static SUNXI_CCU_GATE(avs_clk, "avs", "osc24M",
> > + 0x144, BIT(31), 0);
> > +
> > +static const char * const hdmi_parents[] = { "pll-video0", "pll-video1" };
> > +static SUNXI_CCU_M_WITH_MUX_GATE(hdmi_clk, "hdmi", hdmi_parents,
> > + 0x150, 0, 4, 24, 2, BIT(31), 0);
>
> Might need CLK_SET_PARENT_RATE for hdmi?
Ack
> > +static SUNXI_CCU_GATE(hdmi_ddc_clk, "hdmi-ddc", "osc24M",
> > + 0x154, BIT(31), 0);
> > +
> > +static const char * const mbus_parents[] = { "osc24M", "pll-periph0-2x",
> > + "pll-ddr0", "pll-ddr1" };
> > +static SUNXI_CCU_M_WITH_MUX_GATE(mbus_clk, "mbus", mbus_parents,
> > + 0x15c, 0, 3, 24, 2, BIT(31), CLK_IS_CRITICAL);
> > +
> > +static const char * const dsi_dphy_parents[] = { "pll-video0", "pll-periph0" };
>
> You need a mux table = { 0, 2 } here.
Indeed
> > +static SUNXI_CCU_M_WITH_MUX_GATE(dsi_dphy_clk, "dsi-dphy", dsi_dphy_parents,
> > + 0x168, 0, 3, 24, 2, BIT(31), 0);
> > +
> > +static SUNXI_CCU_M_WITH_GATE(gpu_clk, "gpu", "pll-gpu",
> > + 0x1a0, 0, 3, BIT(31), 0);
>
> CLK_SET_PARENT_RATE for the GPU clock?
Ack
> > +static CLK_FIXED_FACTOR(pll_video0_2x_clk, "pll-video0-2x",
> > + "pll-video0", 1, 2, 0);
>
> CLK_SET_PARENT_RATE for pll-video0-2x.
Ack
>
> > +
> > +static struct ccu_common *sun50i_a64_ccu_clks[] = {
> > + &pll_cpux_clk.common,
> > + &pll_audio_base_clk.common,
> > + &pll_video0_clk.common,
> > + &pll_ve_clk.common,
> > + &pll_ddr0_clk.common,
> > + &pll_periph0_clk.common,
> > + &pll_periph1_clk.common,
> > + &pll_video1_clk.common,
> > + &pll_gpu_clk.common,
> > + &pll_mipi_clk.common,
> > + &pll_hsic_clk.common,
> > + &pll_de_clk.common,
> > + &pll_ddr1_clk.common,
> > + &cpux_clk.common,
> > + &axi_clk.common,
> > + &ahb1_clk.common,
> > + &apb1_clk.common,
> > + &apb2_clk.common,
> > + &ahb2_clk.common,
> > + &bus_mipi_dsi_clk.common,
> > + &bus_ce_clk.common,
> > + &bus_dma_clk.common,
> > + &bus_mmc0_clk.common,
> > + &bus_mmc1_clk.common,
> > + &bus_mmc2_clk.common,
> > + &bus_nand_clk.common,
> > + &bus_dram_clk.common,
> > + &bus_emac_clk.common,
> > + &bus_ts_clk.common,
> > + &bus_hstimer_clk.common,
> > + &bus_spi0_clk.common,
> > + &bus_spi1_clk.common,
> > + &bus_otg_clk.common,
> > + &bus_ehci0_clk.common,
> > + &bus_ehci1_clk.common,
> > + &bus_ohci0_clk.common,
> > + &bus_ohci1_clk.common,
> > + &bus_ve_clk.common,
> > + &bus_tcon0_clk.common,
> > + &bus_tcon1_clk.common,
> > + &bus_deinterlace_clk.common,
> > + &bus_csi_clk.common,
> > + &bus_hdmi_clk.common,
> > + &bus_de_clk.common,
> > + &bus_gpu_clk.common,
> > + &bus_msgbox_clk.common,
> > + &bus_spinlock_clk.common,
> > + &bus_codec_clk.common,
> > + &bus_spdif_clk.common,
> > + &bus_pio_clk.common,
> > + &bus_ths_clk.common,
> > + &bus_i2s0_clk.common,
> > + &bus_i2s1_clk.common,
> > + &bus_i2s2_clk.common,
> > + &bus_i2c0_clk.common,
> > + &bus_i2c1_clk.common,
> > + &bus_i2c2_clk.common,
> > + &bus_scr_clk.common,
> > + &bus_uart0_clk.common,
> > + &bus_uart1_clk.common,
> > + &bus_uart2_clk.common,
> > + &bus_uart3_clk.common,
> > + &bus_uart4_clk.common,
> > + &bus_dbg_clk.common,
> > + &ths_clk.common,
> > + &nand_clk.common,
> > + &mmc0_clk.common,
> > + &mmc1_clk.common,
> > + &mmc2_clk.common,
> > + &ts_clk.common,
> > + &ce_clk.common,
> > + &spi0_clk.common,
> > + &spi1_clk.common,
> > + &i2s0_clk.common,
> > + &i2s1_clk.common,
> > + &i2s2_clk.common,
> > + &spdif_clk.common,
> > + &usb_phy0_clk.common,
> > + &usb_phy1_clk.common,
> > + &usb_hsic_clk.common,
> > + &usb_hsic_12m_clk.common,
> > + &usb_ohci0_clk.common,
> > + &usb_ohci1_clk.common,
> > + &dram_clk.common,
> > + &dram_ve_clk.common,
> > + &dram_csi_clk.common,
> > + &dram_deinterlace_clk.common,
> > + &dram_ts_clk.common,
> > + &de_clk.common,
> > + &tcon0_clk.common,
> > + &tcon1_clk.common,
> > + &deinterlace_clk.common,
> > + &csi_misc_clk.common,
> > + &csi_sclk_clk.common,
> > + &csi_mclk_clk.common,
> > + &ve_clk.common,
> > + &ac_dig_clk.common,
> > + &ac_dig_4x_clk.common,
> > + &avs_clk.common,
> > + &hdmi_clk.common,
> > + &hdmi_ddc_clk.common,
> > + &mbus_clk.common,
> > + &dsi_dphy_clk.common,
> > + &gpu_clk.common,
> > +};
> > +
> > +static struct clk_hw_onecell_data sun50i_a64_hw_clks = {
> > + .hws = {
> > + [CLK_OSC_12M] = &osc12M_clk.hw,
> > + [CLK_PLL_CPUX] = &pll_cpux_clk.common.hw,
> > + [CLK_PLL_AUDIO_BASE] = &pll_audio_base_clk.common.hw,
> > + [CLK_PLL_AUDIO] = &pll_audio_clk.hw,
> > + [CLK_PLL_AUDIO_2X] = &pll_audio_2x_clk.hw,
> > + [CLK_PLL_AUDIO_4X] = &pll_audio_4x_clk.hw,
> > + [CLK_PLL_AUDIO_8X] = &pll_audio_8x_clk.hw,
> > + [CLK_PLL_VIDEO0] = &pll_video0_clk.common.hw,
> > + [CLK_PLL_VIDEO0_2X] = &pll_video0_2x_clk.hw,
> > + [CLK_PLL_VE] = &pll_ve_clk.common.hw,
> > + [CLK_PLL_DDR0] = &pll_ddr0_clk.common.hw,
> > + [CLK_PLL_PERIPH0] = &pll_periph0_clk.common.hw,
> > + [CLK_PLL_PERIPH0_2X] = &pll_periph0_2x_clk.hw,
> > + [CLK_PLL_PERIPH1] = &pll_periph1_clk.common.hw,
> > + [CLK_PLL_PERIPH1_2X] = &pll_periph1_2x_clk.hw,
> > + [CLK_PLL_VIDEO1] = &pll_video1_clk.common.hw,
> > + [CLK_PLL_GPU] = &pll_gpu_clk.common.hw,
> > + [CLK_PLL_MIPI] = &pll_mipi_clk.common.hw,
> > + [CLK_PLL_HSIC] = &pll_hsic_clk.common.hw,
> > + [CLK_PLL_DE] = &pll_de_clk.common.hw,
> > + [CLK_PLL_DDR1] = &pll_ddr1_clk.common.hw,
> > + [CLK_CPUX] = &cpux_clk.common.hw,
> > + [CLK_AXI] = &axi_clk.common.hw,
> > + [CLK_AHB1] = &ahb1_clk.common.hw,
> > + [CLK_APB1] = &apb1_clk.common.hw,
> > + [CLK_APB2] = &apb2_clk.common.hw,
> > + [CLK_AHB2] = &ahb2_clk.common.hw,
> > + [CLK_BUS_MIPI_DSI] = &bus_mipi_dsi_clk.common.hw,
> > + [CLK_BUS_CE] = &bus_ce_clk.common.hw,
> > + [CLK_BUS_DMA] = &bus_dma_clk.common.hw,
> > + [CLK_BUS_MMC0] = &bus_mmc0_clk.common.hw,
> > + [CLK_BUS_MMC1] = &bus_mmc1_clk.common.hw,
> > + [CLK_BUS_MMC2] = &bus_mmc2_clk.common.hw,
> > + [CLK_BUS_NAND] = &bus_nand_clk.common.hw,
> > + [CLK_BUS_DRAM] = &bus_dram_clk.common.hw,
> > + [CLK_BUS_EMAC] = &bus_emac_clk.common.hw,
> > + [CLK_BUS_TS] = &bus_ts_clk.common.hw,
> > + [CLK_BUS_HSTIMER] = &bus_hstimer_clk.common.hw,
> > + [CLK_BUS_SPI0] = &bus_spi0_clk.common.hw,
> > + [CLK_BUS_SPI1] = &bus_spi1_clk.common.hw,
> > + [CLK_BUS_OTG] = &bus_otg_clk.common.hw,
> > + [CLK_BUS_EHCI0] = &bus_ehci0_clk.common.hw,
> > + [CLK_BUS_EHCI1] = &bus_ehci1_clk.common.hw,
> > + [CLK_BUS_OHCI0] = &bus_ohci0_clk.common.hw,
> > + [CLK_BUS_OHCI1] = &bus_ohci1_clk.common.hw,
> > + [CLK_BUS_VE] = &bus_ve_clk.common.hw,
> > + [CLK_BUS_TCON0] = &bus_tcon0_clk.common.hw,
> > + [CLK_BUS_TCON1] = &bus_tcon1_clk.common.hw,
> > + [CLK_BUS_DEINTERLACE] = &bus_deinterlace_clk.common.hw,
> > + [CLK_BUS_CSI] = &bus_csi_clk.common.hw,
> > + [CLK_BUS_HDMI] = &bus_hdmi_clk.common.hw,
> > + [CLK_BUS_DE] = &bus_de_clk.common.hw,
> > + [CLK_BUS_GPU] = &bus_gpu_clk.common.hw,
> > + [CLK_BUS_MSGBOX] = &bus_msgbox_clk.common.hw,
> > + [CLK_BUS_SPINLOCK] = &bus_spinlock_clk.common.hw,
> > + [CLK_BUS_CODEC] = &bus_codec_clk.common.hw,
> > + [CLK_BUS_SPDIF] = &bus_spdif_clk.common.hw,
> > + [CLK_BUS_PIO] = &bus_pio_clk.common.hw,
> > + [CLK_BUS_THS] = &bus_ths_clk.common.hw,
> > + [CLK_BUS_I2S0] = &bus_i2s0_clk.common.hw,
> > + [CLK_BUS_I2S1] = &bus_i2s1_clk.common.hw,
> > + [CLK_BUS_I2S2] = &bus_i2s2_clk.common.hw,
> > + [CLK_BUS_I2C0] = &bus_i2c0_clk.common.hw,
> > + [CLK_BUS_I2C1] = &bus_i2c1_clk.common.hw,
> > + [CLK_BUS_I2C2] = &bus_i2c2_clk.common.hw,
> > + [CLK_BUS_UART0] = &bus_uart0_clk.common.hw,
> > + [CLK_BUS_UART1] = &bus_uart1_clk.common.hw,
> > + [CLK_BUS_UART2] = &bus_uart2_clk.common.hw,
> > + [CLK_BUS_UART3] = &bus_uart3_clk.common.hw,
> > + [CLK_BUS_UART4] = &bus_uart4_clk.common.hw,
> > + [CLK_BUS_SCR] = &bus_scr_clk.common.hw,
> > + [CLK_BUS_DBG] = &bus_dbg_clk.common.hw,
> > + [CLK_THS] = &ths_clk.common.hw,
> > + [CLK_NAND] = &nand_clk.common.hw,
> > + [CLK_MMC0] = &mmc0_clk.common.hw,
> > + [CLK_MMC1] = &mmc1_clk.common.hw,
> > + [CLK_MMC2] = &mmc2_clk.common.hw,
> > + [CLK_TS] = &ts_clk.common.hw,
> > + [CLK_CE] = &ce_clk.common.hw,
> > + [CLK_SPI0] = &spi0_clk.common.hw,
> > + [CLK_SPI1] = &spi1_clk.common.hw,
> > + [CLK_I2S0] = &i2s0_clk.common.hw,
> > + [CLK_I2S1] = &i2s1_clk.common.hw,
> > + [CLK_I2S2] = &i2s2_clk.common.hw,
> > + [CLK_SPDIF] = &spdif_clk.common.hw,
> > + [CLK_USB_PHY0] = &usb_phy0_clk.common.hw,
> > + [CLK_USB_PHY1] = &usb_phy1_clk.common.hw,
> > + [CLK_USB_HSIC] = &usb_hsic_clk.common.hw,
> > + [CLK_USB_HSIC_12M] = &usb_hsic_12m_clk.common.hw,
> > + [CLK_USB_OHCI0] = &usb_ohci0_clk.common.hw,
> > + [CLK_USB_OHCI1] = &usb_ohci1_clk.common.hw,
> > + [CLK_DRAM] = &dram_clk.common.hw,
> > + [CLK_DRAM_VE] = &dram_ve_clk.common.hw,
> > + [CLK_DRAM_CSI] = &dram_csi_clk.common.hw,
> > + [CLK_DRAM_DEINTERLACE] = &dram_deinterlace_clk.common.hw,
> > + [CLK_DRAM_TS] = &dram_ts_clk.common.hw,
> > + [CLK_DE] = &de_clk.common.hw,
> > + [CLK_TCON0] = &tcon0_clk.common.hw,
> > + [CLK_TCON1] = &tcon1_clk.common.hw,
> > + [CLK_DEINTERLACE] = &deinterlace_clk.common.hw,
> > + [CLK_CSI_MISC] = &csi_misc_clk.common.hw,
> > + [CLK_CSI_SCLK] = &csi_sclk_clk.common.hw,
> > + [CLK_CSI_MCLK] = &csi_mclk_clk.common.hw,
> > + [CLK_VE] = &ve_clk.common.hw,
> > + [CLK_AC_DIG] = &ac_dig_clk.common.hw,
> > + [CLK_AC_DIG_4X] = &ac_dig_4x_clk.common.hw,
> > + [CLK_AVS] = &avs_clk.common.hw,
> > + [CLK_HDMI] = &hdmi_clk.common.hw,
> > + [CLK_HDMI_DDC] = &hdmi_ddc_clk.common.hw,
> > + [CLK_MBUS] = &mbus_clk.common.hw,
> > + [CLK_DSI_DPHY] = &dsi_dphy_clk.common.hw,
> > + [CLK_GPU] = &gpu_clk.common.hw,
> > + },
> > + .num = CLK_NUMBER,
> > +};
> > +
> > +static struct ccu_reset_map sun50i_a64_ccu_resets[] = {
> > + [RST_USB_PHY0] = { 0x0cc, BIT(0) },
> > + [RST_USB_PHY1] = { 0x0cc, BIT(1) },
> > + [RST_USB_HSIC] = { 0x0cc, BIT(2) },
> > +
> > +
> > + [RST_MBUS] = { 0x0fc, BIT(31) },
> > +
> > + [RST_BUS_MIPI_DSI] = { 0x2c0, BIT(1) },
> > + [RST_BUS_CE] = { 0x2c0, BIT(5) },
> > + [RST_BUS_DMA] = { 0x2c0, BIT(6) },
> > + [RST_BUS_MMC0] = { 0x2c0, BIT(8) },
> > + [RST_BUS_MMC1] = { 0x2c0, BIT(9) },
> > + [RST_BUS_MMC2] = { 0x2c0, BIT(10) },
> > + [RST_BUS_NAND] = { 0x2c0, BIT(13) },
> > + [RST_BUS_DRAM] = { 0x2c0, BIT(14) },
> > + [RST_BUS_EMAC] = { 0x2c0, BIT(17) },
> > + [RST_BUS_TS] = { 0x2c0, BIT(18) },
> > + [RST_BUS_HSTIMER] = { 0x2c0, BIT(19) },
> > + [RST_BUS_SPI0] = { 0x2c0, BIT(20) },
> > + [RST_BUS_SPI1] = { 0x2c0, BIT(21) },
> > + [RST_BUS_OTG] = { 0x2c0, BIT(23) },
> > + [RST_BUS_EHCI0] = { 0x2c0, BIT(24) },
> > + [RST_BUS_EHCI1] = { 0x2c0, BIT(25) },
> > + [RST_BUS_OHCI0] = { 0x2c0, BIT(28) },
> > + [RST_BUS_OHCI1] = { 0x2c0, BIT(29) },
> > +
> > + [RST_BUS_VE] = { 0x2c4, BIT(0) },
> > + [RST_BUS_TCON0] = { 0x2c4, BIT(3) },
> > + [RST_BUS_TCON1] = { 0x2c4, BIT(4) },
> > + [RST_BUS_DEINTERLACE] = { 0x2c4, BIT(5) },
> > + [RST_BUS_CSI] = { 0x2c4, BIT(8) },
> > + [RST_BUS_HDMI0] = { 0x2c4, BIT(10) },
> > + [RST_BUS_HDMI1] = { 0x2c4, BIT(11) },
> > + [RST_BUS_DE] = { 0x2c4, BIT(12) },
> > + [RST_BUS_GPU] = { 0x2c4, BIT(20) },
> > + [RST_BUS_MSGBOX] = { 0x2c4, BIT(21) },
> > + [RST_BUS_SPINLOCK] = { 0x2c4, BIT(22) },
> > + [RST_BUS_DBG] = { 0x2c4, BIT(31) },
> > +
> > + [RST_BUS_LVDS] = { 0x2c8, BIT(0) },
> > +
> > + [RST_BUS_CODEC] = { 0x2d0, BIT(0) },
> > + [RST_BUS_SPDIF] = { 0x2d0, BIT(1) },
> > + [RST_BUS_THS] = { 0x2d0, BIT(8) },
> > + [RST_BUS_I2S0] = { 0x2d0, BIT(12) },
> > + [RST_BUS_I2S1] = { 0x2d0, BIT(13) },
> > + [RST_BUS_I2S2] = { 0x2d0, BIT(14) },
> > +
> > + [RST_BUS_I2C0] = { 0x2d8, BIT(0) },
> > + [RST_BUS_I2C1] = { 0x2d8, BIT(1) },
> > + [RST_BUS_I2C2] = { 0x2d8, BIT(2) },
> > + [RST_BUS_SCR] = { 0x2d8, BIT(5) },
> > + [RST_BUS_UART0] = { 0x2d8, BIT(16) },
> > + [RST_BUS_UART1] = { 0x2d8, BIT(17) },
> > + [RST_BUS_UART2] = { 0x2d8, BIT(18) },
> > + [RST_BUS_UART3] = { 0x2d8, BIT(19) },
> > + [RST_BUS_UART4] = { 0x2d8, BIT(20) },
> > +};
> > +
> > +static const struct sunxi_ccu_desc sun50i_a64_ccu_desc = {
> > + .ccu_clks = sun50i_a64_ccu_clks,
> > + .num_ccu_clks = ARRAY_SIZE(sun50i_a64_ccu_clks),
> > +
> > + .hw_clks = &sun50i_a64_hw_clks,
> > +
> > + .resets = sun50i_a64_ccu_resets,
> > + .num_resets = ARRAY_SIZE(sun50i_a64_ccu_resets),
> > +};
> > +
> > +static void __init sun50i_a64_ccu_setup(struct device_node *node)
> > +{
> > + void __iomem *reg;
> > + u32 val;
> > +
> > + reg = of_io_request_and_map(node, 0, of_node_full_name(node));
> > + if (IS_ERR(reg)) {
> > + pr_err("%s: Could not map the clock registers\n",
> > + of_node_full_name(node));
> > + return;
> > + }
> > +
> > + /* Force the PLL-Audio-1x divider to 4 */
> > + val = readl(reg + SUN50I_A64_PLL_AUDIO_REG);
> > + val &= ~GENMASK(19, 16);
> > + writel(val | (3 << 16), reg + SUN50I_A64_PLL_AUDIO_REG);
> > +
> > + writel(0x515, reg + SUN50I_A64_PLL_MIPI_REG);
> > +
> > + sunxi_ccu_probe(node, reg, &sun50i_a64_ccu_desc);
> > +}
> > +CLK_OF_DECLARE(sun50i_a64_ccu, "allwinner,sun50i-a64-ccu",
> > + sun50i_a64_ccu_setup);
> > diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a64.h b/drivers/clk/sunxi-ng/ccu-sun50i-a64.h
> > new file mode 100644
> > index 000000000000..e3c77d92af1c
> > --- /dev/null
> > +++ b/drivers/clk/sunxi-ng/ccu-sun50i-a64.h
> > @@ -0,0 +1,68 @@
> > +/*
> > + * Copyright 2016 Maxime Ripard
> > + *
> > + * Maxime Ripard <maxime.ripard@free-electrons.com>
> > + *
> > + * This program is free software; you can redistribute it and/or modify
> > + * it under the terms of the GNU General Public License as published by
> > + * the Free Software Foundation; either version 2 of the License, or
> > + * (at your option) any later version.
> > + *
> > + * This program is distributed in the hope that it will be useful,
> > + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> > + * GNU General Public License for more details.
> > + */
> > +
> > +#ifndef _CCU_SUN50I_A64_H_
> > +#define _CCU_SUN50I_A64_H_
> > +
> > +#include <dt-bindings/clock/sun50i-a64-ccu.h>
> > +#include <dt-bindings/reset/sun50i-a64-ccu.h>
> > +
> > +#define CLK_OSC_12M 0
> > +#define CLK_PLL_CPUX 1
> > +#define CLK_PLL_AUDIO_BASE 2
> > +#define CLK_PLL_AUDIO 3
> > +#define CLK_PLL_AUDIO_2X 4
> > +#define CLK_PLL_AUDIO_4X 5
> > +#define CLK_PLL_AUDIO_8X 6
> > +#define CLK_PLL_VIDEO0 7
> > +#define CLK_PLL_VIDEO0_2X 8
> > +#define CLK_PLL_VE 9
> > +#define CLK_PLL_DDR0 10
> > +#define CLK_PLL_PERIPH0 11
> > +#define CLK_PLL_PERIPH0_2X 12
> > +#define CLK_PLL_PERIPH1 13
> > +#define CLK_PLL_PERIPH1_2X 14
> > +#define CLK_PLL_VIDEO1 15
> > +#define CLK_PLL_GPU 16
> > +#define CLK_PLL_MIPI 17
> > +#define CLK_PLL_HSIC 18
> > +#define CLK_PLL_DE 19
> > +#define CLK_PLL_DDR1 20
> > +#define CLK_CPUX 21
> > +#define CLK_AXI 22
> > +#define CLK_APB 23
>
> This is listed but never implemented.
Yes, on purpose. If we ever need to implement it, we won't have an
headache.
> > +#define RST_USB_PHY0 0
> > +#define RST_USB_PHY1 1
> > +#define RST_USB_HSIC 2
>
> There's also a DRAM reset in 0xf4 (DRAM configuration)
Ack.
Thanks!
Maxime
--
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160917/b43d379f/attachment-0001.sig>
^ permalink raw reply
* [PATCH v2 1/4] clk: sunxi-ng: Add A64 clocks
From: Maxime Ripard @ 2016-09-17 14:23 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20160914214554.GH7243@codeaurora.org>
Hi Stephen,
On Wed, Sep 14, 2016 at 02:45:54PM -0700, Stephen Boyd wrote:
> On 09/09, Maxime Ripard wrote:
> > index 106cba27c331..964f22091a10 100644
> > --- a/drivers/clk/sunxi-ng/Makefile
> > +++ b/drivers/clk/sunxi-ng/Makefile
> > @@ -22,3 +22,4 @@ obj-$(CONFIG_SUN6I_A31_CCU) += ccu-sun6i-a31.o
> > obj-$(CONFIG_SUN8I_A23_CCU) += ccu-sun8i-a23.o
> > obj-$(CONFIG_SUN8I_A33_CCU) += ccu-sun8i-a33.o
> > obj-$(CONFIG_SUN8I_H3_CCU) += ccu-sun8i-h3.o
> > +obj-$(CONFIG_SUN50I_A64_CCU) += ccu-sun50i-a64.o
>
> Maybe do alphanumeric ordering?
Yes, of course.
> > diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
> > new file mode 100644
> > index 000000000000..d51ee416f515
> > --- /dev/null
> > +++ b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
> > @@ -0,0 +1,870 @@
> > +
> > +static void __init sun50i_a64_ccu_setup(struct device_node *node)
> > +{
> > + void __iomem *reg;
> > + u32 val;
> > +
> > + reg = of_io_request_and_map(node, 0, of_node_full_name(node));
> > + if (IS_ERR(reg)) {
> > + pr_err("%s: Could not map the clock registers\n",
> > + of_node_full_name(node));
> > + return;
> > + }
> > +
> > + /* Force the PLL-Audio-1x divider to 4 */
> > + val = readl(reg + SUN50I_A64_PLL_AUDIO_REG);
> > + val &= ~GENMASK(19, 16);
> > + writel(val | (3 << 16), reg + SUN50I_A64_PLL_AUDIO_REG);
> > +
> > + writel(0x515, reg + SUN50I_A64_PLL_MIPI_REG);
> > +
> > + sunxi_ccu_probe(node, reg, &sun50i_a64_ccu_desc);
> > +}
> > +CLK_OF_DECLARE(sun50i_a64_ccu, "allwinner,sun50i-a64-ccu",
> > + sun50i_a64_ccu_setup);
>
> Is there a reason it can't be a platform driver?
We have timers connected to those clocks. I'm not sure we'll ever use
them, since we also have the arch timers, and we can always change
that later, I'll change that.
Maxime
--
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160917/cb0efd43/attachment.sig>
^ permalink raw reply
* [RFC PATCH] PCI/ACPI: xgene: Add ECAM quirk for X-Gene PCIe controller
From: Duc Dang @ 2016-09-17 14:24 UTC (permalink / raw)
To: linux-arm-kernel
PCIe controller in X-Gene SoCs is not ECAM compliant: software
needs to configure additional concontroller register to address
device at bus:dev:function.
This patch depends on "ECAM quirks handling for ARM64 platforms"
series (http://www.spinics.net/lists/arm-kernel/msg530692.html)
to address the limitation above for X-Gene PCIe controller.
The quirk will only be applied for X-Gene PCIe MCFG table with
OEM revison 1, 2, 3 or 4 (PCIe controller v1 and v2 on X-Gene SoCs).
Signed-off-by: Duc Dang <dhdang@apm.com>
---
drivers/acpi/pci_mcfg.c | 32 +++++
drivers/pci/host/Makefile | 2 +-
drivers/pci/host/pci-xgene-ecam.c | 280 ++++++++++++++++++++++++++++++++++++++
include/linux/pci-ecam.h | 5 +
4 files changed, 318 insertions(+), 1 deletion(-)
create mode 100644 drivers/pci/host/pci-xgene-ecam.c
diff --git a/drivers/acpi/pci_mcfg.c b/drivers/acpi/pci_mcfg.c
index ddf338b..adce35f 100644
--- a/drivers/acpi/pci_mcfg.c
+++ b/drivers/acpi/pci_mcfg.c
@@ -123,6 +123,38 @@ static struct mcfg_fixup mcfg_quirks[] = {
{ "CAVIUM", "THUNDERX", 2, 13, MCFG_BUS_ANY, &pci_thunder_ecam_ops,
MCFG_RES_EMPTY},
#endif
+#ifdef CONFIG_PCI_XGENE
+ {"APM ", "XGENE ", 1, 0, MCFG_BUS_ANY,
+ &xgene_v1_pcie_ecam_ops, MCFG_RES_EMPTY},
+ {"APM ", "XGENE ", 1, 1, MCFG_BUS_ANY,
+ &xgene_v1_pcie_ecam_ops, MCFG_RES_EMPTY},
+ {"APM ", "XGENE ", 1, 2, MCFG_BUS_ANY,
+ &xgene_v1_pcie_ecam_ops, MCFG_RES_EMPTY},
+ {"APM ", "XGENE ", 1, 3, MCFG_BUS_ANY,
+ &xgene_v1_pcie_ecam_ops, MCFG_RES_EMPTY},
+ {"APM ", "XGENE ", 1, 4, MCFG_BUS_ANY,
+ &xgene_v1_pcie_ecam_ops, MCFG_RES_EMPTY},
+ {"APM ", "XGENE ", 2, 0, MCFG_BUS_ANY,
+ &xgene_v1_pcie_ecam_ops, MCFG_RES_EMPTY},
+ {"APM ", "XGENE ", 2, 1, MCFG_BUS_ANY,
+ &xgene_v1_pcie_ecam_ops, MCFG_RES_EMPTY},
+ {"APM ", "XGENE ", 2, 2, MCFG_BUS_ANY,
+ &xgene_v1_pcie_ecam_ops, MCFG_RES_EMPTY},
+ {"APM ", "XGENE ", 2, 3, MCFG_BUS_ANY,
+ &xgene_v1_pcie_ecam_ops, MCFG_RES_EMPTY},
+ {"APM ", "XGENE ", 2, 4, MCFG_BUS_ANY,
+ &xgene_v1_pcie_ecam_ops, MCFG_RES_EMPTY},
+ {"APM ", "XGENE ", 3, 0, MCFG_BUS_ANY,
+ &xgene_v2_1_pcie_ecam_ops, MCFG_RES_EMPTY},
+ {"APM ", "XGENE ", 3, 1, MCFG_BUS_ANY,
+ &xgene_v2_1_pcie_ecam_ops, MCFG_RES_EMPTY},
+ {"APM ", "XGENE ", 4, 0, MCFG_BUS_ANY,
+ &xgene_v2_2_pcie_ecam_ops, MCFG_RES_EMPTY},
+ {"APM ", "XGENE ", 4, 1, MCFG_BUS_ANY,
+ &xgene_v2_2_pcie_ecam_ops, MCFG_RES_EMPTY},
+ {"APM ", "XGENE ", 4, 2, MCFG_BUS_ANY,
+ &xgene_v2_2_pcie_ecam_ops, MCFG_RES_EMPTY},
+#endif
};
static char mcfg_oem_id[ACPI_OEM_ID_SIZE];
diff --git a/drivers/pci/host/Makefile b/drivers/pci/host/Makefile
index 8843410..af4f505 100644
--- a/drivers/pci/host/Makefile
+++ b/drivers/pci/host/Makefile
@@ -15,7 +15,7 @@ obj-$(CONFIG_PCIE_SPEAR13XX) += pcie-spear13xx.o
obj-$(CONFIG_PCI_KEYSTONE) += pci-keystone-dw.o pci-keystone.o
obj-$(CONFIG_PCIE_XILINX) += pcie-xilinx.o
obj-$(CONFIG_PCIE_XILINX_NWL) += pcie-xilinx-nwl.o
-obj-$(CONFIG_PCI_XGENE) += pci-xgene.o
+obj-$(CONFIG_PCI_XGENE) += pci-xgene.o pci-xgene-ecam.o
obj-$(CONFIG_PCI_XGENE_MSI) += pci-xgene-msi.o
obj-$(CONFIG_PCI_LAYERSCAPE) += pci-layerscape.o
obj-$(CONFIG_PCI_VERSATILE) += pci-versatile.o
diff --git a/drivers/pci/host/pci-xgene-ecam.c b/drivers/pci/host/pci-xgene-ecam.c
new file mode 100644
index 0000000..b66a04f
--- /dev/null
+++ b/drivers/pci/host/pci-xgene-ecam.c
@@ -0,0 +1,280 @@
+/*
+ * APM X-Gene PCIe ECAM fixup driver
+ *
+ * Copyright (c) 2016, Applied Micro Circuits Corporation
+ * Author:
+ * Duc Dang <dhdang@apm.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. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of_pci.h>
+#include <linux/pci-acpi.h>
+#include <linux/platform_device.h>
+#include <linux/pci-ecam.h>
+
+#ifdef CONFIG_ACPI
+#define RTDID 0x160
+#define ROOT_CAP_AND_CTRL 0x5C
+
+/* PCIe IP version */
+#define XGENE_PCIE_IP_VER_UNKN 0
+#define XGENE_PCIE_IP_VER_1 1
+#define XGENE_PCIE_IP_VER_2 2
+
+#define XGENE_CSR_LENGTH 0x10000
+
+struct xgene_pcie_acpi_root {
+ void __iomem *csr_base;
+ u32 version;
+};
+
+static int xgene_v1_pcie_ecam_init(struct pci_config_window *cfg)
+{
+ struct xgene_pcie_acpi_root *xgene_root;
+ struct device *dev = cfg->parent;
+ u32 csr_base;
+
+ xgene_root = devm_kzalloc(dev, sizeof(*xgene_root), GFP_KERNEL);
+ if (!xgene_root)
+ return -ENOMEM;
+
+ switch (cfg->res.start) {
+ case 0xE0D0000000ULL:
+ csr_base = 0x1F2B0000;
+ break;
+ case 0xD0D0000000ULL:
+ csr_base = 0x1F2C0000;
+ break;
+ case 0x90D0000000ULL:
+ csr_base = 0x1F2D0000;
+ break;
+ case 0xA0D0000000ULL:
+ csr_base = 0x1F500000;
+ break;
+ case 0xC0D0000000ULL:
+ csr_base = 0x1F510000;
+ break;
+ default:
+ return -ENODEV;
+ }
+
+ xgene_root->csr_base = ioremap(csr_base, XGENE_CSR_LENGTH);
+ if (!xgene_root->csr_base) {
+ kfree(xgene_root);
+ return -ENODEV;
+ }
+
+ xgene_root->version = XGENE_PCIE_IP_VER_1;
+
+ cfg->priv = xgene_root;
+
+ return 0;
+}
+
+static int xgene_v2_1_pcie_ecam_init(struct pci_config_window *cfg)
+{
+ struct xgene_pcie_acpi_root *xgene_root;
+ struct device *dev = cfg->parent;
+ resource_size_t csr_base;
+
+ xgene_root = devm_kzalloc(dev, sizeof(*xgene_root), GFP_KERNEL);
+ if (!xgene_root)
+ return -ENOMEM;
+
+ switch (cfg->res.start) {
+ case 0xC0D0000000ULL:
+ csr_base = 0x1F2B0000;
+ break;
+ case 0xA0D0000000ULL:
+ csr_base = 0x1F2C0000;
+ break;
+ default:
+ return -ENODEV;
+ }
+
+ xgene_root->csr_base = ioremap(csr_base, XGENE_CSR_LENGTH);
+ if (!xgene_root->csr_base) {
+ kfree(xgene_root);
+ return -ENODEV;
+ }
+
+ xgene_root->version = XGENE_PCIE_IP_VER_2;
+
+ cfg->priv = xgene_root;
+
+ return 0;
+}
+
+static int xgene_v2_2_pcie_ecam_init(struct pci_config_window *cfg)
+{
+ struct xgene_pcie_acpi_root *xgene_root;
+ struct device *dev = cfg->parent;
+ resource_size_t csr_base;
+
+ xgene_root = devm_kzalloc(dev, sizeof(*xgene_root), GFP_KERNEL);
+ if (!xgene_root)
+ return -ENOMEM;
+
+ switch (cfg->res.start) {
+ case 0xE0D0000000ULL:
+ csr_base = 0x1F2B0000;
+ break;
+ case 0xA0D0000000ULL:
+ csr_base = 0x1F500000;
+ break;
+ case 0x90D0000000ULL:
+ csr_base = 0x1F2D0000;
+ break;
+ default:
+ return -ENODEV;
+ }
+
+ xgene_root->csr_base = ioremap(csr_base, XGENE_CSR_LENGTH);
+ if (!xgene_root->csr_base) {
+ kfree(xgene_root);
+ return -ENODEV;
+ }
+
+ xgene_root->version = XGENE_PCIE_IP_VER_2;
+
+ cfg->priv = xgene_root;
+
+ return 0;
+}
+/*
+ * For Configuration request, RTDID register is used as Bus Number,
+ * Device Number and Function number of the header fields.
+ */
+static void xgene_pcie_set_rtdid_reg(struct pci_bus *bus, uint devfn)
+{
+ struct pci_config_window *cfg = bus->sysdata;
+ struct xgene_pcie_acpi_root *port = cfg->priv;
+ unsigned int b, d, f;
+ u32 rtdid_val = 0;
+
+ b = bus->number;
+ d = PCI_SLOT(devfn);
+ f = PCI_FUNC(devfn);
+
+ if (!pci_is_root_bus(bus))
+ rtdid_val = (b << 8) | (d << 3) | f;
+
+ writel(rtdid_val, port->csr_base + RTDID);
+ /* read the register back to ensure flush */
+ readl(port->csr_base + RTDID);
+}
+
+/*
+ * X-Gene PCIe port uses BAR0-BAR1 of RC's configuration space as
+ * the translation from PCI bus to native BUS. Entire DDR region
+ * is mapped into PCIe space using these registers, so it can be
+ * reached by DMA from EP devices. The BAR0/1 of bridge should be
+ * hidden during enumeration to avoid the sizing and resource allocation
+ * by PCIe core.
+ */
+static bool xgene_pcie_hide_rc_bars(struct pci_bus *bus, int offset)
+{
+ if (pci_is_root_bus(bus) && ((offset == PCI_BASE_ADDRESS_0) ||
+ (offset == PCI_BASE_ADDRESS_1)))
+ return true;
+
+ return false;
+}
+
+void __iomem *xgene_pcie_ecam_map_bus(struct pci_bus *bus,
+ unsigned int devfn, int where)
+{
+ struct pci_config_window *cfg = bus->sysdata;
+ unsigned int busn = bus->number;
+ void __iomem *base;
+
+ if (busn < cfg->busr.start || busn > cfg->busr.end)
+ return NULL;
+
+ if ((pci_is_root_bus(bus) && devfn != 0) ||
+ xgene_pcie_hide_rc_bars(bus, where))
+ return NULL;
+
+ xgene_pcie_set_rtdid_reg(bus, devfn);
+
+ if (busn > cfg->busr.start)
+ base = cfg->win + (1 << cfg->ops->bus_shift);
+ else
+ base = cfg->win;
+
+ return base + where;
+}
+
+static int xgene_pcie_config_read32(struct pci_bus *bus, unsigned int devfn,
+ int where, int size, u32 *val)
+{
+ struct pci_config_window *cfg = bus->sysdata;
+ struct xgene_pcie_acpi_root *port = cfg->priv;
+
+ if (pci_generic_config_read32(bus, devfn, where & ~0x3, 4, val) !=
+ PCIBIOS_SUCCESSFUL)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ /*
+ * The v1 controller has a bug in its Configuration Request
+ * Retry Status (CRS) logic: when CRS is enabled and we read the
+ * Vendor and Device ID of a non-existent device, the controller
+ * fabricates return data of 0xFFFF0001 ("device exists but is not
+ * ready") instead of 0xFFFFFFFF ("device does not exist"). This
+ * causes the PCI core to retry the read until it times out.
+ * Avoid this by not claiming to support CRS.
+ */
+ if (pci_is_root_bus(bus) && (port->version == XGENE_PCIE_IP_VER_1) &&
+ ((where & ~0x3) == ROOT_CAP_AND_CTRL))
+ *val &= ~(PCI_EXP_RTCAP_CRSVIS << 16);
+
+ if (size <= 2)
+ *val = (*val >> (8 * (where & 3))) & ((1 << (size * 8)) - 1);
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+struct pci_ecam_ops xgene_v1_pcie_ecam_ops = {
+ .bus_shift = 16,
+ .init = xgene_v1_pcie_ecam_init,
+ .pci_ops = {
+ .map_bus = xgene_pcie_ecam_map_bus,
+ .read = xgene_pcie_config_read32,
+ .write = pci_generic_config_write,
+ }
+};
+
+struct pci_ecam_ops xgene_v2_1_pcie_ecam_ops = {
+ .bus_shift = 16,
+ .init = xgene_v2_1_pcie_ecam_init,
+ .pci_ops = {
+ .map_bus = xgene_pcie_ecam_map_bus,
+ .read = xgene_pcie_config_read32,
+ .write = pci_generic_config_write,
+ }
+};
+
+struct pci_ecam_ops xgene_v2_2_pcie_ecam_ops = {
+ .bus_shift = 16,
+ .init = xgene_v2_2_pcie_ecam_init,
+ .pci_ops = {
+ .map_bus = xgene_pcie_ecam_map_bus,
+ .read = xgene_pcie_config_read32,
+ .write = pci_generic_config_write,
+ }
+};
+#endif
diff --git a/include/linux/pci-ecam.h b/include/linux/pci-ecam.h
index 35f0e81..40da3e7 100644
--- a/include/linux/pci-ecam.h
+++ b/include/linux/pci-ecam.h
@@ -65,6 +65,11 @@ extern struct pci_ecam_ops pci_thunder_pem_ops;
#ifdef CONFIG_PCI_HOST_THUNDER_ECAM
extern struct pci_ecam_ops pci_thunder_ecam_ops;
#endif
+#ifdef CONFIG_PCI_XGENE
+extern struct pci_ecam_ops xgene_v1_pcie_ecam_ops;
+extern struct pci_ecam_ops xgene_v2_1_pcie_ecam_ops;
+extern struct pci_ecam_ops xgene_v2_2_pcie_ecam_ops;
+#endif
#ifdef CONFIG_PCI_HOST_GENERIC
/* for DT-based PCI controllers that support ECAM */
--
1.9.1
^ permalink raw reply related
* [PATCH v2 3/4] arm64: dts: add Allwinner A64 SoC .dtsi
From: Maxime Ripard @ 2016-09-17 14:51 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <fad78d40-b595-633c-6d43-6246ec893635@arm.com>
On Thu, Sep 15, 2016 at 01:08:45AM +0100, Andr? Przywara wrote:
> > --- a/MAINTAINERS
> > +++ b/MAINTAINERS
> > @@ -982,6 +982,7 @@ M: Chen-Yu Tsai <wens@csie.org>
> > L: linux-arm-kernel at lists.infradead.org (moderated for non-subscribers)
> > S: Maintained
> > N: sun[x456789]i
> > +F: arch/arm64/boot/dts/allwinner/
>
> If you promise to not break it needlessly ;-)
We started doing so since 4.7, and we're already fighting needlessly
with maintainers because of that.
> > + cpus {
> > + #address-cells = <1>;
> > + #size-cells = <0>;
> > +
> > + cpu at 0 {
>
> This is probably me to blame here since I put you up to it, but you need
> "cpux" names (e.g. "cpu0: cpu at 0 {") to match the ones that the PMU node
> references below. dtc will refuse to compile it otherwise.
Gaah, yes, of course.
> > + i2c1_pins: i2c1_pins {
> > + allwinner,pins = "PH2", "PH3";
> > + allwinner,function = "i2c1";
> > + allwinner,drive = <SUN4I_PINCTRL_10_MA>;
> > + allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
> > + };
> > +
> > + uart0_pins_a: uart0 at 0 {
> > + allwinner,pins = "PB8", "PB9";
> > + allwinner,function = "uart0";
> > + allwinner,drive = <SUN4I_PINCTRL_10_MA>;
> > + allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
> > + };
>
> So did I get this right that there is a strict "no user - no pins"
> policy here?
> I don't see a reason why we shouldn't have at least the other UART pins
> described here as well - since they are a pure SoC property. That would
> make it easier for people to enable them (with a simple, scripted fdt
> one-liner command in U-Boot, for instance).
To avoid having huge DT that are longer to load and parse, especially
since every one wires it in the exact same way all the time. And the
combination is just too high.
On the A64, the UART0 can be exposed through PB9 and PF4 for TX, and
PB8 and PF2 for RX. Even though the common usage would be to use PB8
and PB9, or PF4 and PF6. But absolutely nothing prevents from using
PB8 and PF4.
You can then add CTS and RTS into the mix, and multiply that by the
number of devices in the SoC.
> I guess there will never be an official DT with more than 2 UARTs
> enabled, although we have actually five UARTs on the headers on the
> Pine64, for instance (and personally I am looking into using one as a
> terminal server).
We relaxed the rule lately however. Boards that have access to those
UARTs on their headers can put a node in their DT with the right
muxing filled already. Which brings you the simple, script fdt
one-liner in U-Boot.
> Also UART1 is connected to that WiFi/Bluetooth slot, having it enabled
> should make BT work without further ado (but I haven't tested this).
That's probably not true. You'll most likely need to enable a few
regulators to have it working.
Maxime
--
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160917/cca5bec3/attachment.sig>
^ permalink raw reply
* [PATCH 00/24] ste_dma40: Fine-tuning for several function implementations
From: SF Markus Elfring @ 2016-09-17 15:05 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <566ABCD9.1060404@users.sourceforge.net>
From: Markus Elfring <elfring@users.sourceforge.net>
Date: Sat, 17 Sep 2016 16:56:56 +0200
Several update suggestions were taken into account
from static source code analysis.
Markus Elfring (24):
Use kmalloc_array() in d40_lcla_allocate()
Return directly after a failed kmalloc_array()
Rename a jump label in d40_lcla_allocate()
Move an assignment in d40_lcla_allocate()
Improve a size determination in d40_of_probe()
Replace four kzalloc() calls by kcalloc() in d40_hw_detect_init()
Use kmalloc_array() in d40_hw_detect_init()
Less checks in d40_hw_detect_init() after error detection
Delete unnecessary variable initialisations in d40_hw_detect_init()
Adjust the position of a jump label in d40_probe()
Rename a jump label in d40_probe()
Rename jump labels in d40_dmaengine_init()
Rename a jump label in d40_alloc_chan_resources()
One check less in d40_prep_sg() after error detection
Move two assignments in d40_prep_sg()
Rename a jump label in d40_prep_desc()
Move an assignment in d40_prep_desc()
Rename a jump label in d40_is_paused()
Rename a jump label in d40_free_dma()
Rename a jump label in d40_alloc_mask_free()
Rename jump labels in d40_alloc_mask_set()
Rename a jump label in dma_tasklet()
Rename a jump label in __d40_execute_command_phy()
Rename a jump label in d40_log_lli_to_lcxa()
drivers/dma/ste_dma40.c | 253 +++++++++++++++++++++++-------------------------
1 file changed, 122 insertions(+), 131 deletions(-)
--
2.10.0
^ permalink raw reply
* [PATCH 01/24] ste_dma40: Use kmalloc_array() in d40_lcla_allocate()
From: SF Markus Elfring @ 2016-09-17 15:07 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <92810066-69b6-94e7-dcec-a28594b1328f@users.sourceforge.net>
From: Markus Elfring <elfring@users.sourceforge.net>
Date: Fri, 16 Sep 2016 17:56:07 +0200
* A multiplication for the size determination of a memory allocation
indicated that an array data structure should be processed.
Thus use the corresponding function "kmalloc_array".
This issue was detected by using the Coccinelle software.
* Replace the specification of a data type by a pointer dereference
to make the corresponding size determination a bit safer according to
the Linux coding style convention.
Signed-off-by: Markus Elfring <elfring@users.sourceforge.net>
---
drivers/dma/ste_dma40.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c
index 73203ac..fbebeff 100644
--- a/drivers/dma/ste_dma40.c
+++ b/drivers/dma/ste_dma40.c
@@ -3409,9 +3409,9 @@ static int __init d40_lcla_allocate(struct d40_base *base)
* To full fill this hardware requirement without wasting 256 kb
* we allocate pages until we get an aligned one.
*/
- page_list = kmalloc(sizeof(unsigned long) * MAX_LCLA_ALLOC_ATTEMPTS,
- GFP_KERNEL);
-
+ page_list = kmalloc_array(MAX_LCLA_ALLOC_ATTEMPTS,
+ sizeof(*page_list),
+ GFP_KERNEL);
if (!page_list) {
ret = -ENOMEM;
goto failure;
--
2.10.0
^ permalink raw reply related
* [PATCH 02/24] ste_dma40: Return directly after a failed kmalloc_array()
From: SF Markus Elfring @ 2016-09-17 15:08 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <92810066-69b6-94e7-dcec-a28594b1328f@users.sourceforge.net>
From: Markus Elfring <elfring@users.sourceforge.net>
Date: Sat, 17 Sep 2016 08:21:30 +0200
Return directly after a memory allocation failed in this function
at the beginning.
Signed-off-by: Markus Elfring <elfring@users.sourceforge.net>
---
drivers/dma/ste_dma40.c | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c
index fbebeff..80a199a 100644
--- a/drivers/dma/ste_dma40.c
+++ b/drivers/dma/ste_dma40.c
@@ -3412,10 +3412,8 @@ static int __init d40_lcla_allocate(struct d40_base *base)
page_list = kmalloc_array(MAX_LCLA_ALLOC_ATTEMPTS,
sizeof(*page_list),
GFP_KERNEL);
- if (!page_list) {
- ret = -ENOMEM;
- goto failure;
- }
+ if (!page_list)
+ return -ENOMEM;
/* Calculating how many pages that are required */
base->lcla_pool.pages = SZ_1K * base->num_phy_chans / PAGE_SIZE;
--
2.10.0
^ permalink raw reply related
* [PATCH 03/24] ste_dma40: Rename a jump label in d40_lcla_allocate()
From: SF Markus Elfring @ 2016-09-17 15:09 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <92810066-69b6-94e7-dcec-a28594b1328f@users.sourceforge.net>
From: Markus Elfring <elfring@users.sourceforge.net>
Date: Sat, 17 Sep 2016 08:23:37 +0200
Adjust jump labels according to the current Linux coding style convention.
Signed-off-by: Markus Elfring <elfring@users.sourceforge.net>
---
drivers/dma/ste_dma40.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c
index 80a199a..76d63b6 100644
--- a/drivers/dma/ste_dma40.c
+++ b/drivers/dma/ste_dma40.c
@@ -3429,7 +3429,7 @@ static int __init d40_lcla_allocate(struct d40_base *base)
for (j = 0; j < i; j++)
free_pages(page_list[j], base->lcla_pool.pages);
- goto failure;
+ goto free_page_list;
}
if ((virt_to_phys((void *)page_list[i]) &
@@ -3456,7 +3456,7 @@ static int __init d40_lcla_allocate(struct d40_base *base)
GFP_KERNEL);
if (!base->lcla_pool.base_unaligned) {
ret = -ENOMEM;
- goto failure;
+ goto free_page_list;
}
base->lcla_pool.base = PTR_ALIGN(base->lcla_pool.base_unaligned,
@@ -3469,12 +3469,12 @@ static int __init d40_lcla_allocate(struct d40_base *base)
if (dma_mapping_error(base->dev, pool->dma_addr)) {
pool->dma_addr = 0;
ret = -ENOMEM;
- goto failure;
+ goto free_page_list;
}
writel(virt_to_phys(base->lcla_pool.base),
base->virtbase + D40_DREG_LCLA);
-failure:
+ free_page_list:
kfree(page_list);
return ret;
}
--
2.10.0
^ permalink raw reply related
* [PATCH 04/24] ste_dma40: Move an assignment in d40_lcla_allocate()
From: SF Markus Elfring @ 2016-09-17 15:10 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <92810066-69b6-94e7-dcec-a28594b1328f@users.sourceforge.net>
From: Markus Elfring <elfring@users.sourceforge.net>
Date: Sat, 17 Sep 2016 08:24:46 +0200
Move one assignment for the local variable "ret" so that its setting
will only be performed after corresponding data processing succeeded
by this function.
Signed-off-by: Markus Elfring <elfring@users.sourceforge.net>
---
drivers/dma/ste_dma40.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c
index 76d63b6..220129e 100644
--- a/drivers/dma/ste_dma40.c
+++ b/drivers/dma/ste_dma40.c
@@ -3402,7 +3402,7 @@ static int __init d40_lcla_allocate(struct d40_base *base)
struct d40_lcla_pool *pool = &base->lcla_pool;
unsigned long *page_list;
int i, j;
- int ret = 0;
+ int ret;
/*
* This is somewhat ugly. We need 8192 bytes that are 18 bit aligned,
@@ -3474,6 +3474,7 @@ static int __init d40_lcla_allocate(struct d40_base *base)
writel(virt_to_phys(base->lcla_pool.base),
base->virtbase + D40_DREG_LCLA);
+ ret = 0;
free_page_list:
kfree(page_list);
return ret;
--
2.10.0
^ permalink raw reply related
* [PATCH 05/24] ste_dma40: Improve a size determination in d40_of_probe()
From: SF Markus Elfring @ 2016-09-17 15:11 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <92810066-69b6-94e7-dcec-a28594b1328f@users.sourceforge.net>
From: Markus Elfring <elfring@users.sourceforge.net>
Date: Sat, 17 Sep 2016 08:28:05 +0200
Replace the specification of a data structure by a pointer dereference
as the parameter for the operator "sizeof" to make the corresponding size
determination a bit safer according to the Linux coding style convention.
Signed-off-by: Markus Elfring <elfring@users.sourceforge.net>
---
drivers/dma/ste_dma40.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c
index 220129e..57d87a8 100644
--- a/drivers/dma/ste_dma40.c
+++ b/drivers/dma/ste_dma40.c
@@ -3487,9 +3487,7 @@ static int __init d40_of_probe(struct platform_device *pdev,
int num_phy = 0, num_memcpy = 0, num_disabled = 0;
const __be32 *list;
- pdata = devm_kzalloc(&pdev->dev,
- sizeof(struct stedma40_platform_data),
- GFP_KERNEL);
+ pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata)
return -ENOMEM;
--
2.10.0
^ permalink raw reply related
* [PATCH 06/24] ste_dma40: Replace four kzalloc() calls by kcalloc() in d40_hw_detect_init()
From: SF Markus Elfring @ 2016-09-17 15:12 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <92810066-69b6-94e7-dcec-a28594b1328f@users.sourceforge.net>
From: Markus Elfring <elfring@users.sourceforge.net>
Date: Sat, 17 Sep 2016 09:56:32 +0200
* The script "checkpatch.pl" can point information out like the following.
WARNING: Prefer kcalloc over kzalloc with multiply
Thus fix the affected source code places.
* Replace the specification of data types by pointer dereferences
to make the corresponding size determination a bit safer according to
the Linux coding style convention.
Signed-off-by: Markus Elfring <elfring@users.sourceforge.net>
---
drivers/dma/ste_dma40.c | 18 ++++++++++--------
1 file changed, 10 insertions(+), 8 deletions(-)
diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c
index 57d87a8..b5d15a1 100644
--- a/drivers/dma/ste_dma40.c
+++ b/drivers/dma/ste_dma40.c
@@ -3281,19 +3281,20 @@ static struct d40_base * __init d40_hw_detect_init(struct platform_device *pdev)
base->gen_dmac.init_reg_size = ARRAY_SIZE(dma_init_reg_v4a);
}
- base->phy_res = kzalloc(num_phy_chans * sizeof(struct d40_phy_res),
+ base->phy_res = kcalloc(num_phy_chans,
+ sizeof(*base->phy_res),
GFP_KERNEL);
if (!base->phy_res)
goto failure;
- base->lookup_phy_chans = kzalloc(num_phy_chans *
- sizeof(struct d40_chan *),
+ base->lookup_phy_chans = kcalloc(num_phy_chans,
+ sizeof(*base->lookup_phy_chans),
GFP_KERNEL);
if (!base->lookup_phy_chans)
goto failure;
- base->lookup_log_chans = kzalloc(num_log_chans *
- sizeof(struct d40_chan *),
+ base->lookup_log_chans = kcalloc(num_log_chans,
+ sizeof(*base->lookup_log_chans),
GFP_KERNEL);
if (!base->lookup_log_chans)
goto failure;
@@ -3304,9 +3305,10 @@ static struct d40_base * __init d40_hw_detect_init(struct platform_device *pdev)
if (!base->reg_val_backup_chan)
goto failure;
- base->lcla_pool.alloc_map =
- kzalloc(num_phy_chans * sizeof(struct d40_desc *)
- * D40_LCLA_LINK_PER_EVENT_GRP, GFP_KERNEL);
+ base->lcla_pool.alloc_map = kcalloc(num_phy_chans
+ * D40_LCLA_LINK_PER_EVENT_GRP,
+ sizeof(*base->lcla_pool.alloc_map),
+ GFP_KERNEL);
if (!base->lcla_pool.alloc_map)
goto failure;
--
2.10.0
^ permalink raw reply related
* [PATCH 07/24] ste_dma40: Use kmalloc_array() in d40_hw_detect_init()
From: SF Markus Elfring @ 2016-09-17 15:15 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <92810066-69b6-94e7-dcec-a28594b1328f@users.sourceforge.net>
From: Markus Elfring <elfring@users.sourceforge.net>
Date: Sat, 17 Sep 2016 11:44:55 +0200
A multiplication for the size determination of a memory allocation
indicated that an array data structure should be processed.
Thus use the corresponding function "kmalloc_array".
This issue was detected also by using the Coccinelle software.
Signed-off-by: Markus Elfring <elfring@users.sourceforge.net>
---
drivers/dma/ste_dma40.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c
index b5d15a1..f813056 100644
--- a/drivers/dma/ste_dma40.c
+++ b/drivers/dma/ste_dma40.c
@@ -3299,9 +3299,9 @@ static struct d40_base * __init d40_hw_detect_init(struct platform_device *pdev)
if (!base->lookup_log_chans)
goto failure;
- base->reg_val_backup_chan = kmalloc(base->num_phy_chans *
- sizeof(d40_backup_regs_chan),
- GFP_KERNEL);
+ base->reg_val_backup_chan = kmalloc_array(base->num_phy_chans,
+ sizeof(d40_backup_regs_chan),
+ GFP_KERNEL);
if (!base->reg_val_backup_chan)
goto failure;
--
2.10.0
^ permalink raw reply related
* [PATCH 08/24] ste_dma40: Less checks in d40_hw_detect_init() after error detection
From: SF Markus Elfring @ 2016-09-17 15:16 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <92810066-69b6-94e7-dcec-a28594b1328f@users.sourceforge.net>
From: Markus Elfring <elfring@users.sourceforge.net>
Date: Sat, 17 Sep 2016 14:10:47 +0200
Four checks could be repeated by the d40_hw_detect_init() function during
error handling even if the passed variables contained a null pointer.
* Adjust jump targets according to the Linux coding style convention.
* Call the interface "iounmap" only once at the end.
* Delete the repeated checks which became unnecessary with
this refactoring.
Signed-off-by: Markus Elfring <elfring@users.sourceforge.net>
---
drivers/dma/ste_dma40.c | 67 ++++++++++++++++++++++++-------------------------
1 file changed, 33 insertions(+), 34 deletions(-)
diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c
index f813056..c680dd3 100644
--- a/drivers/dma/ste_dma40.c
+++ b/drivers/dma/ste_dma40.c
@@ -3158,27 +3158,27 @@ static struct d40_base * __init d40_hw_detect_init(struct platform_device *pdev)
clk = clk_get(&pdev->dev, NULL);
if (IS_ERR(clk)) {
d40_err(&pdev->dev, "No matching clock found\n");
- goto failure;
+ goto check_prepare_enabled;
}
clk_ret = clk_prepare_enable(clk);
if (clk_ret) {
d40_err(&pdev->dev, "Failed to prepare/enable clock\n");
- goto failure;
+ goto disable_unprepare;
}
/* Get IO for DMAC base address */
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "base");
if (!res)
- goto failure;
+ goto disable_unprepare;
if (request_mem_region(res->start, resource_size(res),
D40_NAME " I/O base") == NULL)
- goto failure;
+ goto release_region;
virtbase = ioremap(res->start, resource_size(res));
if (!virtbase)
- goto failure;
+ goto release_region;
/* This is just a regular AMBA PrimeCell ID actually */
for (pid = 0, i = 0; i < 4; i++)
@@ -3190,13 +3190,13 @@ static struct d40_base * __init d40_hw_detect_init(struct platform_device *pdev)
if (cid != AMBA_CID) {
d40_err(&pdev->dev, "Unknown hardware! No PrimeCell ID\n");
- goto failure;
+ goto unmap_io;
}
if (AMBA_MANF_BITS(pid) != AMBA_VENDOR_ST) {
d40_err(&pdev->dev, "Unknown designer! Got %x wanted %x\n",
AMBA_MANF_BITS(pid),
AMBA_VENDOR_ST);
- goto failure;
+ goto unmap_io;
}
/*
* HW revision:
@@ -3210,7 +3210,7 @@ static struct d40_base * __init d40_hw_detect_init(struct platform_device *pdev)
rev = AMBA_REV_BITS(pid);
if (rev < 2) {
d40_err(&pdev->dev, "hardware revision: %d is not supported", rev);
- goto failure;
+ goto unmap_io;
}
/* The number of physical channels on this HW */
@@ -3236,7 +3236,7 @@ static struct d40_base * __init d40_hw_detect_init(struct platform_device *pdev)
sizeof(struct d40_chan), GFP_KERNEL);
if (base == NULL)
- goto failure;
+ goto unmap_io;
base->rev = rev;
base->clk = clk;
@@ -3285,63 +3285,62 @@ static struct d40_base * __init d40_hw_detect_init(struct platform_device *pdev)
sizeof(*base->phy_res),
GFP_KERNEL);
if (!base->phy_res)
- goto failure;
+ goto free_base;
base->lookup_phy_chans = kcalloc(num_phy_chans,
sizeof(*base->lookup_phy_chans),
GFP_KERNEL);
if (!base->lookup_phy_chans)
- goto failure;
+ goto free_phy_res;
base->lookup_log_chans = kcalloc(num_log_chans,
sizeof(*base->lookup_log_chans),
GFP_KERNEL);
if (!base->lookup_log_chans)
- goto failure;
+ goto free_phy_chans;
base->reg_val_backup_chan = kmalloc_array(base->num_phy_chans,
sizeof(d40_backup_regs_chan),
GFP_KERNEL);
if (!base->reg_val_backup_chan)
- goto failure;
+ goto free_log_chans;
base->lcla_pool.alloc_map = kcalloc(num_phy_chans
* D40_LCLA_LINK_PER_EVENT_GRP,
sizeof(*base->lcla_pool.alloc_map),
GFP_KERNEL);
if (!base->lcla_pool.alloc_map)
- goto failure;
+ goto free_backup_chan;
base->desc_slab = kmem_cache_create(D40_NAME, sizeof(struct d40_desc),
0, SLAB_HWCACHE_ALIGN,
NULL);
if (base->desc_slab == NULL)
- goto failure;
+ goto free_map;
return base;
-
-failure:
+ free_map:
+ kfree(base->lcla_pool.alloc_map);
+ free_backup_chan:
+ kfree(base->reg_val_backup_chan);
+ free_log_chans:
+ kfree(base->lookup_log_chans);
+ free_phy_chans:
+ kfree(base->lookup_phy_chans);
+ free_phy_res:
+ kfree(base->phy_res);
+ free_base:
+ kfree(base);
+ unmap_io:
+ iounmap(virtbase);
+ release_region:
+ release_mem_region(res->start, resource_size(res));
+ check_prepare_enabled:
if (!clk_ret)
+ disable_unprepare:
clk_disable_unprepare(clk);
if (!IS_ERR(clk))
clk_put(clk);
- if (virtbase)
- iounmap(virtbase);
- if (res)
- release_mem_region(res->start,
- resource_size(res));
- if (virtbase)
- iounmap(virtbase);
-
- if (base) {
- kfree(base->lcla_pool.alloc_map);
- kfree(base->reg_val_backup_chan);
- kfree(base->lookup_log_chans);
- kfree(base->lookup_phy_chans);
- kfree(base->phy_res);
- kfree(base);
- }
-
return NULL;
}
--
2.10.0
^ permalink raw reply related
* [PATCH 09/24] ste_dma40: Delete unnecessary variable initialisations in d40_hw_detect_init()
From: SF Markus Elfring @ 2016-09-17 15:17 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <92810066-69b6-94e7-dcec-a28594b1328f@users.sourceforge.net>
From: Markus Elfring <elfring@users.sourceforge.net>
Date: Sat, 17 Sep 2016 14:34:18 +0200
Five local variables will be set to an appropriate value a bit later.
Thus omit the explicit initialisation which became unnecessary with
a previous update step.
Signed-off-by: Markus Elfring <elfring@users.sourceforge.net>
---
drivers/dma/ste_dma40.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c
index c680dd3..ebb00a8 100644
--- a/drivers/dma/ste_dma40.c
+++ b/drivers/dma/ste_dma40.c
@@ -3142,11 +3142,11 @@ static int __init d40_phy_res_init(struct d40_base *base)
static struct d40_base * __init d40_hw_detect_init(struct platform_device *pdev)
{
struct stedma40_platform_data *plat_data = dev_get_platdata(&pdev->dev);
- struct clk *clk = NULL;
- void __iomem *virtbase = NULL;
- struct resource *res = NULL;
- struct d40_base *base = NULL;
- int num_log_chans = 0;
+ struct clk *clk;
+ void __iomem *virtbase;
+ struct resource *res;
+ struct d40_base *base;
+ int num_log_chans;
int num_phy_chans;
int num_memcpy_chans;
int clk_ret = -EINVAL;
--
2.10.0
^ permalink raw reply related
* [PATCH 10/24] ste_dma40: Adjust the position of a jump label in d40_probe()
From: SF Markus Elfring @ 2016-09-17 15:18 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <92810066-69b6-94e7-dcec-a28594b1328f@users.sourceforge.net>
From: Markus Elfring <elfring@users.sourceforge.net>
Date: Sat, 17 Sep 2016 14:36:26 +0200
Add a space character before a single jump label in this function
according to the current Linux coding style convention.
Signed-off-by: Markus Elfring <elfring@users.sourceforge.net>
---
drivers/dma/ste_dma40.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c
index ebb00a8..4ebc825 100644
--- a/drivers/dma/ste_dma40.c
+++ b/drivers/dma/ste_dma40.c
@@ -3728,7 +3728,7 @@ failure:
kfree(base->lookup_phy_chans);
kfree(base->phy_res);
kfree(base);
-report_failure:
+ report_failure:
d40_err(&pdev->dev, "probe failed\n");
return ret;
}
--
2.10.0
^ permalink raw reply related
* [PATCH 11/24] ste_dma40: Rename a jump label in d40_probe()
From: SF Markus Elfring @ 2016-09-17 15:19 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <92810066-69b6-94e7-dcec-a28594b1328f@users.sourceforge.net>
From: Markus Elfring <elfring@users.sourceforge.net>
Date: Sat, 17 Sep 2016 14:50:53 +0200
Adjust jump labels according to the current Linux coding style convention.
Signed-off-by: Markus Elfring <elfring@users.sourceforge.net>
---
drivers/dma/ste_dma40.c | 25 ++++++++++++-------------
1 file changed, 12 insertions(+), 13 deletions(-)
diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c
index 4ebc825..ed96039 100644
--- a/drivers/dma/ste_dma40.c
+++ b/drivers/dma/ste_dma40.c
@@ -3570,7 +3570,7 @@ static int __init d40_probe(struct platform_device *pdev)
if (!res) {
ret = -ENOENT;
d40_err(&pdev->dev, "No \"lcpa\" memory resource\n");
- goto failure;
+ goto destroy_cache;
}
base->lcpa_size = resource_size(res);
base->phy_lcpa = res->start;
@@ -3579,7 +3579,7 @@ static int __init d40_probe(struct platform_device *pdev)
D40_NAME " I/O lcpa") == NULL) {
ret = -EBUSY;
d40_err(&pdev->dev, "Failed to request LCPA region %pR\n", res);
- goto failure;
+ goto destroy_cache;
}
/* We make use of ESRAM memory for this. */
@@ -3595,7 +3595,7 @@ static int __init d40_probe(struct platform_device *pdev)
if (!base->lcpa_base) {
ret = -ENOMEM;
d40_err(&pdev->dev, "Failed to ioremap LCPA region\n");
- goto failure;
+ goto destroy_cache;
}
/* If lcla has to be located in ESRAM we don't need to allocate */
if (base->plat_data->use_esram_lcla) {
@@ -3605,14 +3605,14 @@ static int __init d40_probe(struct platform_device *pdev)
ret = -ENOENT;
d40_err(&pdev->dev,
"No \"lcla_esram\" memory resource\n");
- goto failure;
+ goto destroy_cache;
}
base->lcla_pool.base = ioremap(res->start,
resource_size(res));
if (!base->lcla_pool.base) {
ret = -ENOMEM;
d40_err(&pdev->dev, "Failed to ioremap LCLA region\n");
- goto failure;
+ goto destroy_cache;
}
writel(res->start, base->virtbase + D40_DREG_LCLA);
@@ -3620,7 +3620,7 @@ static int __init d40_probe(struct platform_device *pdev)
ret = d40_lcla_allocate(base);
if (ret) {
d40_err(&pdev->dev, "Failed to allocate LCLA area\n");
- goto failure;
+ goto destroy_cache;
}
}
@@ -3631,7 +3631,7 @@ static int __init d40_probe(struct platform_device *pdev)
ret = request_irq(base->irq, d40_handle_interrupt, 0, D40_NAME, base);
if (ret) {
d40_err(&pdev->dev, "No IRQ defined\n");
- goto failure;
+ goto destroy_cache;
}
if (base->plat_data->use_esram_lcla) {
@@ -3641,7 +3641,7 @@ static int __init d40_probe(struct platform_device *pdev)
d40_err(&pdev->dev, "Failed to get lcpa_regulator\n");
ret = PTR_ERR(base->lcpa_regulator);
base->lcpa_regulator = NULL;
- goto failure;
+ goto destroy_cache;
}
ret = regulator_enable(base->lcpa_regulator);
@@ -3650,7 +3650,7 @@ static int __init d40_probe(struct platform_device *pdev)
"Failed to enable lcpa_regulator\n");
regulator_put(base->lcpa_regulator);
base->lcpa_regulator = NULL;
- goto failure;
+ goto destroy_cache;
}
}
@@ -3665,13 +3665,13 @@ static int __init d40_probe(struct platform_device *pdev)
ret = d40_dmaengine_init(base, num_reserved_chans);
if (ret)
- goto failure;
+ goto destroy_cache;
base->dev->dma_parms = &base->dma_parms;
ret = dma_set_max_seg_size(base->dev, STEDMA40_MAX_SEG_SIZE);
if (ret) {
d40_err(&pdev->dev, "Failed to set dma max seg size\n");
- goto failure;
+ goto destroy_cache;
}
d40_hw_init(base);
@@ -3685,8 +3685,7 @@ static int __init d40_probe(struct platform_device *pdev)
dev_info(base->dev, "initialized\n");
return 0;
-
-failure:
+ destroy_cache:
kmem_cache_destroy(base->desc_slab);
if (base->virtbase)
iounmap(base->virtbase);
--
2.10.0
^ permalink raw reply related
* [PATCH 12/24] ste_dma40: Rename jump labels in d40_dmaengine_init()
From: SF Markus Elfring @ 2016-09-17 15:20 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <92810066-69b6-94e7-dcec-a28594b1328f@users.sourceforge.net>
From: Markus Elfring <elfring@users.sourceforge.net>
Date: Sat, 17 Sep 2016 15:10:15 +0200
Adjust jump labels according to the current Linux coding style convention.
Signed-off-by: Markus Elfring <elfring@users.sourceforge.net>
---
drivers/dma/ste_dma40.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c
index ed96039..c7b73f1 100644
--- a/drivers/dma/ste_dma40.c
+++ b/drivers/dma/ste_dma40.c
@@ -2889,7 +2889,7 @@ static int __init d40_dmaengine_init(struct d40_base *base,
if (err) {
d40_err(base->dev, "Failed to register slave channels\n");
- goto failure1;
+ goto exit;
}
d40_chan_init(base, &base->dma_memcpy, base->log_chans,
@@ -2906,7 +2906,7 @@ static int __init d40_dmaengine_init(struct d40_base *base,
if (err) {
d40_err(base->dev,
"Failed to register memcpy only channels\n");
- goto failure2;
+ goto unregister_slave;
}
d40_chan_init(base, &base->dma_both, base->phy_chans,
@@ -2924,14 +2924,14 @@ static int __init d40_dmaengine_init(struct d40_base *base,
if (err) {
d40_err(base->dev,
"Failed to register logical and physical capable channels\n");
- goto failure3;
+ goto unregister_memcpy;
}
return 0;
-failure3:
+ unregister_memcpy:
dma_async_device_unregister(&base->dma_memcpy);
-failure2:
+ unregister_slave:
dma_async_device_unregister(&base->dma_slave);
-failure1:
+ exit:
return err;
}
--
2.10.0
^ permalink raw reply related
* [PATCH 13/24] ste_dma40: Rename a jump label in d40_alloc_chan_resources()
From: SF Markus Elfring @ 2016-09-17 15:22 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <92810066-69b6-94e7-dcec-a28594b1328f@users.sourceforge.net>
From: Markus Elfring <elfring@users.sourceforge.net>
Date: Sat, 17 Sep 2016 15:15:15 +0200
Adjust jump labels according to the current Linux coding style convention.
Signed-off-by: Markus Elfring <elfring@users.sourceforge.net>
---
drivers/dma/ste_dma40.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c
index c7b73f1..0788add 100644
--- a/drivers/dma/ste_dma40.c
+++ b/drivers/dma/ste_dma40.c
@@ -2424,7 +2424,7 @@ static int d40_alloc_chan_resources(struct dma_chan *chan)
err = d40_config_memcpy(d40c);
if (err) {
chan_err(d40c, "Failed to configure memcpy channel\n");
- goto fail;
+ goto mark_last_busy;
}
}
@@ -2432,7 +2432,7 @@ static int d40_alloc_chan_resources(struct dma_chan *chan)
if (err) {
chan_err(d40c, "Failed to allocate channel\n");
d40c->configured = false;
- goto fail;
+ goto mark_last_busy;
}
pm_runtime_get_sync(d40c->base->dev);
@@ -2466,7 +2466,7 @@ static int d40_alloc_chan_resources(struct dma_chan *chan)
*/
if (is_free_phy)
d40_config_write(d40c);
-fail:
+ mark_last_busy:
pm_runtime_mark_last_busy(d40c->base->dev);
pm_runtime_put_autosuspend(d40c->base->dev);
spin_unlock_irqrestore(&d40c->lock, flags);
--
2.10.0
^ permalink raw reply related
* [PATCH] mtd: s3c2410: add device tree support
From: Sergio Prado @ 2016-09-17 15:22 UTC (permalink / raw)
To: linux-arm-kernel
Tested on FriendlyARM Mini2440
Signed-off-by: Sergio Prado <sergio.prado@e-labworks.com>
---
.../devicetree/bindings/mtd/samsung-s3c2410.txt | 70 +++++++++++
drivers/mtd/nand/s3c2410.c | 129 ++++++++++++++++++++-
include/linux/platform_data/mtd-nand-s3c2410.h | 1 +
3 files changed, 195 insertions(+), 5 deletions(-)
create mode 100644 Documentation/devicetree/bindings/mtd/samsung-s3c2410.txt
diff --git a/Documentation/devicetree/bindings/mtd/samsung-s3c2410.txt b/Documentation/devicetree/bindings/mtd/samsung-s3c2410.txt
new file mode 100644
index 000000000000..1c39f6cf483b
--- /dev/null
+++ b/Documentation/devicetree/bindings/mtd/samsung-s3c2410.txt
@@ -0,0 +1,70 @@
+* Samsung S3C2410 and compatible NAND flash controller
+
+Required properties:
+- compatible : The possible values are:
+ "samsung,s3c2410-nand"
+ "samsung,s3c2412-nand"
+ "samsung,s3c2440-nand"
+ "samsung,s3c6400-nand"
+- reg : register's location and length.
+- #address-cells, #size-cells : see nand.txt
+- clocks : phandle to the nand controller clock
+- clock-names : must contain "nand"
+
+Optional properties:
+- samsung,tacls : time for active CLE/ALE to nWE/nOE
+- samsung,twrph0 : active time for nWE/nOE
+- samsung,twrph1 : time for release CLE/ALE from nWE/nOE inactive
+- samsung,ignore_unset_ecc : boolean to ignore error when we have
+ 0xff,0xff,0xff read ECC, on the
+ assumption that it is an un-eccd page
+
+Optional children nodes:
+Children nodes representing the available nand chips.
+
+Optional children properties:
+- nand-ecc-mode : see nand.txt
+- nand-on-flash-bbt : see nand.txt
+
+Each children device node may optionally contain a 'partitions' sub-node,
+which further contains sub-nodes describing the flash partition mapping.
+See partition.txt for more detail.
+
+Example:
+
+nand at 4e000000 {
+ compatible = "samsung,s3c2440-nand";
+ reg = <0x4e000000 0x40>;
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ clocks = <&clocks HCLK_NAND>;
+ clock-names = "nand";
+
+ samsung,tacls = <0>;
+ samsung,twrph0 = <25>;
+ samsung,twrph1 = <15>;
+ samsung,ignore_unset_ecc;
+
+ nand at 0 {
+ nand-ecc-mode = "soft";
+ nand-on-flash-bbt;
+
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ partition at 0 {
+ label = "u-boot";
+ reg = <0 0x040000>;
+ };
+
+ partition at 40000 {
+ label = "kernel";
+ reg = <0x040000 0x500000>;
+ };
+ };
+ };
+};
diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/s3c2410.c
index d9309cf0ce2e..ecbb9c9c1e9a 100644
--- a/drivers/mtd/nand/s3c2410.c
+++ b/drivers/mtd/nand/s3c2410.c
@@ -39,6 +39,8 @@
#include <linux/slab.h>
#include <linux/clk.h>
#include <linux/cpufreq.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
@@ -185,6 +187,26 @@ struct s3c2410_nand_info {
#endif
};
+struct s3c24XX_nand_devtype_data {
+ enum s3c_cpu_type type;
+};
+
+struct s3c24XX_nand_devtype_data s3c2410_nand_devtype_data = {
+ .type = TYPE_S3C2410,
+};
+
+struct s3c24XX_nand_devtype_data s3c2412_nand_devtype_data = {
+ .type = TYPE_S3C2412,
+};
+
+struct s3c24XX_nand_devtype_data s3c2440_nand_devtype_data = {
+ .type = TYPE_S3C2440,
+};
+
+struct s3c24XX_nand_devtype_data s3c6400_nand_devtype_data = {
+ .type = TYPE_S3C2412,
+};
+
/* conversion functions */
static struct s3c2410_nand_mtd *s3c2410_nand_mtd_toours(struct mtd_info *mtd)
@@ -813,6 +835,8 @@ static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info,
struct nand_chip *chip = &nmtd->chip;
void __iomem *regs = info->regs;
+ nand_set_flash_node(chip, set->of_node);
+
chip->write_buf = s3c2410_nand_write_buf;
chip->read_buf = s3c2410_nand_read_buf;
chip->select_chip = s3c2410_nand_select_chip;
@@ -947,6 +971,96 @@ static void s3c2410_nand_update_chip(struct s3c2410_nand_info *info,
}
}
+#ifdef CONFIG_OF_MTD
+static const struct of_device_id s3c24xx_nand_dt_ids[] = {
+ {
+ .compatible = "samsung,s3c2410-nand",
+ .data = &s3c2410_nand_devtype_data,
+ }, {
+ .compatible = "samsung,s3c2412-nand",
+ .data = &s3c2412_nand_devtype_data,
+ }, {
+ .compatible = "samsung,s3c2440-nand",
+ .data = &s3c2440_nand_devtype_data,
+ }, {
+ .compatible = "samsung,s3c6400-nand",
+ .data = &s3c6400_nand_devtype_data,
+ },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, s3c24xx_nand_dt_ids);
+
+static int s3c24xx_nand_probe_dt(struct platform_device *pdev)
+{
+ const struct s3c24XX_nand_devtype_data *devtype_data;
+ struct s3c2410_platform_nand *pdata;
+ struct s3c2410_nand_info *info = platform_get_drvdata(pdev);
+ struct device_node *np = pdev->dev.of_node, *child;
+ const struct of_device_id *of_id;
+ struct s3c2410_nand_set *sets;
+
+ of_id = of_match_device(s3c24xx_nand_dt_ids, &pdev->dev);
+ if (!of_id)
+ return 1;
+
+ devtype_data = of_id->data;
+ info->cpu_type = devtype_data->type;
+
+ pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+ if (!pdata)
+ return -ENOMEM;
+
+ pdev->dev.platform_data = pdata;
+
+ of_property_read_u32(np, "samsung,tacls", &pdata->tacls);
+ of_property_read_u32(np, "samsung,twrph0", &pdata->twrph0);
+ of_property_read_u32(np, "samsung,twrph1", &pdata->twrph1);
+
+ if (of_get_property(np, "samsung,ignore_unset_ecc", NULL))
+ pdata->ignore_unset_ecc = 1;
+
+ pdata->nr_sets = of_get_child_count(np);
+ if (!pdata->nr_sets)
+ return 0;
+
+ sets = devm_kzalloc(&pdev->dev, sizeof(*sets) * pdata->nr_sets,
+ GFP_KERNEL);
+ if (!sets)
+ return -ENOMEM;
+
+ pdata->sets = sets;
+
+ for_each_available_child_of_node(np, child) {
+
+ sets->name = (char *)child->name;
+ sets->of_node = child;
+ sets->nr_chips = 1;
+
+ if (!of_property_match_string(child, "nand-ecc-mode", "none"))
+ sets->disable_ecc = 1;
+
+ if (of_get_property(child, "nand-on-flash-bbt", NULL))
+ sets->flash_bbt = 1;
+
+ sets++;
+ }
+
+ return 0;
+}
+#else
+static int s3c24xx_nand_probe_dt(struct platform_device *pdev)
+{
+ return 1;
+}
+#endif
+
+static void s3c24xx_nand_probe_pdata(struct platform_device *pdev)
+{
+ struct s3c2410_nand_info *info = platform_get_drvdata(pdev);
+
+ info->cpu_type = platform_get_device_id(pdev)->driver_data;
+}
+
/* s3c24xx_nand_probe
*
* called by device layer when it finds a device matching
@@ -956,8 +1070,7 @@ static void s3c2410_nand_update_chip(struct s3c2410_nand_info *info,
*/
static int s3c24xx_nand_probe(struct platform_device *pdev)
{
- struct s3c2410_platform_nand *plat = to_nand_plat(pdev);
- enum s3c_cpu_type cpu_type;
+ struct s3c2410_platform_nand *plat;
struct s3c2410_nand_info *info;
struct s3c2410_nand_mtd *nmtd;
struct s3c2410_nand_set *sets;
@@ -967,8 +1080,6 @@ static int s3c24xx_nand_probe(struct platform_device *pdev)
int nr_sets;
int setno;
- cpu_type = platform_get_device_id(pdev)->driver_data;
-
info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
if (info == NULL) {
err = -ENOMEM;
@@ -991,6 +1102,14 @@ static int s3c24xx_nand_probe(struct platform_device *pdev)
s3c2410_nand_clk_set_state(info, CLOCK_ENABLE);
+ err = s3c24xx_nand_probe_dt(pdev);
+ if (err > 0)
+ s3c24xx_nand_probe_pdata(pdev);
+ else if (err < 0)
+ goto exit_error;
+
+ plat = to_nand_plat(pdev);
+
/* allocate and map the resource */
/* currently we assume we have the one resource */
@@ -999,7 +1118,6 @@ static int s3c24xx_nand_probe(struct platform_device *pdev)
info->device = &pdev->dev;
info->platform = plat;
- info->cpu_type = cpu_type;
info->regs = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(info->regs)) {
@@ -1156,6 +1274,7 @@ static struct platform_driver s3c24xx_nand_driver = {
.id_table = s3c24xx_driver_ids,
.driver = {
.name = "s3c24xx-nand",
+ .of_match_table = s3c24xx_nand_dt_ids,
},
};
diff --git a/include/linux/platform_data/mtd-nand-s3c2410.h b/include/linux/platform_data/mtd-nand-s3c2410.h
index c55e42ee57fa..9d20871e4bbd 100644
--- a/include/linux/platform_data/mtd-nand-s3c2410.h
+++ b/include/linux/platform_data/mtd-nand-s3c2410.h
@@ -40,6 +40,7 @@ struct s3c2410_nand_set {
char *name;
int *nr_map;
struct mtd_partition *partitions;
+ struct device_node *of_node;
};
struct s3c2410_platform_nand {
--
1.9.1
^ permalink raw reply related
* [PATCH 14/24] ste_dma40: One check less in d40_prep_sg() after error detection
From: SF Markus Elfring @ 2016-09-17 15:23 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <92810066-69b6-94e7-dcec-a28594b1328f@users.sourceforge.net>
From: Markus Elfring <elfring@users.sourceforge.net>
Date: Sat, 17 Sep 2016 15:34:07 +0200
* Adjust jump targets according to the Linux coding style convention.
* Delete a repeated check which became unnecessary with this refactoring.
Signed-off-by: Markus Elfring <elfring@users.sourceforge.net>
---
drivers/dma/ste_dma40.c | 11 +++++------
1 file changed, 5 insertions(+), 6 deletions(-)
diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c
index 0788add..a7e7cd0 100644
--- a/drivers/dma/ste_dma40.c
+++ b/drivers/dma/ste_dma40.c
@@ -2251,7 +2251,7 @@ d40_prep_sg(struct dma_chan *dchan, struct scatterlist *sg_src,
desc = d40_prep_desc(chan, sg_src, sg_len, dma_flags);
if (desc == NULL)
- goto err;
+ goto unlock;
if (sg_next(&sg_src[sg_len - 1]) == sg_src)
desc->cyclic = true;
@@ -2271,7 +2271,7 @@ d40_prep_sg(struct dma_chan *dchan, struct scatterlist *sg_src,
if (ret) {
chan_err(chan, "Failed to prepare %s sg job: %d\n",
chan_is_logical(chan) ? "log" : "phy", ret);
- goto err;
+ goto free_desc;
}
/*
@@ -2283,10 +2283,9 @@ d40_prep_sg(struct dma_chan *dchan, struct scatterlist *sg_src,
spin_unlock_irqrestore(&chan->lock, flags);
return &desc->txd;
-
-err:
- if (desc)
- d40_desc_free(chan, desc);
+ free_desc:
+ d40_desc_free(chan, desc);
+ unlock:
spin_unlock_irqrestore(&chan->lock, flags);
return NULL;
}
--
2.10.0
^ permalink raw reply related
* [PATCH 15/24] ste_dma40: Move two assignments in d40_prep_sg()
From: SF Markus Elfring @ 2016-09-17 15:25 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <92810066-69b6-94e7-dcec-a28594b1328f@users.sourceforge.net>
From: Markus Elfring <elfring@users.sourceforge.net>
Date: Sat, 17 Sep 2016 15:40:05 +0200
Move assignments for two local variables so that their setting
will only be performed after corresponding data processing succeeded
by this function.
Signed-off-by: Markus Elfring <elfring@users.sourceforge.net>
---
drivers/dma/ste_dma40.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c
index a7e7cd0..6725b66 100644
--- a/drivers/dma/ste_dma40.c
+++ b/drivers/dma/ste_dma40.c
@@ -2236,8 +2236,8 @@ d40_prep_sg(struct dma_chan *dchan, struct scatterlist *sg_src,
enum dma_transfer_direction direction, unsigned long dma_flags)
{
struct d40_chan *chan = container_of(dchan, struct d40_chan, chan);
- dma_addr_t src_dev_addr = 0;
- dma_addr_t dst_dev_addr = 0;
+ dma_addr_t src_dev_addr;
+ dma_addr_t dst_dev_addr;
struct d40_desc *desc;
unsigned long flags;
int ret;
@@ -2256,6 +2256,8 @@ d40_prep_sg(struct dma_chan *dchan, struct scatterlist *sg_src,
if (sg_next(&sg_src[sg_len - 1]) == sg_src)
desc->cyclic = true;
+ src_dev_addr = 0;
+ dst_dev_addr = 0;
if (direction == DMA_DEV_TO_MEM)
src_dev_addr = chan->runtime_addr;
else if (direction == DMA_MEM_TO_DEV)
--
2.10.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