* Re: [PATCH 1/2] devicetree: power: add bindings for GPIO-driven power switches
From: Bartosz Golaszewski @ 2016-12-15 10:57 UTC (permalink / raw)
To: Jonathan Cameron
Cc: Rob Herring, Jonathan Cameron, Hartmut Knaack, Lars-Peter Clausen,
Peter Meerwald-Stadler, Mark Rutland, linux-iio, linux-devicetree,
LKML, Kevin Hilman, Patrick Titiano, Neil Armstrong,
Linus Walleij, Alexandre Courbot, linux-gpio, Sebastian Reichel,
linux-pm, Mark Brown, Liam Girdwood
In-Reply-To: <54679B04-3A57-4F0E-8EE6-BB37785F8E10@jic23.retrosnub.co.uk>
2016-12-14 18:36 GMT+01:00 Jonathan Cameron <jic23@jic23.retrosnub.co.uk>:
>
>
> On 14 December 2016 16:58:21 GMT+00:00, Bartosz Golaszewski
> <bgolaszewski@baylibre.com> wrote:
>>2016-12-13 20:27 GMT+01:00 Rob Herring <robh@kernel.org>:
>>> On Sun, Dec 11, 2016 at 11:21:44PM +0100, Bartosz Golaszewski wrote:
>>>> Some boards are equipped with simple, GPIO-driven power load
>>switches.
>>>> An example of such ICs is the TI tps229* series.
>>>
>>> How is this different than a GPIO regulator? The input and output
>>> voltages just happen to be the same. I could be convinced this is
>>> different enough to have a different compatible, but it somewhat
>>seems
>>> you want to use this for IIO, so you are creating a different binding
>>> for that usecase.
>>>
>>
>>It's more of a fixed regulator I suppose. Do you mean adding a new
>>compatible to the fixed-regulator binding (e.g. "gpio-power-switch" or
>>"simple-power-switch") and then providing an iio driver for toggling
>>the switch?
>
> I am rather torn on whether the IIO interface makes any sense beyond that of
> convenience.
>
The question is: will the iio maintainers be ok with adding support
for interfaces different than iio (I guess so since Lars already
mentioned wanting to support the GPIO chardev)? If so, I'm ok with not
using the iio framework in the kernel.
> A bridge to a regulator in general might make sense to cover the case of a
> reg effectively
> acting as a DAC at the edge of the known hardware.
>
> Lars' point about perhaps adding support for the new gpio userspace stuff to
> libiio would in
> this case also be rather papering over the issue.
> There is known hardware there so we should describe it!
>
> I think we should be considering this as the general case of the Linux
> controlled power supply.
> How do we want to represent that?
> Ultimately does a general regulator userspace interface make sense?
>
> Classic case of people cutting our hardware in half and making boundaries
> beyond which lie dragons.
>
> I would love to see the general case covered.
>
It seems as if this is already covered by the userspace-consumer
regulator driver, but it doesn't speak device tree yet. I guess we
could reuse it by merging the proposed gpio-power-switch binding and
extending it to parse DT.
Best regards,
Bartosz Golaszewski
^ permalink raw reply
* Re: [PATCH 6/6] watchdog: ts4600: add driver for TS-4600 watchdog
From: kbuild test robot @ 2016-12-15 10:28 UTC (permalink / raw)
Cc: kbuild-all, linux-kernel, linux-watchdog, linux-arm-kernel,
devicetree, kernel, 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-7-sebastien.bourdelin@savoirfairelinux.com>
[-- Attachment #1: Type: text/plain, Size: 1211 bytes --]
Hi Sebastien,
[auto build test ERROR on linus/master]
[also build test ERROR on v4.9]
[cannot apply to next-20161215]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
url: https://github.com/0day-ci/linux/commits/Sebastien-Bourdelin/of-documentation-add-bindings-documentation-for-TS-4600/20161215-072238
config: i386-allyesconfig (attached as .config)
compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901
reproduce:
# save the attached .config to linux build tree
make ARCH=i386
All errors (new ones prefixed by >>):
drivers/built-in.o: In function `ts4600_wdt_start':
>> ts4600_wdt.c:(.text+0x2333d64): undefined reference to `ts_nbus_write'
drivers/built-in.o: In function `ts4600_wdt_stop':
ts4600_wdt.c:(.text+0x2333d85): undefined reference to `ts_nbus_write'
drivers/built-in.o: In function `ts4600_wdt_probe':
ts4600_wdt.c:(.text+0x2333e66): undefined reference to `ts_nbus_write'
>> ts4600_wdt.c:(.text+0x2333ee9): undefined reference to `ts_nbus_is_ready'
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 57052 bytes --]
^ permalink raw reply
* Re: [PATCH] ARM: dts: r8a7791: link DU to VSPDs
From: Magnus Damm @ 2016-12-15 9:59 UTC (permalink / raw)
To: Sergei Shtylyov
Cc: Simon Horman [Horms], Linux-Renesas, Rob Herring, Mark Rutland,
devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
Russell King - ARM Linux,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org
In-Reply-To: <1922293.x1RvWWSErN-gHKXc3Y1Z8zGSmamagVegGFoWSdPRAKMAL8bYrjMMd8@public.gmane.org>
Hi Sergei,
On Thu, Dec 15, 2016 at 7:07 AM, Sergei Shtylyov
<sergei.shtylyov-M4DtvfQ/ZS1MRgGoP+s0PdBPR1lH4CV8@public.gmane.org> wrote:
> Add the "vsps" property to the DU device node in order to link this node to
> the VSPD nodes.
>
> Signed-off-by: Sergei Shtylyov <sergei.shtylyov-M4DtvfQ/ZS1MRgGoP+s0PdBPR1lH4CV8@public.gmane.org>
>
> ---
> This patch is against the 'renesas-devel-20161212-v4.9' of Simon Horman's
> 'renesas.git' repo. It's only meaningful if the DU driver patch I've just
> posted is applied.
Next time, please consider pointing out the exact name of the patch
you are referring to.
Thanks,
/ magnus
--
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
* [PATCH 1/7] PM / devfreq: exynos-bus: Add the detailed correlation for Exynos5433
From: Chanwoo Choi @ 2016-12-15 9:30 UTC (permalink / raw)
To: myungjoo.ham, kyungmin.park
Cc: rjw, chanwoo, linux-pm, linux-kernel, Chanwoo Choi, Rob Herring,
devicetree
In-Reply-To: <1481794243-5046-1-git-send-email-cw00.choi@samsung.com>
This patch adds the detailed corrleation between sub-blocks and VDD_INT power
line for Exynos5433. VDD_INT provided the power source to INT (Internal) block.
Cc: Rob Herring <robh+dt@kernel.org>
Cc: devicetree@vger.kernel.org
Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com>
---
Documentation/devicetree/bindings/devfreq/exynos-bus.txt | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/Documentation/devicetree/bindings/devfreq/exynos-bus.txt b/Documentation/devicetree/bindings/devfreq/exynos-bus.txt
index d3ec8e676b6b..d085ef90d27c 100644
--- a/Documentation/devicetree/bindings/devfreq/exynos-bus.txt
+++ b/Documentation/devicetree/bindings/devfreq/exynos-bus.txt
@@ -123,6 +123,20 @@ Detailed correlation between sub-blocks and power line according to Exynos SoC:
|--- FSYS
|--- FSYS2
+- In case of Exynos5433, there is VDD_INT power line as following:
+ VDD_INT |--- G2D (parent device)
+ |--- MSCL
+ |--- GSCL
+ |--- JPEG
+ |--- MFC
+ |--- HEVC
+ |--- BUS0
+ |--- BUS1
+ |--- BUS2
+ |--- PERIS (Fixed clock rate)
+ |--- PERIC (Fixed clock rate)
+ |--- FSYS (Fixed clock rate)
+
Example1:
Show the AXI buses of Exynos3250 SoC. Exynos3250 divides the buses to
power line (regulator). The MIF (Memory Interface) AXI bus is used to
--
1.9.1
^ permalink raw reply related
* [PATCH v3] power: supply: bq24735-charger: optionally poll the ac-detect gpio
From: Peter Rosin @ 2016-12-15 9:28 UTC (permalink / raw)
To: linux-kernel-u79uwXL29TY76Z2rM5mHXA
Cc: Peter Rosin, Sebastian Reichel, Rob Herring, Mark Rutland,
linux-pm-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20161214151026.5q6goxlfscv53tol@earth>
If the ac-detect gpio does not support interrupts, provide a fallback
to poll the gpio at a configurable interval.
Signed-off-by: Peter Rosin <peda-koto5C5qi+TLoDKTGw+V6w@public.gmane.org>
---
v2 -> v3 changes:
- use device_property_read_u32 instead of of_property_read_u32
v1 -> v2 changes:
- use poll-interval instead of ti,poll-interval-ms in the bindings
Cheers,
peda
.../bindings/power/supply/ti,bq24735.txt | 2 +
drivers/power/supply/bq24735-charger.c | 49 +++++++++++++++++++---
2 files changed, 46 insertions(+), 5 deletions(-)
diff --git a/Documentation/devicetree/bindings/power/supply/ti,bq24735.txt b/Documentation/devicetree/bindings/power/supply/ti,bq24735.txt
index 3bf55757ceec..799d0e5d6f26 100644
--- a/Documentation/devicetree/bindings/power/supply/ti,bq24735.txt
+++ b/Documentation/devicetree/bindings/power/supply/ti,bq24735.txt
@@ -25,6 +25,8 @@ Optional properties :
- ti,external-control : Indicates that the charger is configured externally
and that the host should not attempt to enable/disable charging or set the
charge voltage/current.
+ - poll-interval : In case 'interrupts' is not specified, poll AC presence
+ on the ti,ac-detect-gpios GPIO with this interval (milliseconds).
Example:
diff --git a/drivers/power/supply/bq24735-charger.c b/drivers/power/supply/bq24735-charger.c
index 1d5c9206e0ed..8a0242c13b7e 100644
--- a/drivers/power/supply/bq24735-charger.c
+++ b/drivers/power/supply/bq24735-charger.c
@@ -50,6 +50,8 @@ struct bq24735 {
struct bq24735_platform *pdata;
struct mutex lock;
struct gpio_desc *status_gpio;
+ struct delayed_work poll;
+ u32 poll_interval;
bool charging;
};
@@ -209,11 +211,8 @@ static int bq24735_charger_is_charging(struct bq24735 *charger)
return !(ret & BQ24735_CHG_OPT_CHARGE_DISABLE);
}
-static irqreturn_t bq24735_charger_isr(int irq, void *devid)
+static void bq24735_update(struct bq24735 *charger)
{
- struct power_supply *psy = devid;
- struct bq24735 *charger = to_bq24735(psy);
-
mutex_lock(&charger->lock);
if (charger->charging && bq24735_charger_is_present(charger))
@@ -223,11 +222,29 @@ static irqreturn_t bq24735_charger_isr(int irq, void *devid)
mutex_unlock(&charger->lock);
- power_supply_changed(psy);
+ power_supply_changed(charger->charger);
+}
+
+static irqreturn_t bq24735_charger_isr(int irq, void *devid)
+{
+ struct power_supply *psy = devid;
+ struct bq24735 *charger = to_bq24735(psy);
+
+ bq24735_update(charger);
return IRQ_HANDLED;
}
+static void bq24735_poll(struct work_struct *work)
+{
+ struct bq24735 *charger = container_of(work, struct bq24735, poll.work);
+
+ bq24735_update(charger);
+
+ schedule_delayed_work(&charger->poll,
+ msecs_to_jiffies(charger->poll_interval));
+}
+
static int bq24735_charger_get_property(struct power_supply *psy,
enum power_supply_property psp,
union power_supply_propval *val)
@@ -455,11 +472,32 @@ static int bq24735_charger_probe(struct i2c_client *client,
client->irq, ret);
return ret;
}
+ } else if (charger->status_gpio) {
+ ret = device_property_read_u32(&client->dev, "poll-interval",
+ &charger->poll_interval);
+ if (ret)
+ return 0;
+ if (!charger->poll_interval)
+ return 0;
+
+ INIT_DELAYED_WORK(&charger->poll, bq24735_poll);
+ schedule_delayed_work(&charger->poll,
+ msecs_to_jiffies(charger->poll_interval));
}
return 0;
}
+static int bq24735_charger_remove(struct i2c_client *client)
+{
+ struct bq24735 *charger = i2c_get_clientdata(client);
+
+ if (charger->poll_interval)
+ cancel_delayed_work_sync(&charger->poll);
+
+ return 0;
+}
+
static const struct i2c_device_id bq24735_charger_id[] = {
{ "bq24735-charger", 0 },
{}
@@ -478,6 +516,7 @@ static struct i2c_driver bq24735_charger_driver = {
.of_match_table = bq24735_match_ids,
},
.probe = bq24735_charger_probe,
+ .remove = bq24735_charger_remove,
.id_table = bq24735_charger_id,
};
--
2.1.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 v4 2/2] mtd: spi-nor: add rockchip serial flash controller driver
From: Shawn Lin @ 2016-12-15 9:27 UTC (permalink / raw)
To: David Woodhouse, Brian Norris
Cc: Marek Vasut, Cyrille Pitchen, Rob Herring,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-rockchip-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Heiko Stuebner,
Shawn Lin
In-Reply-To: <1481794068-241619-1-git-send-email-shawn.lin-TNX95d0MmH7DzftRWevZcw@public.gmane.org>
Add rockchip serial flash controller driver
Signed-off-by: Shawn Lin <shawn.lin-TNX95d0MmH7DzftRWevZcw@public.gmane.org>
---
Changes in v4:
- simplify the code of get_if_type
- use dma_dir to simplify the code
- simplify the rockchip_sfc_do_rd_wr
- some minor improvements
- add reset controller when doing resume
Changes in v3:
- use io{read32,write32}_rep to simplify the corner cases
- remove more unnecessary bit definitions
- some minor comment fixes and improvement
- fix wrong unregister function
- unify more code
- use nor to avoid constantly replicating the whole
sfc->flash[sfc->num_chip].nor
- add email for MODULE_AUTHOR
- remove #if 1 --- #endif
- extract DMA code to imporve the code structure
- reset all when failing to do dma
- pass sfc to get_if_type
- rename sfc-no-dma to sfc-no-DMA
Changes in v2:
- fix typos
- add some comment for buffer and others operations
- rename SFC_MAX_CHIP_NUM to MAX_CHIPSELECT_NUM
- use u8 for cs
- return -EINVAL for default case of get_if_type
- use readl_poll_*() to check timeout cases
- simplify and clarify some condition checks
- rework the bitshifts to simplify the code
- define SFC_CMD_DUMMY(x)
- fix ummap for dma read path and finish all the
cache maintenance.
- rename to rockchip_sfc_chip_priv and embed struct spi_nor
in it.
- add MODULE_AUTHOR
- add runtime PM and general PM support.
- Thanks for Marek's comments. Link:
http://lists.infradead.org/pipermail/linux-mtd/2016-November/070321.html
MAINTAINERS | 8 +
drivers/mtd/spi-nor/Kconfig | 7 +
drivers/mtd/spi-nor/Makefile | 1 +
drivers/mtd/spi-nor/rockchip-sfc.c | 872 +++++++++++++++++++++++++++++++++++++
4 files changed, 888 insertions(+)
create mode 100644 drivers/mtd/spi-nor/rockchip-sfc.c
diff --git a/MAINTAINERS b/MAINTAINERS
index 1cd38a7..eb7e06d 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -10266,6 +10266,14 @@ L: linux-serial-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
S: Odd Fixes
F: drivers/tty/serial/rp2.*
+ROCKCHIP SERIAL FLASH CONTROLLER DRIVER
+M: Shawn Lin <shawn.lin-TNX95d0MmH7DzftRWevZcw@public.gmane.org>
+L: linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org
+L: linux-rockchip-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org
+S: Maintained
+F: Documentation/devicetree/bindings/mtd/rockchip-sfc.txt
+F: drivers/mtd/spi-nor/rockchip-sfc.c
+
ROSE NETWORK LAYER
M: Ralf Baechle <ralf-6z/3iImG2C8G8FEW9MqTrA@public.gmane.org>
L: linux-hams-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
diff --git a/drivers/mtd/spi-nor/Kconfig b/drivers/mtd/spi-nor/Kconfig
index 4a682ee..bf783a8 100644
--- a/drivers/mtd/spi-nor/Kconfig
+++ b/drivers/mtd/spi-nor/Kconfig
@@ -76,4 +76,11 @@ config SPI_NXP_SPIFI
Flash. Enable this option if you have a device with a SPIFI
controller and want to access the Flash as a mtd device.
+config SPI_ROCKCHIP_SFC
+ tristate "Rockchip Serial Flash Controller(SFC)"
+ depends on ARCH_ROCKCHIP || COMPILE_TEST
+ depends on HAS_IOMEM && HAS_DMA
+ help
+ This enables support for rockchip serial flash controller.
+
endif # MTD_SPI_NOR
diff --git a/drivers/mtd/spi-nor/Makefile b/drivers/mtd/spi-nor/Makefile
index 121695e..364d4c6 100644
--- a/drivers/mtd/spi-nor/Makefile
+++ b/drivers/mtd/spi-nor/Makefile
@@ -5,3 +5,4 @@ obj-$(CONFIG_SPI_FSL_QUADSPI) += fsl-quadspi.o
obj-$(CONFIG_SPI_HISI_SFC) += hisi-sfc.o
obj-$(CONFIG_MTD_MT81xx_NOR) += mtk-quadspi.o
obj-$(CONFIG_SPI_NXP_SPIFI) += nxp-spifi.o
+obj-$(CONFIG_SPI_ROCKCHIP_SFC) += rockchip-sfc.o
diff --git a/drivers/mtd/spi-nor/rockchip-sfc.c b/drivers/mtd/spi-nor/rockchip-sfc.c
new file mode 100644
index 0000000..102c08f
--- /dev/null
+++ b/drivers/mtd/spi-nor/rockchip-sfc.c
@@ -0,0 +1,872 @@
+/*
+ * Rockchip Serial Flash Controller Driver
+ *
+ * Copyright (c) 2016, Rockchip Inc.
+ * Author: Shawn Lin <shawn.lin-TNX95d0MmH7DzftRWevZcw@public.gmane.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/bitops.h>
+#include <linux/clk.h>
+#include <linux/completion.h>
+#include <linux/dma-mapping.h>
+#include <linux/iopoll.h>
+#include <linux/module.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/spi-nor.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/slab.h>
+
+/* System control */
+#define SFC_CTRL 0x0
+#define SFC_CTRL_COMMON_BITS_1 0x0
+#define SFC_CTRL_COMMON_BITS_2 0x1
+#define SFC_CTRL_COMMON_BITS_4 0x2
+#define SFC_CTRL_DATA_BITS_SHIFT 12
+#define SFC_CTRL_ADDR_BITS_SHIFT 10
+#define SFC_CTRL_CMD_BITS_SHIFT 8
+#define SFC_CTRL_PHASE_SEL_NEGETIVE BIT(1)
+
+/* Interrupt mask */
+#define SFC_IMR 0x4
+#define SFC_IMR_RX_FULL BIT(0)
+#define SFC_IMR_RX_UFLOW BIT(1)
+#define SFC_IMR_TX_OFLOW BIT(2)
+#define SFC_IMR_TX_EMPTY BIT(3)
+#define SFC_IMR_TRAN_FINISH BIT(4)
+#define SFC_IMR_BUS_ERR BIT(5)
+#define SFC_IMR_NSPI_ERR BIT(6)
+#define SFC_IMR_DMA BIT(7)
+/* Interrupt clear */
+#define SFC_ICLR 0x8
+#define SFC_ICLR_RX_FULL BIT(0)
+#define SFC_ICLR_RX_UFLOW BIT(1)
+#define SFC_ICLR_TX_OFLOW BIT(2)
+#define SFC_ICLR_TX_EMPTY BIT(3)
+#define SFC_ICLR_TRAN_FINISH BIT(4)
+#define SFC_ICLR_BUS_ERR BIT(5)
+#define SFC_ICLR_NSPI_ERR BIT(6)
+#define SFC_ICLR_DMA BIT(7)
+/* FIFO threshold level */
+#define SFC_FTLR 0xc
+#define SFC_FTLR_TX_SHIFT 0
+#define SFC_FTLR_TX_MASK 0x1f
+#define SFC_FTLR_RX_SHIFT 8
+#define SFC_FTLR_RX_MASK 0x1f
+/* Reset FSM and FIFO */
+#define SFC_RCVR 0x10
+#define SFC_RCVR_RESET BIT(0)
+/* Enhanced mode */
+#define SFC_AX 0x14
+/* Address Bit number */
+#define SFC_ABIT 0x18
+/* Interrupt status */
+#define SFC_ISR 0x1c
+#define SFC_ISR_RX_FULL_SHIFT BIT(0)
+#define SFC_ISR_RX_UFLOW_SHIFT BIT(1)
+#define SFC_ISR_TX_OFLOW_SHIFT BIT(2)
+#define SFC_ISR_TX_EMPTY_SHIFT BIT(3)
+#define SFC_ISR_TX_FINISH_SHIFT BIT(4)
+#define SFC_ISR_BUS_ERR_SHIFT BIT(5)
+#define SFC_ISR_NSPI_ERR_SHIFT BIT(6)
+#define SFC_ISR_DMA_SHIFT BIT(7)
+/* FIFO status */
+#define SFC_FSR 0x20
+#define SFC_FSR_TX_IS_FULL BIT(0)
+#define SFC_FSR_TX_IS_EMPTY BIT(1)
+#define SFC_FSR_RX_IS_EMPTY BIT(2)
+#define SFC_FSR_RX_IS_FULL BIT(3)
+/* FSM status */
+#define SFC_SR 0x24
+#define SFC_SR_IS_IDLE 0x0
+#define SFC_SR_IS_BUSY 0x1
+/* Raw interrupt status */
+#define SFC_RISR 0x28
+#define SFC_RISR_RX_FULL BIT(0)
+#define SFC_RISR_RX_UNDERFLOW BIT(1)
+#define SFC_RISR_TX_OVERFLOW BIT(2)
+#define SFC_RISR_TX_EMPTY BIT(3)
+#define SFC_RISR_TRAN_FINISH BIT(4)
+#define SFC_RISR_BUS_ERR BIT(5)
+#define SFC_RISR_NSPI_ERR BIT(6)
+#define SFC_RISR_DMA BIT(7)
+/* Master trigger */
+#define SFC_DMA_TRIGGER 0x80
+/* Src or Dst addr for master */
+#define SFC_DMA_ADDR 0x84
+/* Command */
+#define SFC_CMD 0x100
+#define SFC_CMD_IDX_SHIFT 0
+#define SFC_CMD_DUMMY_SHIFT 8
+#define SFC_CMD_DIR_RD 0
+#define SFC_CMD_DIR_WR 1
+#define SFC_CMD_DIR_SHIFT 12
+#define SFC_CMD_ADDR_ZERO (0x0 << 14)
+#define SFC_CMD_ADDR_24BITS (0x1 << 14)
+#define SFC_CMD_ADDR_32BITS (0x2 << 14)
+#define SFC_CMD_ADDR_FRS (0x3 << 14)
+#define SFC_CMD_TRAN_BYTES_SHIFT 16
+#define SFC_CMD_CS_SHIFT 30
+/* Address */
+#define SFC_ADDR 0x104
+/* Data */
+#define SFC_DATA 0x108
+
+#define SFC_MAX_CHIPSELECT_NUM 4
+#define SFC_DMA_MAX_LEN 0x4000
+#define SFC_CMD_DUMMY(x) \
+ ((x) << SFC_CMD_DUMMY_SHIFT)
+
+enum rockchip_sfc_iftype {
+ IF_TYPE_STD,
+ IF_TYPE_DUAL,
+ IF_TYPE_QUAD,
+};
+
+struct rockchip_sfc;
+struct rockchip_sfc_chip_priv {
+ u8 cs;
+ u32 clk_rate;
+ struct spi_nor nor;
+ struct rockchip_sfc *sfc;
+};
+
+struct rockchip_sfc {
+ struct device *dev;
+ struct mutex lock;
+ void __iomem *regbase;
+ struct clk *hclk;
+ struct clk *clk;
+ /* virtual mapped addr for dma_buffer */
+ void *buffer;
+ dma_addr_t dma_buffer;
+ struct completion cp;
+ struct rockchip_sfc_chip_priv flash[SFC_MAX_CHIPSELECT_NUM];
+ u32 num_chip;
+ bool use_dma;
+ /* use negative edge of hclk to latch data */
+ bool negative_edge;
+};
+
+static int get_if_type(struct rockchip_sfc *sfc, enum read_mode flash_read)
+{
+ if (flash_read == SPI_NOR_DUAL)
+ return IF_TYPE_DUAL;
+ else if (flash_read == SPI_NOR_QUAD)
+ return IF_TYPE_QUAD;
+ else if (flash_read == SPI_NOR_NORMAL ||
+ flash_read == SPI_NOR_FAST)
+ return IF_TYPE_STD;
+
+ dev_err(sfc->dev, "unsupported SPI read mode\n");
+ return -EINVAL;
+}
+
+static int rockchip_sfc_reset(struct rockchip_sfc *sfc)
+{
+ int err;
+ u32 status;
+
+ writel_relaxed(SFC_RCVR_RESET, sfc->regbase + SFC_RCVR);
+
+ err = readl_poll_timeout(sfc->regbase + SFC_RCVR, status,
+ !(status & SFC_RCVR_RESET), 20,
+ jiffies_to_usecs(HZ));
+ if (err)
+ dev_err(sfc->dev, "SFC reset never finished\n");
+
+ /* Still need to clear the masked interrupt from RISR */
+ writel_relaxed(SFC_ICLR_RX_FULL | SFC_ICLR_RX_UFLOW |
+ SFC_ICLR_TX_OFLOW | SFC_ICLR_TX_EMPTY |
+ SFC_ICLR_TRAN_FINISH | SFC_ICLR_BUS_ERR |
+ SFC_ICLR_NSPI_ERR | SFC_ICLR_DMA,
+ sfc->regbase + SFC_ICLR);
+ return err;
+}
+
+static int rockchip_sfc_init(struct rockchip_sfc *sfc)
+{
+ int err;
+
+ err = rockchip_sfc_reset(sfc);
+ if (err)
+ return err;
+
+ /* Mask all eight interrupts */
+ writel_relaxed(0xff, sfc->regbase + SFC_IMR);
+
+ /*
+ * Phase configure for sfc to latch data by using
+ * ahb clock, and this configuration should be Soc
+ * specific.
+ */
+ if (sfc->negative_edge)
+ writel_relaxed(SFC_CTRL_PHASE_SEL_NEGETIVE,
+ sfc->regbase + SFC_CTRL);
+ else
+ writel_relaxed(0, sfc->regbase + SFC_CTRL);
+
+ return 0;
+}
+
+static int rockchip_sfc_prep(struct spi_nor *nor, enum spi_nor_ops ops)
+{
+ struct rockchip_sfc_chip_priv *priv = nor->priv;
+ struct rockchip_sfc *sfc = priv->sfc;
+ int ret;
+
+ mutex_lock(&sfc->lock);
+ pm_runtime_get_sync(sfc->dev);
+
+ ret = clk_set_rate(sfc->clk, priv->clk_rate);
+ if (ret)
+ goto out;
+
+ ret = clk_prepare_enable(sfc->clk);
+ if (ret)
+ goto out;
+
+ return 0;
+
+out:
+ mutex_unlock(&sfc->lock);
+ return ret;
+}
+
+static void rockchip_sfc_unprep(struct spi_nor *nor, enum spi_nor_ops ops)
+{
+ struct rockchip_sfc_chip_priv *priv = nor->priv;
+ struct rockchip_sfc *sfc = priv->sfc;
+
+ clk_disable_unprepare(sfc->clk);
+ mutex_unlock(&sfc->lock);
+ pm_runtime_mark_last_busy(sfc->dev);
+ pm_runtime_put_autosuspend(sfc->dev);
+}
+
+static int rockchip_sfc_wait_op_finish(struct rockchip_sfc *sfc)
+{
+ int err;
+ u32 status;
+
+ /*
+ * Note: tx and rx share the same fifo, so the rx's water level
+ * is the same as rx's, which means this function could be reused
+ * for checking the read operations as well.
+ */
+ err = readl_poll_timeout(sfc->regbase + SFC_FSR, status,
+ status & SFC_FSR_TX_IS_EMPTY,
+ 20, jiffies_to_usecs(2 * HZ));
+ if (err)
+ dev_err(sfc->dev, "SFC fifo never empty\n");
+
+ return err;
+}
+
+static int rockchip_sfc_op_reg(struct spi_nor *nor,
+ u8 opcode, int len, u8 optype)
+{
+ struct rockchip_sfc_chip_priv *priv = nor->priv;
+ struct rockchip_sfc *sfc = priv->sfc;
+ u32 reg;
+ bool tx_no_empty, rx_no_empty, is_busy;
+ int err;
+
+ reg = readl_relaxed(sfc->regbase + SFC_FSR);
+ tx_no_empty = !(reg & SFC_FSR_TX_IS_EMPTY);
+ rx_no_empty = !(reg & SFC_FSR_RX_IS_EMPTY);
+
+ is_busy = readl_relaxed(sfc->regbase + SFC_SR);
+
+ if (tx_no_empty || rx_no_empty || is_busy) {
+ err = rockchip_sfc_reset(sfc);
+ if (err)
+ return err;
+ }
+
+ reg = opcode << SFC_CMD_IDX_SHIFT;
+ reg |= len << SFC_CMD_TRAN_BYTES_SHIFT;
+ reg |= priv->cs << SFC_CMD_CS_SHIFT;
+ reg |= optype << SFC_CMD_DIR_SHIFT;
+
+ writel_relaxed(reg, sfc->regbase + SFC_CMD);
+
+ return rockchip_sfc_wait_op_finish(sfc);
+}
+
+static void rockchip_sfc_read_fifo(struct rockchip_sfc *sfc, u8 *buf, int len)
+{
+ u32 tmp, i;
+ int total_len = len;
+
+ /* 32-bit access only */
+ if (len >= 4 && !((u32)buf & 0x03)) {
+ ioread32_rep(sfc->regbase + SFC_DATA, buf, len >> 2);
+ len %= 4;
+ buf += total_len - len;
+ }
+
+ /* read the rest bytes */
+ for (i = 0; i < len; i++) {
+ if (!(i & 0x03))
+ tmp = readl_relaxed(sfc->regbase + SFC_DATA);
+ buf[i] = (tmp >> ((i & 0x03) * 8)) & 0xff;
+ }
+}
+
+static int rockchip_sfc_read_reg(struct spi_nor *nor, u8 opcode,
+ u8 *buf, int len)
+{
+ struct rockchip_sfc_chip_priv *priv = nor->priv;
+ struct rockchip_sfc *sfc = priv->sfc;
+ int ret;
+
+ ret = rockchip_sfc_op_reg(nor, opcode, len, SFC_CMD_DIR_RD);
+ if (ret)
+ return ret;
+
+ rockchip_sfc_read_fifo(sfc, buf, len);
+
+ return 0;
+}
+
+static int rockchip_sfc_write_reg(struct spi_nor *nor, u8 opcode,
+ u8 *buf, int len)
+{
+ struct rockchip_sfc_chip_priv *priv = nor->priv;
+ struct rockchip_sfc *sfc = priv->sfc;
+ u32 dwords;
+
+ /* Align bytes to dwords */
+ dwords = DIV_ROUND_UP(len, sizeof(u32));
+ iowrite32_rep(sfc->regbase + SFC_DATA, buf, dwords);
+
+ return rockchip_sfc_op_reg(nor, opcode, len, SFC_CMD_DIR_WR);
+}
+
+static inline void rockchip_sfc_setup_transfer(struct spi_nor *nor,
+ loff_t from_to,
+ size_t len, u8 op_type)
+{
+ struct rockchip_sfc_chip_priv *priv = nor->priv;
+ struct rockchip_sfc *sfc = priv->sfc;
+ u32 reg;
+ u8 if_type = 0;
+
+ if_type = get_if_type(sfc, nor->flash_read);
+ writel_relaxed((if_type << SFC_CTRL_DATA_BITS_SHIFT) |
+ (if_type << SFC_CTRL_ADDR_BITS_SHIFT) |
+ (if_type << SFC_CTRL_CMD_BITS_SHIFT) |
+ (sfc->negative_edge ? SFC_CTRL_PHASE_SEL_NEGETIVE : 0),
+ sfc->regbase + SFC_CTRL);
+
+ if (op_type == SFC_CMD_DIR_WR)
+ reg = nor->program_opcode << SFC_CMD_IDX_SHIFT;
+ else
+ reg = nor->read_opcode << SFC_CMD_IDX_SHIFT;
+
+ reg |= op_type << SFC_CMD_DIR_SHIFT;
+ reg |= (nor->addr_width == 4) ?
+ SFC_CMD_ADDR_32BITS : SFC_CMD_ADDR_24BITS;
+
+ reg |= priv->cs << SFC_CMD_CS_SHIFT;
+ reg |= len << SFC_CMD_TRAN_BYTES_SHIFT;
+
+ if (op_type == SFC_CMD_DIR_RD)
+ reg |= SFC_CMD_DUMMY(nor->read_dummy);
+
+ /* Should minus one as 0x0 means 1 bit flash address */
+ writel_relaxed(nor->addr_width * 8 - 1, sfc->regbase + SFC_ABIT);
+ writel_relaxed(reg, sfc->regbase + SFC_CMD);
+ writel_relaxed(from_to, sfc->regbase + SFC_ADDR);
+}
+
+static int rockchip_sfc_do_dma_transfer(struct spi_nor *nor, loff_t from_to,
+ dma_addr_t dma_buf, size_t len,
+ u8 op_type)
+{
+ struct rockchip_sfc_chip_priv *priv = nor->priv;
+ struct rockchip_sfc *sfc = priv->sfc;
+ u32 reg;
+ int err = 0;
+
+ init_completion(&sfc->cp);
+
+ writel_relaxed(SFC_ICLR_RX_FULL | SFC_ICLR_RX_UFLOW |
+ SFC_ICLR_TX_OFLOW | SFC_ICLR_TX_EMPTY |
+ SFC_ICLR_TRAN_FINISH | SFC_ICLR_BUS_ERR |
+ SFC_ICLR_NSPI_ERR | SFC_ICLR_DMA,
+ sfc->regbase + SFC_ICLR);
+
+ /* Enable transfer complete interrupt */
+ reg = readl_relaxed(sfc->regbase + SFC_IMR);
+ reg &= ~SFC_IMR_TRAN_FINISH;
+ writel_relaxed(reg, sfc->regbase + SFC_IMR);
+
+ rockchip_sfc_setup_transfer(nor, from_to, len, op_type);
+ writel_relaxed(dma_buf, sfc->regbase + SFC_DMA_ADDR);
+
+ /*
+ * Start dma but note that the sfc->dma_buffer is derived from
+ * dmam_alloc_coherent so we don't actually need any sync operations
+ * for coherent dma memory.
+ */
+ writel_relaxed(0x1, sfc->regbase + SFC_DMA_TRIGGER);
+
+ /* Wait for the interrupt. */
+ if (!wait_for_completion_timeout(&sfc->cp, msecs_to_jiffies(2000))) {
+ dev_err(sfc->dev, "DMA wait for transfer finish timeout\n");
+ err = -ETIMEDOUT;
+ }
+
+ /* Disable transfer finish interrupt */
+ reg = readl_relaxed(sfc->regbase + SFC_IMR);
+ reg |= SFC_IMR_TRAN_FINISH;
+ writel_relaxed(reg, sfc->regbase + SFC_IMR);
+
+ if (err) {
+ rockchip_sfc_reset(sfc);
+ return err;
+ }
+
+ return rockchip_sfc_wait_op_finish(sfc);
+}
+
+static inline int rockchip_sfc_pio_write(struct rockchip_sfc *sfc, u_char *buf,
+ size_t len)
+{
+ u32 dwords;
+
+ /*
+ * Align bytes to dwords, although we will write some extra
+ * bytes to fifo but the transfer bytes number in SFC_CMD
+ * register will make sure we just send out the expected
+ * byte numbers and the extra bytes will be clean before
+ * setting up the next transfer. We should always round up
+ * to align to DWORD as the ahb for Rockchip Socs won't
+ * support non-aligned-to-DWORD transfer.
+ */
+ dwords = DIV_ROUND_UP(len, sizeof(u32));
+ iowrite32_rep(sfc->regbase + SFC_DATA, buf, dwords);
+
+ return rockchip_sfc_wait_op_finish(sfc);
+}
+
+static inline int rockchip_sfc_pio_read(struct rockchip_sfc *sfc, u_char *buf,
+ size_t len)
+{
+ rockchip_sfc_read_fifo(sfc, buf, len);
+
+ return rockchip_sfc_wait_op_finish(sfc);
+}
+
+static int rockchip_sfc_pio_transfer(struct spi_nor *nor, loff_t from_to,
+ size_t len, u_char *buf, u8 op_type)
+{
+ struct rockchip_sfc_chip_priv *priv = nor->priv;
+ struct rockchip_sfc *sfc = priv->sfc;
+
+ rockchip_sfc_setup_transfer(nor, from_to, len, op_type);
+
+ if (op_type == SFC_CMD_DIR_WR)
+ return rockchip_sfc_pio_write(sfc, buf, len);
+ else
+ return rockchip_sfc_pio_read(sfc, buf, len);
+}
+
+static int rockchip_sfc_dma_transfer(struct spi_nor *nor, loff_t from_to,
+ size_t len, u_char *buf, u8 op_type)
+{
+ struct rockchip_sfc_chip_priv *priv = nor->priv;
+ struct rockchip_sfc *sfc = priv->sfc;
+ size_t offset;
+ int ret;
+ dma_addr_t dma_addr = 0;
+ int dma_dir;
+
+ dma_dir = (op_type == SFC_CMD_DIR_RD) ?
+ DMA_FROM_DEVICE : DMA_TO_DEVICE;
+
+ for (offset = 0; offset < len; offset += SFC_DMA_MAX_LEN) {
+ size_t trans = min_t(size_t, SFC_DMA_MAX_LEN, len - offset);
+
+ dma_addr = dma_map_single(NULL, (void *)buf, trans, dma_dir);
+
+ if (dma_mapping_error(sfc->dev, dma_addr)) {
+ /*
+ * If we use pre-allocated dma_buffer, we need to
+ * do a copy here.
+ */
+ if (op_type == SFC_CMD_DIR_WR)
+ memcpy(sfc->buffer, buf + offset, trans);
+
+ dma_addr = 0;
+ }
+
+ if (op_type == SFC_CMD_DIR_WR)
+ /*
+ * Flush the write data from write_buf to dma_addr
+ * if using dynamic allocated dma buffer before dma
+ * moves data from dma_addr to fifo.
+ */
+ dma_sync_single_for_device(sfc->dev, dma_addr,
+ trans, DMA_TO_DEVICE);
+
+
+ /* If failing to map dma, use pre-allocated area instead */
+ ret = rockchip_sfc_do_dma_transfer(nor, from_to + offset,
+ dma_addr ? dma_addr :
+ sfc->dma_buffer,
+ trans, op_type);
+
+ if (dma_addr) {
+ /*
+ * Invalidate the read data from dma_addr if using
+ * dynamic allocated dma buffer after dma moves data
+ * from fifo to dma_addr.
+ */
+ if (op_type == SFC_CMD_DIR_RD)
+ dma_sync_single_for_cpu(sfc->dev, dma_addr,
+ trans, DMA_FROM_DEVICE);
+
+ dma_unmap_single(NULL, dma_addr,
+ trans, dma_dir);
+ }
+
+ if (ret) {
+ dev_warn(nor->dev, "DMA read timeout\n");
+ return ret;
+ }
+ /*
+ * If we use pre-allocated dma_buffer for read, we need to
+ * do a copy here.
+ */
+ if (!dma_addr && (op_type == SFC_CMD_DIR_RD))
+ memcpy(buf + offset, sfc->buffer, trans);
+ }
+
+ return len;
+}
+
+static ssize_t rockchip_sfc_do_rd_wr(struct spi_nor *nor, loff_t from_to,
+ size_t len, u_char *buf, u32 op_type)
+{
+ struct rockchip_sfc_chip_priv *priv = nor->priv;
+ struct rockchip_sfc *sfc = priv->sfc;
+ int ret;
+
+ if (likely(sfc->use_dma))
+ return rockchip_sfc_dma_transfer(nor, from_to, len,
+ buf, op_type);
+
+ /* Fall back to PIO mode if DMA isn't present */
+ ret = rockchip_sfc_pio_transfer(nor, from_to, len,
+ (u_char *)buf, op_type);
+ if (ret) {
+ if (op_type == SFC_CMD_DIR_RD)
+ dev_warn(nor->dev, "PIO read timeout\n");
+ else
+ dev_warn(nor->dev, "PIO write timeout\n");
+ return ret;
+ }
+
+ return len;
+}
+
+static ssize_t rockchip_sfc_read(struct spi_nor *nor, loff_t from,
+ size_t len, u_char *read_buf)
+{
+ return rockchip_sfc_do_rd_wr(nor, from, len,
+ read_buf, SFC_CMD_DIR_RD);
+}
+
+static ssize_t rockchip_sfc_write(struct spi_nor *nor, loff_t to,
+ size_t len, const u_char *write_buf)
+{
+ return rockchip_sfc_do_rd_wr(nor, to, len,
+ (u_char *)write_buf,
+ SFC_CMD_DIR_WR);
+}
+
+static int rockchip_sfc_register(struct device_node *np,
+ struct rockchip_sfc *sfc)
+{
+ struct device *dev = sfc->dev;
+ struct mtd_info *mtd;
+ struct spi_nor *nor;
+ int ret;
+
+ nor = &sfc->flash[sfc->num_chip].nor;
+ nor->dev = dev;
+ spi_nor_set_flash_node(nor, np);
+
+ ret = of_property_read_u8(np, "reg", &sfc->flash[sfc->num_chip].cs);
+ if (ret) {
+ dev_err(dev, "No reg property for %s\n",
+ np->full_name);
+ return ret;
+ }
+
+ ret = of_property_read_u32(np, "spi-max-frequency",
+ &sfc->flash[sfc->num_chip].clk_rate);
+ if (ret) {
+ dev_err(dev, "No spi-max-frequency property for %s\n",
+ np->full_name);
+ return ret;
+ }
+
+ sfc->flash[sfc->num_chip].sfc = sfc;
+ nor->priv = &(sfc->flash[sfc->num_chip]);
+
+ nor->prepare = rockchip_sfc_prep;
+ nor->unprepare = rockchip_sfc_unprep;
+ nor->read_reg = rockchip_sfc_read_reg;
+ nor->write_reg = rockchip_sfc_write_reg;
+ nor->read = rockchip_sfc_read;
+ nor->write = rockchip_sfc_write;
+ nor->erase = NULL;
+ ret = spi_nor_scan(nor, NULL, SPI_NOR_QUAD);
+ if (ret)
+ return ret;
+
+ mtd = &(nor->mtd);
+ mtd->name = np->name;
+ ret = mtd_device_register(mtd, NULL, 0);
+ if (ret)
+ return ret;
+
+ sfc->num_chip++;
+ return 0;
+}
+
+static void rockchip_sfc_unregister_all(struct rockchip_sfc *sfc)
+{
+ int i;
+
+ for (i = 0; i < sfc->num_chip; i++)
+ mtd_device_unregister(&sfc->flash[i].nor.mtd);
+}
+
+static int rockchip_sfc_register_all(struct rockchip_sfc *sfc)
+{
+ struct device *dev = sfc->dev;
+ struct device_node *np;
+ int ret;
+
+ for_each_available_child_of_node(dev->of_node, np) {
+ ret = rockchip_sfc_register(np, sfc);
+ if (ret)
+ goto fail;
+
+ if (sfc->num_chip == SFC_MAX_CHIPSELECT_NUM) {
+ dev_warn(dev, "Exceeds the max cs limitation\n");
+ break;
+ }
+ }
+
+ return 0;
+
+fail:
+ dev_err(dev, "Failed to register all chips\n");
+ /* Unregister all the _registered_ nor flash */
+ rockchip_sfc_unregister_all(sfc);
+ return ret;
+}
+
+static irqreturn_t rockchip_sfc_irq_handler(int irq, void *dev_id)
+{
+ struct rockchip_sfc *sfc = dev_id;
+ u32 reg;
+
+ reg = readl_relaxed(sfc->regbase + SFC_RISR);
+ dev_dbg(sfc->dev, "Get irq: 0x%x\n", reg);
+
+ /* Clear interrupt */
+ writel_relaxed(reg, sfc->regbase + SFC_ICLR);
+
+ if (reg & SFC_RISR_TRAN_FINISH)
+ complete(&sfc->cp);
+
+ return IRQ_HANDLED;
+}
+
+static int rockchip_sfc_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct resource *res;
+ struct rockchip_sfc *sfc;
+ int ret;
+
+ sfc = devm_kzalloc(dev, sizeof(*sfc), GFP_KERNEL);
+ if (!sfc)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, sfc);
+ sfc->dev = dev;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ sfc->regbase = devm_ioremap_resource(dev, res);
+ if (IS_ERR(sfc->regbase))
+ return PTR_ERR(sfc->regbase);
+
+ sfc->clk = devm_clk_get(&pdev->dev, "sfc");
+ if (IS_ERR(sfc->clk)) {
+ dev_err(&pdev->dev, "Failed to get sfc interface clk\n");
+ return PTR_ERR(sfc->clk);
+ }
+
+ sfc->hclk = devm_clk_get(&pdev->dev, "hsfc");
+ if (IS_ERR(sfc->hclk)) {
+ dev_err(&pdev->dev, "Failed to get sfc ahp clk\n");
+ return PTR_ERR(sfc->hclk);
+ }
+
+ ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
+ if (ret) {
+ dev_warn(dev, "Unable to set dma mask\n");
+ return ret;
+ }
+
+ sfc->buffer = dmam_alloc_coherent(dev, SFC_DMA_MAX_LEN,
+ &sfc->dma_buffer, GFP_KERNEL);
+ if (!sfc->buffer)
+ return -ENOMEM;
+
+ mutex_init(&sfc->lock);
+
+ ret = clk_prepare_enable(sfc->hclk);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to enable hclk\n");
+ goto err_hclk;
+ }
+
+ ret = clk_prepare_enable(sfc->clk);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to enable clk\n");
+ goto err_clk;
+ }
+
+ sfc->use_dma = !of_property_read_bool(sfc->dev->of_node,
+ "rockchip,sfc-no-DMA");
+
+ sfc->negative_edge = of_device_is_compatible(sfc->dev->of_node,
+ "rockchip,rk1108-sfc");
+ /* Find the irq */
+ ret = platform_get_irq(pdev, 0);
+ if (ret < 0) {
+ dev_err(dev, "Failed to get the irq\n");
+ goto err_irq;
+ }
+
+ ret = devm_request_irq(dev, ret, rockchip_sfc_irq_handler,
+ 0, pdev->name, sfc);
+ if (ret) {
+ dev_err(dev, "Failed to request irq\n");
+ goto err_irq;
+ }
+
+ sfc->num_chip = 0;
+ ret = rockchip_sfc_init(sfc);
+ if (ret)
+ goto err_irq;
+
+ pm_runtime_get_noresume(&pdev->dev);
+ pm_runtime_set_active(&pdev->dev);
+ pm_runtime_enable(&pdev->dev);
+ pm_runtime_set_autosuspend_delay(&pdev->dev, 50);
+ pm_runtime_use_autosuspend(&pdev->dev);
+
+ ret = rockchip_sfc_register_all(sfc);
+ if (ret)
+ goto err_register;
+
+ clk_disable_unprepare(sfc->clk);
+ pm_runtime_put_autosuspend(&pdev->dev);
+ return 0;
+
+err_register:
+ pm_runtime_disable(&pdev->dev);
+ pm_runtime_set_suspended(&pdev->dev);
+ pm_runtime_put_noidle(&pdev->dev);
+err_irq:
+ clk_disable_unprepare(sfc->clk);
+err_clk:
+ clk_disable_unprepare(sfc->hclk);
+err_hclk:
+ mutex_destroy(&sfc->lock);
+ return ret;
+}
+
+static int rockchip_sfc_remove(struct platform_device *pdev)
+{
+ struct rockchip_sfc *sfc = platform_get_drvdata(pdev);
+
+ pm_runtime_get_sync(&pdev->dev);
+ pm_runtime_disable(&pdev->dev);
+ pm_runtime_put_noidle(&pdev->dev);
+
+ rockchip_sfc_unregister_all(sfc);
+ mutex_destroy(&sfc->lock);
+ clk_disable_unprepare(sfc->clk);
+ clk_disable_unprepare(sfc->hclk);
+ return 0;
+}
+
+#ifdef CONFIG_PM
+int rockchip_sfc_runtime_suspend(struct device *dev)
+{
+ struct rockchip_sfc *sfc = dev_get_drvdata(dev);
+
+ clk_disable_unprepare(sfc->hclk);
+ return 0;
+}
+
+int rockchip_sfc_runtime_resume(struct device *dev)
+{
+ struct rockchip_sfc *sfc = dev_get_drvdata(dev);
+
+ clk_prepare_enable(sfc->hclk);
+ return rockchip_sfc_reset(sfc);
+}
+#endif /* CONFIG_PM */
+
+static const struct of_device_id rockchip_sfc_dt_ids[] = {
+ { .compatible = "rockchip,sfc"},
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, rockchip_sfc_dt_ids);
+
+static const struct dev_pm_ops rockchip_sfc_dev_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
+ pm_runtime_force_resume)
+ SET_RUNTIME_PM_OPS(rockchip_sfc_runtime_suspend,
+ rockchip_sfc_runtime_resume, NULL)
+};
+
+static struct platform_driver rockchip_sfc_driver = {
+ .driver = {
+ .name = "rockchip-sfc",
+ .of_match_table = rockchip_sfc_dt_ids,
+ .pm = &rockchip_sfc_dev_pm_ops,
+ },
+ .probe = rockchip_sfc_probe,
+ .remove = rockchip_sfc_remove,
+};
+module_platform_driver(rockchip_sfc_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Rockchip Serial Flash Controller Driver");
+MODULE_AUTHOR("Shawn Lin <shawn.lin-TNX95d0MmH7DzftRWevZcw@public.gmane.org>");
--
1.9.1
--
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 v4 1/2] mtd: spi-nor: Bindings for Rockchip serial flash controller
From: Shawn Lin @ 2016-12-15 9:27 UTC (permalink / raw)
To: David Woodhouse, Brian Norris
Cc: Marek Vasut, Cyrille Pitchen, Rob Herring,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-rockchip-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Heiko Stuebner,
Shawn Lin
In-Reply-To: <1481794068-241619-1-git-send-email-shawn.lin-TNX95d0MmH7DzftRWevZcw@public.gmane.org>
Add binding document for the Rockchip serial flash controller.
Signed-off-by: Shawn Lin <shawn.lin-TNX95d0MmH7DzftRWevZcw@public.gmane.org>
Acked-by: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
---
Changes in v4:
- use uppercase DMA for description
Changes in v3: None
Changes in v2: None
.../devicetree/bindings/mtd/rockchip-sfc.txt | 31 ++++++++++++++++++++++
1 file changed, 31 insertions(+)
create mode 100644 Documentation/devicetree/bindings/mtd/rockchip-sfc.txt
diff --git a/Documentation/devicetree/bindings/mtd/rockchip-sfc.txt b/Documentation/devicetree/bindings/mtd/rockchip-sfc.txt
new file mode 100644
index 0000000..2a889c9
--- /dev/null
+++ b/Documentation/devicetree/bindings/mtd/rockchip-sfc.txt
@@ -0,0 +1,31 @@
+Rockchip Serial Flash Controller
+
+Required properties:
+- compatible : Should be
+ "rockchip,rk1108-sfc", "rockchip,sfc" for ROCKCHIP RK1108.
+- address-cells : Should be 1.
+- size-cells : Should be 0.
+- clocks: Must contain two entries for each entry in clock-names.
+- clock-names: Shall be "sfc" for the transfer-clock, and "hsfc" for
+ the peripheral clock.
+- interrupts : Should contain the interrupt for the device.
+- reg: Physical base address of the controller and length of memory mapped.
+
+Optional properties:
+- rockchip,sfc-no-dma: Indicate the controller doesn't support DMA transfer.
+
+Example:
+nor_flash: sfc@301c0000 {
+ compatible = "rockchip,rk1108-sfc", "rockchip,sfc";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ clocks = <&cru SCLK_SFC>, <&cru HCLK_SFC>;
+ clock-names = "sfc", "hsfc";
+ interrupts = <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>;
+ reg = <0x301c0000 0x1000>;
+ spi-nor@0 {
+ compatible = "jedec,spi-nor";
+ spi-max-frequency = <12000000>;
+ reg = <0>;
+ };
+};
--
1.9.1
--
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 v4 0/2] Add rockchip serial flash controller support
From: Shawn Lin @ 2016-12-15 9:27 UTC (permalink / raw)
To: David Woodhouse, Brian Norris
Cc: Marek Vasut, Cyrille Pitchen, Rob Herring,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-rockchip-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Heiko Stuebner,
Shawn Lin
Here is another try for adding serial flash controller
, namely SFC, found on Rockchip RK1108 platform.
Feature:
(1) Support x1, x2, x4 data bits mode
(2) Support up to 4 chip select
(3) Support two independent clock domain: AHB clock and SPI clock
(4) Support DMA master up to 16KB/transfer
Test environment:
This patchset was tested on RK1108 evb boards with Winboud flash
(w25q256) and working fine with PIO or DMA mode.
How-to:
Any rockchip guys who are interested in testing it could refer to
the following steps:
(1) enable CONFIG_MTD_M25P80
(2) enable CONFIG_SPI_ROCKCHIP_SFC
(3) enable CONFIG_MTD_CMDLINE_PARTS
(4) enable CONFIG_SQUASHFS
(4) CONFIG_CMDLINE="root=/dev/mtdblock2
mtdparts=spi-nor:256k@0(loader)ro,8m(kernel)ro,7m(rootfs),-(freedisk)"
Of course, you should check the partition layout if you modify it. Also
you could pass it from your loader to the kernel's cmdline.
(5) Add dts support:
nor_flash: sfc@301c0000 {
compatible = "rockchip,rk1108-sfc", "rockchip,sfc";
#address-cells = <1>;
#size-cells = <0>;
clocks = <&cru SCLK_SFC>, <&cru HCLK_SFC>;
clock-names = "sfc", "hsfc";
interrupts = <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>;
reg = <0x301c0000 0x1000>;
/* If you want to use PIO mode, activate this */
#rockchip,sfc-no-dma;
spi-nor@0 {
compatible = "jedec,spi-nor";
spi-max-frequency = <12000000>;
reg = <0>;
}
};
please make sure your DT's mdtid matchs what you assgin to the
mdtparts(cmdline), namely they are both *spi-nor* here.
With enabling DBG for cmdlinepart.c, you could get following log and
boot kernel and rootfs successfully.
[ 0.481420] rockchip-sfc 301c0000.sfc: w25q256 (32768 Kbytes)
[ 0.481962] DEBUG-CMDLINE-PART: parsing
<256k@0(loader)ro,8m(kernel)ro,7m(rootfs)ro,-(freedisk)>
[ 0.482897] DEBUG-CMDLINE-PART: partition 3: name
<freedisk>, offset ffffffffffffffff, size ffffffffffffffff, mask flags 0
[ 0.484021] DEBUG-CMDLINE-PART: partition 2: name
<rootfs>, offset ffffffffffffffff, size 700000, mask flags 400
[ 0.485066] DEBUG-CMDLINE-PART: partition 1: name
<kernel>, offset ffffffffffffffff, size 800000, mask flags 400
[ 0.486108] DEBUG-CMDLINE-PART: partition 0: name
<loader>, offset 0, size 40000, mask flags 400
[ 0.487152] DEBUG-CMDLINE-PART: mtdid=<spi-nor> num_parts=<4>
[ 0.487827] 4 cmdlinepart partitions found on MTD device spi-nor
[ 0.488370] Creating 4 MTD partitions on "spi-nor":
[ 0.488826] 0x000000000000-0x000000040000 : "loader"
[ 0.492340] 0x000000040000-0x000000840000 : "kernel"
[ 0.495679] 0x000000840000-0x000000f40000 : "rootfs"
[ 0.499241] 0x000000f40000-0x000002000000 : "freedisk"
[root@arm-linux]#
[root@arm-linux]#mount
/dev/root on / type squashfs (ro,relatime)
devtmpfs on /dev type devtmpfs
(rw,relatime,size=26124k,nr_inodes=6531,mode=755)
proc on /proc type proc (rw,relatime)
none on /tmp type ramfs (rw,relatime)
none on /var type ramfs (rw,relatime)
sysfs on /sys type sysfs (rw,relatime)
debug on /sys/kernel/debug type debugfs (rw,relatime)
none on /dev/pts type devpts (rw,relatime,mode=600,ptmxmode=000)
Changes in v4:
- use uppercase DMA for description
- simplify the code of get_if_type
- use dma_dir to simplify the code
- simplify the rockchip_sfc_do_rd_wr
- some minor improvements
- add reset controller when doing resume
Changes in v3:
- use io{read32,write32}_rep to simplify the corner cases
- remove more unnecessary bit definitions
- some minor comment fixes and improvement
- fix wrong unregister function
- unify more code
- use nor to avoid constantly replicating the whole
sfc->flash[sfc->num_chip].nor
- add email for MODULE_AUTHOR
- remove #if 1 --- #endif
- extract DMA code to imporve the code structure
- reset all when failing to do dma
- pass sfc to get_if_type
- rename sfc-no-dma to sfc-no-DMA
Changes in v2:
- fix typos
- add some comment for buffer and others operations
- rename SFC_MAX_CHIP_NUM to MAX_CHIPSELECT_NUM
- use u8 for cs
- return -EINVAL for default case of get_if_type
- use readl_poll_*() to check timeout cases
- simplify and clarify some condition checks
- rework the bitshifts to simplify the code
- define SFC_CMD_DUMMY(x)
- fix ummap for dma read path and finish all the
cache maintenance.
- rename to rockchip_sfc_chip_priv and embed struct spi_nor
in it.
- add MODULE_AUTHOR
- add runtime PM and general PM support.
- Thanks for Marek's comments. Link:
http://lists.infradead.org/pipermail/linux-mtd/2016-November/070321.html
Shawn Lin (2):
mtd: spi-nor: Bindings for Rockchip serial flash controller
mtd: spi-nor: add rockchip serial flash controller driver
.../devicetree/bindings/mtd/rockchip-sfc.txt | 31 +
MAINTAINERS | 8 +
drivers/mtd/spi-nor/Kconfig | 7 +
drivers/mtd/spi-nor/Makefile | 1 +
drivers/mtd/spi-nor/rockchip-sfc.c | 872 +++++++++++++++++++++
5 files changed, 919 insertions(+)
create mode 100644 Documentation/devicetree/bindings/mtd/rockchip-sfc.txt
create mode 100644 drivers/mtd/spi-nor/rockchip-sfc.c
--
1.9.1
--
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: [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
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