* [PATCH] dt-bindings: mfd: Improve readability for TPS65217 interrupt sources
From: Milo Kim @ 2016-11-23 13:06 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <33562327.jVWx4tN2gP@wuerfel>
On 11/23/2016 08:51 PM, Arnd Bergmann wrote:
> Ah, the numbers come from the data sheet. Please just remove the
> header then, there is no need to keep them as an ABI, in particular
> when the driver doesn't even include that header today.
Got it.
> What matters here is the binding documentation in
> Documentation/devicetree/bindings/power/supply/tps65217_charger.txt
OK, in addition to this, the interrupt specifier needs to be added in
Documentation/devicetree/bindings/input/tps65218-pwrbutton.txt.
> Please fix that instead to mandate that the two interrupts are
> required, what their functions are, and what the interrupt-names
> (not interrupts-names) property must list.
Oops, wrong interrupt name property - my bad.
Thanks for all your feedback.
Best regards,
Milo
^ permalink raw reply
* [PATCH net-next 1/4] net: mvneta: Convert to be 64 bits compatible
From: Gregory CLEMENT @ 2016-11-23 13:07 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <9432400.S1OrxC027t@wuerfel>
Hi Jisheng, Arnd,
Thanks for your feedback.
On mer., nov. 23 2016, Arnd Bergmann <arnd@arndb.de> wrote:
> On Wednesday, November 23, 2016 5:53:41 PM CET Jisheng Zhang wrote:
>> On Tue, 22 Nov 2016 22:04:12 +0100 Arnd Bergmann wrote:
>>
>> > On Tuesday, November 22, 2016 5:48:41 PM CET Gregory CLEMENT wrote:
>> > > +#ifdef CONFIG_64BIT
>> > > + void *data_tmp;
>> > > +
>> > > + /* In Neta HW only 32 bits data is supported, so in order to
>> > > + * obtain whole 64 bits address from RX descriptor, we store
>> > > + * the upper 32 bits when allocating buffer, and put it back
>> > > + * when using buffer cookie for accessing packet in memory.
>> > > + * Frags should be allocated from single 'memory' region,
>> > > + * hence common upper address half should be sufficient.
>> > > + */
>> > > + data_tmp = mvneta_frag_alloc(pp->frag_size);
>> > > + if (data_tmp) {
>> > > + pp->data_high = (u64)upper_32_bits((u64)data_tmp) << 32;
>> > > + mvneta_frag_free(pp->frag_size, data_tmp);
>> > > + }
>> > >
>> >
>> > How does this work when the region spans a n*4GB address boundary?
>>
>> indeed. We also make use of this driver on 64bit platforms. We use
>> different solution to make the driver 64bit safe.
>>
>> solA: make use of the reserved field in the mvneta_rx_desc, such
>> as reserved2 etc. Yes, the field is marked as "for future use, PnC", but
>> now it's not used at all. This is one possible solution however.
>
> Right, this sounds like the most straightforward choice.
The PnC (which stands for Parsing and Classification) is not used yet
indeed but this field will be needed when we will enable it. It is
something we want to do but it is not planned in a near future. However
from the datasheets I have it seems only present on the Armada XP. It is
not mentioned on datasheets for the Armada 38x or the Armada 3700.
That would mean it was safe to use on of this field in 64-bits mode on
the Armada 3700.
So I am going to take this approach.
Thanks,
Gregory
>
>> solB: allocate a shadow buf cookie during init, e.g
>>
>> rxq->descs_bufcookie = kmalloc(rxq->size * sizeof(void*), GFP_KERNEL);
>>
>> then modify mvneta_rx_desc_fill a bit to save the 64bit pointer in
>> the shadow buf cookie, e.g
>> static void mvneta_rx_desc_fill(struct mvneta_rx_desc *rx_desc,
>> u32 phys_addr, u32 cookie,
>> struct mvneta_rx_queue *rxq)
>>
>> {
>> int i;
>>
>> rx_desc->buf_cookie = cookie;
>> rx_desc->buf_phys_addr = phys_addr;
>> i = rx_desc - rxq->descs;
>> rxq->descs_bufcookie[i] = cookie;
>> }
>>
>> then fetch the desc from the shadow buf cookie in all code path, such
>> as mvneta_rx() etc.
>>
>> Both solutions should not have the problems pointed out by Arnd.
>
> Wait, since you compute an index 'i' here, can't you just store 'i'
> directly in the descriptor instead of the pointer?
>
> Arnd
--
Gregory Clement, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com
^ permalink raw reply
* [PATCH 2/3] arm64: dts: r8a7796: Add CAN support
From: Geert Uytterhoeven @ 2016-11-23 13:10 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1479903279-1950-1-git-send-email-chris.paterson2@renesas.com>
On Wed, Nov 23, 2016 at 1:14 PM, Chris Paterson
<chris.paterson2@renesas.com> wrote:
> Adds CAN controller nodes for r8a7796.
>
> Based on a patch for r8a7795 by Ramesh Shanmugasundaram.
>
> Signed-off-by: Chris Paterson <chris.paterson2@renesas.com>
Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert at linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
^ permalink raw reply
* [PATCH 1/3] arm64: dts: r8a7796: Add CAN external clock support
From: Geert Uytterhoeven @ 2016-11-23 13:10 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1479903264-1909-1-git-send-email-chris.paterson2@renesas.com>
On Wed, Nov 23, 2016 at 1:14 PM, Chris Paterson
<chris.paterson2@renesas.com> wrote:
> Adds external CAN clock node for r8a7796. This clock can be used as
> fCAN clock of CAN and CAN FD controller.
>
> Based on a patch for r8a7795 by Ramesh Shanmugasundaram.
>
> Signed-off-by: Chris Paterson <chris.paterson2@renesas.com>
Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert at linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
^ permalink raw reply
* [PATCH 0/3] arm64: dts: r8a7796: Add CAN/CAN FD support
From: Marc Kleine-Budde @ 2016-11-23 13:18 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1479903243-1860-1-git-send-email-chris.paterson2@renesas.com>
On 11/23/2016 01:14 PM, Chris Paterson wrote:
> This patch series adds CAN and CAN FD support to the r8a7796.
>
> Based on renesas-devel-20161122-v4.9-rc6.
>
> Chris Paterson (3):
> arm64: dts: r8a7796: Add CAN external clock support
> arm64: dts: r8a7796: Add CAN support
> arm64: dts: r8a7796: Add CAN FD support
>
> .../devicetree/bindings/net/can/rcar_can.txt | 12 +++--
> .../devicetree/bindings/net/can/rcar_canfd.txt | 12 +++--
> arch/arm64/boot/dts/renesas/r8a7796.dtsi | 61 ++++++++++++++++++++++
> 3 files changed, 75 insertions(+), 10 deletions(-)
For all three:
Acked-by: Marc Kleine-Budde <mkl@pengutronix.de>
Who takes this series?
Marc
--
Pengutronix e.K. | Marc Kleine-Budde |
Industrial Linux Solutions | Phone: +49-231-2826-924 |
Vertretung West/Dortmund | Fax: +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686 | http://www.pengutronix.de |
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: OpenPGP digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20161123/1a4068ca/attachment.sig>
^ permalink raw reply
* [PATCH 3/3] arm64: dts: r8a7796: Add CAN FD support
From: Geert Uytterhoeven @ 2016-11-23 13:19 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1479903288-2009-1-git-send-email-chris.paterson2@renesas.com>
On Wed, Nov 23, 2016 at 1:14 PM, Chris Paterson
<chris.paterson2@renesas.com> wrote:
> Adds CAN FD controller node for r8a7796.
>
> Based on a patch for r8a7795 by Ramesh Shanmugasundaram.
>
> Signed-off-by: Chris Paterson <chris.paterson2@renesas.com>
Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert at linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
^ permalink raw reply
* [RFC PATCH v2 1/2] macb: Add 1588 support in Cadence GEM.
From: Andrei Pistirica @ 2016-11-23 13:34 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161120191823.GA6950@localhost.localdomain>
On 20.11.2016 20:18, Richard Cochran wrote:
> On Fri, Nov 18, 2016 at 03:21:51PM +0100, Andrei Pistirica wrote:
>> - Frequency adjustment is not directly supported by this IP.
>
> This statement still makes no sense. Doesn't the following text...
This statement is inherited from original patch, and it refers to the
fact that it doesn't change directly the frequency, it changes the
increment value.
I'll remove it to avoid any confusion.
>
>> addend is the initial value ns increment and similarly addendesub.
>> The ppb (parts per billion) provided is used as
>> ns_incr = addend +/- (ppb/rate).
>> Similarly the remainder of the above is used to populate subns increment.
>
> describe how frequency adjustment is in fact supported?
Ack, I will clarify.
>
>> +config MACB_USE_HWSTAMP
>> + bool "Use IEEE 1588 hwstamp"
>> + depends on MACB
>> + default y
>> + select PTP_1588_CLOCK
>
> This "select" pattern is going to be replaced with "imply" soon.
>
> http://www.mail-archive.com/linux-kernel at vger.kernel.org/msg1269181.html
>
> You should use the new "imply" key word and reference that series in
> your change log.
Ack.
>
>> diff --git a/drivers/net/ethernet/cadence/macb.h b/drivers/net/ethernet/cadence/macb.h
>> index 3f385ab..2ee9af8 100644
>> --- a/drivers/net/ethernet/cadence/macb.h
>> +++ b/drivers/net/ethernet/cadence/macb.h
>> @@ -10,6 +10,10 @@
>> #ifndef _MACB_H
>> #define _MACB_H
>>
>> +#include <linux/net_tstamp.h>
>> +#include <linux/ptp_clock.h>
>> +#include <linux/ptp_clock_kernel.h>
>
> Don't need net_tstamp.h here. Move it into the .c file please.
Ack.
>
>> @@ -840,8 +902,26 @@ struct macb {
>>
>> unsigned int rx_frm_len_mask;
>> unsigned int jumbo_max_len;
>> +
>> +#ifdef CONFIG_MACB_USE_HWSTAMP
>> + unsigned int hwts_tx_en;
>> + unsigned int hwts_rx_en;
>
> These two can be bool'eans.
Ack.
>
>> + spinlock_t tsu_clk_lock;
>> + unsigned int tsu_rate;
>> +
>> + struct ptp_clock *ptp_clock;
>> + struct ptp_clock_info ptp_caps;
>> + unsigned int ns_incr;
>> + unsigned int subns_incr;
>
> These two are 32 bit register values, right? Then use the u32 type.
Yes. I will make the change.
>
>> +#endif
>> };
>
>> +static inline void macb_tsu_set_time(struct macb *bp,
>> + const struct timespec64 *ts)
>> +{
>> + u32 ns, sech, secl;
>> + s64 word_mask = 0xffffffff;
>> +
>> + sech = (u32)ts->tv_sec;
>> + secl = (u32)ts->tv_sec;
>> + ns = ts->tv_nsec;
>> + if (ts->tv_sec > word_mask)
>> + sech = (ts->tv_sec >> 32);
>> +
>> + spin_lock(&bp->tsu_clk_lock);
>> +
>> + /* TSH doesn't latch the time and no atomicity! */
>> + gem_writel(bp, TSH, sech);
>> + gem_writel(bp, TSL, secl);
>
> If TN overflows here then the clock will be off by one whole second!
> Why not clear TN first?
Ack.
>
>> + gem_writel(bp, TN, ns);
>> +
>> + spin_unlock(&bp->tsu_clk_lock);
>> +}
>> +
>> +static int macb_ptp_adjfreq(struct ptp_clock_info *ptp, s32 ppb)
>> +{
>> + struct macb *bp = container_of(ptp, struct macb, ptp_caps);
>> + u32 addend, addend_frac, rem;
>> + u64 drift_tmr, diff, diff_frac = 0;
>> + int neg_adj = 0;
>> +
>> + if (ppb < 0) {
>> + neg_adj = 1;
>> + ppb = -ppb;
>> + }
>> +
>> + /* drift/period */
>> + drift_tmr = (bp->ns_incr * ppb) +
>> + ((bp->subns_incr * ppb) >> 16);
>
> What? Why the 16 bit shift? Last time your said it was 24 bits.
SAMA5D2/3/4 uses GEM-PTP version (16bit), while Harini wrote a driver
for GEM-GXL (24bit). Probably will be a patch on top of this one for
GXL. This confusion was because I tried to keep the original patch
unchanged.
>
>> + /* drift/cycle */
>> + diff = div_u64_rem(drift_tmr, 1000000000ULL, &rem);
>> +
>> + /* drift fraction/cycle, if necessary */
>> + if (rem) {
>> + u64 fraction = rem;
>> + fraction = fraction << 16;
>> +
>> + diff_frac = div_u64(fraction, 1000000000ULL);
>
> If you use a combined tuning word like I explained last time, then you
> will not need a second division.
From what I understand, your suggestion is:
(ns | frac) * ppb = (total_ns | total_frac)
(total_ns | total_frac) / 10^9 = (adj_ns | adj_frac)
This is correct iff total_ns/10^9 >= 1, but the problem is that there
are missed fractions due to the following approximation:
frac*ppb =~
(ns*ppb+frac*ppb*2^16)*2^16-10^9*2^16*flor(ns*ppb+frac*ppb*2^16, 10^9).
An example which uses values from a real test:
let ppb=4891, ns=12 and frac=3158
- using suggested algorithm, yields: adj_ns = 0 and adj_frac = 0
- using in-place algorithm, yields: adj_ns = 0, adj_frac = 4
You can check the calculus.
Therefore, I would like to keep the in-place algorithm.
>
> Also, please use the new adjfine() PHC method, as adjfreq() is now deprecated.
Yes, I will port the patches on net-next and use adjfine.
>
>> + }
>> +
>> + /* adjustmets */
>> + addend = neg_adj ? (bp->ns_incr - diff) : (bp->ns_incr + diff);
>> + addend_frac = neg_adj ? (bp->subns_incr - diff_frac) :
>> + (bp->subns_incr + diff_frac);
>> +
>> + spin_lock(&bp->tsu_clk_lock);
>> +
>> + gem_writel(bp, TISUBN, GEM_BF(SUBNSINCR, addend_frac));
>> + gem_writel(bp, TI, GEM_BF(NSINCR, addend));
>> +
>> + spin_unlock(&bp->tsu_clk_lock);
>> + return 0;
>> +}
>
>> +void macb_ptp_init(struct net_device *ndev)
>> +{
>> + struct macb *bp = netdev_priv(ndev);
>> + struct timespec64 now;
>> + u32 rem = 0;
>> +
>> + if (!(bp->caps | MACB_CAPS_GEM_HAS_PTP)){
>> + netdev_vdbg(bp->dev, "Platform does not support PTP!\n");
>> + return;
>> + }
>> +
>> + spin_lock_init(&bp->tsu_clk_lock);
>> +
>> + bp->ptp_caps = macb_ptp_caps;
>> + bp->tsu_rate = clk_get_rate(bp->pclk);
>> +
>> + getnstimeofday64(&now);
>> + macb_tsu_set_time(bp, (const struct timespec64 *)&now);
>> +
>> + bp->ns_incr = div_u64_rem(NSEC_PER_SEC, bp->tsu_rate, &rem);
>> + if (rem) {
>> + u64 adj = rem;
>> + /* Multiply by 2^16 as subns register is 16 bits */
>
> Last time you said:
>> + /* Multiple by 2^24 as subns field is 24 bits */
>
>> + adj <<= 16;
>> + bp->subns_incr = div_u64(adj, bp->tsu_rate);
>> + } else {
>> + bp->subns_incr = 0;
>> + }
>> +
>> + gem_writel(bp, TISUBN, GEM_BF(SUBNSINCR, bp->subns_incr));
>> + gem_writel(bp, TI, GEM_BF(NSINCR, bp->ns_incr));
>> + gem_writel(bp, TA, 0);
>> +
>> + bp->ptp_clock = ptp_clock_register(&bp->ptp_caps, NULL);
>
> You call regsiter, but you never call unregister!
Ack. I did a stupid mistake... sorry.
>
>> + if (IS_ERR(&bp->ptp_clock)) {
>> + bp->ptp_clock = NULL;
>> + pr_err("ptp clock register failed\n");
>> + return;
>> + }
>> +
>> + dev_info(&bp->pdev->dev, "%s ptp clock registered.\n", GMAC_TIMER_NAME);
>> +}
>> +
>> --
>> 1.9.1
>>
>
> Thanks,
> Richard
>
Regards,
Andrei
^ permalink raw reply
* [RFC PATCH v2 2/2] macb: Enable 1588 support in SAMA5D2 platform.
From: Andrei Pistirica @ 2016-11-23 13:35 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161120195413.GB7874@localhost.localdomain>
On 20.11.2016 20:54, Richard Cochran wrote:
> On Fri, Nov 18, 2016 at 03:21:52PM +0100, Andrei Pistirica wrote:
>> diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c
>> index d975882..eb66b76 100644
>> --- a/drivers/net/ethernet/cadence/macb.c
>> +++ b/drivers/net/ethernet/cadence/macb.c
>> @@ -697,6 +697,8 @@ static void macb_tx_interrupt(struct macb_queue *queue)
>>
>> /* First, update TX stats if needed */
>> if (skb) {
>> + macb_ptp_do_txstamp(bp, skb);
>
> This is in the hot path, and so you should have an inline wrapper that
> tests (bp->hwts_tx_en) and THEN calls into macb_ptp.c
Ack.
>
> In case PTP isn't configured, then the inline wrapper should be empty.
>
>> netdev_vdbg(bp->dev, "skb %u (data %p) TX complete\n",
>> macb_tx_ring_wrap(tail), skb->data);
>> bp->stats.tx_packets++;
>> @@ -853,6 +855,8 @@ static int gem_rx(struct macb *bp, int budget)
>> GEM_BFEXT(RX_CSUM, ctrl) & GEM_RX_CSUM_CHECKED_MASK)
>> skb->ip_summed = CHECKSUM_UNNECESSARY;
>>
>> + macb_ptp_do_rxstamp(bp, skb);
>
> Same here.
>
>> bp->stats.rx_packets++;
>> bp->stats.rx_bytes += skb->len;
>>
>> @@ -1946,6 +1950,8 @@ static int macb_open(struct net_device *dev)
>>
>> netif_tx_start_all_queues(dev);
>>
>> + macb_ptp_init(dev);
>
> This leaks PHC instances starting the second time that the interface goes up!
Yes, I will call unregister at interface down.
>
>> return 0;
>> }
>>
>> @@ -2204,7 +2210,7 @@ static const struct ethtool_ops gem_ethtool_ops = {
>> .get_regs_len = macb_get_regs_len,
>> .get_regs = macb_get_regs,
>> .get_link = ethtool_op_get_link,
>> - .get_ts_info = ethtool_op_get_ts_info,
>> + .get_ts_info = macb_get_ts_info,
>
> You enable the time stamping logic unconditionally here ...
I will add a wrapper to test if macb is gem and if it has PTP
capability, otherwise call ethtool_op_get_ts_info.
>
>> .get_ethtool_stats = gem_get_ethtool_stats,
>> .get_strings = gem_get_ethtool_strings,
>> .get_sset_count = gem_get_sset_count,
>> @@ -2221,7 +2227,14 @@ static int macb_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
>> if (!phydev)
>> return -ENODEV;
>>
>> - return phy_mii_ioctl(phydev, rq, cmd);
>> + switch (cmd) {
>> + case SIOCSHWTSTAMP:
>> + return macb_hwtst_set(dev, rq, cmd);
>> + case SIOCGHWTSTAMP:
>> + return macb_hwtst_get(dev, rq);
>
> and here.
>
> Is that logic always available on every MACB device? If so, is the
> implementation also identical?
As before, I will add a wrapper and the related tests.
>
> Thanks,
> Richard
>
Regards,
Andrei
^ permalink raw reply
* [PATCH] arm64: defconfig: Do not lower CONFIG_LOG_BUF_SHIFT
From: Geert Uytterhoeven @ 2016-11-23 13:36 UTC (permalink / raw)
To: linux-arm-kernel
The default value of 17 for CONFIG_LOG_BUF_SHIFT is much more suitable
than 14. The latter easily leads to lost kernel messages on systems with
only one CPU core.
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
---
arch/arm64/configs/defconfig | 1 -
1 file changed, 1 deletion(-)
diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index 0e41290f6cbb4101..f284568373adf917 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -11,7 +11,6 @@ CONFIG_TASK_XACCT=y
CONFIG_TASK_IO_ACCOUNTING=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
-CONFIG_LOG_BUF_SHIFT=14
CONFIG_MEMCG=y
CONFIG_MEMCG_SWAP=y
CONFIG_BLK_CGROUP=y
--
1.9.1
^ permalink raw reply related
* [RFC PATCH v2 1/2] macb: Add 1588 support in Cadence GEM.
From: Andrei Pistirica @ 2016-11-23 13:36 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161120193720.GA7874@localhost.localdomain>
On 20.11.2016 20:37, Richard Cochran wrote:
> On Fri, Nov 18, 2016 at 03:21:51PM +0100, Andrei Pistirica wrote:
>> +#ifdef CONFIG_MACB_USE_HWSTAMP
>> +void macb_ptp_init(struct net_device *ndev);
>> +#else
>> +void macb_ptp_init(struct net_device *ndev) { }
>
> static inline ^^^
I can do static inline only when PTP is not enabled (on else branch),
thus the empty function is defined in the header file (since the init
function is defined in macb_ptp and used in macb). To differentiate
between macb versions, I'll add a wrapper.
Would this be ok?
>
>> +#endif
>
>
>> +void macb_ptp_init(struct net_device *ndev)
>> +{
>> + struct macb *bp = netdev_priv(ndev);
>> + struct timespec64 now;
>> + u32 rem = 0;
>> +
>> + if (!(bp->caps | MACB_CAPS_GEM_HAS_PTP)){
>> + netdev_vdbg(bp->dev, "Platform does not support PTP!\n");
>> + return;
>> + }
>
> You would have needed '&' and not '|' here.
Yes. Another stupid mistake... sorry. I will be more careful next time.
>
> Also, using a flag limits the code to your platform. This works for
> you, but it is short sighted. The other MACB PTP blocks have
> different register layouts, and this patch does not lay the ground
> work for the others.
>
> The driver needs to be designed to support the other platforms.
It will support Xilinx.
>
> Thanks,
> Richard
>
Regards,
Andrei
^ permalink raw reply
* [PATCH v4 0/2] da8xx: fix section mismatch in new drivers
From: Bartosz Golaszewski @ 2016-11-23 13:39 UTC (permalink / raw)
To: linux-arm-kernel
Sekhar noticed there's a section mismatch in the da8xx-mstpri and
da8xx-ddrctl drivers. This is caused by calling
of_flat_dt_get_machine_name() which has an __init annotation.
This series makes the drivers drop the call and not print the
machine name in the error message.
v1 -> v2:
- drop patch [1/3] from v1
- introduce internal routines in the drivers instead of a general
function in of/base.c
v2 -> v3:
- use of_property_read_string_index() instead of
of_property_read_string() to get the first compatible entry
- s/priotities/priorities
v3 -> v4:
- drop the compatible string printing altogether as the new function
is not safe
- merge the typo fix into patch [1/2]
Bartosz Golaszewski (2):
bus: da8xx-mstpri: drop the call to of_flat_dt_get_machine_name()
memory: da8xx-ddrctl: drop the call to of_flat_dt_get_machine_name()
drivers/bus/da8xx-mstpri.c | 4 +---
drivers/memory/da8xx-ddrctl.c | 4 +---
2 files changed, 2 insertions(+), 6 deletions(-)
--
2.9.3
^ permalink raw reply
* [PATCH v4 1/2] bus: da8xx-mstpri: drop the call to of_flat_dt_get_machine_name()
From: Bartosz Golaszewski @ 2016-11-23 13:39 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1479908400-10136-1-git-send-email-bgolaszewski@baylibre.com>
In order to avoid a section mismatch drop the call to
of_flat_dt_get_machine_name() when printing the error message.
While we're at it: fix a typo.
Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
---
drivers/bus/da8xx-mstpri.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/drivers/bus/da8xx-mstpri.c b/drivers/bus/da8xx-mstpri.c
index 85f0b53..063397f 100644
--- a/drivers/bus/da8xx-mstpri.c
+++ b/drivers/bus/da8xx-mstpri.c
@@ -16,7 +16,6 @@
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/regmap.h>
-#include <linux/of_fdt.h>
/*
* REVISIT: Linux doesn't have a good framework for the kind of performance
@@ -226,8 +225,7 @@ static int da8xx_mstpri_probe(struct platform_device *pdev)
prio_list = da8xx_mstpri_get_board_prio();
if (!prio_list) {
- dev_err(dev, "no master priotities defined for board '%s'\n",
- of_flat_dt_get_machine_name());
+ dev_err(dev, "no master priorities defined for this board\n");
return -EINVAL;
}
--
2.9.3
^ permalink raw reply related
* [PATCH v4 2/2] memory: da8xx-ddrctl: drop the call to of_flat_dt_get_machine_name()
From: Bartosz Golaszewski @ 2016-11-23 13:40 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1479908400-10136-1-git-send-email-bgolaszewski@baylibre.com>
In order to avoid a section mismatch drop the call to
of_flat_dt_get_machine_name() when printing the error message.
Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
---
drivers/memory/da8xx-ddrctl.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/drivers/memory/da8xx-ddrctl.c b/drivers/memory/da8xx-ddrctl.c
index a20e7bb..030afbe 100644
--- a/drivers/memory/da8xx-ddrctl.c
+++ b/drivers/memory/da8xx-ddrctl.c
@@ -14,7 +14,6 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
-#include <linux/of_fdt.h>
#include <linux/platform_device.h>
#include <linux/io.h>
@@ -117,8 +116,7 @@ static int da8xx_ddrctl_probe(struct platform_device *pdev)
setting = da8xx_ddrctl_get_board_settings();
if (!setting) {
- dev_err(dev, "no settings for board '%s'\n",
- of_flat_dt_get_machine_name());
+ dev_err(dev, "no settings defined for this board\n");
return -EINVAL;
}
--
2.9.3
^ permalink raw reply related
* [PATCH RESEND 0/2] add support for AXP209 GPIOs functions
From: Quentin Schulz @ 2016-11-23 14:11 UTC (permalink / raw)
To: linux-arm-kernel
The AXP209 PMIC has three GPIOs. Two of them can be muxed in other modes
(namely adc or regulator)[1] which cannot be used while the pin is in one
of GPIO modes.
This adds the possibility to use all functions of the GPIOs present in
the AXP209 PMIC thanks to the pinctrl subsystem.
An upcoming ADC driver for the AXP209 PMIC will make use of this pinctrl to
read ADC values of GPIO0 and GPIO1. At the moment, no driver is pinctrling
these GPIOs.
This patch also corrects the register used to read GPIO input status.
[1] see registers 90H, 92H and 93H at
http://dl.linux-sunxi.org/AXP/AXP209_Datasheet_v1.0en.pdf
Quentin Schulz (2):
gpio: axp209: use correct register for GPIO input status
gpio: axp209: add pinctrl support
.../devicetree/bindings/gpio/gpio-axp209.txt | 28 +-
drivers/gpio/gpio-axp209.c | 557 ++++++++++++++++++---
2 files changed, 504 insertions(+), 81 deletions(-)
--
Adding Maxime Ripard (original driver author) and LKML to mail recipients.
2.9.3
^ permalink raw reply
* [PATCH RESEND 1/2] gpio: axp209: use correct register for GPIO input status
From: Quentin Schulz @ 2016-11-23 14:11 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161123141151.25315-1-quentin.schulz@free-electrons.com>
The GPIO input status was read from control register
(AXP20X_GPIO[210]_CTRL) instead of status register (AXP20X_GPIO20_SS).
Signed-off-by: Quentin Schulz <quentin.schulz@free-electrons.com>
---
drivers/gpio/gpio-axp209.c | 8 ++------
1 file changed, 2 insertions(+), 6 deletions(-)
diff --git a/drivers/gpio/gpio-axp209.c b/drivers/gpio/gpio-axp209.c
index d9c2a51..4a346b7 100644
--- a/drivers/gpio/gpio-axp209.c
+++ b/drivers/gpio/gpio-axp209.c
@@ -64,13 +64,9 @@ static int axp20x_gpio_get(struct gpio_chip *chip, unsigned offset)
{
struct axp20x_gpio *gpio = gpiochip_get_data(chip);
unsigned int val;
- int reg, ret;
-
- reg = axp20x_gpio_get_reg(offset);
- if (reg < 0)
- return reg;
+ int ret;
- ret = regmap_read(gpio->regmap, reg, &val);
+ ret = regmap_read(gpio->regmap, AXP20X_GPIO20_SS, &val);
if (ret)
return ret;
--
2.9.3
^ permalink raw reply related
* [PATCH RESEND 2/2] gpio: axp209: add pinctrl support
From: Quentin Schulz @ 2016-11-23 14:11 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161123141151.25315-1-quentin.schulz@free-electrons.com>
The GPIOs present in the AXP209 PMIC have multiple functions. They
typically allow a pin to be used as GPIO input or output and can also be
used as ADC or regulator for example.[1]
This adds the possibility to use all functions of the GPIOs present in
the AXP209 PMIC thanks to pinctrl subsystem.
[1] see registers 90H, 92H and 93H at
http://dl.linux-sunxi.org/AXP/AXP209_Datasheet_v1.0en.pdf
Signed-off-by: Quentin Schulz <quentin.schulz@free-electrons.com>
---
.../devicetree/bindings/gpio/gpio-axp209.txt | 28 +-
drivers/gpio/gpio-axp209.c | 551 ++++++++++++++++++---
2 files changed, 503 insertions(+), 76 deletions(-)
diff --git a/Documentation/devicetree/bindings/gpio/gpio-axp209.txt b/Documentation/devicetree/bindings/gpio/gpio-axp209.txt
index a661130..a5bfe87 100644
--- a/Documentation/devicetree/bindings/gpio/gpio-axp209.txt
+++ b/Documentation/devicetree/bindings/gpio/gpio-axp209.txt
@@ -1,4 +1,4 @@
-AXP209 GPIO controller
+AXP209 GPIO & pinctrl controller
This driver follows the usual GPIO bindings found in
Documentation/devicetree/bindings/gpio/gpio.txt
@@ -28,3 +28,29 @@ axp209: pmic at 34 {
#gpio-cells = <2>;
};
};
+
+The GPIOs can be muxed to other functions and therefore, must be a subnode of
+axp_gpio.
+
+Example:
+
+&axp_gpio {
+ gpio0_adc: gpio0_adc {
+ pin = "GPIO0";
+ function = "adc";
+ };
+};
+
+&example_node {
+ pinctrl-names = "default";
+ pinctrl-0 = <&gpio0_adc>;
+};
+
+GPIOs and their functions
+-------------------------
+
+GPIO | Functions
+------------------------
+GPIO0 | gpio_in, gpio_out, ldo, adc
+GPIO1 | gpio_in, gpio_out, ldo, adc
+GPIO2 | gpio_in, gpio_out
diff --git a/drivers/gpio/gpio-axp209.c b/drivers/gpio/gpio-axp209.c
index 4a346b7..0a64cfc 100644
--- a/drivers/gpio/gpio-axp209.c
+++ b/drivers/gpio/gpio-axp209.c
@@ -1,7 +1,8 @@
/*
- * AXP20x GPIO driver
+ * AXP20x Pin control driver
*
* Copyright (C) 2016 Maxime Ripard <maxime.ripard@free-electrons.com>
+ * Copyright (C) 2016 Quentin Schulz <quentin.schulz@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
@@ -21,52 +22,103 @@
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/slab.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/pinctrl/pinconf-generic.h>
#define AXP20X_GPIO_FUNCTIONS 0x7
#define AXP20X_GPIO_FUNCTION_OUT_LOW 0
#define AXP20X_GPIO_FUNCTION_OUT_HIGH 1
#define AXP20X_GPIO_FUNCTION_INPUT 2
-struct axp20x_gpio {
- struct gpio_chip chip;
- struct regmap *regmap;
-};
+#define AXP20X_PINCTRL_PIN(_pin_num, _pin, _regs) \
+ { \
+ .number = _pin_num, \
+ .name = _pin, \
+ .drv_data = _regs, \
+ }
-static int axp20x_gpio_get_reg(unsigned offset)
-{
- switch (offset) {
- case 0:
- return AXP20X_GPIO0_CTRL;
- case 1:
- return AXP20X_GPIO1_CTRL;
- case 2:
- return AXP20X_GPIO2_CTRL;
+#define AXP20X_PIN(_pin, ...) \
+ { \
+ .pin = _pin, \
+ .functions = (struct axp20x_desc_function[]) { \
+ __VA_ARGS__, { } }, \
}
- return -EINVAL;
-}
+#define AXP20X_FUNCTION(_val, _name) \
+ { \
+ .name = _name, \
+ .muxval = _val, \
+ }
-static int axp20x_gpio_input(struct gpio_chip *chip, unsigned offset)
-{
- struct axp20x_gpio *gpio = gpiochip_get_data(chip);
- int reg;
+struct axp20x_desc_function {
+ const char *name;
+ u8 muxval;
+};
- reg = axp20x_gpio_get_reg(offset);
- if (reg < 0)
- return reg;
+struct axp20x_desc_pin {
+ struct pinctrl_pin_desc pin;
+ struct axp20x_desc_function *functions;
+};
- return regmap_update_bits(gpio->regmap, reg,
- AXP20X_GPIO_FUNCTIONS,
- AXP20X_GPIO_FUNCTION_INPUT);
-}
+struct axp20x_pinctrl_desc {
+ const struct axp20x_desc_pin *pins;
+ int npins;
+ unsigned int pin_base;
+};
+
+struct axp20x_pinctrl_function {
+ const char *name;
+ const char **groups;
+ unsigned int ngroups;
+};
+
+struct axp20x_pinctrl_group {
+ const char *name;
+ unsigned long config;
+ unsigned int pin;
+};
+
+struct axp20x_pctl {
+ struct pinctrl_dev *pctl_dev;
+ struct device *dev;
+ struct gpio_chip chip;
+ struct regmap *regmap;
+ const struct axp20x_pinctrl_desc *desc;
+ struct axp20x_pinctrl_group *groups;
+ unsigned int ngroups;
+ struct axp20x_pinctrl_function *functions;
+ unsigned int nfunctions;
+};
+
+static const struct axp20x_desc_pin axp209_pins[] = {
+ AXP20X_PIN(AXP20X_PINCTRL_PIN(0, "GPIO0", (void *)AXP20X_GPIO0_CTRL),
+ AXP20X_FUNCTION(0x0, "gpio_out"),
+ AXP20X_FUNCTION(0x2, "gpio_in"),
+ AXP20X_FUNCTION(0x3, "ldo"),
+ AXP20X_FUNCTION(0x4, "adc")),
+ AXP20X_PIN(AXP20X_PINCTRL_PIN(1, "GPIO1", (void *)AXP20X_GPIO1_CTRL),
+ AXP20X_FUNCTION(0x0, "gpio_out"),
+ AXP20X_FUNCTION(0x2, "gpio_in"),
+ AXP20X_FUNCTION(0x3, "ldo"),
+ AXP20X_FUNCTION(0x4, "adc")),
+ AXP20X_PIN(AXP20X_PINCTRL_PIN(2, "GPIO2", (void *)AXP20X_GPIO2_CTRL),
+ AXP20X_FUNCTION(0x0, "gpio_out"),
+ AXP20X_FUNCTION(0x2, "gpio_in")),
+};
+
+static const struct axp20x_pinctrl_desc axp20x_pinctrl_data = {
+ .pins = axp209_pins,
+ .npins = ARRAY_SIZE(axp209_pins),
+};
static int axp20x_gpio_get(struct gpio_chip *chip, unsigned offset)
{
- struct axp20x_gpio *gpio = gpiochip_get_data(chip);
+ struct axp20x_pctl *pctl = gpiochip_get_data(chip);
unsigned int val;
int ret;
- ret = regmap_read(gpio->regmap, AXP20X_GPIO20_SS, &val);
+ ret = regmap_read(pctl->regmap, AXP20X_GPIO20_SS, &val);
if (ret)
return ret;
@@ -75,15 +127,12 @@ static int axp20x_gpio_get(struct gpio_chip *chip, unsigned offset)
static int axp20x_gpio_get_direction(struct gpio_chip *chip, unsigned offset)
{
- struct axp20x_gpio *gpio = gpiochip_get_data(chip);
+ struct axp20x_pctl *pctl = gpiochip_get_data(chip);
+ int pin_reg = (int)pctl->desc->pins[offset].pin.drv_data;
unsigned int val;
- int reg, ret;
-
- reg = axp20x_gpio_get_reg(offset);
- if (reg < 0)
- return reg;
+ int ret;
- ret = regmap_read(gpio->regmap, reg, &val);
+ ret = regmap_read(pctl->regmap, pin_reg, &val);
if (ret)
return ret;
@@ -102,33 +151,335 @@ static int axp20x_gpio_get_direction(struct gpio_chip *chip, unsigned offset)
return val & 2;
}
-static int axp20x_gpio_output(struct gpio_chip *chip, unsigned offset,
+static void axp20x_gpio_set(struct gpio_chip *chip, unsigned int offset,
+ int value)
+{
+ struct axp20x_pctl *pctl = gpiochip_get_data(chip);
+ int pin_reg = (int)pctl->desc->pins[offset].pin.drv_data;
+
+ regmap_update_bits(pctl->regmap, pin_reg,
+ AXP20X_GPIO_FUNCTIONS,
+ value ? AXP20X_GPIO_FUNCTION_OUT_HIGH
+ : AXP20X_GPIO_FUNCTION_OUT_LOW);
+}
+
+static int axp20x_gpio_input(struct gpio_chip *chip, unsigned int offset)
+{
+ return pinctrl_gpio_direction_input(chip->base + offset);
+}
+
+static int axp20x_gpio_output(struct gpio_chip *chip, unsigned int offset,
int value)
{
- struct axp20x_gpio *gpio = gpiochip_get_data(chip);
- int reg;
+ chip->set(chip, offset, value);
- reg = axp20x_gpio_get_reg(offset);
- if (reg < 0)
- return reg;
+ return 0;
+}
- return regmap_update_bits(gpio->regmap, reg,
- AXP20X_GPIO_FUNCTIONS,
- value ? AXP20X_GPIO_FUNCTION_OUT_HIGH
- : AXP20X_GPIO_FUNCTION_OUT_LOW);
+static int axp20x_pmx_set(struct pinctrl_dev *pctldev, unsigned int offset,
+ u8 config)
+{
+ struct axp20x_pctl *pctl = pinctrl_dev_get_drvdata(pctldev);
+ int pin_reg = (int)pctl->desc->pins[offset].pin.drv_data;
+
+ return regmap_update_bits(pctl->regmap, pin_reg, AXP20X_GPIO_FUNCTIONS,
+ config);
}
-static void axp20x_gpio_set(struct gpio_chip *chip, unsigned offset,
- int value)
+static int axp20x_pmx_func_cnt(struct pinctrl_dev *pctldev)
+{
+ struct axp20x_pctl *pctl = pinctrl_dev_get_drvdata(pctldev);
+
+ return pctl->nfunctions;
+}
+
+static const char *axp20x_pmx_func_name(struct pinctrl_dev *pctldev,
+ unsigned int selector)
+{
+ struct axp20x_pctl *pctl = pinctrl_dev_get_drvdata(pctldev);
+
+ return pctl->functions[selector].name;
+}
+
+static int axp20x_pmx_func_groups(struct pinctrl_dev *pctldev,
+ unsigned int selector,
+ const char * const **groups,
+ unsigned int *num_groups)
+{
+ struct axp20x_pctl *pctl = pinctrl_dev_get_drvdata(pctldev);
+
+ *groups = pctl->functions[selector].groups;
+ *num_groups = pctl->functions[selector].ngroups;
+
+ return 0;
+}
+
+static struct axp20x_desc_function *
+axp20x_pinctrl_desc_find_func_by_name(struct axp20x_pctl *pctl,
+ const char *group, const char *func)
+{
+ const struct axp20x_desc_pin *pin;
+ struct axp20x_desc_function *desc_func;
+ int i;
+
+ for (i = 0; i < pctl->desc->npins; i++) {
+ pin = &pctl->desc->pins[i];
+
+ if (!strcmp(pin->pin.name, group)) {
+ desc_func = pin->functions;
+
+ while (desc_func->name) {
+ if (!strcmp(desc_func->name, func))
+ return desc_func;
+ desc_func++;
+ }
+
+ /*
+ * Pins are uniquely named. Groups are named after one
+ * pin name. If one pin matches group name but its
+ * function cannot be found, no other pin will match
+ * group name.
+ */
+ return NULL;
+ }
+ }
+
+ return NULL;
+}
+
+static int axp20x_pmx_set_mux(struct pinctrl_dev *pctldev,
+ unsigned int function, unsigned int group)
+{
+ struct axp20x_pctl *pctl = pinctrl_dev_get_drvdata(pctldev);
+ struct axp20x_pinctrl_group *g = pctl->groups + group;
+ struct axp20x_pinctrl_function *func = pctl->functions + function;
+ struct axp20x_desc_function *desc_func =
+ axp20x_pinctrl_desc_find_func_by_name(pctl, g->name,
+ func->name);
+ if (!desc_func)
+ return -EINVAL;
+
+ return axp20x_pmx_set(pctldev, g->pin, desc_func->muxval);
+}
+
+static struct axp20x_desc_function *
+axp20x_pctl_desc_find_func_by_pin(struct axp20x_pctl *pctl, unsigned int offset,
+ const char *func)
+{
+ const struct axp20x_desc_pin *pin;
+ struct axp20x_desc_function *desc_func;
+ int i;
+
+ for (i = 0; i < pctl->desc->npins; i++) {
+ pin = &pctl->desc->pins[i];
+
+ if (pin->pin.number == offset) {
+ desc_func = pin->functions;
+
+ while (desc_func->name) {
+ if (!strcmp(desc_func->name, func))
+ return desc_func;
+
+ desc_func++;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+static int axp20x_pmx_gpio_set_direction(struct pinctrl_dev *pctldev,
+ struct pinctrl_gpio_range *range,
+ unsigned int offset, bool input)
+{
+ struct axp20x_pctl *pctl = pinctrl_dev_get_drvdata(pctldev);
+ struct axp20x_desc_function *desc_func;
+ const char *func;
+
+ if (input)
+ func = "gpio_in";
+ else
+ func = "gpio_out";
+
+ desc_func = axp20x_pctl_desc_find_func_by_pin(pctl, offset, func);
+ if (!desc_func)
+ return -EINVAL;
+
+ return axp20x_pmx_set(pctldev, offset, desc_func->muxval);
+}
+
+static const struct pinmux_ops axp20x_pmx_ops = {
+ .get_functions_count = axp20x_pmx_func_cnt,
+ .get_function_name = axp20x_pmx_func_name,
+ .get_function_groups = axp20x_pmx_func_groups,
+ .set_mux = axp20x_pmx_set_mux,
+ .gpio_set_direction = axp20x_pmx_gpio_set_direction,
+ .strict = true,
+};
+
+static int axp20x_groups_cnt(struct pinctrl_dev *pctldev)
+{
+ struct axp20x_pctl *pctl = pinctrl_dev_get_drvdata(pctldev);
+
+ return pctl->ngroups;
+}
+
+static int axp20x_group_pins(struct pinctrl_dev *pctldev, unsigned int selector,
+ const unsigned int **pins, unsigned int *num_pins)
+{
+ struct axp20x_pctl *pctl = pinctrl_dev_get_drvdata(pctldev);
+ struct axp20x_pinctrl_group *g = pctl->groups + selector;
+
+ *pins = (unsigned int *)&g->pin;
+ *num_pins = 1;
+
+ return 0;
+}
+
+static const char *axp20x_group_name(struct pinctrl_dev *pctldev,
+ unsigned int selector)
+{
+ struct axp20x_pctl *pctl = pinctrl_dev_get_drvdata(pctldev);
+
+ return pctl->groups[selector].name;
+}
+
+static const struct pinctrl_ops axp20x_pctrl_ops = {
+ .dt_node_to_map = pinconf_generic_dt_node_to_map_group,
+ .dt_free_map = pinconf_generic_dt_free_map,
+ .get_groups_count = axp20x_groups_cnt,
+ .get_group_name = axp20x_group_name,
+ .get_group_pins = axp20x_group_pins,
+};
+
+static struct axp20x_pinctrl_function *
+axp20x_pinctrl_function_by_name(struct axp20x_pctl *pctl, const char *name)
+{
+ struct axp20x_pinctrl_function *func = pctl->functions;
+
+ while (func->name) {
+ if (!strcmp(func->name, name))
+ return func;
+ func++;
+ }
+
+ return NULL;
+}
+
+static int axp20x_pinctrl_add_function(struct axp20x_pctl *pctl,
+ const char *name)
{
- axp20x_gpio_output(chip, offset, value);
+ struct axp20x_pinctrl_function *func = pctl->functions;
+
+ while (func->name) {
+ if (!strcmp(func->name, name)) {
+ func->ngroups++;
+ return -EEXIST;
+ }
+
+ func++;
+ }
+
+ func->name = name;
+ func->ngroups = 1;
+
+ pctl->nfunctions++;
+
+ return 0;
}
-static int axp20x_gpio_probe(struct platform_device *pdev)
+static int axp20x_attach_group_function(struct platform_device *pdev,
+ const struct axp20x_desc_pin *pin)
+{
+ struct axp20x_pctl *pctl = platform_get_drvdata(pdev);
+ struct axp20x_desc_function *desc_func = pin->functions;
+ struct axp20x_pinctrl_function *func;
+ const char **func_grp;
+
+ while (desc_func->name) {
+ func = axp20x_pinctrl_function_by_name(pctl, desc_func->name);
+ if (!func)
+ return -EINVAL;
+
+ if (!func->groups) {
+ func->groups = devm_kzalloc(&pdev->dev,
+ func->ngroups * sizeof(const char *),
+ GFP_KERNEL);
+ if (!func->groups)
+ return -ENOMEM;
+ }
+
+ func_grp = func->groups;
+ while (*func_grp)
+ func_grp++;
+
+ *func_grp = pin->pin.name;
+ desc_func++;
+ }
+
+ return 0;
+}
+
+static int axp20x_build_state(struct platform_device *pdev)
+{
+ struct axp20x_pctl *pctl = platform_get_drvdata(pdev);
+ unsigned int npins = pctl->desc->npins;
+ const struct axp20x_desc_pin *pin;
+ struct axp20x_desc_function *func;
+ int i, ret;
+
+ pctl->ngroups = npins;
+ pctl->groups = devm_kzalloc(&pdev->dev,
+ pctl->ngroups * sizeof(*pctl->groups),
+ GFP_KERNEL);
+ if (!pctl->groups)
+ return -ENOMEM;
+
+ for (i = 0; i < npins; i++) {
+ pctl->groups[i].name = pctl->desc->pins[i].pin.name;
+ pctl->groups[i].pin = pctl->desc->pins[i].pin.number;
+ }
+
+ /* We assume 4 functions per pin should be enough as a default max */
+ pctl->functions = devm_kzalloc(&pdev->dev,
+ npins * 4 * sizeof(*pctl->functions),
+ GFP_KERNEL);
+ if (!pctl->functions)
+ return -ENOMEM;
+
+ /* Create a list of uniquely named functions */
+ for (i = 0; i < npins; i++) {
+ pin = &pctl->desc->pins[i];
+ func = pin->functions;
+
+ while (func->name) {
+ axp20x_pinctrl_add_function(pctl, func->name);
+ func++;
+ }
+ }
+
+ pctl->functions = krealloc(pctl->functions,
+ pctl->nfunctions * sizeof(*pctl->functions),
+ GFP_KERNEL);
+
+ for (i = 0; i < npins; i++) {
+ pin = &pctl->desc->pins[i];
+ ret = axp20x_attach_group_function(pdev, pin);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int axp20x_pctl_probe(struct platform_device *pdev)
{
struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent);
- struct axp20x_gpio *gpio;
- int ret;
+ const struct axp20x_desc_pin *pin;
+ struct axp20x_pctl *pctl;
+ struct pinctrl_desc *pctrl_desc;
+ struct pinctrl_pin_desc *pins;
+ int ret, i;
if (!of_device_is_available(pdev->dev.of_node))
return -ENODEV;
@@ -138,51 +489,101 @@ static int axp20x_gpio_probe(struct platform_device *pdev)
return -EINVAL;
}
- gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL);
- if (!gpio)
+ pctl = devm_kzalloc(&pdev->dev, sizeof(*pctl), GFP_KERNEL);
+ if (!pctl)
+ return -ENOMEM;
+
+ pctl->chip.base = -1;
+ pctl->chip.can_sleep = true;
+ pctl->chip.request = gpiochip_generic_request;
+ pctl->chip.free = gpiochip_generic_free;
+ pctl->chip.parent = &pdev->dev;
+ pctl->chip.label = dev_name(&pdev->dev);
+ pctl->chip.owner = THIS_MODULE;
+ pctl->chip.get = axp20x_gpio_get;
+ pctl->chip.get_direction = axp20x_gpio_get_direction;
+ pctl->chip.set = axp20x_gpio_set;
+ pctl->chip.direction_input = axp20x_gpio_input;
+ pctl->chip.direction_output = axp20x_gpio_output;
+ pctl->chip.ngpio = 3;
+ pctl->chip.can_sleep = true;
+
+ pctl->regmap = axp20x->regmap;
+
+ pctl->desc = &axp20x_pinctrl_data;
+ pctl->dev = &pdev->dev;
+
+ platform_set_drvdata(pdev, pctl);
+
+ ret = axp20x_build_state(pdev);
+ if (ret)
+ return ret;
+
+ pins = devm_kzalloc(&pdev->dev, pctl->desc->npins * sizeof(*pins),
+ GFP_KERNEL);
+ if (!pins)
return -ENOMEM;
- gpio->chip.base = -1;
- gpio->chip.can_sleep = true;
- gpio->chip.parent = &pdev->dev;
- gpio->chip.label = dev_name(&pdev->dev);
- gpio->chip.owner = THIS_MODULE;
- gpio->chip.get = axp20x_gpio_get;
- gpio->chip.get_direction = axp20x_gpio_get_direction;
- gpio->chip.set = axp20x_gpio_set;
- gpio->chip.direction_input = axp20x_gpio_input;
- gpio->chip.direction_output = axp20x_gpio_output;
- gpio->chip.ngpio = 3;
-
- gpio->regmap = axp20x->regmap;
-
- ret = devm_gpiochip_add_data(&pdev->dev, &gpio->chip, gpio);
+ for (i = 0; i < pctl->desc->npins; i++)
+ pins[i] = pctl->desc->pins[i].pin;
+
+ pctrl_desc = devm_kzalloc(&pdev->dev, sizeof(*pctrl_desc), GFP_KERNEL);
+ if (!pctrl_desc)
+ return -ENOMEM;
+
+ pctrl_desc->name = dev_name(&pdev->dev);
+ pctrl_desc->owner = THIS_MODULE;
+ pctrl_desc->pins = pins;
+ pctrl_desc->npins = pctl->desc->npins;
+ pctrl_desc->pctlops = &axp20x_pctrl_ops;
+ pctrl_desc->pmxops = &axp20x_pmx_ops;
+
+ pctl->pctl_dev = devm_pinctrl_register(&pdev->dev, pctrl_desc, pctl);
+ if (IS_ERR(pctl->pctl_dev)) {
+ dev_err(&pdev->dev, "couldn't register pinctrl driver\n");
+ return PTR_ERR(pctl->pctl_dev);
+ }
+
+ ret = devm_gpiochip_add_data(&pdev->dev, &pctl->chip, pctl);
if (ret) {
dev_err(&pdev->dev, "Failed to register GPIO chip\n");
return ret;
}
+ for (i = 0; i < pctl->desc->npins; i++) {
+ pin = pctl->desc->pins + i;
+
+ ret = gpiochip_add_pin_range(&pctl->chip, dev_name(&pdev->dev),
+ pin->pin.number, pin->pin.number,
+ 1);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to add pin range\n");
+ return ret;
+ }
+ }
+
dev_info(&pdev->dev, "AXP209 GPIO driver loaded\n");
return 0;
}
-static const struct of_device_id axp20x_gpio_match[] = {
+static const struct of_device_id axp20x_pctl_match[] = {
{ .compatible = "x-powers,axp209-gpio" },
{ }
};
-MODULE_DEVICE_TABLE(of, axp20x_gpio_match);
+MODULE_DEVICE_TABLE(of, axp20x_pctl_match);
-static struct platform_driver axp20x_gpio_driver = {
- .probe = axp20x_gpio_probe,
+static struct platform_driver axp20x_pctl_driver = {
+ .probe = axp20x_pctl_probe,
.driver = {
.name = "axp20x-gpio",
- .of_match_table = axp20x_gpio_match,
+ .of_match_table = axp20x_pctl_match,
},
};
-module_platform_driver(axp20x_gpio_driver);
+module_platform_driver(axp20x_pctl_driver);
MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>");
+MODULE_AUTHOR("Quentin Schulz <quentin.schulz@free-electrons.com>");
MODULE_DESCRIPTION("AXP20x PMIC GPIO driver");
MODULE_LICENSE("GPL");
--
2.9.3
^ permalink raw reply related
* [PATCH 1/2] i2c: designware: report short transfers
From: Jarkko Nikula @ 2016-11-23 14:13 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161121103200.GG1446@lahna.fi.intel.com>
On 21.11.2016 12:32, Mika Westerberg wrote:
> On Fri, Nov 18, 2016 at 07:40:04PM +0000, Russell King wrote:
>> Rather than reporting success for a short transfer due to interrupt
>> latency, report an error both to the caller, as well as to the kernel
>> log.
>>
>> Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
>
> Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com>
>
Acked-by: Jarkko Nikula <jarkko.nikula@linux.intel.com>
^ permalink raw reply
* [PATCH 2/2] i2c: designware: fix rx fifo depth tracking
From: Jarkko Nikula @ 2016-11-23 14:13 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161121104032.GH1446@lahna.fi.intel.com>
On 21.11.2016 12:40, Mika Westerberg wrote:
> On Fri, Nov 18, 2016 at 07:40:10PM +0000, Russell King wrote:
>> When loading the TX fifo to receive bytes on the I2C bus, we incorrectly
>> count the number of bytes:
>>
>> rx_limit = dev->rx_fifo_depth - dw_readl(dev, DW_IC_RXFLR);
>>
>> while (buf_len > 0 && tx_limit > 0 && rx_limit > 0) {
>> if (rx_limit - dev->rx_outstanding <= 0)
>> break;
>> rx_limit--;
>> dev->rx_outstanding++;
>> }
>>
>> DW_IC_RXFLR indicates how many bytes are available to be read in the
>> FIFO, dev->rx_fifo_depth is the FIFO size, and dev->rx_outstanding is
>> the number of bytes that we've requested to be read so far, but which
>> have not been read.
>>
>> Firstly, increasing dev->rx_outstanding and decreasing rx_limit and then
>> comparing them results in each byte consuming "two" bytes in this
>> tracking, so this is obviously wrong.
>>
>> Secondly, the number of bytes that _could_ be received into the FIFO at
>> any time is the number of bytes we have so far requested but not yet
>> read from the FIFO - in other words dev->rx_outstanding.
>>
>> So, in order to request enough bytes to fill the RX FIFO, we need to
>> request dev->rx_fifo_depth - dev->rx_outstanding bytes.
>>
>> Modifying the code thusly results in us reaching the maximum number of
>> bytes outstanding each time we queue more "receive" operations, provided
>> the transfer allows that to happen.
>>
>> Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
>
> Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com>
>
Acked-by: Jarkko Nikula <jarkko.nikula@linux.intel.com>
^ permalink raw reply
* [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
From: Arnd Bergmann @ 2016-11-23 14:16 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <EE11001F9E5DDD47B7634E2F8A612F2E1F921A0F@lhreml507-mbx>
On Friday, November 18, 2016 5:03:11 PM CET Gabriele Paoloni wrote:
> > On Friday, November 18, 2016 4:18:07 PM CET Gabriele Paoloni wrote:
> > > From: Arnd Bergmann [mailto:arnd at arndb.de]
> > > > On Friday, November 18, 2016 12:53:08 PM CET Gabriele Paoloni
> > wrote:
> > > > For the ISA/LPC spaces there are only 4k of addresses, they
> > > > the bus addresses always overlap, but we can trivially
> > > > figure out the bus address from Linux I/O port number
> > > > by subtracting the start of the range.
> > >
> > > Are you saying that our LPC controller should specify a
> > > range property to map bus addresses into a cpu address range?
> >
> > No. There is not CPU address associated with it, because it's
> > not memory mapped.
> >
> > Instead, we need to associate a bus address with a logical
> > Linux port number, both in of_address_to_resource and
> > in inb()/outb().
>
> I think this is effectively what we are doing so far with patch 2/3.
> The problem with this patch is that we are carving out a "forbidden"
> IO tokens range that goes from 0 to PCIBIOS_MIN_IO.
>
> I think that the proper solution would be to have the LPC driver to
> set the carveout threshold used in pci_register_io_range(),
> pci_pio_to_address(), pci_address_to_pio(), but this would impose
> a probe dependency on the LPC itself that should be probed before
> the PCI controller (or before any other devices calling these
> functions...)
Why do you think the order matters? My point was that we should
be able to register any region of logical port numbers for any
bus here.
> > > > > To be honest with you I would keep things simple for this
> > > > > LPC and introduce more complex reworks later if more devices
> > > > > need to be introduced.
> > > > >
> > > > > What if we stick on a single domain now where we introduce a
> > > > > reserved threshold for the IO space (say INDIRECT_MAX_IO).
> > > >
> > > > I said having a single domain is fine, but I still don't
> > > > like the idea of reserving low port numbers for this hack,
> > > > it would mean that the numbers change for everyone else.
> > >
> > > I don't get this much...I/O tokens that are passed to the I/O
> > > accessors are not fixed anyway and they vary depending on the order
> > > of adding ranges to io_range_list...so I don't see a big issue
> > > with this...
> >
> > On machines with a legacy devices behind the PCI bridge,
> > there may still be a reason to have the low I/O port range
> > reserved for the primary bus, e.g. to get a VGA text console
> > to work.
> >
> > On powerpc, this is called the "primary" PCI host, i.e. the
> > only one that is allowed to have an ISA bridge.
>
> Yes but
> 1) isn't the PCI controller range property that defines how IO bus address
> map into physical CPU addresses?
Correct, but the DT knows nothing about logical port numbers in Linux.
> 2) How can you guarantee that the cpu range associated with this
> IO bus range is the first to be registered in pci_register_io_range()?
> ( i.e. are you saying that they are just relying on the fact that it is the
> only IO range in the system and by chance the IO tokens and corresponding
> bus addresses are the same? )
To clarify: the special properties of having the first 0x1000 logical
port numbers go to a particular physical bus are very obscure. I think
it's more important to not change the behavior for existing systems
that might rely on it than for new systems that have no such legacy.
The ipmi and uart drivers in particular will get the port numbers filled
in their platform device from the DT bus scanning, so they don't care
at all about having the same numeric value for port numbers on the bus
and logical numbers, but other drivers might rely on particular ports
to be mapped on a specific PCI host, especially when those drivers
are used only on systems that don't have more than one PCI domain.
Arnd
^ permalink raw reply
* [GIT PULL] Second Round of Renesas ARM Based SoC DT Updates for v4.10
From: Simon Horman @ 2016-11-23 14:16 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161123095717.GA16339@verge.net.au>
On Wed, Nov 23, 2016 at 10:57:18AM +0100, Simon Horman wrote:
> On Mon, Nov 21, 2016 at 11:53:18AM +0100, Simon Horman wrote:
> > On Fri, Nov 18, 2016 at 05:49:29PM -0800, Olof Johansson wrote:
> > > On Thu, Nov 17, 2016 at 03:11:45PM +0100, Simon Horman wrote:
> > > > Hi Olof, Hi Kevin, Hi Arnd,
> > > >
> > > > Please consider these second round of Renesas ARM based SoC DT updates for v4.10.
> > > >
> > > > This pull request is based on a merge of:
> > > >
> > > > * The previous round of such requests, tagged as renesas-dt-for-v4.10,
> > > > which I have already sent a pull-request for.
> > > > * The rzg-clock-defs tag of Geert Uytterhoeven's renesas-driver's tree.
> > > > This is to provide dependencies for adding the r8a7743 and r8a7745 SoCs.
> > > > * The "Second Round of Renesas ARM Based SoC Drivers Updates for v4.10",
> > > > tagged as renesas-drivers2-for-v4.10, which I have also sent a pull
> > > > request for. This is included to provide dependencies for adding device
> > > > nodes for PRR, and adding the r8a7743 and r8a7745 SoCs.
> > >
> > > Again, nack. And again, I don't understand why you create dependencies that
> > > aren't needed. Please fix.
> >
> > Hi Olof,
> >
> > I agree that calling out PRR above was incorrect. Please disregard that.
> >
> > However, there are dependencies for adding r8a7743 and r8a7745 SoCs
> > in the form of header files:
> >
> > * The rzg-clock-defs tag provides dt-bindings/clock/r8a774[35]-cpg-mssr.h
> > * The renesas-drivers2-for-v4.10 tag provides
> > dt-bindings/power/r8a774[35]-sysc.h
> >
> > The drivers branches are usually pretty light-weight. But this time it is a
> > bit heavy and you rightly raised some questions about it. After some
> > discussion with Geert we'd like to suggest that for future releases
> > we provide a "driver-defs" branch which both driver code and DT can
> > depend on. Thus avoiding pulling (non essential) driver changes into the DT
> > branch.
> >
> > Unfortunately its a bit late to do that for v4.10 as the r8a7743 sysc
> > driver and its defines were already accepted accepted together
> > (renesas-drivers-for-v4.10 tag). So for this release we would be grateful
> > if you could re-consider the renesas-drivers2-for-v4.10 tag given the
> > feedback which Geert has provided. And in turn re-consider this pull
> > request.
>
> Hi again,
>
> while the above remains my preferred option I would like to put another one
> on the table in case it would help in any way for v4.10.
>
> I could split this pull-request up as follows:
> 1. The patches that add the r8a774[35] SoCs:
> - r8a7743 depends on renesas-drivers-for-v4.10 and rzg-clock-defs
> - r8a7745 depends on renesas-drivers2-for-v4.10 and rzg-clock-defs
> 2. The patches rest of the patches
> - I believe these have no special dependencies
After some discussion on IRC with Arnd I think it makes sense to simplify
the dependencies pulled in to this pull request to the extent of
only pulling in patches which provide headers for macros used in DT.
I am working on making this so.
^ permalink raw reply
* [PATCH 0/2] ARM: dts: r8a7743/r8a7745: Move RST nodes before SYSC nodes
From: Simon Horman @ 2016-11-23 14:18 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1479464663-19054-1-git-send-email-geert+renesas@glider.be>
On Fri, Nov 18, 2016 at 11:24:21AM +0100, Geert Uytterhoeven wrote:
> Hi Simon, Magnus,
>
> This patch series moves the RST nodes in the recently added RZ/G DTS
> files before the SYSC nodes, to preserve both alphabetical (label) and
> numerical ordering (unit address).
>
> Thanks for applying!
Thanks, I have queued these up for v4.11.
^ permalink raw reply
* [PATCH] drm/sun4i: Only count TCON endpoints as valid outputs
From: Chen-Yu Tsai @ 2016-11-23 14:19 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161122153730.nj5fl34oleu2uylz@lukather>
On Tue, Nov 22, 2016 at 11:37 PM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> Hi,
>
> On Fri, Nov 18, 2016 at 10:22:40AM +0800, Chen-Yu Tsai wrote:
>> On Fri, Nov 18, 2016 at 3:02 AM, Maxime Ripard
>> <maxime.ripard@free-electrons.com> wrote:
>> > On Wed, Nov 16, 2016 at 05:37:31PM +0800, Chen-Yu Tsai wrote:
>> >> The sun4i DRM driver counts the number of endpoints it found and
>> >> registers the whole DRM pipeline if any endpoints are found.
>> >>
>> >> However, if the TCON and its child endpoints (LCD panels, TV encoder,
>> >> HDMI encoder, MIPI DSI encoder, etc.) aren't found, that means we
>> >> don't have any usable CRTCs, and the display pipeline is incomplete
>> >> and useless.
>> >
>> > If some node set as available is not probed, then yes, it does, but
>> > I'm not really sure how it's a problem. Quite the opposite actually.
>>
>> Actually the problem occurs when the TCON is _not_ available, but
>> the other endpoints preceding it are.
>
> By preceding, you mean the display engine or the HDMI or TV encoders?
The display engine.
>> >> The debug message "Queued %d outputs on pipeline %d\n" is also telling.
>> >>
>> >> This patch makes the driver only count enabled TCON endpoints. If
>> >> none are found, the DRM pipeline is not used. This avoids screwing
>> >> up the simple framebuffer provided by the bootloader in cases where
>> >> we aren't able to support the display with the DRM subsystem, due
>> >> to lack of panel or bridge drivers, or just lack of progress.
>> >
>> > The framebuffer is removed only at bind time, which means that all the
>> > drivers have probed already. Lack of progress isn't an issue here,
>> > since the node simply won't be there, and we wouldn't have it in the
>> > component lists. And lack of drivers shouldn't be an issue either,
>> > since in order for bind to be called, all the drivers would have
>> > gone through their probe.
>> >
>> > So I'm not really sure what it fixes.
>>
>> To recap, on sun6i I had enabled the display engine node by default
>> in the dtsi, along with the backend and drc. The tcon is disabled
>> by default, so it doesn't get added to the list of components.
>> The available components get probed, binded, and simplefb gets
>> pushed out.
>>
>> I suppose disabling the display engine by default would be better?
>> At least simplefb still works.
>
> Yep, that works for me.
OK. I'll send out a patch.
ChenYu
^ permalink raw reply
* [PATCH 0/2] ARM: dts: r8a7743/r8a7745: Add device nodes for PRR
From: Simon Horman @ 2016-11-23 14:19 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1479465463-19572-1-git-send-email-geert+renesas@glider.be>
On Fri, Nov 18, 2016 at 11:37:41AM +0100, Geert Uytterhoeven wrote:
> Hi Simon, Magnus,
>
> This patch series adds the device nodes for the Product Register to the
> recently added RZ/G DTS files, which allow to provide SoC product
> and revision information.
>
> This depends on "[PATCH 0/2] ARM: dts: r8a7743/r8a7745: Move RST nodes
> before SYSC nodes".
Thanks, I have queued these up for v4.11.
^ permalink raw reply
* [PATCH] arm64: dts: r8a7796: Add all MSIOF nodes
From: Simon Horman @ 2016-11-23 14:23 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1479749213-13744-1-git-send-email-geert+renesas@glider.be>
On Mon, Nov 21, 2016 at 06:26:53PM +0100, Geert Uytterhoeven wrote:
> Add the device nodes for all MSIOF SPI controllers.
>
> Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
> ---
> Tested with MSIOF2(B) on EXIO connector D of r8a7796/salvator-x, using
> spidev, gpio-74x164, and a logic analyzer.
Thanks, I have queued this up for v4.11.
^ permalink raw reply
* [PATCH 2/4] ARM: dts: exynos: specify snps, dwmac in compatible string for gmac
From: Niklas Cassel @ 2016-11-23 14:24 UTC (permalink / raw)
To: linux-arm-kernel
From: Niklas Cassel <niklas.cassel@axis.com>
devicetree binding for stmmac states:
- compatible: Should be "snps,dwmac-<ip_version>", "snps,dwmac"
For backwards compatibility: "st,spear600-gmac" is also supported.
No functional change intended.
Signed-off-by: Niklas Cassel <niklas.cassel@axis.com>
---
arch/arm/boot/dts/exynos5440.dtsi | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm/boot/dts/exynos5440.dtsi b/arch/arm/boot/dts/exynos5440.dtsi
index 97c9f0e38526..2a2e570bbee6 100644
--- a/arch/arm/boot/dts/exynos5440.dtsi
+++ b/arch/arm/boot/dts/exynos5440.dtsi
@@ -197,7 +197,7 @@
};
gmac: ethernet at 00230000 {
- compatible = "snps,dwmac-3.70a";
+ compatible = "snps,dwmac-3.70a", "snps,dwmac";
reg = <0x00230000 0x8000>;
interrupt-parent = <&gic>;
interrupts = <GIC_SPI 31 4>;
--
2.1.4
^ 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