* Re: [RFC] New Device Tree property - "bonding"
From: Geert Uytterhoeven @ 2016-12-15 9:07 UTC (permalink / raw)
To: Ramesh Shanmugasundaram
Cc: Rob Herring, Laurent Pinchart, frowand.list@gmail.com,
mark.rutland@arm.com, pantelis.antoniou@konsulko.com,
Chris Paterson, Geert Uytterhoeven,
laurent.pinchart+renesas@ideasonboard.com,
devicetree@vger.kernel.org, linux-renesas-soc@vger.kernel.org,
Maxime Ripard
In-Reply-To: <SG2PR06MB1038FDD0F2C70D6CB0AED298C3820@SG2PR06MB1038.apcprd06.prod.outlook.com>
On Tue, Dec 6, 2016 at 6:45 PM, Ramesh Shanmugasundaram
<ramesh.shanmugasundaram@bp.renesas.com> wrote:
>> >> On Monday 05 Dec 2016 09:57:32 Rob Herring wrote:
>> >> > On Mon, Dec 5, 2016 at 8:40 AM, Laurent Pinchart wrote:
>> >> > > On Monday 05 Dec 2016 08:18:34 Rob Herring wrote:
>> >> > >> On Fri, Nov 25, 2016 at 10:55 AM, Ramesh Shanmugasundaram wrote:
>> >> > >>> Hello DT maintainers,
>> >> > >>>
>> >> > >>> In one of the Renesas SoCs we have a device called DRIF
>> >> > >>> (Digital Radio
>> >> > >>> Interface) controller. A DRIF channel contains 4 external pins
>> >> > >>> - SCK, SYNC, Data pins D0 & D1.
>> >> > >>>
>> >> > >>> Internally a DRIF channel is made up of two SPI slave devices
>> >> > >>> (also called sub-channels here) that share common CLK & SYNC
>> >> > >>> signals but have their own resource set. The DRIF channel can
>> >> > >>> have either one of the sub-channel active at a time or both.
>> >> > >>> When both sub-channels are active, they need to be managed
>> >> > >>> together as one device as they share same CLK & SYNC. We plan
>> >> > >>> to tie these two sub-channels together with a new property called
>> "renesas,bonding".
>> >> > >>
>> >> > >> Is there no need to describe the master device? No GPIOs,
>> >> > >> regulators or other sideband controls needed? If that's never
>> >> > >> needed (which seems doubtful), then I would do something
>> >> > >> different here probably with the master device as a child of one
>> >> > >> DRIF and then phandles to master from the other DRIFs.
>> >> > >> Otherwise, this looks
>> >> fine to me.
>> >> > >
>> >> > > Here's a bit of background.
>> >> > >
>> >> > > The DRIF is an SPI receiver. It has three input pins, a clock
>> >> > > line, a data line and a sync signal. The device is designed to be
>> >> > > connected to a variety of data sources, usually plain SPI (1 data
>> >> > > line), IIS (1 data
>> >> > > line) but also radio tuners that output I/Q data
>> >> > > (http://www.ni.com/tutorial/4805/en/) over two data lines.
>> >> > >
>> >> > > In the case of IQ each data sample is split in two I and Q values
>> >> > > (typically 16 to 20 bits each in this case), and the values are
>> >> > > transmitted serially over one data line each. The synchronization
>> >> > > and clock signals are common to both data lines. The DRIF is
>> >> > > optimized for this use case as the DRIF instances in the SoC
>> >> > > (each of them having independent clocks, interrupts and control
>> >> > > registers) are grouped by two, and the two instances in a group
>> >> > > handle a single data line each but share the same clock and sync
>> input.
>> >> > >
>> >> > > On the software side we need to group the I and Q values, which
>> >> > > are DMA'ed to memory by the two DRIF instances, and make them
>> >> > > available to userspace. The V4L2 API used here in SDR (Software
>> >> > > Defined Radio) mode supports such use cases and exposes a single
>> >> > > device node to userspace that allows control of the two DRIF
>> >> > > instances as a single device. To be able to implement this we
>> >> > > need kernel code to be aware of DRIF groups and, while binding to
>> >> > > the DRIF instances separately, expose only one V4L2 device to
>> userspace for each group.
>> >> > >
>> >> > > There's no master or slave instance from a hardware point of
>> >> > > view, but the two instances are not interchangeable as they carry
>> >> > > separate
>> >> information.
>> >> > > They must thus be identified at the driver level.
>> >> >
>> >> > By master, I meant the external master device that generates the IQ
>> >> > data, not which of the internal DRIF blocks is a master of the other.
>> >> > So back to my question, does the external master device need to be
>> >> > described? I worry the answer now for a simple case is no, but then
>> >> > later people are going to have cases needing to describe more. We
>> >> > need to answer this question first before we can decide what this
>> >> > binding should look like.
>> >>
>> >> Oh yes the external device certainly needs to be described. As it is
>> >> controlled through a separate, general-purpose I2C or SPI controller,
>> >> it should be a child node of that controller. The DRIF handles the
>> >> data interface only, not the control interface of the external device.
>> >
>> > Yes, as Laurent mentioned, the external master will be described
>> separately. The data interface with the master is described through port
>> nodes. E.g.
>> >
>> > port {
>> > drif0_ep: endpoint {
>> > remote-endpoint = <&tuner_ep>;
>> > };
>> > };
>> >
>> > Do we agree on this model please?
>>
>> Well, that's not complete as you should have both DRIF0 and DRIF1 having
>> connections to the tuner. Then you can walk the graph and find everything,
>> and you then don't need the bonding property.
>
> Assuming the third party tuner exposes it's two data lines as two endpoints, it seems possible with of_graph.h apis to walk through tuner end points and get the phandle of the other DRIF device. However, there are couple of points coming to mind.
>
> - The ctrl pins shared between two DRIFs needs to be enabled in one of the DRIF device. Do we choose this device arbitrarily? Do we expose the CTRL signal properties (msb/lsb first, polarity etc) on both DRIF devices? Should we think about scalability?
>
> - It mandates the third party tuner device to expose it's two data lines as two endpoints. It assumes that a single third party master device controls both the data lines coming to each DRIF device.
>
> The bonding property looks a bit cleaner on these aspects because it describes only the DRIF device.
Does of_graph and endpoints need to be mandatory?
I can easily imagine using a single DRIF device as a receive-only MSIOF SPI
slave, without a tuner connected.
Cfr. spi-slave-system-control from my SPI skave mode support series
(https://lwn.net/Articles/700433/).
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@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
* Re: [PATCH v2 0/7] ath9k: EEPROM swapping improvements
From: Valo, Kalle @ 2016-12-15 8:34 UTC (permalink / raw)
To: Martin Blumenstingl
Cc: ath9k-devel,
linux-wireless-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
ath9k-devel-xDcbHBWguxHbcTqmT+pZeQ@public.gmane.org,
devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
arnd-r2nGTMty4D4@public.gmane.org,
chunkeey-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org,
nbd-Vt+b4OUoWG0@public.gmane.org
In-Reply-To: <20161002222913.12223-1-martin.blumenstingl-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>
Martin Blumenstingl <martin.blumenstingl-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org> writes:
> There are two types of swapping the EEPROM data in the ath9k driver.
> Before this series one type of swapping could not be used without the
> other.
>
> The first type of swapping looks at the "magic bytes" at the start of
> the EEPROM data and performs swab16 on the EEPROM contents if needed.
> The second type of swapping is EEPROM format specific and swaps
> specific fields within the EEPROM itself (swab16, swab32 - depends on
> the EEPROM format).
>
> With this series the second part now looks at the EEPMISC register
> inside the EEPROM, which uses a bit to indicate if the EEPROM data
> is Big Endian (this is also done by the FreeBSD kernel).
> This has a nice advantage: currently there are some out-of-tree hacks
> (in OpenWrt and LEDE) where the EEPROM has a Big Endian header on a
> Big Endian system (= no swab16 is performed) but the EEPROM itself
> indicates that it's data is Little Endian. Until now the out-of-tree
> code simply did a swab16 before passing the data to ath9k, so ath9k
> first did the swab16 - this also enabled the format specific swapping.
> These out-of-tree hacks are still working with the new logic, but it
> is recommended to remove them. This implementation is based on a
> discussion with Arnd Bergmann who raised concerns about the
> robustness and portability of the swapping logic in the original OF
> support patch review, see [0].
>
> After a second round of patches (= v1 of this series) neither Arnd
> Bergmann nor I were really happy with the complexity of the EEPROM
> swapping logic. Based on a discussion (see [1] and [2]) we decided
> that ath9k should use a defined format (specifying the endianness
> of the data - I went with __le16 and __le32) when accessing the
> EEPROM fields. A benefit of this is that we enable the EEPMISC based
> swapping logic by default, just like the FreeBSD driver, see [3]. On
> the devices which I have tested (see below) ath9k now works without
> having to specify the "endian_check" field in ath9k_platform_data (or
> a similar logic which could provide this via devicetree) as ath9k now
> detects the endianness automatically. Only EEPROMs which are mangled
> by some out-of-tree code still need the endian_check flag (or one can
> simply remove that mangling from the out-of-tree code).
>
> Testing:
> - tested by myself on AR9287 with Big Endian EEPROM
> - tested by myself on AR9227 with Little Endian EEPROM
> - tested by myself on AR9381 (using the ar9003_eeprom implementation,
> which did not suffer from this whole problem)
> - how do we proceed with testing? maybe we could keep this in a
> feature-branch and add these patches to LEDE once we have an ACK to
> get more people to test this
>
> This series depends on my other series (v7):
> "add devicetree support to ath9k" - see [4]
>
> Changes since v1:
> - reworked description in the cover-letter to describe the reasons
> behind the new patch 7
> - reworked patch "Set the "big endian" bit of the AR9003 EEPROM
> templates" as ar9003_eeprom.c sets all values as Little Endian, thus
> the Big Endian bit should never be set (the new patch makes this
> clear)
> - dropped "ath9k: Make EEPROM endianness swapping configurable via
> devicetree" as it is not needed anymore with the new logic from
> patch 7
> - added patches 4 and 5 as small cleanup (this made it easier to
> implement the le{16,32}_to_cpu() changes where needed)
>
>
> [0] http://www.spinics.net/lists/linux-wireless/msg152634.html
> [1] https://marc.info/?l=linux-wireless&m=147250597503174&w=2
> [2] https://marc.info/?l=linux-wireless&m=147254388611344&w=2
> [3] https://github.com/freebsd/freebsd/blob/50719b56d9ce8d7d4beb53b16e9edb2e9a4a7a18/sys/dev/ath/ath_hal/ah_eeprom_9287.c#L351
> [4] https://marc.info/?l=linux-wireless&m=147544488619822&w=2
>
> Martin Blumenstingl (7):
> ath9k: Add a #define for the EEPROM "eepmisc" endianness bit
> ath9k: indicate that the AR9003 EEPROM template values are little
> endian
> ath9k: Add an eeprom_ops callback for retrieving the eepmisc value
> ath9k: replace eeprom_param EEP_MINOR_REV with get_eeprom_rev
> ath9k: consistently use get_eeprom_rev(ah)
> ath9k: Make the EEPROM swapping check use the eepmisc register
> ath9k: define all EEPROM fields in Little Endian format
Applied to ath-next on ath.git, thanks.
(My automatic "accepted" email failed, so had to send this manually.)
--
Kalle Valo--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH 3/3] Bluetooth: btusb: Configure Marvel to use one of the pins for oob wakeup
From: Gregory CLEMENT @ 2016-12-15 8:29 UTC (permalink / raw)
To: Rajat Jain
Cc: Rob Herring, Mark Rutland, Marcel Holtmann, Gustavo Padovan,
Johan Hedberg, Amitkumar Karwar, Wei-Ning Huang, Xinming Hu,
netdev-u79uwXL29TY76Z2rM5mHXA, devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-bluetooth-u79uwXL29TY76Z2rM5mHXA, Brian Norris,
rajatxjain-Re5JQEeQqe8AvxtiuMwx3w
In-Reply-To: <1481742779-15105-3-git-send-email-rajatja-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org>
Hi Rajat,
On mer., déc. 14 2016, Rajat Jain <rajatja-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org> wrote:
In your title unless you speak about the comic books you should do a
s/Marvel/Marvell/ :)
Gregory
> The Marvell devices may have many gpio pins, and hence for wakeup
> on these out-of-band pins, the chip needs to be told which pin is
> to be used for wakeup, using an hci command.
>
> Thus, we read the pin number etc from the device tree node and send
> a command to the chip.
>
> Signed-off-by: Rajat Jain <rajatja-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org>
> ---
> Note that while I would have liked to name the compatible string as more
> like "marvell, usb8997-bt", the devicetrees/bindings/usb/usb-device.txt
> requires the compatible property to be of the form "usbVID,PID".
>
> .../{marvell-bt-sd8xxx.txt => marvell-bt-8xxx.txt} | 25 ++++++++-
> drivers/bluetooth/btusb.c | 59 ++++++++++++++++++++++
> 2 files changed, 82 insertions(+), 2 deletions(-)
> rename Documentation/devicetree/bindings/net/{marvell-bt-sd8xxx.txt => marvell-bt-8xxx.txt} (76%)
>
> diff --git a/Documentation/devicetree/bindings/net/marvell-bt-sd8xxx.txt b/Documentation/devicetree/bindings/net/marvell-bt-8xxx.txt
> similarity index 76%
> rename from Documentation/devicetree/bindings/net/marvell-bt-sd8xxx.txt
> rename to Documentation/devicetree/bindings/net/marvell-bt-8xxx.txt
> index 6a9a63c..471bef8 100644
> --- a/Documentation/devicetree/bindings/net/marvell-bt-sd8xxx.txt
> +++ b/Documentation/devicetree/bindings/net/marvell-bt-8xxx.txt
> @@ -1,4 +1,4 @@
> -Marvell 8897/8997 (sd8897/sd8997) bluetooth SDIO devices
> +Marvell 8897/8997 (sd8897/sd8997) bluetooth devices (SDIO or USB based)
> ------
>
> Required properties:
> @@ -6,11 +6,13 @@ Required properties:
> - compatible : should be one of the following:
> * "marvell,sd8897-bt"
> * "marvell,sd8997-bt"
> + * "usb1286,204e"
>
> Optional properties:
>
> - marvell,cal-data: Calibration data downloaded to the device during
> initialization. This is an array of 28 values(u8).
> + This is only applicable to SDIO devices.
>
> - marvell,wakeup-pin: It represents wakeup pin number of the bluetooth chip.
> firmware will use the pin to wakeup host system (u16).
> @@ -29,7 +31,9 @@ Example:
> IRQ pin 119 is used as system wakeup source interrupt.
> wakeup pin 13 and gap 100ms are configured so that firmware can wakeup host
> using this device side pin and wakeup latency.
> -calibration data is also available in below example.
> +
> +Example for SDIO device follows (calibration data is also available in
> +below example).
>
> &mmc3 {
> status = "okay";
> @@ -54,3 +58,20 @@ calibration data is also available in below example.
> marvell,wakeup-gap-ms = /bits/ 16 <0x64>;
> };
> };
> +
> +Example for USB device:
> +
> +&usb_host1_ohci {
> + status = "okay";
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + mvl_bt1: bt@1 {
> + compatible = "usb1286,204e";
> + reg = <1>;
> + interrupt-parent = <&gpio0>;
> + interrupts = <119 IRQ_TYPE_LEVEL_LOW>;
> + marvell,wakeup-pin = /bits/ 16 <0x0d>;
> + marvell,wakeup-gap-ms = /bits/ 16 <0x64>;
> + };
> +};
> diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
> index 32a6f22..99d7f6d 100644
> --- a/drivers/bluetooth/btusb.c
> +++ b/drivers/bluetooth/btusb.c
> @@ -2343,6 +2343,58 @@ static int btusb_shutdown_intel(struct hci_dev *hdev)
> return 0;
> }
>
> +#ifdef CONFIG_PM
> +static const struct of_device_id mvl_oob_wake_match_table[] = {
> + { .compatible = "usb1286,204e" },
> + { }
> +};
> +MODULE_DEVICE_TABLE(of, mvl_oob_wake_match_table);
> +
> +/* Configure an out-of-band gpio as wake-up pin, if specified in device tree */
> +static int marvell_config_oob_wake(struct hci_dev *hdev)
> +{
> + struct sk_buff *skb;
> + struct btusb_data *data = hci_get_drvdata(hdev);
> + struct device *dev = &data->udev->dev;
> + u16 pin, gap, opcode;
> + int ret;
> + u8 cmd[5];
> +
> + if (!of_match_device(mvl_oob_wake_match_table, dev))
> + return 0;
> +
> + if (of_property_read_u16(dev->of_node, "marvell,wakeup-pin", &pin) ||
> + of_property_read_u16(dev->of_node, "marvell,wakeup-gap-ms", &gap))
> + return -EINVAL;
> +
> + /* Vendor specific command to configure a GPIO as wake-up pin */
> + opcode = hci_opcode_pack(0x3F, 0x59);
> + cmd[0] = opcode & 0xFF;
> + cmd[1] = opcode >> 8;
> + cmd[2] = 2; /* length of parameters that follow */
> + cmd[3] = pin;
> + cmd[4] = gap; /* time in ms, for which wakeup pin should be asserted */
> +
> + skb = bt_skb_alloc(sizeof(cmd), GFP_KERNEL);
> + if (!skb) {
> + bt_dev_err(hdev, "%s: No memory\n", __func__);
> + return -ENOMEM;
> + }
> +
> + memcpy(skb_put(skb, sizeof(cmd)), cmd, sizeof(cmd));
> + hci_skb_pkt_type(skb) = HCI_COMMAND_PKT;
> +
> + ret = btusb_send_frame(hdev, skb);
> + if (ret) {
> + bt_dev_err(hdev, "%s: configuration failed\n", __func__);
> + kfree_skb(skb);
> + return ret;
> + }
> +
> + return 0;
> +}
> +#endif
> +
> static int btusb_set_bdaddr_marvell(struct hci_dev *hdev,
> const bdaddr_t *bdaddr)
> {
> @@ -2917,6 +2969,13 @@ static int btusb_probe(struct usb_interface *intf,
> err = btusb_config_oob_wake(hdev);
> if (err)
> goto out_free_dev;
> +
> + /* Marvel devices may need a specific chip configuration */
> + if (id->driver_info & BTUSB_MARVELL && data->oob_wake_irq) {
> + err = marvell_config_oob_wake(hdev);
> + if (err)
> + goto out_free_dev;
> + }
> #endif
> if (id->driver_info & BTUSB_CW6622)
> set_bit(HCI_QUIRK_BROKEN_STORED_LINK_KEY, &hdev->quirks);
> --
> 2.8.0.rc3.226.g39d4020
>
--
Gregory Clement, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com
^ permalink raw reply
* Re: [PATCH 00/26] drm/omap: Convert to use videomode from omap_video_timings
From: Peter Ujfalusi @ 2016-12-15 8:12 UTC (permalink / raw)
To: Laurent Pinchart, dri-devel
Cc: thierry.reding, airlied, tomi.valkeinen, Mark Rutland, devicetree,
daniel.vetter, linux-kernel, Rob Herring
In-Reply-To: <3115831.KSyLVyBdAU@avalon>
On 12/14/2016 11:32 PM, Laurent Pinchart wrote:
> Hi Peter,
>
> On Thursday 01 Sep 2016 14:22:54 Peter Ujfalusi wrote:
>> Hi,
>>
>> The following series will convert the omapdrm stack to use the generic
>> videmode instead of the private omap_video_timings struct for the panel
>> information.
>>
>> Since we have several panels under omapdrm/displays/ where the data drive
>> edge is set to be different then the sync drive edge, the first three patch
>> will add support to select the sync drive edge via DT.
>> I was not able to locate the datasheet for all the panels and because the
>> different edge was used in omapdrm and omapfb for a long time without
>> complains from users - and they were written this way - I think it is a
>> valid that we can have panels requiring different edge for data and sync to
>> be driven.
>
> That's very peculiar. Have you been able to locate at least one panel
> datasheet that documents this requirement ?
No, not really. patch 23-26 adds comments to panel drivers where the
existing implementation contradicts the information in the panel's
documentation. I was not able to locate any document for the Sony
acx565akm panel.
I opted to not change the behavior of the panel drivers regarding to
this since I don't have access to neither of the boards with the given
displays and this was the configuration they were using and I assume
they were/are working fine.
>> The rest of the patches are most mechanical ones. I have decided to split it
>> up to small chunks and did one change at the time to finally remove the
>> omap_video_timings from omapdrm.
>>
>>
>> CC: Rob Herring <robh+dt@kernel.org>
>> CC: Mark Rutland <mark.rutland@arm.com>
>> CC: devicetree@vger.kernel.org
>>
>> Regards,
>> Peter
>> ---
>> Peter Ujfalusi (26):
>> dt-bindings: display: display-timing: Add property to configure sync
>> drive edge
>> video: display_timing: Add flags to select the edge when the sync is
>> driven
>> video: of: display_timing: Add support for syncclk-active property
>> drm/omap: omap_display_timings: rename x_res to hactive
>> drm/omap: omap_display_timings: rename y_res to vactive
>> drm/omap: omap_display_timings: rename hsw to hsync_len
>> drm/omap: omap_display_timings: rename hfp to hfront_porch
>> drm/omap: omap_display_timings: rename hbp to hback_porch
>> drm/omap: omap_display_timings: rename vsw to vsync_len
>> drm/omap: omap_display_timings: rename vfp to vfront_porch
>> drm/omap: omap_display_timings: rename vbp to vback_porch
>> drm/omap: HDMI5: Use pointer to cfg->v_fc_config.timings in
>> hdmi_core_video_config
>> drm/omap: omap_display_timings: Use display_flags for interlace mode
>> drm/omap: dispc: Simplify _dispc_mgr_set_lcd_timings() parameters
>> drm/omap: omap_display_timings: Use display_flags for h/vsync level
>> drm/omap: omap_display_timings: Use display_flags for DE level
>> drm/omap: omap_display_timings: Use display_flags for double_pixel
>> mode
>> drm/omap: omap_display_timings: Use display_flags for pixel data edge
>> drm/omap: omap_display_timings: Use display_flags for sync edge
>> drm/omap: Change the types of struct omap_video_timings members
>> drm/omap: Replace struct omap_video_timings with videomode
>> drm/omap: Use consistent name for struct videomode
>> drm/omap: panel-tpo-td043mtea1: Add note for incorrect sync drive edge
>> drm/omap: panel-tpo-td028ttec1: Add note for incorrect sync drive edge
>> drm/omap: panel-sharp-ls037v7dw01: Add note for incorrect data drive
>> edge
>> drm/omap: panel-lgphilips-lb035q02: Add note for incorrect data drive
>> edge and DE level
>>
>> .../bindings/display/panel/display-timing.txt | 6 +
>> .../gpu/drm/omapdrm/displays/connector-analog-tv.c | 47 ++---
>> drivers/gpu/drm/omapdrm/displays/connector-dvi.c | 50 +++--
>> drivers/gpu/drm/omapdrm/displays/connector-hdmi.c | 49 +++--
>> drivers/gpu/drm/omapdrm/displays/encoder-opa362.c | 20 +-
>> drivers/gpu/drm/omapdrm/displays/encoder-tfp410.c | 31 ++-
>> .../gpu/drm/omapdrm/displays/encoder-tpd12s015.c | 20 +-
>> drivers/gpu/drm/omapdrm/displays/panel-dpi.c | 30 ++-
>> drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c | 25 ++-
>> .../omapdrm/displays/panel-lgphilips-lb035q02.c | 59 +++---
>> .../drm/omapdrm/displays/panel-nec-nl8048hl11.c | 52 +++--
>> .../drm/omapdrm/displays/panel-sharp-ls037v7dw01.c | 58 +++---
>> .../drm/omapdrm/displays/panel-sony-acx565akm.c | 53 +++--
>> .../drm/omapdrm/displays/panel-tpo-td028ttec1.c | 57 +++---
>> .../drm/omapdrm/displays/panel-tpo-td043mtea1.c | 54 ++---
>> drivers/gpu/drm/omapdrm/dss/dispc.c | 222 ++++++++----------
>> drivers/gpu/drm/omapdrm/dss/display.c | 78 +-------
>> drivers/gpu/drm/omapdrm/dss/dpi.c | 40 ++--
>> drivers/gpu/drm/omapdrm/dss/dsi.c | 156 ++++++++-------
>> drivers/gpu/drm/omapdrm/dss/dss.h | 5 +-
>> drivers/gpu/drm/omapdrm/dss/hdmi.h | 8 +-
>> drivers/gpu/drm/omapdrm/dss/hdmi4.c | 31 +--
>> drivers/gpu/drm/omapdrm/dss/hdmi4_core.c | 8 +-
>> drivers/gpu/drm/omapdrm/dss/hdmi5.c | 31 +--
>> drivers/gpu/drm/omapdrm/dss/hdmi5_core.c | 85 ++++----
>> drivers/gpu/drm/omapdrm/dss/hdmi_wp.c | 73 ++++---
>> drivers/gpu/drm/omapdrm/dss/omapdss.h | 98 +++------
>> drivers/gpu/drm/omapdrm/dss/output.c | 5 +-
>> drivers/gpu/drm/omapdrm/dss/rfbi.c | 49 +++--
>> drivers/gpu/drm/omapdrm/dss/sdi.c | 33 ++-
>> drivers/gpu/drm/omapdrm/dss/venc.c | 97 +++++----
>> drivers/gpu/drm/omapdrm/omap_connector.c | 87 +-------
>> drivers/gpu/drm/omapdrm/omap_crtc.c | 17 +-
>> drivers/gpu/drm/omapdrm/omap_drv.h | 7 +-
>> drivers/gpu/drm/omapdrm/omap_encoder.c | 10 +-
>> drivers/video/of_display_timing.c | 9 +
>> include/video/display_timing.h | 4 +
>> 37 files changed, 778 insertions(+), 986 deletions(-)
>
--
Péter
^ permalink raw reply
* Re: [PATCH 00/26] drm/omap: Convert to use videomode from omap_video_timings
From: Tomi Valkeinen @ 2016-12-15 7:56 UTC (permalink / raw)
To: Laurent Pinchart, dri-devel
Cc: Mark Rutland, devicetree, daniel.vetter, linux-kernel,
Rob Herring, Peter Ujfalusi
In-Reply-To: <3115831.KSyLVyBdAU@avalon>
[-- Attachment #1.1.1: Type: text/plain, Size: 1518 bytes --]
On 14/12/16 23:32, Laurent Pinchart wrote:
> Hi Peter,
>
> On Thursday 01 Sep 2016 14:22:54 Peter Ujfalusi wrote:
>> Hi,
>>
>> The following series will convert the omapdrm stack to use the generic
>> videmode instead of the private omap_video_timings struct for the panel
>> information.
>>
>> Since we have several panels under omapdrm/displays/ where the data drive
>> edge is set to be different then the sync drive edge, the first three patch
>> will add support to select the sync drive edge via DT.
>> I was not able to locate the datasheet for all the panels and because the
>> different edge was used in omapdrm and omapfb for a long time without
>> complains from users - and they were written this way - I think it is a
>> valid that we can have panels requiring different edge for data and sync to
>> be driven.
>
> That's very peculiar. Have you been able to locate at least one panel
> datasheet that documents this requirement ?
I think I remember seeing some panel or encoder asking for different
edges. But it's rather vague memory =).
Interestingly, the default behavior of OMAP DSS is to have data and sync
at different edges. I don't know what was the rationale for that design.
Another, slightly related, interesting thing is that only from OMAP4
forward we have had the possibility to have hsync and vsync happen at
the same time. Earlier hsync came first, followed by vsync. This old
behavior caused problems at least on one encoder I worked on.
Tomi
[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]
[-- Attachment #2: Type: text/plain, Size: 160 bytes --]
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel
^ permalink raw reply
* Re: [PATCH 3/3] arm64: dts: rockchip: add clk-480m for ehci and ohci of rk3399
From: Frank Wang @ 2016-12-15 6:41 UTC (permalink / raw)
To: Xing Zheng, Doug Anderson, Brian Norris, Heiko Stübner
Cc: William wu, Rob Herring, Mark Rutland, Catalin Marinas,
Will Deacon, Caesar Wang, Jianqun Xu, Elaine Zhang,
devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org, Dmitry Torokhov, Tao Huang,
open list:ARM/Rockchip SoC..., 'daniel.meng', Kever Yang,
frank.wang
In-Reply-To: <5ce521da-119a-2de8-026c-5992fedfef43@rock-chips.com>
Hi Brain, Doug and Heiko,
I would like to summarize why this story was constructed.
The ehci/ohci-platform suspend process are blocked due to UTMI clock
which directly output from usb-phy has been disabled, and why the UTMI
clock was disabled?
UTMI clock and 480m clock all output from the same internal PLL of
usb-phy, and there is only one bit can use to control this PLL on or
off, which we named "otg_commononn"(GRF, offset 0x0e450/0x0e460 bit4 )
in RK3399 TRM.
When system boot up, ehci/ohci-platform probe function invoke
phy_power_on(), further invoke rockchip_usb2phy_power_on() to enable
480m clock, actually, it sets the otg_commononn bit on, and then usb-phy
will go to (auto)suspend if there is no devices plug-in after 1 minute,
the rockchip_usb2phy_power_off() will be invoked and the 480m clock may
be disabled in the (auto)suspend process. As a result, the otg_commononn
bit may be turned off, and all output clock of usb-phy will be disabled.
However, ehci/ohci-platform PM suspend operation (read/write controller
register) are based on the UTMI clock.
So we introduced "clk_usbphy0_480m_src"/"clk_usbphy1_480m_src" as one
input clock for ehci/ohci-platform, in this way, the otg_commononn bit
is not turned off until ehci/ohci-platform go to PM suspend.
BR.
Frank
On 2016/12/15 10:41, Xing Zheng wrote:
> // Frank
>
> Hi Doug, Brain,
> Thanks for the reply.
> Sorry I forgot these patches have been sent earlier, and Frank
> have some explained and discussed with Heiko.
> Please see https://patchwork.kernel.org/patch/9255245/
> Perhaps we can move to that patch tree to continue the discussion.
>
> I think Frank and William will help us to continue checking these.
>
> Thanks
>
> 在 2016年12月15日 08:10, Doug Anderson 写道:
>> Hi,
>>
>> On Wed, Dec 14, 2016 at 2:11 AM, Xing Zheng
>> <zhengxing@rock-chips.com> wrote:
>>> From: William wu <wulf@rock-chips.com>
>>>
>>> We found that the suspend process was blocked when it run into
>>> ehci/ohci module due to clk-480m of usb2-phy was disabled.
>>>
>>> The root cause is that usb2-phy suspended earlier than ehci/ohci
>>> (usb2-phy will be auto suspended if no devices plug-in).
>> This is really weird, but I can confirm it is true on my system too
>> (kernel-4.4 based). At least I see:
>>
>> [ 208.012065] calling usb1+ @ 4984, parent: fe380000.usb, cb:
>> usb_dev_suspend
>> [ 208.569112] calling ff770000.syscon:usb2-phy@e450+ @ 4983, parent:
>> ff770000.syscon, cb: platform_pm_suspend
>> [ 208.569113] call ff770000.syscon:usb2-phy@e450+ returned 0 after 0
>> usecs
>> [ 208.569439] calling fe380000.usb+ @ 4983, parent: platform, cb:
>> platform_pm_suspend
>> [ 208.569444] call fe380000.usb+ returned 0 after 4 usecs
>>
>>
>> In general I thought that suspend order was supposed to be related to
>> probe order. So if your probe order is A, B, C then your suspend
>> order would be C, B, A. ...and we know for sure that the USB PHY
>> needs to probe _before_ the main USB controller. If it didn't then
>> you'd get an EPROBE_DEFER in the USB controller, right? So that means
>> that the USB controller should be suspending before its PHY.
>>
>> Any chance this is somehow related to async probe? I'm not a huge
>> expert on async probe but I guess I could imagine things getting
>> confused if you had a sequence like this:
>>
>> 1. Start USB probe (async)
>> 2. Start PHY probe
>> 3. Finish PHY probe
>> 4. In USB probe, ask for PHY--no problems since PHY probe finished
>> 5. Finish USB probe
>>
>> The probe order would be USB before PHY even though the USB probe
>> _depended_ on the PHY probe being finished... :-/ Anyway, probably
>> I'm just misunderstanding something and someone can tell me how dumb I
>> am...
>>
>> I also notice that the ehci_platform_power_off() function we're
>> actually making PHY commands right before the same commands that turn
>> off our clocks. Presumably those commands aren't really so good to do
>> if the PHY has already been suspended?
>>
>> Actually, does the PHY suspend from platform_pm_suspend() actually
>> even do anything? It doesn't look like it. It looks as if all the
>> PHY cares about is init/exit and on/off... ...and it looks as if the
>> PHY should be turned off by the EHCI controller at about the same time
>> it turns off its clocks...
>>
>> I haven't fully dug, but is there any chance that things are getting
>> confused between the OTG PHY and the Host PHY? Maybe when we turn off
>> the OTG PHY it turns off something that the host PHY needs?
>>
>>
>>> and the
>>> clk-480m provided by it was disabled if no module used. However,
>>> some suspend process related ehci/ohci are base on this clock,
>>> so we should refer it into ehci/ohci driver to prevent this case.
>> Though I don't actually have details about the internals of the chip,
>> it does seem highly likely that the USB block actually uses this clock
>> for some things, so it doesn't seem insane (to me) to have the USB
>> controller request that the clock be on. So, in general, I don't have
>> lots of objections to including the USB PHY Clock here.
>>
>> ...but I think you have the wrong clock (please correct me if I'm
>> wrong). I think you really wanted your input clock to be
>> "clk_usbphy0_480m", not "clk_usbphy0_480m_src". Specifically I
>> believe there is a gate between the clock outputted by the PHY and the
>> USB Controller itself. I'm guessing that the gate is only there
>> between the PHY and the "clk_usbphy_480m" MUX.
>>
>> As evidence, I have a totally functioning system right now where
>> "clk_usbphy0_480m_src" is currently gated.
>>
>> That means really you should be changing your clocks to this (untested):
>>
>> clocks = <&cru HCLK_HOST0>, <&cru HCLK_HOST0_ARB>,
>> <&u2phy0>;
>>
>> ...and then you could drop the other two patches in this series.
>>
>> ===
>>
>> OK, I actually briefly tested my proposed change and it at least seems
>> to build and boot OK. You'd have to test it to make sure it makes
>> your tests pass...
>>
>> ===
>>
>> So I guess to summarize all the above:
>>
>> * It seems to me like there's some deeper root cause and your patch
>> will at most put a band-aid on it. Seems like digging out the root
>> cause is a good idea.
>>
>> * Though I don't believe it solves the root problem, the idea of the
>> USB Controller holding onto the PHY clock doesn't seem wrong.
>>
>> * You're holding onto the wrong clock in your patch--you want the one
>> before the gate (I think).
>>
>>
>> -Doug
>>
>>
>>
>
>
^ permalink raw reply
* [PATCH 2/2] clk: hi3660: Clock driver support for Hisilicon hi3660 SoC
From: Zhangfei Gao @ 2016-12-15 5:58 UTC (permalink / raw)
To: Stephen Boyd, Rob Herring, Arnd Bergmann,
haojian.zhuang-QSEj5FYQhm4dnm+yROfE0A, guodong Xu
Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
devicetree-u79uwXL29TY76Z2rM5mHXA, Zhangfei Gao
In-Reply-To: <1481781493-6188-1-git-send-email-zhangfei.gao-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
Signed-off-by: Zhangfei Gao <zhangfei.gao-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
---
drivers/clk/hisilicon/Kconfig | 7 +
drivers/clk/hisilicon/Makefile | 1 +
drivers/clk/hisilicon/clk-hi3660.c | 601 +++++++++++++++++++++++++++++++
include/dt-bindings/clock/hi3660-clock.h | 194 ++++++++++
4 files changed, 803 insertions(+)
create mode 100644 drivers/clk/hisilicon/clk-hi3660.c
create mode 100644 include/dt-bindings/clock/hi3660-clock.h
diff --git a/drivers/clk/hisilicon/Kconfig b/drivers/clk/hisilicon/Kconfig
index 3f537a0..36759b7 100644
--- a/drivers/clk/hisilicon/Kconfig
+++ b/drivers/clk/hisilicon/Kconfig
@@ -6,6 +6,13 @@ config COMMON_CLK_HI3519
help
Build the clock driver for hi3519.
+config COMMON_CLK_HI3660
+ bool "Hi3660 Clock Driver"
+ depends on ARCH_HISI || COMPILE_TEST
+ default ARCH_HISI
+ help
+ Build the Hisilicon Hi3660 clock driver based on the common clock framework.
+
config COMMON_CLK_HI6220
bool "Hi6220 Clock Driver"
depends on ARCH_HISI || COMPILE_TEST
diff --git a/drivers/clk/hisilicon/Makefile b/drivers/clk/hisilicon/Makefile
index e169ec7..c872587 100644
--- a/drivers/clk/hisilicon/Makefile
+++ b/drivers/clk/hisilicon/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_ARCH_HI3xxx) += clk-hi3620.o
obj-$(CONFIG_ARCH_HIP04) += clk-hip04.o
obj-$(CONFIG_ARCH_HIX5HD2) += clk-hix5hd2.o
obj-$(CONFIG_COMMON_CLK_HI3519) += clk-hi3519.o
+obj-$(CONFIG_COMMON_CLK_HI3660) += clk-hi3660.o
obj-$(CONFIG_COMMON_CLK_HI6220) += clk-hi6220.o
obj-$(CONFIG_RESET_HISI) += reset.o
obj-$(CONFIG_STUB_CLK_HI6220) += clk-hi6220-stub.o
diff --git a/drivers/clk/hisilicon/clk-hi3660.c b/drivers/clk/hisilicon/clk-hi3660.c
new file mode 100644
index 0000000..42ca47d
--- /dev/null
+++ b/drivers/clk/hisilicon/clk-hi3660.c
@@ -0,0 +1,601 @@
+/*
+ * Copyright (c) 2016-2017 Linaro Ltd.
+ * Copyright (c) 2016-2017 HiSilicon Technologies Co., Ltd.
+ *
+ * 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.
+ */
+
+#include <dt-bindings/clock/hi3660-clock.h>
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include "clk.h"
+
+enum hi3660_clk_type {
+ HI3660_CRGCTRL = 1,
+ HI3660_PCTRL,
+ HI3660_PMUCTRL,
+ HI3660_SCTRL,
+ HI3660_IOMCU,
+};
+
+static const struct hisi_fixed_rate_clock hi3660_fixed_rate_clks[] = {
+ { HI3660_CLKIN_SYS, "clkin_sys", NULL, 0, 19200000, },
+ { HI3660_CLKIN_REF, "clkin_ref", NULL, 0, 32764, },
+ { HI3660_CLK_FLL_SRC, "clk_fll_src", NULL, 0, 128000000, },
+ { HI3660_CLK_PPLL0, "clk_ppll0", NULL, 0, 1600000000, },
+ { HI3660_CLK_PPLL1, "clk_ppll1", NULL, 0, 1866000000, },
+ { HI3660_CLK_PPLL2, "clk_ppll2", NULL, 0, 960000000, },
+ { HI3660_CLK_PPLL3, "clk_ppll3", NULL, 0, 1290000000, },
+ { HI3660_CLK_SCPLL, "clk_scpll", NULL, 0, 245760000, },
+ { HI3660_PCLK, "pclk", NULL, 0, 20000000, },
+ { HI3660_CLK_UART0_DBG, "clk_uart0_dbg", NULL, 0, 19200000, },
+ { HI3660_CLK_UART6, "clk_uart6", NULL, 0, 19200000, },
+ { HI3660_OSC32K, "osc32k", NULL, 0, 32764, },
+ { HI3660_OSC19M, "osc19m", NULL, 0, 19200000, },
+ { HI3660_CLK_480M, "clk_480m", NULL, 0, 480000000, },
+ { HI3660_CLK_INV, "clk_inv", NULL, 0, 10000000, },
+};
+
+/* crgctrl */
+static const struct hisi_fixed_factor_clock hi3660_crg_fixed_factor_clks[] = {
+ { HI3660_FACTOR_UART3, "clk_factor_uart3", "iomcu_peri0", 1, 8, 0, },
+ { HI3660_CLK_FACTOR_MMC, "clk_factor_mmc", "clkin_sys", 1, 6, 0, },
+ { HI3660_CLK_GATE_I2C0, "clk_gate_i2c0", "clk_i2c0_iomcu", 1, 4, 0, },
+ { HI3660_CLK_GATE_I2C1, "clk_gate_i2c1", "clk_i2c1_iomcu", 1, 4, 0, },
+ { HI3660_CLK_GATE_I2C2, "clk_gate_i2c2", "clk_i2c2_iomcu", 1, 4, 0, },
+ { HI3660_CLK_GATE_I2C6, "clk_gate_i2c6", "clk_i2c6_iomcu", 1, 4, 0, },
+ { HI3660_CLK_DIV_SYSBUS, "clk_div_sysbus", "clk_mux_sysbus", 1, 7, 0, },
+ { HI3660_CLK_DIV_320M, "clk_div_320m", "clk_320m_pll_gt", 1, 5, 0, },
+ { HI3660_CLK_DIV_A53, "clk_div_a53hpm", "clk_a53hpm_andgt", 1, 2, 0, },
+ { HI3660_CLK_GATE_SPI0, "clk_gate_spi0", "clk_ppll0", 1, 8, 0, },
+ { HI3660_CLK_GATE_SPI2, "clk_gate_spi2", "clk_ppll0", 1, 8, 0, },
+ { HI3660_PCIEPHY_REF, "clk_pciephy_ref", "clk_div_pciephy", 1, 1, 0, },
+ { HI3660_CLK_ABB_USB, "clk_abb_usb", "clk_gate_usb_tcxo_en", 1, 1, 0 },
+};
+
+static const struct hisi_gate_clock hi3660_crgctrl_gate_sep_clks[] = {
+ { HI3660_HCLK_GATE_SDIO0, "hclk_gate_sdio0", "clk_div_sysbus",
+ CLK_SET_RATE_PARENT, 0x0, 21, 0, },
+ { HI3660_HCLK_GATE_SD, "hclk_gate_sd", "clk_div_sysbus",
+ CLK_SET_RATE_PARENT, 0x0, 30, 0, },
+ { HI3660_CLK_GATE_AOMM, "clk_gate_aomm", "clk_div_aomm",
+ CLK_SET_RATE_PARENT, 0x0, 31, 0, },
+ { HI3660_PCLK_GPIO0, "pclk_gpio0", "clk_div_cfgbus",
+ CLK_SET_RATE_PARENT, 0x10, 0, 0, },
+ { HI3660_PCLK_GPIO1, "pclk_gpio1", "clk_div_cfgbus",
+ CLK_SET_RATE_PARENT, 0x10, 1, 0, },
+ { HI3660_PCLK_GPIO2, "pclk_gpio2", "clk_div_cfgbus",
+ CLK_SET_RATE_PARENT, 0x10, 2, 0, },
+ { HI3660_PCLK_GPIO3, "pclk_gpio3", "clk_div_cfgbus",
+ CLK_SET_RATE_PARENT, 0x10, 3, 0, },
+ { HI3660_PCLK_GPIO4, "pclk_gpio4", "clk_div_cfgbus",
+ CLK_SET_RATE_PARENT, 0x10, 4, 0, },
+ { HI3660_PCLK_GPIO5, "pclk_gpio5", "clk_div_cfgbus",
+ CLK_SET_RATE_PARENT, 0x10, 5, 0, },
+ { HI3660_PCLK_GPIO6, "pclk_gpio6", "clk_div_cfgbus",
+ CLK_SET_RATE_PARENT, 0x10, 6, 0, },
+ { HI3660_PCLK_GPIO7, "pclk_gpio7", "clk_div_cfgbus",
+ CLK_SET_RATE_PARENT, 0x10, 7, 0, },
+ { HI3660_PCLK_GPIO8, "pclk_gpio8", "clk_div_cfgbus",
+ CLK_SET_RATE_PARENT, 0x10, 8, 0, },
+ { HI3660_PCLK_GPIO9, "pclk_gpio9", "clk_div_cfgbus",
+ CLK_SET_RATE_PARENT, 0x10, 9, 0, },
+ { HI3660_PCLK_GPIO10, "pclk_gpio10", "clk_div_cfgbus",
+ CLK_SET_RATE_PARENT, 0x10, 10, 0, },
+ { HI3660_PCLK_GPIO11, "pclk_gpio11", "clk_div_cfgbus",
+ CLK_SET_RATE_PARENT, 0x10, 11, 0, },
+ { HI3660_PCLK_GPIO12, "pclk_gpio12", "clk_div_cfgbus",
+ CLK_SET_RATE_PARENT, 0x10, 12, 0, },
+ { HI3660_PCLK_GPIO13, "pclk_gpio13", "clk_div_cfgbus",
+ CLK_SET_RATE_PARENT, 0x10, 13, 0, },
+ { HI3660_PCLK_GPIO14, "pclk_gpio14", "clk_div_cfgbus",
+ CLK_SET_RATE_PARENT, 0x10, 14, 0, },
+ { HI3660_PCLK_GPIO15, "pclk_gpio15", "clk_div_cfgbus",
+ CLK_SET_RATE_PARENT, 0x10, 15, 0, },
+ { HI3660_PCLK_GPIO16, "pclk_gpio16", "clk_div_cfgbus",
+ CLK_SET_RATE_PARENT, 0x10, 16, 0, },
+ { HI3660_PCLK_GPIO17, "pclk_gpio17", "clk_div_cfgbus",
+ CLK_SET_RATE_PARENT, 0x10, 17, 0, },
+ { HI3660_PCLK_GPIO18, "pclk_gpio18", "clk_div_ioperi",
+ CLK_SET_RATE_PARENT, 0x10, 18, 0, },
+ { HI3660_PCLK_GPIO19, "pclk_gpio19", "clk_div_ioperi",
+ CLK_SET_RATE_PARENT, 0x10, 19, 0, },
+ { HI3660_PCLK_GPIO20, "pclk_gpio20", "clk_div_cfgbus",
+ CLK_SET_RATE_PARENT, 0x10, 20, 0, },
+ { HI3660_PCLK_GPIO21, "pclk_gpio21", "clk_div_cfgbus",
+ CLK_SET_RATE_PARENT, 0x10, 21, 0, },
+ { HI3660_CLK_GATE_SPI3, "clk_gate_spi3", "clk_div_ioperi",
+ CLK_SET_RATE_PARENT, 0x10, 30, 0, },
+ { HI3660_CLK_GATE_I2C7, "clk_gate_i2c7", "clk_mux_i2c",
+ CLK_SET_RATE_PARENT, 0x10, 31, 0, },
+ { HI3660_CLK_GATE_I2C3, "clk_gate_i2c3", "clk_mux_i2c",
+ CLK_SET_RATE_PARENT, 0x20, 7, 0, },
+ { HI3660_CLK_GATE_SPI1, "clk_gate_spi1", "clk_mux_spi",
+ CLK_SET_RATE_PARENT, 0x20, 9, 0, },
+ { HI3660_CLK_GATE_UART1, "clk_gate_uart1", "clk_mux_uarth",
+ CLK_SET_RATE_PARENT, 0x20, 11, 0, },
+ { HI3660_CLK_GATE_UART2, "clk_gate_uart2", "clk_mux_uart1",
+ CLK_SET_RATE_PARENT, 0x20, 12, 0, },
+ { HI3660_CLK_GATE_UART4, "clk_gate_uart4", "clk_mux_uarth",
+ CLK_SET_RATE_PARENT, 0x20, 14, 0, },
+ { HI3660_CLK_GATE_UART5, "clk_gate_uart5", "clk_mux_uart1",
+ CLK_SET_RATE_PARENT, 0x20, 15, 0, },
+ { HI3660_CLK_GATE_I2C4, "clk_gate_i2c4", "clk_mux_i2c",
+ CLK_SET_RATE_PARENT, 0x20, 27, 0, },
+ { HI3660_CLK_GATE_DMAC, "clk_gate_dmac", "clk_div_sysbus",
+ CLK_SET_RATE_PARENT, 0x30, 1, 0, },
+ { HI3660_PCLK_GATE_DSS, "pclk_gate_dss", "clk_div_cfgbus",
+ CLK_SET_RATE_PARENT, 0x30, 12, 0, },
+ { HI3660_ACLK_GATE_DSS, "aclk_gate_dss", "clk_gate_vivobus",
+ CLK_SET_RATE_PARENT, 0x30, 13, 0, },
+ { HI3660_CLK_GATE_LDI1, "clk_gate_ldi1", "clk_div_ldi1",
+ CLK_SET_RATE_PARENT, 0x30, 14, 0, },
+ { HI3660_CLK_GATE_LDI0, "clk_gate_ldi0", "clk_div_ldi0",
+ CLK_SET_RATE_PARENT, 0x30, 15, 0, },
+ { HI3660_CLK_GATE_VIVOBUS, "clk_gate_vivobus", "clk_div_vivobus",
+ CLK_SET_RATE_PARENT, 0x30, 16, 0, },
+ { HI3660_CLK_GATE_EDC0, "clk_gate_edc0", "clk_div_edc0",
+ CLK_SET_RATE_PARENT, 0x30, 17, 0, },
+ { HI3660_CLK_GATE_TXDPHY0_CFG, "clk_gate_txdphy0_cfg", "clkin_sys",
+ CLK_SET_RATE_PARENT, 0x30, 28, 0, },
+ { HI3660_CLK_GATE_TXDPHY0_REF, "clk_gate_txdphy0_ref", "clkin_sys",
+ CLK_SET_RATE_PARENT, 0x30, 29, 0, },
+ { HI3660_CLK_GATE_TXDPHY1_CFG, "clk_gate_txdphy1_cfg", "clkin_sys",
+ CLK_SET_RATE_PARENT, 0x30, 30, 0, },
+ { HI3660_CLK_GATE_TXDPHY1_REF, "clk_gate_txdphy1_ref", "clkin_sys",
+ CLK_SET_RATE_PARENT, 0x30, 31, 0, },
+ { HI3660_ACLK_GATE_USB3OTG, "aclk_gate_usb3otg", "clk_div_mmc0bus",
+ CLK_SET_RATE_PARENT, 0x40, 1, 0, },
+ { HI3660_CLK_GATE_SPI4, "clk_gate_spi4", "clk_mux_spi",
+ CLK_SET_RATE_PARENT, 0x40, 4, 0, },
+ { HI3660_CLK_GATE_SD, "clk_gate_sd", "clk_mux_sd_sys",
+ CLK_SET_RATE_PARENT, 0x40, 17, 0, },
+ { HI3660_CLK_GATE_SDIO0, "clk_gate_sdio0", "clk_mux_sdio_sys",
+ CLK_SET_RATE_PARENT, 0x40, 19, 0, },
+ { HI3660_CLK_GATE_UFS_SUBSYS, "clk_gate_ufs_subsys", "clk_div_sysbus",
+ CLK_SET_RATE_PARENT, 0x50, 21, 0, },
+ { HI3660_PCLK_GATE_DSI0, "pclk_gate_dsi0", "clk_div_cfgbus",
+ CLK_SET_RATE_PARENT, 0x50, 28, 0, },
+ { HI3660_PCLK_GATE_DSI1, "pclk_gate_dsi1", "clk_div_cfgbus",
+ CLK_SET_RATE_PARENT, 0x50, 29, 0, },
+ { HI3660_ACLK_GATE_PCIE, "aclk_gate_pcie", "clk_div_mmc1bus",
+ CLK_SET_RATE_PARENT, 0x420, 5, 0, },
+ { HI3660_PCLK_GATE_PCIE_SYS, "pclk_gate_pcie_sys", "clk_div_mmc1bus",
+ CLK_SET_RATE_PARENT, 0x420, 7, 0, },
+ { HI3660_CLK_GATE_PCIEAUX, "clk_gate_pcieaux", "clkin_sys",
+ CLK_SET_RATE_PARENT, 0x420, 8, 0, },
+ { HI3660_PCLK_GATE_PCIE_PHY, "pclk_gate_pcie_phy", "clk_div_mmc1bus",
+ CLK_SET_RATE_PARENT, 0x420, 9, 0, },
+};
+
+static const struct hisi_gate_clock hi3660_crgctrl_gate_clks[] = {
+ { HI3660_CLK_ANDGT_LDI0, "clk_andgt_ldi0", "clk_mux_ldi0",
+ CLK_SET_RATE_PARENT, 0xf0, 6, CLK_GATE_HIWORD_MASK, },
+ { HI3660_CLK_ANDGT_LDI1, "clk_andgt_ldi1", "clk_mux_ldi1",
+ CLK_SET_RATE_PARENT, 0xf0, 7, CLK_GATE_HIWORD_MASK, },
+ { HI3660_CLK_ANDGT_EDC0, "clk_andgt_edc0", "clk_mux_edc0",
+ CLK_SET_RATE_PARENT, 0xf0, 8, CLK_GATE_HIWORD_MASK, },
+ { HI3660_CLK_GATE_UFSPHY_GT, "clk_gate_ufsphy_gt", "clk_div_ufsperi",
+ CLK_SET_RATE_PARENT, 0xf4, 1, CLK_GATE_HIWORD_MASK, },
+ { HI3660_CLK_ANDGT_MMC, "clk_andgt_mmc", "clk_mux_mmc_pll",
+ CLK_SET_RATE_PARENT, 0xf4, 2, CLK_GATE_HIWORD_MASK, },
+ { HI3660_CLK_ANDGT_SD, "clk_andgt_sd", "clk_mux_sd_pll",
+ CLK_SET_RATE_PARENT, 0xf4, 3, CLK_GATE_HIWORD_MASK, },
+ { HI3660_CLK_A53HPM_ANDGT, "clk_a53hpm_andgt", "clk_mux_a53hpm",
+ CLK_SET_RATE_PARENT, 0xf4, 7, CLK_GATE_HIWORD_MASK, },
+ { HI3660_CLK_ANDGT_SDIO, "clk_andgt_sdio", "clk_mux_sdio_pll",
+ CLK_SET_RATE_PARENT, 0xf4, 8, CLK_GATE_HIWORD_MASK, },
+ { HI3660_CLK_ANDGT_UART0, "clk_andgt_uart0", "clk_div_320m",
+ CLK_SET_RATE_PARENT, 0xf4, 9, CLK_GATE_HIWORD_MASK, },
+ { HI3660_CLK_ANDGT_UART1, "clk_andgt_uart1", "clk_div_320m",
+ CLK_SET_RATE_PARENT, 0xf4, 10, CLK_GATE_HIWORD_MASK, },
+ { HI3660_CLK_ANDGT_UARTH, "clk_andgt_uarth", "clk_div_320m",
+ CLK_SET_RATE_PARENT, 0xf4, 11, CLK_GATE_HIWORD_MASK, },
+ { HI3660_CLK_ANDGT_SPI, "clk_andgt_spi", "clk_div_320m",
+ CLK_SET_RATE_PARENT, 0xf4, 13, CLK_GATE_HIWORD_MASK, },
+ { HI3660_CLK_VIVOBUS_ANDGT, "clk_vivobus_andgt", "clk_mux_vivobus",
+ CLK_SET_RATE_PARENT, 0xf8, 1, CLK_GATE_HIWORD_MASK, },
+ { HI3660_CLK_AOMM_ANDGT, "clk_aomm_andgt", "clk_ppll2",
+ CLK_SET_RATE_PARENT, 0xf8, 3, CLK_GATE_HIWORD_MASK, },
+ { HI3660_CLK_320M_PLL_GT, "clk_320m_pll_gt", "clk_mux_320m",
+ CLK_SET_RATE_PARENT, 0xf8, 10, 0, },
+ { HI3660_AUTODIV_EMMC0BUS, "autodiv_emmc0bus", "autodiv_sysbus",
+ CLK_SET_RATE_PARENT, 0x404, 1, CLK_GATE_HIWORD_MASK, },
+ { HI3660_AUTODIV_SYSBUS, "autodiv_sysbus", "clk_div_sysbus",
+ CLK_SET_RATE_PARENT, 0x404, 5, CLK_GATE_HIWORD_MASK, },
+ { HI3660_CLK_GATE_UFSPHY_CFG, "clk_gate_ufsphy_cfg",
+ "clk_div_ufsphy_cfg", CLK_SET_RATE_PARENT, 0x420, 12, 0, },
+ { HI3660_CLK_GATE_UFSIO_REF, "clk_gate_ufsio_ref",
+ "clk_gate_ufs_tcxo_en", CLK_SET_RATE_PARENT, 0x420, 14, 0, },
+};
+
+static const char *const
+clk_mux_sdio_sys_p[] = {"clk_factor_mmc", "clk_div_sdio",};
+static const char *const
+clk_mux_sd_sys_p[] = {"clk_factor_mmc", "clk_div_sd",};
+static const char *const
+clk_mux_pll_p[] = {"clk_ppll0", "clk_ppll1", "clk_ppll2", "clk_ppll2",};
+static const char *const
+clk_mux_pll0123_p[] = {"clk_ppll0", "clk_ppll1", "clk_ppll2", "clk_ppll3",};
+static const char *const
+clk_mux_edc0_p[] = {"clk_inv", "clk_ppll0", "clk_ppll1", "clk_inv",
+ "clk_ppll2", "clk_inv", "clk_inv", "clk_inv",
+ "clk_ppll3", "clk_inv", "clk_inv", "clk_inv",
+ "clk_inv", "clk_inv", "clk_inv", "clk_inv",};
+static const char *const
+clk_mux_ldi0_p[] = {"clk_inv", "clk_ppll0", "clk_ppll2", "clk_inv",
+ "clk_ppll1", "clk_inv", "clk_inv", "clk_inv",
+ "clk_ppll3", "clk_inv", "clk_inv", "clk_inv",
+ "clk_inv", "clk_inv", "clk_inv", "clk_inv",};
+static const char *const
+clk_mux_uart0_p[] = {"clkin_sys", "clk_div_uart0",};
+static const char *const
+clk_mux_uart1_p[] = {"clkin_sys", "clk_div_uart1",};
+static const char *const
+clk_mux_uarth_p[] = {"clkin_sys", "clk_div_uarth",};
+static const char *const
+clk_mux_pll02p[] = {"clk_ppll0", "clk_ppll2",};
+static const char *const
+clk_mux_ioperi_p[] = {"clk_div_320m", "clk_div_a53hpm",};
+static const char *const
+clk_mux_spi_p[] = {"clkin_sys", "clk_div_spi",};
+static const char *const
+clk_mux_i2c_p[] = {"clkin_sys", "clk_div_i2c",};
+
+static const struct hisi_mux_clock hi3660_crgctrl_mux_clks[] = {
+ { HI3660_CLK_MUX_SYSBUS, "clk_mux_sysbus", clk_mux_sdio_sys_p,
+ ARRAY_SIZE(clk_mux_sdio_sys_p), CLK_SET_RATE_PARENT, 0xac, 0, 1,
+ CLK_MUX_HIWORD_MASK, },
+ { HI3660_CLK_MUX_UART0, "clk_mux_uart0", clk_mux_uart0_p,
+ ARRAY_SIZE(clk_mux_uart0_p), CLK_SET_RATE_PARENT, 0xac, 2, 1,
+ CLK_MUX_HIWORD_MASK, },
+ { HI3660_CLK_MUX_UART1, "clk_mux_uart1", clk_mux_uart1_p,
+ ARRAY_SIZE(clk_mux_uart1_p), CLK_SET_RATE_PARENT, 0xac, 3, 1,
+ CLK_MUX_HIWORD_MASK, },
+ { HI3660_CLK_MUX_UARTH, "clk_mux_uarth", clk_mux_uarth_p,
+ ARRAY_SIZE(clk_mux_uarth_p), CLK_SET_RATE_PARENT, 0xac, 4, 1,
+ CLK_MUX_HIWORD_MASK, },
+ { HI3660_CLK_MUX_SPI, "clk_mux_spi", clk_mux_spi_p,
+ ARRAY_SIZE(clk_mux_spi_p), CLK_SET_RATE_PARENT, 0xac, 8, 1,
+ CLK_MUX_HIWORD_MASK, },
+ { HI3660_CLK_MUX_I2C, "clk_mux_i2c", clk_mux_i2c_p,
+ ARRAY_SIZE(clk_mux_i2c_p), CLK_SET_RATE_PARENT, 0xac, 13, 1,
+ CLK_MUX_HIWORD_MASK, },
+ { HI3660_CLK_MUX_MMC_PLL, "clk_mux_mmc_pll", clk_mux_pll02p,
+ ARRAY_SIZE(clk_mux_pll02p), CLK_SET_RATE_PARENT, 0xb4, 0, 1,
+ CLK_MUX_HIWORD_MASK, },
+ { HI3660_CLK_MUX_LDI1, "clk_mux_ldi1", clk_mux_ldi0_p,
+ ARRAY_SIZE(clk_mux_ldi0_p), CLK_SET_RATE_PARENT, 0xb4, 8, 4,
+ CLK_MUX_HIWORD_MASK, },
+ { HI3660_CLK_MUX_LDI0, "clk_mux_ldi0", clk_mux_ldi0_p,
+ ARRAY_SIZE(clk_mux_ldi0_p), CLK_SET_RATE_PARENT, 0xb4, 12, 4,
+ CLK_MUX_HIWORD_MASK, },
+ { HI3660_CLK_MUX_SD_PLL, "clk_mux_sd_pll", clk_mux_pll_p,
+ ARRAY_SIZE(clk_mux_pll_p), CLK_SET_RATE_PARENT, 0xb8, 4, 2,
+ CLK_MUX_HIWORD_MASK, },
+ { HI3660_CLK_MUX_SD_SYS, "clk_mux_sd_sys", clk_mux_sd_sys_p,
+ ARRAY_SIZE(clk_mux_sd_sys_p), CLK_SET_RATE_PARENT, 0xb8, 6, 1,
+ CLK_MUX_HIWORD_MASK, },
+ { HI3660_CLK_MUX_EDC0, "clk_mux_edc0", clk_mux_edc0_p,
+ ARRAY_SIZE(clk_mux_edc0_p), CLK_SET_RATE_PARENT, 0xbc, 6, 4,
+ CLK_MUX_HIWORD_MASK, },
+ { HI3660_CLK_MUX_SDIO_SYS, "clk_mux_sdio_sys", clk_mux_sdio_sys_p,
+ ARRAY_SIZE(clk_mux_sdio_sys_p), CLK_SET_RATE_PARENT, 0xc0, 6, 1,
+ CLK_MUX_HIWORD_MASK, },
+ { HI3660_CLK_MUX_SDIO_PLL, "clk_mux_sdio_pll", clk_mux_pll_p,
+ ARRAY_SIZE(clk_mux_pll_p), CLK_SET_RATE_PARENT, 0xc0, 4, 2,
+ CLK_MUX_HIWORD_MASK, },
+ { HI3660_CLK_MUX_VIVOBUS, "clk_mux_vivobus", clk_mux_pll0123_p,
+ ARRAY_SIZE(clk_mux_pll0123_p), CLK_SET_RATE_PARENT, 0xd0, 12, 2,
+ CLK_MUX_HIWORD_MASK, },
+ { HI3660_CLK_MUX_A53HPM, "clk_mux_a53hpm", clk_mux_pll02p,
+ ARRAY_SIZE(clk_mux_pll02p), CLK_SET_RATE_PARENT, 0xd4, 9, 1,
+ CLK_MUX_HIWORD_MASK, },
+ { HI3660_CLK_MUX_320M, "clk_mux_320m", clk_mux_pll02p,
+ ARRAY_SIZE(clk_mux_pll02p), CLK_SET_RATE_PARENT, 0x100, 0, 1,
+ CLK_MUX_HIWORD_MASK, },
+ { HI3660_CLK_MUX_IOPERI, "clk_mux_ioperi", clk_mux_ioperi_p,
+ ARRAY_SIZE(clk_mux_ioperi_p), CLK_SET_RATE_PARENT, 0x108, 10, 1,
+ CLK_MUX_HIWORD_MASK, },
+};
+
+static const struct hisi_divider_clock hi3660_crgctrl_divider_clks[] = {
+ { HI3660_CLK_DIV_UART0, "clk_div_uart0", "clk_andgt_uart0",
+ CLK_SET_RATE_PARENT, 0xb0, 4, 4, CLK_DIVIDER_HIWORD_MASK, 0, },
+ { HI3660_CLK_DIV_UART1, "clk_div_uart1", "clk_andgt_uart1",
+ CLK_SET_RATE_PARENT, 0xb0, 8, 4, CLK_DIVIDER_HIWORD_MASK, 0, },
+ { HI3660_CLK_DIV_UARTH, "clk_div_uarth", "clk_andgt_uarth",
+ CLK_SET_RATE_PARENT, 0xb0, 12, 4, CLK_DIVIDER_HIWORD_MASK, 0, },
+ { HI3660_CLK_DIV_MMC, "clk_div_mmc", "clk_andgt_mmc",
+ CLK_SET_RATE_PARENT, 0xb4, 3, 4, CLK_DIVIDER_HIWORD_MASK, 0, },
+ { HI3660_CLK_DIV_SD, "clk_div_sd", "clk_andgt_sd",
+ CLK_SET_RATE_PARENT, 0xb8, 0, 4, CLK_DIVIDER_HIWORD_MASK, 0, },
+ { HI3660_CLK_DIV_EDC0, "clk_div_edc0", "clk_andgt_edc0",
+ CLK_SET_RATE_PARENT, 0xbc, 0, 6, CLK_DIVIDER_HIWORD_MASK, 0, },
+ { HI3660_CLK_DIV_LDI0, "clk_div_ldi0", "clk_andgt_ldi0",
+ CLK_SET_RATE_PARENT, 0xbc, 10, 6, CLK_DIVIDER_HIWORD_MASK, 0, },
+ { HI3660_CLK_DIV_SDIO, "clk_div_sdio", "clk_andgt_sdio",
+ CLK_SET_RATE_PARENT, 0xc0, 0, 4, CLK_DIVIDER_HIWORD_MASK, 0, },
+ { HI3660_CLK_DIV_LDI1, "clk_div_ldi1", "clk_andgt_ldi1",
+ CLK_SET_RATE_PARENT, 0xc0, 8, 6, CLK_DIVIDER_HIWORD_MASK, 0, },
+ { HI3660_CLK_DIV_SPI, "clk_div_spi", "clk_andgt_spi",
+ CLK_SET_RATE_PARENT, 0xc4, 12, 4, CLK_DIVIDER_HIWORD_MASK, 0, },
+ { HI3660_CLK_DIV_VIVOBUS, "clk_div_vivobus", "clk_vivobus_andgt",
+ CLK_SET_RATE_PARENT, 0xd0, 7, 5, CLK_DIVIDER_HIWORD_MASK, 0, },
+ { HI3660_CLK_DIV_I2C, "clk_div_i2c", "clk_div_320m",
+ CLK_SET_RATE_PARENT, 0xe8, 4, 4, CLK_DIVIDER_HIWORD_MASK, 0, },
+ { HI3660_CLK_DIV_UFSPHY, "clk_div_ufsphy_cfg", "clk_gate_ufsphy_gt",
+ CLK_SET_RATE_PARENT, 0xe8, 9, 2, CLK_DIVIDER_HIWORD_MASK, 0, },
+ { HI3660_CLK_DIV_CFGBUS, "clk_div_cfgbus", "clk_div_sysbus",
+ CLK_SET_RATE_PARENT, 0xec, 0, 2, CLK_DIVIDER_HIWORD_MASK, 0, },
+ { HI3660_CLK_DIV_MMC0BUS, "clk_div_mmc0bus", "autodiv_emmc0bus",
+ CLK_SET_RATE_PARENT, 0xec, 2, 1, CLK_DIVIDER_HIWORD_MASK, 0, },
+ { HI3660_CLK_DIV_MMC1BUS, "clk_div_mmc1bus", "clk_div_sysbus",
+ CLK_SET_RATE_PARENT, 0xec, 3, 1, CLK_DIVIDER_HIWORD_MASK, 0, },
+ { HI3660_CLK_DIV_UFSPERI, "clk_div_ufsperi", "clk_gate_ufs_subsys",
+ CLK_SET_RATE_PARENT, 0xec, 14, 1, CLK_DIVIDER_HIWORD_MASK, 0, },
+ { HI3660_CLK_DIV_AOMM, "clk_div_aomm", "clk_aomm_andgt",
+ CLK_SET_RATE_PARENT, 0x100, 7, 4, CLK_DIVIDER_HIWORD_MASK, 0, },
+ { HI3660_CLK_DIV_IOPERI, "clk_div_ioperi", "clk_mux_ioperi",
+ CLK_SET_RATE_PARENT, 0x108, 11, 4, CLK_DIVIDER_HIWORD_MASK, 0, },
+};
+
+/* clk_pmuctrl */
+/* pmu register need shift 2 bits */
+static const struct hisi_gate_clock hi3660_pmu_gate_clks[] = {
+ { HI3660_GATE_ABB_192, "clk_gate_abb_192", "clkin_sys",
+ CLK_SET_RATE_PARENT, (0x10a << 2), 3, 0, },
+};
+
+/* clk_pctrl */
+static const struct hisi_gate_clock hi3660_pctrl_gate_clks[] = {
+ { HI3660_GATE_UFS_TCXO_EN, "clk_gate_ufs_tcxo_en",
+ "clk_gate_abb_192", CLK_SET_RATE_PARENT, 0x10, 0,
+ CLK_GATE_HIWORD_MASK, },
+ { HI3660_GATE_USB_TCXO_EN, "clk_gate_usb_tcxo_en", "clk_gate_abb_192",
+ CLK_SET_RATE_PARENT, 0x10, 1, CLK_GATE_HIWORD_MASK, },
+};
+
+/* clk_sctrl */
+static const struct hisi_gate_clock hi3660_sctrl_gate_sep_clks[] = {
+ { HI3660_PCLK_AO_GPIO0, "pclk_ao_gpio0", "clk_div_aobus",
+ CLK_SET_RATE_PARENT, 0x160, 11, 0, },
+ { HI3660_PCLK_AO_GPIO1, "pclk_ao_gpio1", "clk_div_aobus",
+ CLK_SET_RATE_PARENT, 0x160, 12, 0, },
+ { HI3660_PCLK_AO_GPIO2, "pclk_ao_gpio2", "clk_div_aobus",
+ CLK_SET_RATE_PARENT, 0x160, 13, 0, },
+ { HI3660_PCLK_AO_GPIO3, "pclk_ao_gpio3", "clk_div_aobus",
+ CLK_SET_RATE_PARENT, 0x160, 14, 0, },
+ { HI3660_PCLK_AO_GPIO4, "pclk_ao_gpio4", "clk_div_aobus",
+ CLK_SET_RATE_PARENT, 0x160, 21, 0, },
+ { HI3660_PCLK_AO_GPIO5, "pclk_ao_gpio5", "clk_div_aobus",
+ CLK_SET_RATE_PARENT, 0x160, 22, 0, },
+ { HI3660_PCLK_AO_GPIO6, "pclk_ao_gpio6", "clk_div_aobus",
+ CLK_SET_RATE_PARENT, 0x160, 25, 0, },
+ { HI3660_PCLK_GATE_MMBUF, "pclk_gate_mmbuf", "pclk_div_mmbuf",
+ CLK_SET_RATE_PARENT, 0x170, 23, 0, },
+ { HI3660_CLK_GATE_DSS_AXI_MM, "clk_gate_dss_axi_mm", "aclk_mux_mmbuf",
+ CLK_SET_RATE_PARENT, 0x170, 24, 0, },
+};
+
+static const struct hisi_gate_clock hi3660_sctrl_gate_clks[] = {
+ { HI3660_PCLK_MMBUF_ANDGT, "pclk_mmbuf_andgt", "clk_sw_mmbuf",
+ CLK_SET_RATE_PARENT, 0x258, 7, CLK_GATE_HIWORD_MASK, },
+ { HI3660_CLK_MMBUF_PLL_ANDGT, "clk_mmbuf_pll_andgt", "clk_ppll0",
+ CLK_SET_RATE_PARENT, 0x260, 11, CLK_DIVIDER_HIWORD_MASK, 0, },
+ { HI3660_CLK_FLL_MMBUF_ANDGT, "clk_fll_mmbuf_andgt", "clk_fll_src",
+ CLK_SET_RATE_PARENT, 0x260, 12, CLK_DIVIDER_HIWORD_MASK, 0, },
+ { HI3660_CLK_SYS_MMBUF_ANDGT, "clk_sys_mmbuf_andgt", "clkin_sys",
+ CLK_SET_RATE_PARENT, 0x260, 13, CLK_DIVIDER_HIWORD_MASK, 0, },
+ { HI3660_CLK_GATE_PCIEPHY_GT, "clk_gate_pciephy_gt", "clk_ppll0",
+ CLK_SET_RATE_PARENT, 0x268, 11, CLK_DIVIDER_HIWORD_MASK, 0, },
+};
+
+static const char *const
+aclk_mux_mmbuf_p[] = {"aclk_div_mmbuf", "clk_gate_aomm",};
+static const char *const
+clk_sw_mmbuf_p[] = {"clk_sys_mmbuf_andgt", "clk_fll_mmbuf_andgt",
+ "aclk_mux_mmbuf", "aclk_mux_mmbuf"};
+
+static const struct hisi_mux_clock hi3660_sctrl_mux_clks[] = {
+ { HI3660_ACLK_MUX_MMBUF, "aclk_mux_mmbuf", aclk_mux_mmbuf_p,
+ ARRAY_SIZE(aclk_mux_mmbuf_p), CLK_SET_RATE_PARENT, 0x250, 12, 1,
+ CLK_MUX_HIWORD_MASK, },
+ { HI3660_CLK_SW_MMBUF, "clk_sw_mmbuf", clk_sw_mmbuf_p,
+ ARRAY_SIZE(clk_sw_mmbuf_p), CLK_SET_RATE_PARENT, 0x258, 8, 2,
+ CLK_MUX_HIWORD_MASK, },
+};
+
+static const struct hisi_divider_clock hi3660_sctrl_divider_clks[] = {
+ { HI3660_CLK_DIV_AOBUS, "clk_div_aobus", "clk_ppll0",
+ CLK_SET_RATE_PARENT, 0x254, 0, 6, CLK_DIVIDER_HIWORD_MASK, 0, },
+ { HI3660_PCLK_DIV_MMBUF, "pclk_div_mmbuf", "pclk_mmbuf_andgt",
+ CLK_SET_RATE_PARENT, 0x258, 10, 2, CLK_DIVIDER_HIWORD_MASK, 0, },
+ { HI3660_ACLK_DIV_MMBUF, "aclk_div_mmbuf", "clk_mmbuf_pll_andgt",
+ CLK_SET_RATE_PARENT, 0x258, 12, 4, CLK_DIVIDER_HIWORD_MASK, 0, },
+ { HI3660_CLK_DIV_PCIEPHY, "clk_div_pciephy", "clk_gate_pciephy_gt",
+ CLK_SET_RATE_PARENT, 0x268, 12, 4, CLK_DIVIDER_HIWORD_MASK, 0, },
+};
+
+/* clk_iomcu */
+static const struct hisi_gate_clock hi3660_iomcu_gate_sep_clks[] = {
+ { HI3660_CLK_I2C0_IOMCU, "clk_i2c0_iomcu", "clk_fll_src",
+ CLK_SET_RATE_PARENT, 0x10, 3, 0, },
+ { HI3660_CLK_I2C1_IOMCU, "clk_i2c1_iomcu", "clk_fll_src",
+ CLK_SET_RATE_PARENT, 0x10, 4, 0, },
+ { HI3660_CLK_I2C2_IOMCU, "clk_i2c2_iomcu", "clk_fll_src",
+ CLK_SET_RATE_PARENT, 0x10, 5, 0, },
+ { HI3660_CLK_I2C6_IOMCU, "clk_i2c6_iomcu", "clk_fll_src",
+ CLK_SET_RATE_PARENT, 0x10, 27, 0, },
+ { HI3660_CLK_IOMCU_PERI0, "iomcu_peri0", "clk_ppll0",
+ CLK_SET_RATE_PARENT, 0x90, 0, 0, },
+};
+
+static void hi3660_clk_iomcu_init(struct device_node *np)
+{
+ struct hisi_clock_data *clk_data;
+ int nr = ARRAY_SIZE(hi3660_iomcu_gate_sep_clks);
+
+ clk_data = hisi_clk_init(np, nr);
+ if (!clk_data)
+ return;
+
+ hisi_clk_register_gate_sep(hi3660_iomcu_gate_sep_clks,
+ ARRAY_SIZE(hi3660_iomcu_gate_sep_clks),
+ clk_data);
+}
+
+static void hi3660_clk_pmuctrl_init(struct device_node *np)
+{
+ struct hisi_clock_data *clk_data;
+ int nr = ARRAY_SIZE(hi3660_pmu_gate_clks);
+
+ clk_data = hisi_clk_init(np, nr);
+ if (!clk_data)
+ return;
+
+ hisi_clk_register_gate(hi3660_pmu_gate_clks,
+ ARRAY_SIZE(hi3660_pmu_gate_clks), clk_data);
+}
+
+static void hi3660_clk_pctrl_init(struct device_node *np)
+{
+ struct hisi_clock_data *clk_data;
+ int nr = ARRAY_SIZE(hi3660_pctrl_gate_clks);
+
+ clk_data = hisi_clk_init(np, nr);
+ if (!clk_data)
+ return;
+ hisi_clk_register_gate(hi3660_pctrl_gate_clks,
+ ARRAY_SIZE(hi3660_pctrl_gate_clks), clk_data);
+}
+
+static void hi3660_clk_sctrl_init(struct device_node *np)
+{
+ struct hisi_clock_data *clk_data;
+ int nr = ARRAY_SIZE(hi3660_sctrl_gate_clks) +
+ ARRAY_SIZE(hi3660_sctrl_gate_sep_clks) +
+ ARRAY_SIZE(hi3660_sctrl_mux_clks) +
+ ARRAY_SIZE(hi3660_sctrl_divider_clks);
+
+ clk_data = hisi_clk_init(np, nr);
+ if (!clk_data)
+ return;
+ hisi_clk_register_gate(hi3660_sctrl_gate_clks,
+ ARRAY_SIZE(hi3660_sctrl_gate_clks), clk_data);
+ hisi_clk_register_gate_sep(hi3660_sctrl_gate_sep_clks,
+ ARRAY_SIZE(hi3660_sctrl_gate_sep_clks),
+ clk_data);
+ hisi_clk_register_mux(hi3660_sctrl_mux_clks,
+ ARRAY_SIZE(hi3660_sctrl_mux_clks), clk_data);
+ hisi_clk_register_divider(hi3660_sctrl_divider_clks,
+ ARRAY_SIZE(hi3660_sctrl_divider_clks),
+ clk_data);
+}
+
+static void hi3660_clk_crgctrl_init(struct device_node *np)
+{
+ struct hisi_clock_data *clk_data;
+ int nr = ARRAY_SIZE(hi3660_fixed_rate_clks) +
+ ARRAY_SIZE(hi3660_crgctrl_gate_sep_clks) +
+ ARRAY_SIZE(hi3660_crgctrl_gate_clks) +
+ ARRAY_SIZE(hi3660_crgctrl_mux_clks) +
+ ARRAY_SIZE(hi3660_crg_fixed_factor_clks) +
+ ARRAY_SIZE(hi3660_crgctrl_divider_clks);
+
+ clk_data = hisi_clk_init(np, nr);
+ if (!clk_data)
+ return;
+
+ hisi_clk_register_fixed_rate(hi3660_fixed_rate_clks,
+ ARRAY_SIZE(hi3660_fixed_rate_clks),
+ clk_data);
+ hisi_clk_register_gate_sep(hi3660_crgctrl_gate_sep_clks,
+ ARRAY_SIZE(hi3660_crgctrl_gate_sep_clks),
+ clk_data);
+ hisi_clk_register_gate(hi3660_crgctrl_gate_clks,
+ ARRAY_SIZE(hi3660_crgctrl_gate_clks),
+ clk_data);
+ hisi_clk_register_mux(hi3660_crgctrl_mux_clks,
+ ARRAY_SIZE(hi3660_crgctrl_mux_clks),
+ clk_data);
+ hisi_clk_register_fixed_factor(hi3660_crg_fixed_factor_clks,
+ ARRAY_SIZE(hi3660_crg_fixed_factor_clks),
+ clk_data);
+ hisi_clk_register_divider(hi3660_crgctrl_divider_clks,
+ ARRAY_SIZE(hi3660_crgctrl_divider_clks),
+ clk_data);
+}
+
+static const struct of_device_id hi3660_clk_match_table[] = {
+ { .compatible = "hisilicon,hi3660-crgctrl",
+ .data = (void *)HI3660_CRGCTRL },
+ { .compatible = "hisilicon,hi3660-pctrl",
+ .data = (void *)HI3660_PCTRL },
+ { .compatible = "hisilicon,hi3660-pmuctrl",
+ .data = (void *)HI3660_PMUCTRL },
+ { .compatible = "hisilicon,hi3660-sctrl",
+ .data = (void *)HI3660_SCTRL },
+ { .compatible = "hisilicon,hi3660-iomcu",
+ .data = (void *)HI3660_IOMCU },
+ { }
+};
+MODULE_DEVICE_TABLE(of, hi3660_clk_match_table);
+
+static int hi3660_clk_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device_node *np = pdev->dev.of_node;
+ const struct of_device_id *of_id;
+ enum hi3660_clk_type type;
+
+ of_id = of_match_device(hi3660_clk_match_table, dev);
+ if (!of_id)
+ return -EINVAL;
+
+ type = (enum hi3660_clk_type)of_id->data;
+
+ switch (type) {
+ case HI3660_CRGCTRL:
+ hi3660_clk_crgctrl_init(np);
+ break;
+ case HI3660_PCTRL:
+ hi3660_clk_pctrl_init(np);
+ break;
+ case HI3660_PMUCTRL:
+ hi3660_clk_pmuctrl_init(np);
+ break;
+ case HI3660_SCTRL:
+ hi3660_clk_sctrl_init(np);
+ break;
+ case HI3660_IOMCU:
+ hi3660_clk_iomcu_init(np);
+ break;
+ default:
+ break;
+ }
+ return 0;
+}
+
+static struct platform_driver hi3660_clk_driver = {
+ .probe = hi3660_clk_probe,
+ .driver = {
+ .name = "hi3660-clk",
+ .of_match_table = hi3660_clk_match_table,
+ },
+};
+
+static int __init hi3660_clk_init(void)
+{
+ return platform_driver_register(&hi3660_clk_driver);
+}
+core_initcall(hi3660_clk_init);
+
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:hi3660-clk");
+MODULE_DESCRIPTION("HiSilicon Hi3660 Clock Driver");
diff --git a/include/dt-bindings/clock/hi3660-clock.h b/include/dt-bindings/clock/hi3660-clock.h
new file mode 100644
index 0000000..1c00b7f
--- /dev/null
+++ b/include/dt-bindings/clock/hi3660-clock.h
@@ -0,0 +1,194 @@
+/*
+ * Copyright (c) 2016-2017 Linaro Ltd.
+ * Copyright (c) 2016-2017 HiSilicon Technologies Co., Ltd.
+ *
+ * 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.
+ */
+
+#ifndef __DTS_HI3660_CLOCK_H
+#define __DTS_HI3660_CLOCK_H
+
+/* fixed rate clocks */
+#define HI3660_CLKIN_SYS 0
+#define HI3660_CLKIN_REF 1
+#define HI3660_CLK_FLL_SRC 2
+#define HI3660_CLK_PPLL0 3
+#define HI3660_CLK_PPLL1 4
+#define HI3660_CLK_PPLL2 5
+#define HI3660_CLK_PPLL3 6
+#define HI3660_CLK_SCPLL 7
+#define HI3660_PCLK 8
+#define HI3660_CLK_UART0_DBG 9
+#define HI3660_CLK_UART6 10
+#define HI3660_OSC32K 11
+#define HI3660_OSC19M 12
+#define HI3660_CLK_480M 13
+#define HI3660_CLK_INV 14
+
+/* clk in crgctrl */
+#define HI3660_FACTOR_UART3 15
+#define HI3660_CLK_FACTOR_MMC 16
+#define HI3660_CLK_GATE_I2C0 17
+#define HI3660_CLK_GATE_I2C1 18
+#define HI3660_CLK_GATE_I2C2 19
+#define HI3660_CLK_GATE_I2C6 20
+#define HI3660_CLK_DIV_SYSBUS 21
+#define HI3660_CLK_DIV_320M 22
+#define HI3660_CLK_DIV_A53 23
+#define HI3660_CLK_GATE_SPI0 24
+#define HI3660_CLK_GATE_SPI2 25
+#define HI3660_PCIEPHY_REF 26
+#define HI3660_CLK_ABB_USB 27
+#define HI3660_HCLK_GATE_SDIO0 28
+#define HI3660_HCLK_GATE_SD 29
+#define HI3660_CLK_GATE_AOMM 30
+#define HI3660_PCLK_GPIO0 31
+#define HI3660_PCLK_GPIO1 32
+#define HI3660_PCLK_GPIO2 33
+#define HI3660_PCLK_GPIO3 34
+#define HI3660_PCLK_GPIO4 35
+#define HI3660_PCLK_GPIO5 36
+#define HI3660_PCLK_GPIO6 37
+#define HI3660_PCLK_GPIO7 38
+#define HI3660_PCLK_GPIO8 39
+#define HI3660_PCLK_GPIO9 40
+#define HI3660_PCLK_GPIO10 41
+#define HI3660_PCLK_GPIO11 42
+#define HI3660_PCLK_GPIO12 43
+#define HI3660_PCLK_GPIO13 44
+#define HI3660_PCLK_GPIO14 45
+#define HI3660_PCLK_GPIO15 46
+#define HI3660_PCLK_GPIO16 47
+#define HI3660_PCLK_GPIO17 48
+#define HI3660_PCLK_GPIO18 49
+#define HI3660_PCLK_GPIO19 50
+#define HI3660_PCLK_GPIO20 51
+#define HI3660_PCLK_GPIO21 52
+#define HI3660_CLK_GATE_SPI3 53
+#define HI3660_CLK_GATE_I2C7 54
+#define HI3660_CLK_GATE_I2C3 55
+#define HI3660_CLK_GATE_SPI1 56
+#define HI3660_CLK_GATE_UART1 57
+#define HI3660_CLK_GATE_UART2 58
+#define HI3660_CLK_GATE_UART4 59
+#define HI3660_CLK_GATE_UART5 60
+#define HI3660_CLK_GATE_I2C4 61
+#define HI3660_CLK_GATE_DMAC 62
+#define HI3660_PCLK_GATE_DSS 63
+#define HI3660_ACLK_GATE_DSS 64
+#define HI3660_CLK_GATE_LDI1 65
+#define HI3660_CLK_GATE_LDI0 66
+#define HI3660_CLK_GATE_VIVOBUS 67
+#define HI3660_CLK_GATE_EDC0 68
+#define HI3660_CLK_GATE_TXDPHY0_CFG 69
+#define HI3660_CLK_GATE_TXDPHY0_REF 70
+#define HI3660_CLK_GATE_TXDPHY1_CFG 71
+#define HI3660_CLK_GATE_TXDPHY1_REF 72
+#define HI3660_ACLK_GATE_USB3OTG 73
+#define HI3660_CLK_GATE_SPI4 74
+#define HI3660_CLK_GATE_SD 75
+#define HI3660_CLK_GATE_SDIO0 76
+#define HI3660_CLK_GATE_UFS_SUBSYS 77
+#define HI3660_PCLK_GATE_DSI0 78
+#define HI3660_PCLK_GATE_DSI1 79
+#define HI3660_ACLK_GATE_PCIE 80
+#define HI3660_PCLK_GATE_PCIE_SYS 81
+#define HI3660_CLK_GATE_PCIEAUX 82
+#define HI3660_PCLK_GATE_PCIE_PHY 83
+#define HI3660_CLK_ANDGT_LDI0 84
+#define HI3660_CLK_ANDGT_LDI1 85
+#define HI3660_CLK_ANDGT_EDC0 86
+#define HI3660_CLK_GATE_UFSPHY_GT 87
+#define HI3660_CLK_ANDGT_MMC 88
+#define HI3660_CLK_ANDGT_SD 89
+#define HI3660_CLK_A53HPM_ANDGT 90
+#define HI3660_CLK_ANDGT_SDIO 91
+#define HI3660_CLK_ANDGT_UART0 92
+#define HI3660_CLK_ANDGT_UART1 93
+#define HI3660_CLK_ANDGT_UARTH 94
+#define HI3660_CLK_ANDGT_SPI 95
+#define HI3660_CLK_VIVOBUS_ANDGT 96
+#define HI3660_CLK_AOMM_ANDGT 97
+#define HI3660_CLK_320M_PLL_GT 98
+#define HI3660_AUTODIV_EMMC0BUS 99
+#define HI3660_AUTODIV_SYSBUS 100
+#define HI3660_CLK_GATE_UFSPHY_CFG 101
+#define HI3660_CLK_GATE_UFSIO_REF 102
+#define HI3660_CLK_MUX_SYSBUS 103
+#define HI3660_CLK_MUX_UART0 104
+#define HI3660_CLK_MUX_UART1 105
+#define HI3660_CLK_MUX_UARTH 106
+#define HI3660_CLK_MUX_SPI 107
+#define HI3660_CLK_MUX_I2C 108
+#define HI3660_CLK_MUX_MMC_PLL 109
+#define HI3660_CLK_MUX_LDI1 110
+#define HI3660_CLK_MUX_LDI0 111
+#define HI3660_CLK_MUX_SD_PLL 112
+#define HI3660_CLK_MUX_SD_SYS 113
+#define HI3660_CLK_MUX_EDC0 114
+#define HI3660_CLK_MUX_SDIO_SYS 115
+#define HI3660_CLK_MUX_SDIO_PLL 116
+#define HI3660_CLK_MUX_VIVOBUS 117
+#define HI3660_CLK_MUX_A53HPM 118
+#define HI3660_CLK_MUX_320M 119
+#define HI3660_CLK_MUX_IOPERI 120
+#define HI3660_CLK_DIV_UART0 121
+#define HI3660_CLK_DIV_UART1 122
+#define HI3660_CLK_DIV_UARTH 123
+#define HI3660_CLK_DIV_MMC 124
+#define HI3660_CLK_DIV_SD 125
+#define HI3660_CLK_DIV_EDC0 126
+#define HI3660_CLK_DIV_LDI0 127
+#define HI3660_CLK_DIV_SDIO 128
+#define HI3660_CLK_DIV_LDI1 129
+#define HI3660_CLK_DIV_SPI 130
+#define HI3660_CLK_DIV_VIVOBUS 131
+#define HI3660_CLK_DIV_I2C 132
+#define HI3660_CLK_DIV_UFSPHY 133
+#define HI3660_CLK_DIV_CFGBUS 134
+#define HI3660_CLK_DIV_MMC0BUS 135
+#define HI3660_CLK_DIV_MMC1BUS 136
+#define HI3660_CLK_DIV_UFSPERI 137
+#define HI3660_CLK_DIV_AOMM 138
+#define HI3660_CLK_DIV_IOPERI 139
+
+/* clk in pmuctrl */
+#define HI3660_GATE_ABB_192 0
+
+/* clk in pctrl */
+#define HI3660_GATE_UFS_TCXO_EN 0
+#define HI3660_GATE_USB_TCXO_EN 1
+
+/* clk in sctrl */
+#define HI3660_PCLK_AO_GPIO0 0
+#define HI3660_PCLK_AO_GPIO1 1
+#define HI3660_PCLK_AO_GPIO2 2
+#define HI3660_PCLK_AO_GPIO3 3
+#define HI3660_PCLK_AO_GPIO4 4
+#define HI3660_PCLK_AO_GPIO5 5
+#define HI3660_PCLK_AO_GPIO6 6
+#define HI3660_PCLK_GATE_MMBUF 7
+#define HI3660_CLK_GATE_DSS_AXI_MM 8
+#define HI3660_PCLK_MMBUF_ANDGT 9
+#define HI3660_CLK_MMBUF_PLL_ANDGT 10
+#define HI3660_CLK_FLL_MMBUF_ANDGT 11
+#define HI3660_CLK_SYS_MMBUF_ANDGT 12
+#define HI3660_CLK_GATE_PCIEPHY_GT 13
+#define HI3660_ACLK_MUX_MMBUF 14
+#define HI3660_CLK_SW_MMBUF 15
+#define HI3660_CLK_DIV_AOBUS 16
+#define HI3660_PCLK_DIV_MMBUF 17
+#define HI3660_ACLK_DIV_MMBUF 18
+#define HI3660_CLK_DIV_PCIEPHY 19
+
+/* clk in iomcu */
+#define HI3660_CLK_I2C0_IOMCU 0
+#define HI3660_CLK_I2C1_IOMCU 1
+#define HI3660_CLK_I2C2_IOMCU 2
+#define HI3660_CLK_I2C6_IOMCU 3
+#define HI3660_CLK_IOMCU_PERI0 4
+
+#endif /* __DTS_HI3660_CLOCK_H */
--
2.7.4
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH 1/2] dt-bindings: Document the hi3660 clock bindings
From: Zhangfei Gao @ 2016-12-15 5:58 UTC (permalink / raw)
To: Stephen Boyd, Rob Herring, Arnd Bergmann,
haojian.zhuang-QSEj5FYQhm4dnm+yROfE0A, guodong Xu
Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
devicetree-u79uwXL29TY76Z2rM5mHXA, Zhangfei Gao
In-Reply-To: <1481781493-6188-1-git-send-email-zhangfei.gao-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
Add DT bindings documentation for hi3660 SoC clock.
Signed-off-by: Zhangfei Gao <zhangfei.gao-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
---
.../devicetree/bindings/clock/hi3660-clock.txt | 42 ++++++++++++++++++++++
1 file changed, 42 insertions(+)
create mode 100644 Documentation/devicetree/bindings/clock/hi3660-clock.txt
diff --git a/Documentation/devicetree/bindings/clock/hi3660-clock.txt b/Documentation/devicetree/bindings/clock/hi3660-clock.txt
new file mode 100644
index 0000000..7296fd7
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/hi3660-clock.txt
@@ -0,0 +1,42 @@
+* Hisilicon Hi3660 Clock Controller
+
+The Hi3660 clock controller generates and supplies clock to various
+controllers within the Hi3660 SoC.
+
+Required Properties:
+
+- compatible: the compatible should be one of the following strings to
+ indicate the clock controller functionality.
+
+ - "hisilicon,hi3660-crgctrl"
+ - "hisilicon,hi3660-pctrl"
+ - "hisilicon,hi3660-pmuctrl"
+ - "hisilicon,hi3660-sctrl"
+ - "hisilicon,hi3660-iomcu"
+
+- reg: physical base address of the controller and length of memory mapped
+ region.
+
+- #clock-cells: should be 1.
+
+Each clock is assigned an identifier and client nodes use this identifier
+to specify the clock which they consume.
+
+All these identifier could be found in <dt-bindings/clock/hi3660-clock.h>.
+
+Examples:
+ crg_ctrl: crg_ctrl@fff35000 {
+ compatible = "hisilicon,hi3660-crgctrl", "syscon";
+ reg = <0x0 0xfff35000 0x0 0x1000>;
+ #clock-cells = <1>;
+ };
+
+ uart0: uart@fdf02000 {
+ compatible = "arm,pl011", "arm,primecell";
+ reg = <0x0 0xfdf02000 0x0 0x1000>;
+ interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&crg_ctrl HI3660_CLK_MUX_UART0>,
+ <&crg_ctrl HI3660_PCLK>;
+ clock-names = "uartclk", "apb_pclk";
+ status = "disabled";
+ };
--
2.7.4
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH 0/2] add clk-hi3660
From: Zhangfei Gao @ 2016-12-15 5:58 UTC (permalink / raw)
To: Stephen Boyd, Rob Herring, Arnd Bergmann,
haojian.zhuang-QSEj5FYQhm4dnm+yROfE0A, guodong Xu
Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
devicetree-u79uwXL29TY76Z2rM5mHXA, Zhangfei Gao
Zhangfei Gao (2):
dt-bindings: Document the hi3660 clock bindings
clk: hi3660: Clock driver support for Hisilicon hi3660 SoC
.../devicetree/bindings/clock/hi3660-clock.txt | 25 +
drivers/clk/hisilicon/Kconfig | 7 +
drivers/clk/hisilicon/Makefile | 1 +
drivers/clk/hisilicon/clk-hi3660.c | 601 +++++++++++++++++++++
include/dt-bindings/clock/hi3660-clock.h | 194 +++++++
5 files changed, 828 insertions(+)
create mode 100644 Documentation/devicetree/bindings/clock/hi3660-clock.txt
create mode 100644 drivers/clk/hisilicon/clk-hi3660.c
create mode 100644 include/dt-bindings/clock/hi3660-clock.h
--
2.7.4
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH v2 1/5] clk: samsung: exynos5433: Set NoC (Network On Chip) clocks as critical
From: Chanwoo Choi @ 2016-12-15 4:33 UTC (permalink / raw)
To: krzk, javier, kgene, robh+dt, s.nawrocki, tomasz.figa
Cc: myungjoo.ham, kyungmin.park, devicetree, linux-samsung-soc,
linux-arm-kernel, linux-kernel, Michael Turquette, Stephen Boyd
In-Reply-To: <1481173091-9728-2-git-send-email-cw00.choi@samsung.com>
Dear Sylwester,
Could you please review this patch?
--
Regards,
Chanwoo Choi
On 2016년 12월 08일 13:58, Chanwoo Choi wrote:
> The ACLK_BUS0/1/2 are used for NoC (Network on Chip). If NoC's clocks are
> disabled, the system halt happen. Following clock must be always enabled.
> - CLK_ACLK_BUS0_400 : NoC's bus clock for PERIC/PERIS/FSYS/MSCL
> - CLK_ACLK_BUS1_400 : NoC's bus clock for MFC/HEVC/G3D
> - CLK_ACLK_BUS2_400 : NoC's bus clock for GSCL/DISP/G2D/CAM0/CAM1/ISP
>
> Also, this patch adds the CLK_SET_RATE_PARENT flag to the CLK_SCLK_JPEG_MSCL
> because this clock should be used for bus frequency scaling. This clock need to
> be changed on the fly with CLK_SET_RATE_PARENT flag.
>
> Cc: Sylwester Nawrocki <s.nawrocki@samsung.com>
> Cc: Tomasz Figa <tomasz.figa@gmail.com>
> Cc: Chanwoo Choi <cw00.choi@samsung.com>
> Cc: Michael Turquette <mturquette@baylibre.com>
> Cc: Stephen Boyd <sboyd@codeaurora.org>
> Cc:linux-clk@vger.kernel.org
> Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com>
> ---
> drivers/clk/samsung/clk-exynos5433.c | 8 ++++----
> 1 file changed, 4 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/clk/samsung/clk-exynos5433.c b/drivers/clk/samsung/clk-exynos5433.c
> index f096bd7df40c..0db5204c307c 100644
> --- a/drivers/clk/samsung/clk-exynos5433.c
> +++ b/drivers/clk/samsung/clk-exynos5433.c
> @@ -549,10 +549,10 @@
> 29, CLK_IGNORE_UNUSED, 0),
> GATE(CLK_ACLK_BUS0_400, "aclk_bus0_400", "div_aclk_bus0_400",
> ENABLE_ACLK_TOP, 26,
> - CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0),
> + CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, 0),
> GATE(CLK_ACLK_BUS1_400, "aclk_bus1_400", "div_aclk_bus1_400",
> ENABLE_ACLK_TOP, 25,
> - CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0),
> + CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, 0),
> GATE(CLK_ACLK_IMEM_200, "aclk_imem_200", "div_aclk_imem_266",
> ENABLE_ACLK_TOP, 24,
> CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, 0),
> @@ -616,7 +616,7 @@
>
> /* ENABLE_SCLK_TOP_MSCL */
> GATE(CLK_SCLK_JPEG_MSCL, "sclk_jpeg_mscl", "div_sclk_jpeg",
> - ENABLE_SCLK_TOP_MSCL, 0, 0, 0),
> + ENABLE_SCLK_TOP_MSCL, 0, CLK_SET_RATE_PARENT, 0),
>
> /* ENABLE_SCLK_TOP_CAM1 */
> GATE(CLK_SCLK_ISP_SENSOR2, "sclk_isp_sensor2", "div_sclk_isp_sensor2_b",
> @@ -1382,7 +1382,7 @@ static void __init exynos5433_cmu_cpif_init(struct device_node *np)
> /* ENABLE_ACLK_MIF3 */
> GATE(CLK_ACLK_BUS2_400, "aclk_bus2_400", "div_aclk_bus2_400",
> ENABLE_ACLK_MIF3, 4,
> - CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0),
> + CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, 0),
> GATE(CLK_ACLK_DISP_333, "aclk_disp_333", "div_aclk_disp_333",
> ENABLE_ACLK_MIF3, 1,
> CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, 0),
>
^ permalink raw reply
* Re: [PATCH 0/6] USB support for Broadcom NSP SoC
From: Yendapally Reddy Dhananjaya Reddy @ 2016-12-15 3:30 UTC (permalink / raw)
To: Florian Fainelli
Cc: Rob Herring, Mark Rutland, Russell King, Ray Jui, Scott Branden,
Jon Mason, Kishon Vijay Abraham I, BCM Kernel Feedback, netdev,
devicetree, linux-kernel, linux-arm-kernel
On Tue, Dec 13, 2016 at 7:50 AM, Florian Fainelli <f.fainelli@gmail.com> wrote:
> On 11/09/2016 01:33 AM, Yendapally Reddy Dhananjaya Reddy wrote:
>> This patch set contains the usb support for Broadcom NSP SoC.
>> The usb phy is connected through mdio interface. The mdio interface
>> can be used to access either internal phys or external phys using a
>> multiplexer.
>>
>> The first patch provides the documentation details for mdio-mux and
>> second patch provides the documentation details for usb3 phy. The third
>> patch contains the mdio-mux support and fourth patch contains the
>> changes to the mdio bus driver.
>>
>> The fifth patch provides the phy driver and sixth patch provides the
>> enable method for usb.
>>
>> This patch series has been tested on NSP bcm958625HR board.
>> This patch series is based on v4.9.0-rc1 and is available from github-
>> repo: https://github.com/Broadcom/cygnus-linux.git
>> branch:nsp-usb-v1
>
> Can you resubmit this patch series with the feedback from Andrew, Rob
> and Scott addressed?
>
> Thanks!
Hi Florian,
I addressed all the comments. The change suggested by Andrew requires the
latest patches of "mdio-mux-mmioreg" available in "net-next". I need to wait
until these changes are in mainline.
Thanks
Dhananjay
> --
> Florian
^ permalink raw reply
* Re: [PATCH 2/3] Bluetooth: btusb: Add out-of-band wakeup support
From: Brian Norris @ 2016-12-15 3:21 UTC (permalink / raw)
To: Rajat Jain
Cc: Rob Herring, Mark Rutland, Marcel Holtmann, Gustavo Padovan,
Johan Hedberg, Amitkumar Karwar, Wei-Ning Huang, Xinming Hu,
netdev-u79uwXL29TY76Z2rM5mHXA, devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-bluetooth-u79uwXL29TY76Z2rM5mHXA,
rajatxjain-Re5JQEeQqe8AvxtiuMwx3w
In-Reply-To: <1481742779-15105-2-git-send-email-rajatja-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org>
Hi,
On Wed, Dec 14, 2016 at 11:12:58AM -0800, Rajat Jain wrote:
> Some BT chips (e.g. Marvell 8997) contain a wakeup pin that can be
> connected to a gpio on the CPU side, and can be used to wakeup
> the host out-of-band. This can be useful in situations where the
> in-band wakeup is not possible or not preferable (e.g. the in-band
> wakeup may require the USB host controller to remain active, and
> hence consuming more system power during system sleep).
>
> The oob gpio interrupt to be used for wakeup on the CPU side, is
> read from the device tree node, (using standard interrupt descriptors).
> A devcie tree binding document is also added for the driver.
>
> Signed-off-by: Rajat Jain <rajatja-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org>
> ---
> Documentation/devicetree/bindings/net/btusb.txt | 38 ++++++++++++
> drivers/bluetooth/btusb.c | 82 +++++++++++++++++++++++++
> 2 files changed, 120 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/net/btusb.txt
>
> diff --git a/Documentation/devicetree/bindings/net/btusb.txt b/Documentation/devicetree/bindings/net/btusb.txt
> new file mode 100644
> index 0000000..bb27f92
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/net/btusb.txt
> @@ -0,0 +1,38 @@
> +Generic Bluetooth controller over USB (btusb driver)
> +---------------------------------------------------
> +
> +Required properties:
> +
> + - compatible : should comply with the format "usbVID,PID" specified in
> + Documentation/devicetree/bindings/usb/usb-device.txt
> + At the time of writing, the only OF supported devices
> + (more may be added later) are:
> +
> + "usb1286,204e" (Marvell 8997)
> +
> +Optional properties:
> +
> + - interrupt-parent: phandle of the parent interrupt controller
> + - interrupts : The first interrupt specified is the interrupt that shall be
> + used for out-of-band wake-on-bt. Driver will request an irq
> + based on this interrupt number. During system suspend, the irq
> + will be enabled so that the bluetooth chip can wakeup host
> + platform out of band. During system resume, the irq will be
> + disabled to make sure unnecessary interrupt is not received.
Might it be worthwhile to define an 'interrupt-names' property (e.g., =
"wakeup") to help future-proof this?
> +
> +Example:
> +
> +Following example uses irq pin number 3 of gpio0 for out of band wake-on-bt:
> +
> +&usb_host1_ehci {
> + status = "okay";
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + mvl_bt1: bt@1 {
> + compatible = "usb1286,204e";
> + reg = <1>;
> + interrupt-parent = <&gpio0>;
> + interrupts = <3 IRQ_TYPE_LEVEL_LOW>;
> + };
> +};
> diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
> index ce22cef..32a6f22 100644
> --- a/drivers/bluetooth/btusb.c
> +++ b/drivers/bluetooth/btusb.c
> @@ -24,6 +24,8 @@
> #include <linux/module.h>
> #include <linux/usb.h>
> #include <linux/firmware.h>
> +#include <linux/of_device.h>
> +#include <linux/of_irq.h>
> #include <asm/unaligned.h>
>
> #include <net/bluetooth/bluetooth.h>
> @@ -369,6 +371,7 @@ static const struct usb_device_id blacklist_table[] = {
> #define BTUSB_BOOTING 9
> #define BTUSB_RESET_RESUME 10
> #define BTUSB_DIAG_RUNNING 11
> +#define BTUSB_OOB_WAKE_DISABLED 12
>
> struct btusb_data {
> struct hci_dev *hdev;
> @@ -416,6 +419,8 @@ struct btusb_data {
> int (*recv_bulk)(struct btusb_data *data, void *buffer, int count);
>
> int (*setup_on_usb)(struct hci_dev *hdev);
> +
> + int oob_wake_irq; /* irq for out-of-band wake-on-bt */
> };
>
> static inline void btusb_free_frags(struct btusb_data *data)
> @@ -2728,6 +2733,65 @@ static int btusb_bcm_set_diag(struct hci_dev *hdev, bool enable)
> }
> #endif
>
> +#ifdef CONFIG_PM
> +static irqreturn_t btusb_oob_wake_handler(int irq, void *priv)
> +{
> + struct btusb_data *data = priv;
> +
> + /* Disable only if not already disabled (keep it balanced) */
> + if (!test_and_set_bit(BTUSB_OOB_WAKE_DISABLED, &data->flags)) {
> + disable_irq_wake(irq);
> + disable_irq_nosync(irq);
> + }
> + pm_wakeup_event(&data->udev->dev, 0);
> + return IRQ_HANDLED;
> +}
> +
> +static const struct of_device_id btusb_match_table[] = {
> + { .compatible = "usb1286,204e" },
> + { }
> +};
> +MODULE_DEVICE_TABLE(of, btusb_match_table);
> +
> +/* Use an oob wakeup pin? */
> +static int btusb_config_oob_wake(struct hci_dev *hdev)
> +{
> + struct btusb_data *data = hci_get_drvdata(hdev);
> + struct device *dev = &data->udev->dev;
> + int irq, ret;
> +
> + if (!of_match_device(btusb_match_table, dev))
> + return 0;
> +
> + /* Move on if no IRQ specified */
> + irq = irq_of_parse_and_map(dev->of_node, 0);
Better to use of_irq_get{,_byname}(), no?
> + if (!irq) {
> + bt_dev_dbg(hdev, "%s: no oob wake irq in DT", __func__);
> + return 0;
> + }
> +
> + set_bit(BTUSB_OOB_WAKE_DISABLED, &data->flags);
> +
> + ret = devm_request_irq(&hdev->dev, irq, btusb_oob_wake_handler,
> + IRQF_TRIGGER_LOW, "oob wake-on-bt", data);
You're assuming this is level-triggered, and active-low? Can't this just
be specified in the device tree and just pass 0 here?
Also, it seems like it would be a lot more convenient if we could treat
this as edge-triggered, so we don't have to do the set/clear flags,
disable IRQ, etc., dance. You'd just have to change the device tree
definition. Is there any downside to doing that?
It would also then be a better candidate for using something like
dev_pm_set_dedicated_wake_irq() (although last time I tried using that,
it didn't do so great if you don't have autosuspend enabled -- but I
think there are patches outstanding for that; so maybe not yet).
> + if (ret) {
> + bt_dev_err(hdev, "%s: irq request failed", __func__);
> + return ret;
> + }
> +
> + ret = device_init_wakeup(dev, true);
> + if (ret) {
> + bt_dev_err(hdev, "%s: failed to init_wakeup\n", __func__);
> + return ret;
> + }
> +
> + data->oob_wake_irq = irq;
> + disable_irq(irq);
> + bt_dev_info(hdev, "oob wake-on-bt configured at irq %u\n", irq);
oob and bt are typically capitalized in strings. And maybe irq too.
Also, you declared irq as 'int', so %d instead of %u.
Brian
> + return 0;
> +}
> +#endif
> +
> static int btusb_probe(struct usb_interface *intf,
> const struct usb_device_id *id)
> {
> @@ -2849,6 +2913,11 @@ static int btusb_probe(struct usb_interface *intf,
> hdev->send = btusb_send_frame;
> hdev->notify = btusb_notify;
>
> +#ifdef CONFIG_PM
> + err = btusb_config_oob_wake(hdev);
> + if (err)
> + goto out_free_dev;
> +#endif
> if (id->driver_info & BTUSB_CW6622)
> set_bit(HCI_QUIRK_BROKEN_STORED_LINK_KEY, &hdev->quirks);
>
> @@ -3089,6 +3158,12 @@ static int btusb_suspend(struct usb_interface *intf, pm_message_t message)
> btusb_stop_traffic(data);
> usb_kill_anchored_urbs(&data->tx_anchor);
>
> + if (data->oob_wake_irq) {
> + clear_bit(BTUSB_OOB_WAKE_DISABLED, &data->flags);
> + enable_irq(data->oob_wake_irq);
> + enable_irq_wake(data->oob_wake_irq);
> + }
> +
> /* Optionally request a device reset on resume, but only when
> * wakeups are disabled. If wakeups are enabled we assume the
> * device will stay powered up throughout suspend.
> @@ -3126,6 +3201,13 @@ static int btusb_resume(struct usb_interface *intf)
> if (--data->suspend_count)
> return 0;
>
> + /* Disable only if not already disabled (keep it balanced) */
> + if (data->oob_wake_irq &&
> + !test_and_set_bit(BTUSB_OOB_WAKE_DISABLED, &data->flags)) {
> + disable_irq_wake(data->oob_wake_irq);
> + disable_irq(data->oob_wake_irq);
> + }
> +
> if (!test_bit(HCI_RUNNING, &hdev->flags))
> goto done;
>
> --
> 2.8.0.rc3.226.g39d4020
>
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH 3/3] arm64: dts: rockchip: add clk-480m for ehci and ohci of rk3399
From: Brian Norris @ 2016-12-15 3:20 UTC (permalink / raw)
To: Xing Zheng
Cc: Doug Anderson, frank.wang-TNX95d0MmH7DzftRWevZcw,
open list:ARM/Rockchip SoC..., Heiko Stübner, William wu,
Rob Herring, Mark Rutland, Catalin Marinas, Will Deacon,
Caesar Wang, Shawn Lin, Jianqun Xu, Elaine Zhang, David Wu,
devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org,
linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
In-Reply-To: <5ce521da-119a-2de8-026c-5992fedfef43-TNX95d0MmH7DzftRWevZcw@public.gmane.org>
On Thu, Dec 15, 2016 at 10:41:04AM +0800, Xing Zheng wrote:
> // Frank
>
> Hi Doug, Brain,
> Thanks for the reply.
> Sorry I forgot these patches have been sent earlier, and Frank
> have some explained and discussed with Heiko.
> Please see https://patchwork.kernel.org/patch/9255245/
> Perhaps we can move to that patch tree to continue the discussion.
>
> I think Frank and William will help us to continue checking these.
I only briefly read that discussion, but AFAICT it doesn't actually
address all the comments/quetions we had here. For instance, the
power_off() vs. delayed-work race in your USB2 PHY driver (is that
intentional?). Also, the question of why PHY (auto?)suspend is relevant.
I'll check again tomorrow.
Brian
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH 3/3] arm64: dts: rockchip: add clk-480m for ehci and ohci of rk3399
From: Xing Zheng @ 2016-12-15 2:41 UTC (permalink / raw)
To: Doug Anderson, Brian Norris, frank.wang-TNX95d0MmH7DzftRWevZcw
Cc: Mark Rutland, devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
Dmitry Torokhov, Heiko Stübner, Catalin Marinas, Shawn Lin,
Elaine Zhang, Will Deacon,
linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
open list:ARM/Rockchip SoC..., Rob Herring, David Wu, William wu,
Jianqun Xu,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org,
Caesar Wang
In-Reply-To: <CAD=FV=UU4JdRjRgEvc_wxprvi6bo46+jd=x2m2QzOe4uJmuRPA-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
// Frank
Hi Doug, Brain,
Thanks for the reply.
Sorry I forgot these patches have been sent earlier, and Frank have
some explained and discussed with Heiko.
Please see https://patchwork.kernel.org/patch/9255245/
Perhaps we can move to that patch tree to continue the discussion.
I think Frank and William will help us to continue checking these.
Thanks
在 2016年12月15日 08:10, Doug Anderson 写道:
> Hi,
>
> On Wed, Dec 14, 2016 at 2:11 AM, Xing Zheng <zhengxing@rock-chips.com> wrote:
>> From: William wu <wulf@rock-chips.com>
>>
>> We found that the suspend process was blocked when it run into
>> ehci/ohci module due to clk-480m of usb2-phy was disabled.
>>
>> The root cause is that usb2-phy suspended earlier than ehci/ohci
>> (usb2-phy will be auto suspended if no devices plug-in).
> This is really weird, but I can confirm it is true on my system too
> (kernel-4.4 based). At least I see:
>
> [ 208.012065] calling usb1+ @ 4984, parent: fe380000.usb, cb: usb_dev_suspend
> [ 208.569112] calling ff770000.syscon:usb2-phy@e450+ @ 4983, parent:
> ff770000.syscon, cb: platform_pm_suspend
> [ 208.569113] call ff770000.syscon:usb2-phy@e450+ returned 0 after 0 usecs
> [ 208.569439] calling fe380000.usb+ @ 4983, parent: platform, cb:
> platform_pm_suspend
> [ 208.569444] call fe380000.usb+ returned 0 after 4 usecs
>
>
> In general I thought that suspend order was supposed to be related to
> probe order. So if your probe order is A, B, C then your suspend
> order would be C, B, A. ...and we know for sure that the USB PHY
> needs to probe _before_ the main USB controller. If it didn't then
> you'd get an EPROBE_DEFER in the USB controller, right? So that means
> that the USB controller should be suspending before its PHY.
>
> Any chance this is somehow related to async probe? I'm not a huge
> expert on async probe but I guess I could imagine things getting
> confused if you had a sequence like this:
>
> 1. Start USB probe (async)
> 2. Start PHY probe
> 3. Finish PHY probe
> 4. In USB probe, ask for PHY--no problems since PHY probe finished
> 5. Finish USB probe
>
> The probe order would be USB before PHY even though the USB probe
> _depended_ on the PHY probe being finished... :-/ Anyway, probably
> I'm just misunderstanding something and someone can tell me how dumb I
> am...
>
> I also notice that the ehci_platform_power_off() function we're
> actually making PHY commands right before the same commands that turn
> off our clocks. Presumably those commands aren't really so good to do
> if the PHY has already been suspended?
>
> Actually, does the PHY suspend from platform_pm_suspend() actually
> even do anything? It doesn't look like it. It looks as if all the
> PHY cares about is init/exit and on/off... ...and it looks as if the
> PHY should be turned off by the EHCI controller at about the same time
> it turns off its clocks...
>
> I haven't fully dug, but is there any chance that things are getting
> confused between the OTG PHY and the Host PHY? Maybe when we turn off
> the OTG PHY it turns off something that the host PHY needs?
>
>
>> and the
>> clk-480m provided by it was disabled if no module used. However,
>> some suspend process related ehci/ohci are base on this clock,
>> so we should refer it into ehci/ohci driver to prevent this case.
> Though I don't actually have details about the internals of the chip,
> it does seem highly likely that the USB block actually uses this clock
> for some things, so it doesn't seem insane (to me) to have the USB
> controller request that the clock be on. So, in general, I don't have
> lots of objections to including the USB PHY Clock here.
>
> ...but I think you have the wrong clock (please correct me if I'm
> wrong). I think you really wanted your input clock to be
> "clk_usbphy0_480m", not "clk_usbphy0_480m_src". Specifically I
> believe there is a gate between the clock outputted by the PHY and the
> USB Controller itself. I'm guessing that the gate is only there
> between the PHY and the "clk_usbphy_480m" MUX.
>
> As evidence, I have a totally functioning system right now where
> "clk_usbphy0_480m_src" is currently gated.
>
> That means really you should be changing your clocks to this (untested):
>
> clocks = <&cru HCLK_HOST0>, <&cru HCLK_HOST0_ARB>,
> <&u2phy0>;
>
> ...and then you could drop the other two patches in this series.
>
> ===
>
> OK, I actually briefly tested my proposed change and it at least seems
> to build and boot OK. You'd have to test it to make sure it makes
> your tests pass...
>
> ===
>
> So I guess to summarize all the above:
>
> * It seems to me like there's some deeper root cause and your patch
> will at most put a band-aid on it. Seems like digging out the root
> cause is a good idea.
>
> * Though I don't believe it solves the root problem, the idea of the
> USB Controller holding onto the PHY clock doesn't seem wrong.
>
> * You're holding onto the wrong clock in your patch--you want the one
> before the gate (I think).
>
>
> -Doug
>
>
>
--
- Xing Zheng
_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip
^ permalink raw reply
* Re: [PATCH 1/2] drm/panel: Add support for S6E3HA2 panel driver on TM2 board
From: hoegeun kwon @ 2016-12-15 1:53 UTC (permalink / raw)
To: Andrzej Hajda, thierry.reding, kgene, krzk
Cc: devicetree, linux-samsung-soc, Donghwa Lee, linux-kernel,
dri-devel, 최찬우, Hyungwon Hwang, Hoegeun Kwon
In-Reply-To: <583d4da7-a3c5-f84f-ba11-1bb1e6890e9b@samsung.com>
On 12/14/2016 11:14 PM, Andrzej Hajda wrote:
> On 14.12.2016 07:04, Hoegeun Kwon wrote:
>> This patch add support for MIPI-DSI based S6E3HA2 AMOLED panel
>> driver. This panel has 1440x2560 resolution in 5.7-inch physical
>> panel in the TM2 device.
>>
>> Signed-off-by: Donghwa Lee <dh09.lee@samsung.com>
>> Signed-off-by: Hyungwon Hwang <human.hwang@samsung.com>
>> Signed-off-by: Hoegeun Kwon <hoegeun.kwon@samsung.com>
> Hi Hoegeun Kwon,
>
> Is there a reason to upstream obsolete driver? Current version of the
> driver is available at [1]. It differs significantly and contains
> multiple fixes and improvements. I guess it still requires some
> polishing but it is better base for start.
>
> [1]:
> https://review.tizen.org/git/?p=platform/kernel/linux-exynos.git;a=blob;f=drivers/gpu/drm/panel/panel-s6e3ha2.c;hb=refs/heads/tizen
>
> Regards
> Andrzej
Hi Andrzej Hajda,
The current driver focus on basic functionality. Therefore, VR and HMT
modes in [1] have been removed from the patch. VR and HMT modes
are added after the basic functions are reflected.
Best Regards,
Hoegeun Kwon
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel
^ permalink raw reply
* Re: [PATCH 4/4] mmc: pwrseq-simple: add disable-post-power-on option
From: Matt Ranostay @ 2016-12-15 1:46 UTC (permalink / raw)
To: Ulf Hansson
Cc: Rob Herring, devicetree@vger.kernel.org,
linux-mmc@vger.kernel.org, Tony Lindgren, Liam Breck
In-Reply-To: <CAPDyKFp2L7x=dV6O5XrA53-OOXE0sf+P3tNH93XGyzNheX9vjQ@mail.gmail.com>
On Tue, Dec 13, 2016 at 12:01 AM, Ulf Hansson <ulf.hansson@linaro.org> wrote:
> On 9 December 2016 at 19:09, Rob Herring <robh@kernel.org> wrote:
>> On Fri, Dec 02, 2016 at 01:06:47AM -0800, Matt Ranostay wrote:
>>> On Fri, Dec 2, 2016 at 12:28 AM, Ulf Hansson <ulf.hansson@linaro.org> wrote:
>>> > On 2 December 2016 at 08:22, Matt Ranostay <matt@ranostay.consulting> wrote:
>>> >>
>>> >>
>>> >>> On Dec 1, 2016, at 23:13, Ulf Hansson <ulf.hansson@linaro.org> wrote:
>>> >>>
>>> >>>> On 2 December 2016 at 07:17, Matt Ranostay <matt@ranostay.consulting> wrote:
>>> >>>> Add optional device-post-power-on parameters to disable post_power_on
>>> >>>> function from being called since this breaks some device.
>>> >>>>
>>> >>>> Cc: Tony Lindgren <tony@atomide.com>
>>> >>>> Cc: Ulf Hansson <ulf.hansson@linaro.org>
>>> >>>> Signed-off-by: Matt Ranostay <matt@ranostay.consulting>
>>> >>>> ---
>>> >>>> Documentation/devicetree/bindings/mmc/mmc-pwrseq-simple.txt | 2 ++
>>> >>>> drivers/mmc/core/pwrseq_simple.c | 7 +++++++
>>> >>>> 2 files changed, 9 insertions(+)
>>> >>>>
>>> >>>> diff --git a/Documentation/devicetree/bindings/mmc/mmc-pwrseq-simple.txt b/Documentation/devicetree/bindings/mmc/mmc-pwrseq-simple.txt
>>> >>>> index bea306d772d1..09fa153f743e 100644
>>> >>>> --- a/Documentation/devicetree/bindings/mmc/mmc-pwrseq-simple.txt
>>> >>>> +++ b/Documentation/devicetree/bindings/mmc/mmc-pwrseq-simple.txt
>>> >>>> @@ -24,6 +24,8 @@ Optional properties:
>>> >>>> de-asserting the reset-gpios (if any)
>>> >>>> - invert-off-state: Invert the power down state for the reset-gpios (if any)
>>> >>>> and pwrdn-gpios (if any)
>>> >>>> +- disable-post-power-on : Avoid post_power_on function from being called since
>>> >>>> + this breaks some devices
>>> >>>
>>> >>> This is a bit weird. I would like to avoid this, if possible.
>>> >>>
>>> >>> Perhaps if you simply describe the sequence in detail for your device
>>> >>> we can figure out the best option together.
>>> >>
>>> >> Yeah I know it is a bit weird but we need to keep that reset pin high for at least some time after pre power on. So any case it would be another property
>>> >
>>> > This went offlist, please resend.
>>> >
>>> > Moreover, please try to describe the sequence you need in detail
>>> > according to your HW spec.
>>> >
>>>
>>> Yeah oops....
>>>
>>> So basically we need to drive the reset and powerdown lines high with
>>> a 300 milliseconds delay between both...
>>> can't have the reset line low with post power on (pretty sure but
>>> would need a delay anyway), and we need both reset + powerdown line
>>> set low on powerdown.
>>>
>>> So the power down sequence would need to be reversed for this
>>> application in pwrseq-simple.
>>
>> This sounds like you need a device specific sequence to me. Otherwise,
>> write a language to describe any power control waveforms rather than
>> trying to bolt on more and more properties. (Don't really go write a
>> language.)
>
> Actually this isn't so device specific. The cw1200 wifi chip which is
> being used with ux500 SoCs has a very similar sequence. Allow me to
> check the details and get back.
Ok. It would be good to have something common than a bunch of one-off
solutions for sure.
>
> Anyway, my point is that I think we can figure out a common sequence
> to support these kind required sequences. That is to me preferred over
> adding a new (two to support cw1200) device specific pwrseq driver.
>
> Kind regards
> Uffe
^ permalink raw reply
* Re: [PATCH 3/3] arm64: dts: rockchip: add clk-480m for ehci and ohci of rk3399
From: Brian Norris @ 2016-12-15 1:18 UTC (permalink / raw)
To: Doug Anderson
Cc: Mark Rutland, devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
Elaine Zhang, Heiko Stübner, Xing Zheng, Catalin Marinas,
Shawn Lin, Dmitry Torokhov, Will Deacon,
linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
open list:ARM/Rockchip SoC..., Rob Herring, David Wu, William wu,
Jianqun Xu,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org,
Caesar Wang
In-Reply-To: <20161215004737.GA32652-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org>
On Wed, Dec 14, 2016 at 04:47:38PM -0800, Brian Norris wrote:
> On Wed, Dec 14, 2016 at 04:10:38PM -0800, Doug Anderson wrote:
> > On Wed, Dec 14, 2016 at 2:11 AM, Xing Zheng <zhengxing-TNX95d0MmH7DzftRWevZcw@public.gmane.org> wrote:
> > > From: William wu <wulf-TNX95d0MmH7DzftRWevZcw@public.gmane.org>
> > >
> > > We found that the suspend process was blocked when it run into
> > > ehci/ohci module due to clk-480m of usb2-phy was disabled.
One more thing: why is the USB2 PHY relevant to the OHCI controller? And
if it is relevant, why isn't there a PHY phandle for it in
usb_host0_ohci and usb_host1_ohci in rk3399.dtsi? As it stands, your
patch is hacking in USB2 clock references for OHCI, but you're not
actually managing the PHY there at all. Seems like you'd want to do
all-or-nothing if there's a functional dependency between the OHCI
controllers and the USB2 PHYs.
Brian
^ permalink raw reply
* Re: [PATCH 3/3] arm64: dts: rockchip: add clk-480m for ehci and ohci of rk3399
From: Brian Norris @ 2016-12-15 0:47 UTC (permalink / raw)
To: Doug Anderson
Cc: Xing Zheng, open list:ARM/Rockchip SoC..., Heiko Stübner,
William wu, Rob Herring, Mark Rutland, Catalin Marinas,
Will Deacon, Caesar Wang, Shawn Lin, Jianqun Xu, Elaine Zhang,
David Wu, devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org,
linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
In-Reply-To: <CAD=FV=UU4JdRjRgEvc_wxprvi6bo46+jd=x2m2QzOe4uJmuRPA-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
Hi,
I think Doug is probably right on most accounts, and I haven't
thoroughly investigated all the claims. But a few thoughts:
On Wed, Dec 14, 2016 at 04:10:38PM -0800, Doug Anderson wrote:
> On Wed, Dec 14, 2016 at 2:11 AM, Xing Zheng <zhengxing-TNX95d0MmH7DzftRWevZcw@public.gmane.org> wrote:
> > From: William wu <wulf-TNX95d0MmH7DzftRWevZcw@public.gmane.org>
> >
> > We found that the suspend process was blocked when it run into
> > ehci/ohci module due to clk-480m of usb2-phy was disabled.
> >
> > The root cause is that usb2-phy suspended earlier than ehci/ohci
> > (usb2-phy will be auto suspended if no devices plug-in).
When you say "suspend" do you mean USB runtime suspend (i.e., auto
suspend) or do you mean system suspend (i.e., driver .suspend()
callbacks)? The latter are empty intentionally for PHY drivers, since
PHY state is managed by the consumer driver (i.e., the controller
driver). And the former doesn't actually disable any clocks AFAIK, so
that's a red herring IIUC.
> This is really weird, but I can confirm it is true on my system too
> (kernel-4.4 based). At least I see:
>
> [ 208.012065] calling usb1+ @ 4984, parent: fe380000.usb, cb: usb_dev_suspend
> [ 208.569112] calling ff770000.syscon:usb2-phy@e450+ @ 4983, parent:
> ff770000.syscon, cb: platform_pm_suspend
> [ 208.569113] call ff770000.syscon:usb2-phy@e450+ returned 0 after 0 usecs
> [ 208.569439] calling fe380000.usb+ @ 4983, parent: platform, cb:
> platform_pm_suspend
> [ 208.569444] call fe380000.usb+ returned 0 after 4 usecs
>
>
> In general I thought that suspend order was supposed to be related to
> probe order. So if your probe order is A, B, C then your suspend
> order would be C, B, A. ...and we know for sure that the USB PHY
> needs to probe _before_ the main USB controller. If it didn't then
> you'd get an EPROBE_DEFER in the USB controller, right? So that means
> that the USB controller should be suspending before its PHY.
>
> Any chance this is somehow related to async probe? I'm not a huge
> expert on async probe but I guess I could imagine things getting
> confused if you had a sequence like this:
>
> 1. Start USB probe (async)
> 2. Start PHY probe
> 3. Finish PHY probe
> 4. In USB probe, ask for PHY--no problems since PHY probe finished
> 5. Finish USB probe
>
> The probe order would be USB before PHY even though the USB probe
> _depended_ on the PHY probe being finished... :-/ Anyway, probably
> I'm just misunderstanding something and someone can tell me how dumb I
> am...
That may well be true. There isn't a single defined probe order as soon
as you involve async probe, right? So things get a little fuzzier. Also,
I know if you're talking about async suspend/resume, the driver core
only (until quite recently? [1]) respects parent/child relationships.
But I'm not sure of all the async details right now, and async suspend
isn't typically used for the controllers AFAIK -- just for the
hubs/devices.
Anyway, I don't think that's relevant at all because:
> I also notice that the ehci_platform_power_off() function we're
> actually making PHY commands right before the same commands that turn
> off our clocks. Presumably those commands aren't really so good to do
> if the PHY has already been suspended?
>
> Actually, does the PHY suspend from platform_pm_suspend() actually
> even do anything? It doesn't look like it. It looks as if all the
> PHY cares about is init/exit and on/off... ...and it looks as if the
> PHY should be turned off by the EHCI controller at about the same time
> it turns off its clocks...
Right, PHY drivers don't do anything at suspend/resume, since I guess
they presume the consuming driver (the controller) will handle state
transitions (power off, exit).
> I haven't fully dug, but is there any chance that things are getting
> confused between the OTG PHY and the Host PHY? Maybe when we turn off
> the OTG PHY it turns off something that the host PHY needs?
Random thing I noticed: there seems to be a race in
phy-rockchip-inno-usb2.c, if we're worried about the 480M clock getting
disabled too early. See:
static int rockchip_usb2phy_power_off(struct phy *phy)
{
...
clk_disable_unprepare(rphy->clk480m);
...
}
static int rockchip_usb2phy_exit(struct phy *phy)
{
struct rockchip_usb2phy_port *rport = phy_get_drvdata(phy);
if (rport->port_id == USB2PHY_PORT_OTG &&
rport->mode != USB_DR_MODE_HOST) {
cancel_delayed_work_sync(&rport->otg_sm_work);
cancel_delayed_work_sync(&rport->chg_work);
} else if (rport->port_id == USB2PHY_PORT_HOST)
cancel_delayed_work_sync(&rport->sm_work);
return 0;
}
I believe that means any of those work handlers can still be running while
after power_off() -- and therefore can be running after we've disabled the
clock. Might this be your problem?
If so, you're papering that bug by keeping a clock reference in the
controller, which implicitly defers the *actual*
clock_disable_unprepare() until much later.
Brian
[1] commit 9ed9895370ae ("driver core: Functional dependencies tracking
support")
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH 1/3] clk: rockchip: rk3399: add USBPHYx_480M_SRC clock IDs
From: Doug Anderson @ 2016-12-15 0:27 UTC (permalink / raw)
To: Xing Zheng
Cc: open list:ARM/Rockchip SoC..., Heiko Stübner, Rob Herring,
Mark Rutland, Lin Huang, Chris Zhong, devicetree@vger.kernel.org,
linux-kernel@vger.kernel.org
In-Reply-To: <1481710301-1454-2-git-send-email-zhengxing@rock-chips.com>
Hi,
On Wed, Dec 14, 2016 at 2:11 AM, Xing Zheng <zhengxing@rock-chips.com> wrote:
> This patch add two clock IDs for the usb phy 480m source clocks.
>
> Signed-off-by: Xing Zheng <zhengxing@rock-chips.com>
> ---
>
> include/dt-bindings/clock/rk3399-cru.h | 2 ++
> 1 file changed, 2 insertions(+)
>
> diff --git a/include/dt-bindings/clock/rk3399-cru.h b/include/dt-bindings/clock/rk3399-cru.h
> index 220a60f..224daf7 100644
> --- a/include/dt-bindings/clock/rk3399-cru.h
> +++ b/include/dt-bindings/clock/rk3399-cru.h
> @@ -132,6 +132,8 @@
> #define SCLK_RMII_SRC 166
> #define SCLK_PCIEPHY_REF100M 167
> #define SCLK_DDRC 168
> +#define SCLK_USBPHY0_480M_SRC 169
> +#define SCLK_USBPHY1_480M_SRC 170
As mentioned in the dts patch, I don't think you need these since I'm
under the impression that nobody gets this clock. I think the USB
Controller get the ungated version of this clock.
-Doug
^ permalink raw reply
* Re: [PATCH 3/3] arm64: dts: rockchip: add clk-480m for ehci and ohci of rk3399
From: Doug Anderson @ 2016-12-15 0:10 UTC (permalink / raw)
To: Xing Zheng
Cc: open list:ARM/Rockchip SoC..., Heiko Stübner, William wu,
Rob Herring, Mark Rutland, Catalin Marinas, Will Deacon,
Caesar Wang, Brian Norris, Shawn Lin, Jianqun Xu, Elaine Zhang,
David Wu, devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org,
linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
In-Reply-To: <1481710301-1454-4-git-send-email-zhengxing-TNX95d0MmH7DzftRWevZcw@public.gmane.org>
Hi,
On Wed, Dec 14, 2016 at 2:11 AM, Xing Zheng <zhengxing-TNX95d0MmH7DzftRWevZcw@public.gmane.org> wrote:
> From: William wu <wulf-TNX95d0MmH7DzftRWevZcw@public.gmane.org>
>
> We found that the suspend process was blocked when it run into
> ehci/ohci module due to clk-480m of usb2-phy was disabled.
>
> The root cause is that usb2-phy suspended earlier than ehci/ohci
> (usb2-phy will be auto suspended if no devices plug-in).
This is really weird, but I can confirm it is true on my system too
(kernel-4.4 based). At least I see:
[ 208.012065] calling usb1+ @ 4984, parent: fe380000.usb, cb: usb_dev_suspend
[ 208.569112] calling ff770000.syscon:usb2-phy@e450+ @ 4983, parent:
ff770000.syscon, cb: platform_pm_suspend
[ 208.569113] call ff770000.syscon:usb2-phy@e450+ returned 0 after 0 usecs
[ 208.569439] calling fe380000.usb+ @ 4983, parent: platform, cb:
platform_pm_suspend
[ 208.569444] call fe380000.usb+ returned 0 after 4 usecs
In general I thought that suspend order was supposed to be related to
probe order. So if your probe order is A, B, C then your suspend
order would be C, B, A. ...and we know for sure that the USB PHY
needs to probe _before_ the main USB controller. If it didn't then
you'd get an EPROBE_DEFER in the USB controller, right? So that means
that the USB controller should be suspending before its PHY.
Any chance this is somehow related to async probe? I'm not a huge
expert on async probe but I guess I could imagine things getting
confused if you had a sequence like this:
1. Start USB probe (async)
2. Start PHY probe
3. Finish PHY probe
4. In USB probe, ask for PHY--no problems since PHY probe finished
5. Finish USB probe
The probe order would be USB before PHY even though the USB probe
_depended_ on the PHY probe being finished... :-/ Anyway, probably
I'm just misunderstanding something and someone can tell me how dumb I
am...
I also notice that the ehci_platform_power_off() function we're
actually making PHY commands right before the same commands that turn
off our clocks. Presumably those commands aren't really so good to do
if the PHY has already been suspended?
Actually, does the PHY suspend from platform_pm_suspend() actually
even do anything? It doesn't look like it. It looks as if all the
PHY cares about is init/exit and on/off... ...and it looks as if the
PHY should be turned off by the EHCI controller at about the same time
it turns off its clocks...
I haven't fully dug, but is there any chance that things are getting
confused between the OTG PHY and the Host PHY? Maybe when we turn off
the OTG PHY it turns off something that the host PHY needs?
> and the
> clk-480m provided by it was disabled if no module used. However,
> some suspend process related ehci/ohci are base on this clock,
> so we should refer it into ehci/ohci driver to prevent this case.
Though I don't actually have details about the internals of the chip,
it does seem highly likely that the USB block actually uses this clock
for some things, so it doesn't seem insane (to me) to have the USB
controller request that the clock be on. So, in general, I don't have
lots of objections to including the USB PHY Clock here.
...but I think you have the wrong clock (please correct me if I'm
wrong). I think you really wanted your input clock to be
"clk_usbphy0_480m", not "clk_usbphy0_480m_src". Specifically I
believe there is a gate between the clock outputted by the PHY and the
USB Controller itself. I'm guessing that the gate is only there
between the PHY and the "clk_usbphy_480m" MUX.
As evidence, I have a totally functioning system right now where
"clk_usbphy0_480m_src" is currently gated.
That means really you should be changing your clocks to this (untested):
clocks = <&cru HCLK_HOST0>, <&cru HCLK_HOST0_ARB>,
<&u2phy0>;
...and then you could drop the other two patches in this series.
===
OK, I actually briefly tested my proposed change and it at least seems
to build and boot OK. You'd have to test it to make sure it makes
your tests pass...
===
So I guess to summarize all the above:
* It seems to me like there's some deeper root cause and your patch
will at most put a band-aid on it. Seems like digging out the root
cause is a good idea.
* Though I don't believe it solves the root problem, the idea of the
USB Controller holding onto the PHY clock doesn't seem wrong.
* You're holding onto the wrong clock in your patch--you want the one
before the gate (I think).
-Doug
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH v3 1/4] pinctrl: aspeed: Read and write bits in LPC and GFX controllers
From: Andrew Jeffery @ 2016-12-15 0:00 UTC (permalink / raw)
To: Rob Herring
Cc: Linus Walleij, Mark Rutland, Joel Stanley,
linux-gpio-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
In-Reply-To: <CAL_JsqJvhxDSVqpAFCberferxCjvLPRTFXcgTafaPf1DwOa2Xw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
[-- Attachment #1: Type: text/plain, Size: 2606 bytes --]
On Wed, 2016-12-14 at 10:46 -0600, Rob Herring wrote:
> >> > + compatible = "aspeed,g5-pinctrl";
> >>
> >> There's no register range for pinctrl?
> >
> > This may be a mistake on my part; when I wrote this I had no experience
> > with writing devicetree bindings (and still don't have a lot).
> >
> > The SCU does have register regions for pinctrl but on reflection I feel
> > neither the mfd nor syscon bindings describe how children's resources
> > should be treated in general. The example in the mfd bindings is for
> > hardware that is register-bit-led,compatible, whose bindings use the
> > 'offset' property rather than 'reg', which still describes where, but
> > not using the reg property. Given my uncertainty with reg in an mfd
> > child, I wrote the pinctrl/pinmux driver using offsets from the base of
> > the SCU's syscon rather than describing the exact region(s) of the
> > syscon that should be used.
> >
> > The issue you raise here occurred to me when writing the LPC Host
> > Controller bindings, but there I wasn't convinced using the ranges
> > property to give offsets was the right thing to do either.
> >
> > Regardless, whilst there are two dedicated regions of pinmux registers,
> > the mux state also depends on bits in SCU registers outside of these
> > regions. Assuming we define an appropriate ranges property for the SCU
> > syscon the pinctrl reg property would look like:
> >
> > reg = <0x2c 0x1>, <0x3c 0x1>, <0x48 0x1>, <0x70 0x1>, <0x7c 0x1>, <0x80 0x18>, <0xa0 0x10>, <0xd0 0x1>;
> >
> > This is the list of registers affecting the mux taken from the pinctrl-
> > aspeed.h.
>
> With other registers in the holes, right?
Yes.
> If it is sparse like that,
> then yes you probably just want to have reg in the parent for the
> whole block.
Alright, we will leave it as-is.
>
> > What action do you recommend here? The pinctrl dts patches for the
> > Aspeed SoCs are yet to be applied, so changing the bindings to require
> > a reg property can't break any existing in-tree users as there are
> > none. The pinctrl driver can be patched to respect the reg property
> > after the fact, though actually using the region descriptions might be
> > interesting.
> >
> >>
> >> > + aspeed,external-nodes = <&gfx, &lpchc>;
> >
> > Did you have feedback on this approach? I queried you about it in the
> > previous revision, but never received a reply:
>
> It seems okay. At least, I don't have a better suggestion.
Thanks.
Andrew
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 801 bytes --]
^ permalink raw reply
* [PATCH 2/6] ARM: dts: TS-4600: add basic device tree
From: Sebastien Bourdelin @ 2016-12-14 23:12 UTC (permalink / raw)
To: linux-kernel, linux-watchdog, linux-arm-kernel, devicetree,
kernel
Cc: mark, kris, horms+renesas, treding, jonathanh, f.fainelli,
fabio.estevam, kernel, shawnguo, linux, linux, wim, mark.rutland,
robh+dt, damien.riegel, lucile.quirion, olof, arnd,
suzuki.poulose, linus.walleij, will.deacon, yamada.masahiro,
Sebastien Bourdelin
In-Reply-To: <20161214231237.17496-1-sebastien.bourdelin@savoirfairelinux.com>
These device trees add support for the TS-4600 by Technologic Systems.
More details here:
http://wiki.embeddedarm.com/wiki/TS-4600
Signed-off-by: Sebastien Bourdelin <sebastien.bourdelin@savoirfairelinux.com>
---
arch/arm/boot/dts/Makefile | 2 +
arch/arm/boot/dts/imx28-ts4600-common.dtsi | 78 ++++++++++++++++++++++++++++++
arch/arm/boot/dts/imx28-ts4600-rev-a.dts | 22 +++++++++
arch/arm/boot/dts/imx28-ts4600-rev-b.dts | 22 +++++++++
4 files changed, 124 insertions(+)
create mode 100644 arch/arm/boot/dts/imx28-ts4600-common.dtsi
create mode 100644 arch/arm/boot/dts/imx28-ts4600-rev-a.dts
create mode 100644 arch/arm/boot/dts/imx28-ts4600-rev-b.dts
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index c558ba7..5a79fab 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -466,6 +466,8 @@ dtb-$(CONFIG_ARCH_MXS) += \
imx28-m28cu3.dtb \
imx28-m28evk.dtb \
imx28-sps1.dtb \
+ imx28-ts4600-rev-a.dtb \
+ imx28-ts4600-rev-b.dtb \
imx28-tx28.dtb
dtb-$(CONFIG_ARCH_NOMADIK) += \
ste-nomadik-s8815.dtb \
diff --git a/arch/arm/boot/dts/imx28-ts4600-common.dtsi b/arch/arm/boot/dts/imx28-ts4600-common.dtsi
new file mode 100644
index 0000000..04bd5a5
--- /dev/null
+++ b/arch/arm/boot/dts/imx28-ts4600-common.dtsi
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2016 Savoir-Faire Linux
+ * Author: Sebastien Bourdelin <sebastien.bourdelin@savoirfairelinux.com>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+#include "imx28.dtsi"
+#include "dt-bindings/gpio/gpio.h"
+
+/ {
+
+ compatible = "technologic,imx28-ts4600", "fsl,imx28";
+
+ apb@80000000 {
+ apbh@80000000 {
+ ssp0: ssp@80010000 {
+ compatible = "fsl,imx28-mmc";
+ pinctrl-names = "default";
+ pinctrl-0 = <&mmc0_4bit_pins_a
+ &mmc0_sck_cfg
+ &en_sd_pwr>;
+ broken-cd = <1>;
+ bus-width = <4>;
+ vmmc-supply = <®_vddio_sd0>;
+ status = "okay";
+ };
+
+ pinctrl@80018000 {
+ pinctrl-names = "default";
+
+ en_sd_pwr: en_sd_pwr {
+ fsl,pinmux-ids = <
+ MX28_PAD_PWM3__GPIO_3_28
+ >;
+ fsl,drive-strength = <MXS_DRIVE_4mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_DISABLE>;
+ };
+
+ };
+ };
+
+ apbx@80040000 {
+ pwm: pwm@80064000 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pwm2_pins_a>;
+ status = "okay";
+ };
+
+ duart: serial@80074000 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&duart_pins_a>;
+ status = "okay";
+ };
+ };
+ };
+
+ regulators {
+ compatible = "simple-bus";
+
+ reg_vddio_sd0: vddio-sd0 {
+ compatible = "regulator-fixed";
+ regulator-name = "vddio-sd0";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ gpio = <&gpio3 28 0>;
+ };
+ };
+
+};
diff --git a/arch/arm/boot/dts/imx28-ts4600-rev-a.dts b/arch/arm/boot/dts/imx28-ts4600-rev-a.dts
new file mode 100644
index 0000000..e8cb729
--- /dev/null
+++ b/arch/arm/boot/dts/imx28-ts4600-rev-a.dts
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2016 Savoir-Faire Linux
+ * Author: Sebastien Bourdelin <sebastien.bourdelin@savoirfairelinux.com>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include "imx28-ts4600-common.dtsi"
+
+/ {
+ model = "Technologic Systems i.MX28 TS-4600 Rev A";
+
+ memory {
+ reg = <0x40000000 0x08000000>; /* 128MB */
+ };
+
+};
diff --git a/arch/arm/boot/dts/imx28-ts4600-rev-b.dts b/arch/arm/boot/dts/imx28-ts4600-rev-b.dts
new file mode 100644
index 0000000..a115f83
--- /dev/null
+++ b/arch/arm/boot/dts/imx28-ts4600-rev-b.dts
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2016 Savoir-Faire Linux
+ * Author: Sebastien Bourdelin <sebastien.bourdelin@savoirfairelinux.com>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include "imx28-ts4600-common.dtsi"
+
+/ {
+ model = "Technologic Systems i.MX28 TS-4600 Rev B";
+
+ memory {
+ reg = <0x40000000 0x10000000>; /* 256MB */
+ };
+
+};
--
2.10.2
^ permalink raw reply related
* [PATCH 6/6] watchdog: ts4600: add driver for TS-4600 watchdog
From: Sebastien Bourdelin @ 2016-12-14 23:12 UTC (permalink / raw)
To: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
devicetree-u79uwXL29TY76Z2rM5mHXA,
kernel-4ysUXcep3aM1wj+D4I0NRVaTQe2KTcn/
Cc: mark-L1vi/lXTdtvnC/t2CciAbw, kris-L1vi/lXTdtvnC/t2CciAbw,
horms+renesas-/R6kz+dDXgpPR4JQBCEnsQ,
treding-DDmLM1+adcrQT0dZR+AlfA, jonathanh-DDmLM1+adcrQT0dZR+AlfA,
f.fainelli-Re5JQEeQqe8AvxtiuMwx3w, fabio.estevam-3arQi8VN3Tc,
kernel-bIcnvbaLZ9MEGnE8C9+IrQ, shawnguo-DgEjT+Ai2ygdnm+yROfE0A,
linux-I+IVW8TIWO2tmTQ+vhA3Yw, linux-0h96xk9xTtrk1uMJSBkQmQ,
wim-IQzOog9fTRqzQB+pC5nmwQ, mark.rutland-5wv7dgnIgG8,
robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
damien.riegel-4ysUXcep3aM1wj+D4I0NRVaTQe2KTcn/,
lucile.quirion-4ysUXcep3aM1wj+D4I0NRVaTQe2KTcn/,
olof-nZhT3qVonbNeoWH0uzbU5w, arnd-r2nGTMty4D4,
suzuki.poulose-5wv7dgnIgG8, linus.walleij-QSEj5FYQhm4dnm+yROfE0A,
will.deacon-5wv7dgnIgG8, yamada.masahiro-uWyLwvC0a2jby3iVrkZq2A,
Sebastien Bourdelin
In-Reply-To: <20161214231237.17496-1-sebastien.bourdelin-4ysUXcep3aM1wj+D4I0NRVaTQe2KTcn/@public.gmane.org>
This watchdog is instantiated in a FPGA and can only be access using a
GPIOs bit-banged bus, called the NBUS by Technologic Systems.
The watchdog is made of only one register, called the feed register.
Writing to this register will re-arm the watchdog for a given time (and
enable it if it was disable). It can be disabled by writing a special
value into it.
Signed-off-by: Sebastien Bourdelin <sebastien.bourdelin-4ysUXcep3aM1wj+D4I0NRVaTQe2KTcn/@public.gmane.org>
---
.../devicetree/bindings/watchdog/ts4600-wdt.txt | 16 ++
arch/arm/boot/dts/imx28-ts4600-common.dtsi | 5 +
drivers/watchdog/Kconfig | 10 +
drivers/watchdog/Makefile | 1 +
drivers/watchdog/ts4600_wdt.c | 213 +++++++++++++++++++++
5 files changed, 245 insertions(+)
create mode 100644 Documentation/devicetree/bindings/watchdog/ts4600-wdt.txt
create mode 100644 drivers/watchdog/ts4600_wdt.c
diff --git a/Documentation/devicetree/bindings/watchdog/ts4600-wdt.txt b/Documentation/devicetree/bindings/watchdog/ts4600-wdt.txt
new file mode 100644
index 0000000..61d620e
--- /dev/null
+++ b/Documentation/devicetree/bindings/watchdog/ts4600-wdt.txt
@@ -0,0 +1,16 @@
+TS-4600 Technologic Systems Watchdog
+
+Required properties:
+- compatible: must be "technologic,ts4600-wdt"
+- reg: offset to the FPGA's watchdog register
+
+Optional property:
+- timeout-sec: contains the watchdog timeout in seconds.
+
+Example:
+
+wdt {
+ compatible = "technologic,ts4600-wdt";
+ reg = <0x2a>;
+ timeout-sec = <10>;
+};
diff --git a/arch/arm/boot/dts/imx28-ts4600-common.dtsi b/arch/arm/boot/dts/imx28-ts4600-common.dtsi
index b668933..dd7318c 100644
--- a/arch/arm/boot/dts/imx28-ts4600-common.dtsi
+++ b/arch/arm/boot/dts/imx28-ts4600-common.dtsi
@@ -116,6 +116,11 @@
strobe-gpios = <&gpio0 25 GPIO_ACTIVE_HIGH>;
ale-gpios = <&gpio0 26 GPIO_ACTIVE_HIGH>;
rdy-gpios = <&gpio0 21 GPIO_ACTIVE_HIGH>;
+
+ wdt@2a {
+ compatible = "technologic,ts4600-wdt";
+ reg = <0x2a>;
+ };
};
};
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 3eb58cb..7a8e176 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -500,6 +500,16 @@ config NUC900_WATCHDOG
To compile this driver as a module, choose M here: the
module will be called nuc900_wdt.
+config TS4600_WATCHDOG
+ tristate "TS-4600 Watchdog"
+ depends on HAS_IOMEM && OF
+ depends on SOC_IMX28 || COMPILE_TEST
+ select WATCHDOG_CORE
+ help
+ Technologic Systems TS-4600 has watchdog timer implemented in
+ an external FPGA. Say Y here if you want to support for the
+ watchdog timer on TS-4600 board.
+
config TS4800_WATCHDOG
tristate "TS-4800 Watchdog"
depends on HAS_IOMEM && OF
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index caa9f4a..d4b4bd2 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -61,6 +61,7 @@ obj-$(CONFIG_RN5T618_WATCHDOG) += rn5t618_wdt.o
obj-$(CONFIG_COH901327_WATCHDOG) += coh901327_wdt.o
obj-$(CONFIG_STMP3XXX_RTC_WATCHDOG) += stmp3xxx_rtc_wdt.o
obj-$(CONFIG_NUC900_WATCHDOG) += nuc900_wdt.o
+obj-$(CONFIG_TS4600_WATCHDOG) += ts4600_wdt.o
obj-$(CONFIG_TS4800_WATCHDOG) += ts4800_wdt.o
obj-$(CONFIG_TS72XX_WATCHDOG) += ts72xx_wdt.o
obj-$(CONFIG_IMX2_WDT) += imx2_wdt.o
diff --git a/drivers/watchdog/ts4600_wdt.c b/drivers/watchdog/ts4600_wdt.c
new file mode 100644
index 0000000..db91b40
--- /dev/null
+++ b/drivers/watchdog/ts4600_wdt.c
@@ -0,0 +1,213 @@
+/*
+ * Watchdog driver for TS-4600 based boards
+ *
+ * Copyright (c) 2016 - Savoir-faire Linux
+ * Author: Sebastien Bourdelin <sebastien.bourdelin-4ysUXcep3aM1wj+D4I0NRVaTQe2KTcn/@public.gmane.org>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ *
+ * The watchdog on the TS-4600 based boards is in an FPGA and can only be
+ * accessed using a GPIO bit-banged bus called the NBUS by Technologic Systems.
+ * The logic for the watchdog is the same then for the TS-4800 SoM, only the way
+ * to access it change, therefore this driver is heavely based on the ts4800_wdt
+ * driver from Damien Riegel <damien.riegel-4ysUXcep3aM1wj+D4I0NRVaTQe2KTcn/@public.gmane.org>.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/ts-nbus.h>
+#include <linux/watchdog.h>
+
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
+MODULE_PARM_DESC(nowayout,
+ "Watchdog cannot be stopped once started (default="
+ __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
+
+/* possible feed values */
+#define TS4600_WDT_FEED_2S 0x1
+#define TS4600_WDT_FEED_10S 0x2
+#define TS4600_WDT_DISABLE 0x3
+
+struct ts4600_wdt {
+ struct watchdog_device wdd;
+ u32 feed_offset;
+ u32 feed_val;
+};
+
+/*
+ * TS-4600 supports the following timeout values:
+ *
+ * value desc
+ * ---------------------
+ * 0 feed for 338ms
+ * 1 feed for 2.706s
+ * 2 feed for 10.824s
+ * 3 disable watchdog
+ *
+ * Keep the regmap/timeout map ordered by timeout
+ */
+static const struct {
+ const int timeout;
+ const int regval;
+} ts4600_wdt_map[] = {
+ { 2, TS4600_WDT_FEED_2S },
+ { 10, TS4600_WDT_FEED_10S },
+};
+
+#define MAX_TIMEOUT_INDEX (ARRAY_SIZE(ts4600_wdt_map) - 1)
+
+static void ts4600_write_feed(struct ts4600_wdt *wdt, u32 val)
+{
+ ts_nbus_write(wdt->feed_offset, val);
+}
+
+static int ts4600_wdt_start(struct watchdog_device *wdd)
+{
+ struct ts4600_wdt *wdt = watchdog_get_drvdata(wdd);
+
+ ts4600_write_feed(wdt, wdt->feed_val);
+
+ return 0;
+}
+
+static int ts4600_wdt_stop(struct watchdog_device *wdd)
+{
+ struct ts4600_wdt *wdt = watchdog_get_drvdata(wdd);
+
+ ts4600_write_feed(wdt, TS4600_WDT_DISABLE);
+ return 0;
+}
+
+static int ts4600_wdt_set_timeout(struct watchdog_device *wdd,
+ unsigned int timeout)
+{
+ struct ts4600_wdt *wdt = watchdog_get_drvdata(wdd);
+ int i;
+
+ for (i = 0; i < MAX_TIMEOUT_INDEX; i++) {
+ if (ts4600_wdt_map[i].timeout >= timeout)
+ break;
+ }
+
+ wdd->timeout = ts4600_wdt_map[i].timeout;
+ wdt->feed_val = ts4600_wdt_map[i].regval;
+
+ return 0;
+}
+
+static const struct watchdog_ops ts4600_wdt_ops = {
+ .owner = THIS_MODULE,
+ .start = ts4600_wdt_start,
+ .stop = ts4600_wdt_stop,
+ .set_timeout = ts4600_wdt_set_timeout,
+};
+
+static const struct watchdog_info ts4600_wdt_info = {
+ .options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING,
+ .identity = "TS-4600 Watchdog",
+};
+
+static int ts4600_wdt_probe(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ struct watchdog_device *wdd;
+ struct ts4600_wdt *wdt;
+ u32 reg;
+ int ret;
+
+ ret = of_property_read_u32(np, "reg", ®);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "missing reg property\n");
+ return ret;
+ }
+
+ /* check for the NBUS state and defer the probing if it is not ready */
+ if (!ts_nbus_is_ready())
+ return -EPROBE_DEFER;
+
+ /* allocate memory for watchdog struct */
+ wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL);
+ if (!wdt)
+ return -ENOMEM;
+
+ /* set offset to know where to write */
+ wdt->feed_offset = reg;
+
+ /* Initialize struct watchdog_device */
+ wdd = &wdt->wdd;
+ wdd->parent = &pdev->dev;
+ wdd->info = &ts4600_wdt_info;
+ wdd->ops = &ts4600_wdt_ops;
+ wdd->min_timeout = ts4600_wdt_map[0].timeout;
+ wdd->max_timeout = ts4600_wdt_map[MAX_TIMEOUT_INDEX].timeout;
+
+ watchdog_set_drvdata(wdd, wdt);
+ watchdog_set_nowayout(wdd, nowayout);
+ watchdog_init_timeout(wdd, 0, &pdev->dev);
+
+ /*
+ * As this watchdog supports only a few values, ts4600_wdt_set_timeout
+ * must be called to initialize timeout and feed_val with valid values.
+ * Default to maximum timeout if none, or an invalid one, is provided in
+ * device tree.
+ */
+ if (!wdd->timeout)
+ wdd->timeout = wdd->max_timeout;
+ ts4600_wdt_set_timeout(wdd, wdd->timeout);
+
+ /*
+ * The feed register is write-only, so it is not possible to determine
+ * watchdog's state. Disable it to be in a known state.
+ */
+ ts4600_wdt_stop(wdd);
+
+ ret = watchdog_register_device(wdd);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "failed to register watchdog device\n");
+ return ret;
+ }
+
+ platform_set_drvdata(pdev, wdt);
+
+ dev_info(&pdev->dev,
+ "initialized (timeout = %d sec, nowayout = %d)\n",
+ wdd->timeout, nowayout);
+
+ return 0;
+}
+
+static int ts4600_wdt_remove(struct platform_device *pdev)
+{
+ struct ts4600_wdt *wdt = platform_get_drvdata(pdev);
+
+ watchdog_unregister_device(&wdt->wdd);
+
+ return 0;
+}
+
+static const struct of_device_id ts4600_wdt_of_match[] = {
+ { .compatible = "technologic,ts4600-wdt", },
+ { },
+};
+MODULE_DEVICE_TABLE(of, ts4600_wdt_of_match);
+
+static struct platform_driver ts4600_wdt_driver = {
+ .probe = ts4600_wdt_probe,
+ .remove = ts4600_wdt_remove,
+ .driver = {
+ .name = "ts4600_wdt",
+ .of_match_table = ts4600_wdt_of_match,
+ },
+};
+
+module_platform_driver(ts4600_wdt_driver);
+
+MODULE_AUTHOR("Sebastien Bourdelin <sebastien.bourdelin-4ysUXcep3aM1wj+D4I0NRVaTQe2KTcn/@public.gmane.org>");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:ts4600_wdt");
--
2.10.2
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH 5/6] ARM: dts: TS-4600: add NBUS support
From: Sebastien Bourdelin @ 2016-12-14 23:12 UTC (permalink / raw)
To: linux-kernel, linux-watchdog, linux-arm-kernel, devicetree,
kernel
Cc: mark, kris, horms+renesas, treding, jonathanh, f.fainelli,
fabio.estevam, kernel, shawnguo, linux, linux, wim, mark.rutland,
robh+dt, damien.riegel, lucile.quirion, olof, arnd,
suzuki.poulose, linus.walleij, will.deacon, yamada.masahiro,
Sebastien Bourdelin
In-Reply-To: <20161214231237.17496-1-sebastien.bourdelin@savoirfairelinux.com>
This commit enables the NBUS on the TS-4600, using the ts-nbus driver.
Signed-off-by: Sebastien Bourdelin <sebastien.bourdelin@savoirfairelinux.com>
---
arch/arm/boot/dts/imx28-ts4600-common.dtsi | 43 ++++++++++++++++++++++++++++++
1 file changed, 43 insertions(+)
diff --git a/arch/arm/boot/dts/imx28-ts4600-common.dtsi b/arch/arm/boot/dts/imx28-ts4600-common.dtsi
index 04bd5a5..b668933 100644
--- a/arch/arm/boot/dts/imx28-ts4600-common.dtsi
+++ b/arch/arm/boot/dts/imx28-ts4600-common.dtsi
@@ -44,6 +44,28 @@
fsl,pull-up = <MXS_PULL_DISABLE>;
};
+ nbus_pins: nbus_pins {
+ fsl,pinmux-ids = <
+ MX28_PAD_GPMI_D00__GPIO_0_0
+ MX28_PAD_GPMI_D01__GPIO_0_1
+ MX28_PAD_GPMI_D02__GPIO_0_2
+ MX28_PAD_GPMI_D03__GPIO_0_3
+ MX28_PAD_GPMI_D04__GPIO_0_4
+ MX28_PAD_GPMI_D05__GPIO_0_5
+ MX28_PAD_GPMI_D06__GPIO_0_6
+ MX28_PAD_GPMI_D07__GPIO_0_7
+ MX28_PAD_GPMI_CE0N__GPIO_0_16
+ MX28_PAD_GPMI_RDY1__GPIO_0_21
+ MX28_PAD_GPMI_RDN__GPIO_0_24
+ MX28_PAD_GPMI_WRN__GPIO_0_25
+ MX28_PAD_GPMI_ALE__GPIO_0_26
+ >;
+ fsl,drive-strength = <MXS_DRIVE_4mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_DISABLE>;
+
+ };
+
};
};
@@ -75,4 +97,25 @@
};
};
+ nbus {
+ compatible = "technologic,ts-nbus", "simple-bus";
+ pinctrl-0 = <&nbus_pins>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ pwms = <&pwm 2 83>;
+ data-gpios = <&gpio0 0 GPIO_ACTIVE_HIGH
+ &gpio0 1 GPIO_ACTIVE_HIGH
+ &gpio0 2 GPIO_ACTIVE_HIGH
+ &gpio0 3 GPIO_ACTIVE_HIGH
+ &gpio0 4 GPIO_ACTIVE_HIGH
+ &gpio0 5 GPIO_ACTIVE_HIGH
+ &gpio0 6 GPIO_ACTIVE_HIGH
+ &gpio0 7 GPIO_ACTIVE_HIGH>;
+ csn-gpios = <&gpio0 16 GPIO_ACTIVE_HIGH>;
+ txrx-gpios = <&gpio0 24 GPIO_ACTIVE_HIGH>;
+ strobe-gpios = <&gpio0 25 GPIO_ACTIVE_HIGH>;
+ ale-gpios = <&gpio0 26 GPIO_ACTIVE_HIGH>;
+ rdy-gpios = <&gpio0 21 GPIO_ACTIVE_HIGH>;
+ };
+
};
--
2.10.2
^ permalink raw reply related
* [PATCH 4/6] bus: add driver for the Technologic Systems NBUS
From: Sebastien Bourdelin @ 2016-12-14 23:12 UTC (permalink / raw)
To: linux-kernel, linux-watchdog, linux-arm-kernel, devicetree,
kernel
Cc: mark, kris, horms+renesas, treding, jonathanh, f.fainelli,
fabio.estevam, kernel, shawnguo, linux, linux, wim, mark.rutland,
robh+dt, damien.riegel, lucile.quirion, olof, arnd,
suzuki.poulose, linus.walleij, will.deacon, yamada.masahiro,
Sebastien Bourdelin
In-Reply-To: <20161214231237.17496-1-sebastien.bourdelin@savoirfairelinux.com>
This driver implements a GPIOs bit-banged bus, called the NBUS by
Technologic Systems. It is used to communicate with the peripherals in
the FPGA on the TS-4600 SoM.
Signed-off-by: Sebastien Bourdelin <sebastien.bourdelin@savoirfairelinux.com>
---
drivers/bus/Kconfig | 9 +
drivers/bus/Makefile | 1 +
drivers/bus/ts-nbus.c | 451 ++++++++++++++++++++++++++++++++++++++++++++++++
include/linux/ts-nbus.h | 17 ++
4 files changed, 478 insertions(+)
create mode 100644 drivers/bus/ts-nbus.c
create mode 100644 include/linux/ts-nbus.h
diff --git a/drivers/bus/Kconfig b/drivers/bus/Kconfig
index 7875105..74e72b3 100644
--- a/drivers/bus/Kconfig
+++ b/drivers/bus/Kconfig
@@ -150,6 +150,15 @@ config TEGRA_ACONNECT
Driver for the Tegra ACONNECT bus which is used to interface with
the devices inside the Audio Processing Engine (APE) for Tegra210.
+config TS_NBUS
+ tristate "Technologic Systems NBUS Driver"
+ default y
+ depends on SOC_IMX28
+ depends on OF_GPIO && PWM
+ help
+ Driver for the Technologic Systems NBUS which is used to interface
+ with the peripherals in the FPGA of the TS-4600 SoM.
+
config UNIPHIER_SYSTEM_BUS
tristate "UniPhier System Bus driver"
depends on ARCH_UNIPHIER && OF
diff --git a/drivers/bus/Makefile b/drivers/bus/Makefile
index c6cfa6b..83f874a 100644
--- a/drivers/bus/Makefile
+++ b/drivers/bus/Makefile
@@ -19,5 +19,6 @@ obj-$(CONFIG_QCOM_EBI2) += qcom-ebi2.o
obj-$(CONFIG_SUNXI_RSB) += sunxi-rsb.o
obj-$(CONFIG_SIMPLE_PM_BUS) += simple-pm-bus.o
obj-$(CONFIG_TEGRA_ACONNECT) += tegra-aconnect.o
+obj-$(CONFIG_TS_NBUS) += ts-nbus.o
obj-$(CONFIG_UNIPHIER_SYSTEM_BUS) += uniphier-system-bus.o
obj-$(CONFIG_VEXPRESS_CONFIG) += vexpress-config.o
diff --git a/drivers/bus/ts-nbus.c b/drivers/bus/ts-nbus.c
new file mode 100644
index 0000000..44fc89d
--- /dev/null
+++ b/drivers/bus/ts-nbus.c
@@ -0,0 +1,451 @@
+/*
+ * NBUS driver for TS-4600 based boards
+ *
+ * Copyright (c) 2016 - Savoir-faire Linux
+ * Author: Sebastien Bourdelin <sebastien.bourdelin@savoirfairelinux.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ *
+ * This driver implements a GPIOs bit-banged bus, called the NBUS by Technologic
+ * Systems. It is used to communicate with the peripherals in the FPGA on the
+ * TS-4600 SoM.
+ */
+
+#include <linux/gpio.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/platform_device.h>
+#include <linux/pwm.h>
+
+static DEFINE_MUTEX(ts_nbus_lock);
+static bool ts_nbus_ready;
+
+#define TS_NBUS_READ_MODE 0
+#define TS_NBUS_WRITE_MODE 1
+#define TS_NBUS_DIRECTION_IN 0
+#define TS_NBUS_DIRECTION_OUT 1
+#define TS_NBUS_WRITE_ADR 0
+#define TS_NBUS_WRITE_VAL 1
+
+struct ts_nbus {
+ struct pwm_device *pwm;
+ int num_data;
+ int *data;
+ int csn;
+ int txrx;
+ int strobe;
+ int ale;
+ int rdy;
+};
+
+static struct ts_nbus *ts_nbus;
+
+/*
+ * request all gpios required by the bus.
+ */
+static int ts_nbus_init(struct platform_device *pdev)
+{
+ int err;
+ int i;
+
+ for (i = 0; i < ts_nbus->num_data; i++) {
+ err = devm_gpio_request_one(&pdev->dev, ts_nbus->data[i],
+ GPIOF_OUT_INIT_HIGH,
+ "TS NBUS data");
+ if (err)
+ return err;
+ }
+
+ err = devm_gpio_request_one(&pdev->dev, ts_nbus->csn,
+ GPIOF_OUT_INIT_HIGH,
+ "TS NBUS csn");
+ if (err)
+ return err;
+
+ err = devm_gpio_request_one(&pdev->dev, ts_nbus->txrx,
+ GPIOF_OUT_INIT_HIGH,
+ "TS NBUS txrx");
+ if (err)
+ return err;
+
+ err = devm_gpio_request_one(&pdev->dev, ts_nbus->strobe,
+ GPIOF_OUT_INIT_HIGH,
+ "TS NBUS strobe");
+ if (err)
+ return err;
+
+ err = devm_gpio_request_one(&pdev->dev, ts_nbus->ale,
+ GPIOF_OUT_INIT_HIGH,
+ "TS NBUS ale");
+ if (err)
+ return err;
+
+ err = devm_gpio_request_one(&pdev->dev, ts_nbus->rdy,
+ GPIOF_IN,
+ "TS NBUS rdy");
+ if (err)
+ return err;
+
+ return 0;
+}
+
+/*
+ * retrieve all gpios used by the bus from the device tree.
+ */
+static int ts_nbus_get_of_pdata(struct device *dev, struct device_node *np)
+{
+ int num_data;
+ int *data;
+ int ret;
+ int i;
+
+ ret = of_gpio_named_count(np, "data-gpios");
+ if (ret < 0) {
+ dev_err(dev,
+ "failed to count GPIOs in DT property data-gpios\n");
+ return ret;
+ }
+ num_data = ret;
+ data = devm_kzalloc(dev, num_data * sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ for (i = 0; i < num_data; i++) {
+ ret = of_get_named_gpio(np, "data-gpios", i);
+ if (ret < 0) {
+ dev_err(dev, "failed to retrieve data-gpio from dts\n");
+ return ret;
+ }
+ data[i] = ret;
+ }
+ ts_nbus->num_data = num_data;
+ ts_nbus->data = data;
+
+ ret = of_get_named_gpio(np, "csn-gpios", 0);
+ if (ret < 0) {
+ dev_err(dev, "failed to retrieve csn-gpio from dts\n");
+ return ret;
+ }
+ ts_nbus->csn = ret;
+
+ ret = of_get_named_gpio(np, "txrx-gpios", 0);
+ if (ret < 0) {
+ dev_err(dev, "failed to retrieve txrx-gpio from dts\n");
+ return ret;
+ }
+ ts_nbus->txrx = ret;
+
+ ret = of_get_named_gpio(np, "strobe-gpios", 0);
+ if (ret < 0) {
+ dev_err(dev, "failed to retrieve strobe-gpio from dts\n");
+ return ret;
+ }
+ ts_nbus->strobe = ret;
+
+ ret = of_get_named_gpio(np, "ale-gpios", 0);
+ if (ret < 0) {
+ dev_err(dev, "failed to retrieve ale-gpio from dts\n");
+ return ret;
+ }
+ ts_nbus->ale = ret;
+
+ ret = of_get_named_gpio(np, "rdy-gpios", 0);
+ if (ret < 0) {
+ dev_err(dev, "failed to retrieve rdy-gpio from dts\n");
+ return ret;
+ }
+ ts_nbus->rdy = ret;
+
+ return 0;
+}
+
+/*
+ * the txrx gpio is used by the FPGA to know if the following transactions
+ * should be handled to read or write a value.
+ */
+static inline void ts_nbus_set_mode(int mode)
+{
+ if (mode == TS_NBUS_READ_MODE)
+ gpio_set_value(ts_nbus->txrx, 0);
+ else
+ gpio_set_value(ts_nbus->txrx, 1);
+}
+
+/*
+ * the data gpios are used for reading and writing values, their directions
+ * should be adjusted accordingly.
+ */
+static inline void ts_nbus_set_direction(int direction)
+{
+ int i;
+
+ for (i = 0; i < ts_nbus->num_data; i++) {
+ if (direction == TS_NBUS_DIRECTION_IN)
+ gpio_direction_input(ts_nbus->data[i]);
+ else
+ gpio_direction_output(ts_nbus->data[i], 1);
+ }
+}
+
+/*
+ * reset the bus in its initial state.
+ */
+static inline void ts_nbus_reset_bus(void)
+{
+ int i;
+
+ for (i = 0; i < ts_nbus->num_data; i++)
+ gpio_set_value(ts_nbus->data[i], 0);
+
+ gpio_set_value(ts_nbus->csn, 0);
+ gpio_set_value(ts_nbus->strobe, 0);
+ gpio_set_value(ts_nbus->ale, 0);
+}
+
+/*
+ * let the FPGA knows it can process.
+ */
+static inline void ts_nbus_start_transaction(void)
+{
+ gpio_set_value(ts_nbus->strobe, 1);
+}
+
+/*
+ * return the byte value read from the data gpios.
+ */
+static inline u8 ts_nbus_read_byte(void)
+{
+ int i;
+ u8 value = 0;
+
+ for (i = 0; i < ts_nbus->num_data; i++)
+ if (ts_nbus->data[i])
+ value |= 1 << i;
+
+ return value;
+}
+
+/*
+ * set the data gpios accordingly to the byte value.
+ */
+static inline void ts_nbus_write_byte(u8 byte)
+{
+ int i;
+
+ for (i = 0; i < ts_nbus->num_data; i++)
+ if (byte & (1 << i))
+ gpio_set_value(ts_nbus->data[i], 1);
+}
+
+/*
+ * reading the bus consists of resetting the bus, then notifying the FPGA to
+ * send the data in the data gpios and return the read value.
+ */
+static inline u8 ts_nbus_read_bus(void)
+{
+ ts_nbus_reset_bus();
+ ts_nbus_start_transaction();
+
+ return ts_nbus_read_byte();
+}
+
+/*
+ * writing to the bus consists of resetting the bus, then define the type of
+ * command (address/value), write the data and notify the FPGA to retrieve the
+ * value in the data gpios.
+ */
+static inline void ts_nbus_write_bus(int cmd, u8 value)
+{
+ ts_nbus_reset_bus();
+
+ if (cmd == TS_NBUS_WRITE_ADR)
+ gpio_set_value(ts_nbus->ale, 1);
+
+ ts_nbus_write_byte(value);
+ ts_nbus_start_transaction();
+}
+
+/*
+ * read the value in the FPGA register at the given address.
+ */
+u16 ts_nbus_read(u8 adr)
+{
+ int i;
+ u16 val;
+
+ /* bus access must be atomic */
+ mutex_lock(&ts_nbus_lock);
+
+ /* set the bus in read mode */
+ ts_nbus_set_mode(TS_NBUS_READ_MODE);
+
+ /* write address */
+ ts_nbus_write_bus(TS_NBUS_WRITE_ADR, adr);
+
+ /* set the data gpios direction as input before reading */
+ ts_nbus_set_direction(TS_NBUS_DIRECTION_IN);
+
+ /* reading value MSB first */
+ do {
+ val = 0;
+ for (i = 1; i >= 0; i--)
+ val |= (ts_nbus_read_bus() << (i * 8));
+ gpio_set_value(ts_nbus->csn, 1);
+ } while (gpio_get_value(ts_nbus->rdy));
+
+ /* restore the data gpios direction as output after reading */
+ ts_nbus_set_direction(TS_NBUS_DIRECTION_OUT);
+
+ mutex_unlock(&ts_nbus_lock);
+
+ return val;
+}
+EXPORT_SYMBOL_GPL(ts_nbus_read);
+
+/*
+ * write the desired value in the FPGA register at the given address.
+ */
+int ts_nbus_write(u8 adr, u16 value)
+{
+ int i;
+
+ /* bus access must be atomic */
+ mutex_lock(&ts_nbus_lock);
+
+ /* set the bus in write mode */
+ ts_nbus_set_mode(TS_NBUS_WRITE_MODE);
+
+ /* write address */
+ ts_nbus_write_bus(TS_NBUS_WRITE_ADR, adr);
+
+ /* writing value MSB first */
+ for (i = 1; i >= 0; i--)
+ ts_nbus_write_bus(TS_NBUS_WRITE_VAL, (u8)(value >> (i * 8)));
+
+ /* wait for completion */
+ gpio_set_value(ts_nbus->csn, 1);
+ while (gpio_get_value(ts_nbus->rdy) != 0) {
+ gpio_set_value(ts_nbus->csn, 0);
+ gpio_set_value(ts_nbus->csn, 1);
+ }
+
+ mutex_unlock(&ts_nbus_lock);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(ts_nbus_write);
+
+/*
+ * helper function to know the state of the bus.
+ * this function is useful to let peripherals defer their probing while the bus
+ * is not ready.
+ */
+bool ts_nbus_is_ready(void)
+{
+ bool nbus_state;
+
+ mutex_lock(&ts_nbus_lock);
+ nbus_state = ts_nbus_ready;
+ mutex_unlock(&ts_nbus_lock);
+
+ return nbus_state;
+}
+EXPORT_SYMBOL_GPL(ts_nbus_is_ready);
+
+static int ts_nbus_probe(struct platform_device *pdev)
+{
+ struct pwm_device *pwm;
+ struct pwm_args pargs;
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+ int ret;
+
+ ts_nbus = devm_kzalloc(dev, sizeof(*ts_nbus), GFP_KERNEL);
+ if (!ts_nbus)
+ return -ENOMEM;
+
+ ret = ts_nbus_get_of_pdata(dev, np);
+ if (ret)
+ return ret;
+ ret = ts_nbus_init(pdev);
+ if (ret < 0)
+ return ret;
+
+ pwm = devm_pwm_get(dev, NULL);
+ if (IS_ERR(pwm)) {
+ ret = PTR_ERR(pwm);
+ if (ret != -EPROBE_DEFER)
+ dev_err(dev, "unable to request PWM\n");
+ return ret;
+ }
+
+ pwm_get_args(pwm, &pargs);
+ if (!pargs.period) {
+ dev_err(&pdev->dev, "invalid PWM period\n");
+ return -EINVAL;
+ }
+
+ /*
+ * FIXME: pwm_apply_args() should be removed when switching to
+ * the atomic PWM API.
+ */
+ pwm_apply_args(pwm);
+ ret = pwm_config(pwm, pargs.period, pargs.period);
+ if (ret < 0)
+ return ret;
+
+ /*
+ * we can now start the FPGA and let the peripherals knows the bus is
+ * ready.
+ */
+ pwm_enable(pwm);
+ ts_nbus->pwm = pwm;
+
+ mutex_lock(&ts_nbus_lock);
+ ts_nbus_ready = true;
+ mutex_unlock(&ts_nbus_lock);
+
+ dev_info(dev, "initialized\n");
+
+ return 0;
+}
+
+static int ts_nbus_remove(struct platform_device *pdev)
+{
+ /* disable bus access */
+ mutex_lock(&ts_nbus_lock);
+ ts_nbus_ready = false;
+ mutex_unlock(&ts_nbus_lock);
+
+ /* shutdown the FPGA */
+ pwm_disable(ts_nbus->pwm);
+
+ return 0;
+}
+
+static const struct of_device_id ts_nbus_of_match[] = {
+ { .compatible = "technologic,ts-nbus", },
+ { },
+};
+MODULE_DEVICE_TABLE(of, ts_nbus_of_match);
+
+static struct platform_driver ts_nbus_driver = {
+ .probe = ts_nbus_probe,
+ .remove = ts_nbus_remove,
+ .driver = {
+ .name = "ts_nbus",
+ .of_match_table = ts_nbus_of_match,
+ },
+};
+
+module_platform_driver(ts_nbus_driver);
+
+MODULE_ALIAS("platform:ts_nbus");
+MODULE_AUTHOR("Sebastien Bourdelin <sebastien.bourdelin@savoirfairelinux.com>");
+MODULE_DESCRIPTION("Technologic Systems NBUS");
+MODULE_LICENSE("GPL v2");
diff --git a/include/linux/ts-nbus.h b/include/linux/ts-nbus.h
new file mode 100644
index 0000000..5fcdb96
--- /dev/null
+++ b/include/linux/ts-nbus.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2016 - Savoir-faire Linux
+ * Author: Sebastien Bourdelin <sebastien.bourdelin@savoirfairelinux.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#ifndef _TS_NBUS_H
+#define _TS_NBUS_H
+
+extern u16 ts_nbus_read(u8 adr);
+extern int ts_nbus_write(u8 adr, u16 value);
+extern bool ts_nbus_is_ready(void);
+
+#endif /* _TS_NBUS_H */
--
2.10.2
^ 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