Re: [PATCH v1] i2c-hid: introduce HID over i2c specification implementation
On Fri, Sep 14, 2012 at 7:11 PM, benjamin.tissoires wrote: > From: Benjamin Tissoires > > Microsoft published the protocol specification of HID over i2c: > http://msdn.microsoft.com/en-us/library/windows/hardware/hh852380.aspx > > This patch introduces an implementation of this protocol. > > This implementation does not includes the ACPI part of the specification. > This will come when ACPI 5.0 devices will be available. > > Once the ACPI part will be done, OEM will not have to declare HID over I2C > devices in their platform specific driver. > > Signed-off-by: Benjamin Tissoires > --- > > Hi, > > this is finally my first implementation of HID over I2C. > > This has been tested on an Elan Microelectronics HID over I2C device, with > a Samsung Exynos 4412 board. > > Any comments are welcome. > > Cheers, > Benjamin > > drivers/i2c/Kconfig |8 + > drivers/i2c/Makefile|1 + > drivers/i2c/i2c-hid.c | 1027 > +++ > include/linux/i2c/i2c-hid.h | 35 ++ > 4 files changed, 1071 insertions(+) > create mode 100644 drivers/i2c/i2c-hid.c > create mode 100644 include/linux/i2c/i2c-hid.h > > diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig > index 5a3bb3d..5adf65a 100644 > --- a/drivers/i2c/Kconfig > +++ b/drivers/i2c/Kconfig > @@ -47,6 +47,14 @@ config I2C_CHARDEV > This support is also available as a module. If so, the module > will be called i2c-dev. > > +config I2C_HID > + tristate "HID over I2C bus" > + help > + Say Y here to use the HID over i2c protocol implementation. > + > + This support is also available as a module. If so, the module > + will be called i2c-hid. > + > config I2C_MUX > tristate "I2C bus multiplexing support" > help > diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile > index beee6b2..8f38116 100644 > --- a/drivers/i2c/Makefile > +++ b/drivers/i2c/Makefile > @@ -6,6 +6,7 @@ obj-$(CONFIG_I2C_BOARDINFO) += i2c-boardinfo.o > obj-$(CONFIG_I2C) += i2c-core.o > obj-$(CONFIG_I2C_SMBUS)+= i2c-smbus.o > obj-$(CONFIG_I2C_CHARDEV) += i2c-dev.o > +obj-$(CONFIG_I2C_HID) += i2c-hid.o > obj-$(CONFIG_I2C_MUX) += i2c-mux.o > obj-y += algos/ busses/ muxes/ > > diff --git a/drivers/i2c/i2c-hid.c b/drivers/i2c/i2c-hid.c > new file mode 100644 > index 000..eb17d8c > --- /dev/null > +++ b/drivers/i2c/i2c-hid.c > @@ -0,0 +1,1027 @@ > +/* > + * HID over I2C protocol implementation > + * > + * Copyright (c) 2012 Benjamin Tissoires > + * Copyright (c) 2012 Ecole Nationale de l'Aviation Civile, France > + * > + * This code is partly based on "USB HID support for Linux": > + * > + * Copyright (c) 1999 Andreas Gal > + * Copyright (c) 2000-2005 Vojtech Pavlik > + * Copyright (c) 2005 Michael Haboustak for Concept2, > Inc > + * Copyright (c) 2007-2008 Oliver Neukum > + * Copyright (c) 2006-2010 Jiri Kosina > + * > + * This file is subject to the terms and conditions of the GNU General Public > + * License. See the file COPYING in the main directory of this archive for > + * more details. > + */ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +#include > + > +#include > +#include > +#include > + > +#define DRIVER_NAME"i2chid" > +#define DRIVER_DESC"HID over I2C core driver" > + > +#define I2C_HID_COMMAND_TRIES 3 > + > +/* flags */ > +#define I2C_HID_STARTED(1 << 0) > +#define I2C_HID_OUT_RUNNING(1 << 1) > +#define I2C_HID_IN_RUNNING (1 << 2) > +#define I2C_HID_RESET_PENDING (1 << 3) > +#define I2C_HID_SUSPENDED (1 << 4) > + > +#define I2C_HID_PWR_ON 0x00 > +#define I2C_HID_PWR_SLEEP 0x01 > + > +/* debug option */ > +static bool debug = false; > +module_param(debug, bool, 0444); > +MODULE_PARM_DESC(debug, "print a lot of debug informations"); > + > +struct i2chid_desc { > + __le16 wHIDDescLength; > + __le16 bcdVersion; > + __le16 wReportDescLength; > + __le16 wReportDescRegister; > + __le16 wInputRegister; > + __le16 wMaxInputLength; > + __le16 wOutputRegister; > + __le16 wMaxOutputLength; > + __le16 wCommandRegister; > + __le16 wDataRegister; > + __le16 wVendorID; > + __le16 wProductID; > + __le16 wVersionID; > +} __packed; > + > +struct i2chid_cmd { > + enum { > + /* fecth HID descriptor */ > + HID_DESCR_CMD, > + > + /* fetch report descriptors */ > + HID_REPORT_DESCR_CMD, > + > + /* commands */ > + HID_RESET_CMD, > + HID_GET_REPORT_CMD, > + HID_SET_REPORT_CMD, > + HID_GET_IDLE_CMD, > + HID_SET_IDLE_CMD, > + HID_GET_PROTOCOL_CMD, > + HID_SET_PROTOCOL_CMD, > +
Re: [PATCH v1] i2c-hid: introduce HID over i2c specification implementation
On Wed, Oct 3, 2012 at 9:03 PM, Benjamin Tissoires wrote: > Hi, > > thanks also for the review. Two in the same day! I was about to send a > ping on that patch ;-) > > On Wed, Oct 3, 2012 at 8:05 AM, Shubhrajyoti Datta > wrote: >> On Fri, Sep 14, 2012 at 7:11 PM, benjamin.tissoires >> wrote: >>> From: Benjamin Tissoires >>> >>> Microsoft published the protocol specification of HID over i2c: >>> http://msdn.microsoft.com/en-us/library/windows/hardware/hh852380.aspx >>> >>> This patch introduces an implementation of this protocol. >>> >>> This implementation does not includes the ACPI part of the specification. >>> This will come when ACPI 5.0 devices will be available. >>> >>> Once the ACPI part will be done, OEM will not have to declare HID over I2C >>> devices in their platform specific driver. >>> >>> Signed-off-by: Benjamin Tissoires >>> --- >>> >>> Hi, >>> >>> this is finally my first implementation of HID over I2C. >>> >>> This has been tested on an Elan Microelectronics HID over I2C device, with >>> a Samsung Exynos 4412 board. >>> >>> Any comments are welcome. >>> >>> Cheers, >>> Benjamin >>> >>> drivers/i2c/Kconfig |8 + >>> drivers/i2c/Makefile|1 + >>> drivers/i2c/i2c-hid.c | 1027 >>> +++ >>> include/linux/i2c/i2c-hid.h | 35 ++ >>> 4 files changed, 1071 insertions(+) >>> create mode 100644 drivers/i2c/i2c-hid.c >>> create mode 100644 include/linux/i2c/i2c-hid.h >>> >>> diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig >> [...] > > same thing, will change it in v2. > >> >>> + >>> + if (debug) >>> + dev_err(&client->dev, "resetting...\n"); >> this is a little uncustomary. >> >> May be consider bdg > > Sorry for that. I don't get your point here. You don't like the whole > "if(debug) dev_err(...)" or just the "dev_err(...)" call? > Apologies for the typo dev_dbg. -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH] i2c: omap: adopt pinctrl support
On Tue, Oct 16, 2012 at 8:53 PM, Sebastien Guiriec wrote: > Some GPIO expanders need some early pin control muxing. Due to > legacy boards sometimes the driver uses subsys_initcall instead of > module_init. This patch takes advantage of defer probe feature > and pin control in order to wait until pin control probing before > GPIO driver probing. It has been tested on OMAP5 board with TCA6424 > driver. > > log: > > [0.482299] omap_i2c i2c.15: could not find pctldev for node /ocp/pinmux@4a00 > 2840/pinmux_i2c5_pins, deferring probe > [0.482330] platform i2c.15: Driver omap_i2c requests probe deferral > [0.484466] Advanced Linux Sound Architecture Driver Initialized. > > [4.746917] omap_i2c i2c.15: bus 4 rev2.4.0 at 100 kHz > [4.755279] gpiochip_find_base: found new base at 477 > [4.761169] gpiochip_add: registered GPIOs 477 to 500 on device: tca6424a > Thanks, Acked-by: Shubhrajyoti D -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH] spi: omap2-mcspi: Reorder the wait_for_completion for tx
On Tue, Nov 6, 2012 at 2:33 PM, Mark Brown wrote: > On Tue, Nov 06, 2012 at 02:30:19PM +0530, Shubhrajyoti D wrote: >> The commit d7b4394e[Cleanup the omap2_mcspi_txrx_dma function] >> changed the wait_for_completion order. Move the wait so that the >> rx doesnot wait for the tx to complete. > > Applied, thanks. Thanks Mark, -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH] spi: omap2-mcspi: Reorder the wait_for_completion for tx
On Tue, Nov 6, 2012 at 2:52 PM, Mark Brown wrote: > On Tue, Nov 06, 2012 at 02:47:27PM +0530, Shubhrajyoti D wrote: >> The commit d7b4394e[Cleanup the omap2_mcspi_txrx_dma function] >> changed the wait_for_completion order. Move the wait so that the >> rx doesnot wait for the tx to complete. > > Is this a resend of the patch I just applied, or is it something > different? No please ignore this one. Something wrong at my end it got sent twice. Please ignore. -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCHv2 0/3] spi: omap2-mcspi: spi cleanups
On Wed, Aug 22, 2012 at 10:29 PM, Mark Brown wrote: > On Wed, Aug 22, 2012 at 11:35:11AM +0530, Shubhrajyoti D wrote: >> This patch does the following >> >> Calls the pm_runtime_* functions directly. >> Remove the MOD_REG_BIT macro usage thereby removiing un-needed branch. >> At remove dont use the autosuspend runtime calls. > > Applied all, thanks. thanks. > >> The following changes since commit 23dcfa61bac244e1200ff9ad19c6e9144dcb6bb5: >> >> Merge branch 'akpm' (Andrew's patch-bomb) (2012-08-21 17:22:22 -0700) > > When sending pull requests please always base them off a tag of some > kind, normally one of Linus' is a good option if you've no special > needs. This one looks like it's based off -next so can't be pulled into > any other tree, -next is rebased daily. Actually there was a patch in your tree that I sent which is not yet in linus tree so I rebased it to linux-next to avoid any merge conflicts. Henceforth I will rebase it to your tree. -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCHv2 6/6] media: Convert struct i2c_msg initialization to C99 format
On Tue, Sep 18, 2012 at 3:26 PM, Venu Byravarasu wrote: >> -Original Message- >> From: linux-kernel-ow...@vger.kernel.org [mailto:linux-kernel- >> ow...@vger.kernel.org] On Behalf Of Shubhrajyoti D >> Sent: Tuesday, September 18, 2012 3:21 PM >> To: linux-me...@vger.kernel.org >> Cc: linux-kernel@vger.kernel.org; julia.law...@lip6.fr; Shubhrajyoti D >> Subject: [PATCHv2 6/6] media: Convert struct i2c_msg initialization to C99 >> format >> >> Convert the struct i2c_msg initialization to C99 format. This makes >> maintaining and editing the code simpler. Also helps once other >> fields >> like transferred are added in future. >> >> Signed-off-by: Shubhrajyoti D >> --- >> drivers/media/i2c/msp3400-driver.c | 42 >> ++- >> 1 files changed, 36 insertions(+), 6 deletions(-) >> >> diff --git a/drivers/media/i2c/msp3400-driver.c >> b/drivers/media/i2c/msp3400-driver.c >> index aeb22be..b8cef8d 100644 >> --- a/drivers/media/i2c/msp3400-driver.c >> +++ b/drivers/media/i2c/msp3400-driver.c >> @@ -119,12 +119,32 @@ int msp_reset(struct i2c_client *client) >> static u8 write[3] = { I2C_MSP_DSP + 1, 0x00, 0x1e }; >> u8 read[2]; >> struct i2c_msg reset[2] = { >> - { client->addr, I2C_M_IGNORE_NAK, 3, reset_off }, >> - { client->addr, I2C_M_IGNORE_NAK, 3, reset_on }, >> + { >> + .addr = client->addr, >> + .flags = I2C_M_IGNORE_NAK, >> + .len = 3, >> + .buf = reset_off >> + }, >> + { >> + .addr = client->addr, >> + .flags = I2C_M_IGNORE_NAK, >> + .len = 3, >> + .buf = reset_on >> + }, >> }; >> struct i2c_msg test[2] = { >> - { client->addr, 0,3, write }, >> - { client->addr, I2C_M_RD, 2, read }, >> + { >> + .addr = client->addr, >> + .flags = 0, > > Does flags not contain 0 by default? > It does however I felt that 0 means write so letting it be explicit. In case a removal is preferred that's doable too however felt it is more readable this way. -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 2/2] OMAP i2c: pinctrl-ify i2c-omap.c
On Thu, Sep 20, 2012 at 12:04 PM, Pantelis Antoniou wrote: > Add support for pinctrl mux settings in the OMAP I2C driver. > If no such pinctl bindings are found a warning message is printed. > > Signed-off-by: Pantelis Antoniou > --- looks good Acked-by: Shubhrajyoti D -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH] spi: omap2-mcspi: Fix the below warning
On Fri, Jul 20, 2012 at 3:40 PM, Mark Brown wrote: > On Thu, Jul 19, 2012 at 11:16:52PM +0530, Shubhrajyoti D wrote: >> The dma_map and dma_unmap should have same parameter >> passed otherwise we get the below warn. > > Applied, thanks. thanks, -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 1/5] i2c: tegra: remove unused member variable
Hi Laxman, On Tue, Jul 10, 2012 at 4:50 PM, Laxman Dewangan wrote: > Remove unused member variable "iomem" of the > i2c device structure. You might want to mention the commit which removed the last usage etc. > > Signed-off-by: Laxman Dewangan > --- > This patch is resend of earlier patch > i2c: tegra: remove unused member variable. > and sending it as part fo series. > -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH V3 2/3] thermal: exynos: Miscellaneous fixes to support falling threshold interrupt
On 1/17/13, Amit Daniel Kachhap wrote: > Below fixes are done to support falling threshold interrupt, > * Falling interrupt status macro corrected according to exynos5 data sheet. > * The get trend function modified to calculate trip temperature correctly. > * The clearing of interrupt status in the isr is now done after handling > the event that caused the interrupt. One fix per patch would have been better. However not particular. Also are they applicable to older kernels? > > Signed-off-by: Amit Daniel Kachhap > --- -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH] i2c: tegra: remove warning dump if timeout happen in transfer
On Thu, Feb 14, 2013 at 6:13 PM, Laxman Dewangan wrote: > If timeout error occurs in the i2c transfer then it was dumping warning > of call stack. > > Remove the warning dump as there is may be possibility that some slave > devices are busy and not responding the i2c communication. > > Signed-off-by: Laxman Dewangan > --- > The patch is generated based on discussion happen between Stephena and > Wolfram on the patch: > i2c: add bcm2835 driver > > resending patch as Wolfram's email id has been changed. > > drivers/i2c/busses/i2c-tegra.c |2 +- > 1 files changed, 1 insertions(+), 1 deletions(-) > > diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c > index ae2e027..36704e3 100644 > --- a/drivers/i2c/busses/i2c-tegra.c > +++ b/drivers/i2c/busses/i2c-tegra.c > @@ -587,7 +587,7 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev > *i2c_dev, > ret = wait_for_completion_timeout(&i2c_dev->msg_complete, > TEGRA_I2C_TIMEOUT); > tegra_i2c_mask_irq(i2c_dev, int_mask); > > - if (WARN_ON(ret == 0)) { > + if (ret == 0) { I think WARN_ON has a unlikely. If you could do a profiling and have the unlikely. BTW thats not an objection to the patch though. > dev_err(i2c_dev->dev, "i2c transfer timed out\n"); > > tegra_i2c_init(i2c_dev); > -- > 1.7.1.1 > > -- > To unsubscribe from this list: send the line "unsubscribe linux-i2c" in > the body of a message to majord...@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 2/2] input: gpio-keys: Add runtime support
On Thu, Oct 11, 2012 at 7:45 PM, Lee Jones wrote: > From: Jonas Aaberg Some change logs would have helped. > > Cc: Dmitry Torokhov > Cc: linux-in...@vger.kernel.org > Acked-by: Lee Jones > Signed-off-by: Jonas Aaberg > Signed-off-by: Philippe Langlais > Reviewed-by: Bengt Jonsson > --- > drivers/input/keyboard/gpio_keys.c | 16 > 1 file changed, 12 insertions(+), 4 deletions(-) > > diff --git a/drivers/input/keyboard/gpio_keys.c > b/drivers/input/keyboard/gpio_keys.c > index 7947315..78de557 100644 > --- a/drivers/input/keyboard/gpio_keys.c > +++ b/drivers/input/keyboard/gpio_keys.c > @@ -29,6 +29,7 @@ > #include > #include > #include > +#include > > struct gpio_button_data { > const struct gpio_keys_button *button; > @@ -526,6 +527,7 @@ static int gpio_keys_open(struct input_dev *input) > { > struct gpio_keys_drvdata *ddata = input_get_drvdata(input); > > + pm_runtime_get_sync(input->dev.parent); I am not an expert of the runtime. However would be grateful if you explain me what it actually do. Also I did not see any runtime suspend/ resume handlers populated. -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 0/7] i2c: s3c2410: Add devm_* apis and cleanup
On Fri, Nov 23, 2012 at 11:29 AM, Tushar Behera wrote: > This patchset cleans up the probe function of i2c-s3c2410 driver. > These have been tested on Exynos4210 based Origen board. > > Tushar Behera (7): > i2c: s3c2410: Remove unnecessary label err_noclk > i2c: s3c2410: Convert to use devm_clk_get() > i2c: s3c2410: Convert to use devm_request_mem_region() > i2c: s3c2410: Convert to use devm_ioremap() > i2c: s3c2410: Convert to use devm_request_irq() You may want to consider request_and_ioremap. > i2c: s3c2410: Move location of clk_prepare_enable() call in probe > function > i2c: s3c2410: Remove err_cpufreq label > > drivers/i2c/busses/i2c-s3c2410.c | 74 > -- > 1 files changed, 23 insertions(+), 51 deletions(-) > > -- > 1.7.4.1 > > -- > To unsubscribe from this list: send the line "unsubscribe linux-i2c" in > the body of a message to majord...@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH] watchdog: da9052: Fix invalid free of devm_ allocated data
On Thu, Nov 22, 2012 at 10:13 AM, Tushar Behera wrote: > It is not required to free devm_ allocated data. Since kref_put > needs a valid release function, da9052_wdt_release_resources() > is not deleted. > > Fixes following warning. > drivers/watchdog/da9052_wdt.c:59:1-6: WARNING: invalid free of > devm_ allocated data > > Signed-off-by: Tushar Behera > --- > drivers/watchdog/da9052_wdt.c |4 > 1 files changed, 0 insertions(+), 4 deletions(-) > > diff --git a/drivers/watchdog/da9052_wdt.c b/drivers/watchdog/da9052_wdt.c > index f7abbae..20071de 100644 > --- a/drivers/watchdog/da9052_wdt.c > +++ b/drivers/watchdog/da9052_wdt.c > @@ -53,10 +53,6 @@ static const struct { > > static void da9052_wdt_release_resources(struct kref *r) > { > - struct da9052_wdt_data *driver_data = > - container_of(r, struct da9052_wdt_data, kref); > - > - kfree(driver_data); However now the function will be empty right? > } > > static int da9052_wdt_set_timeout(struct watchdog_device *wdt_dev, > -- > 1.7.4.1 > > -- > To unsubscribe from this list: send the line "unsubscribe linux-kernel" in > the body of a message to majord...@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html > Please read the FAQ at http://www.tux.org/lkml/ -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH] gpio: Added zynq specific check for special pins on bank zero
On Tue, Sep 20, 2016 at 2:02 PM, Nava kishore Manne wrote: > From: Nava kishore Manne > > This patch adds zynq specific check for bank 0 pins 7 and 8 > are special and cannot be used as inputs Is there any such pins for zynqmp? > > Signed-off-by: Nava kishore Manne > --- > drivers/gpio/gpio-zynq.c | 17 +++-- > 1 file changed, 15 insertions(+), 2 deletions(-) > > diff --git a/drivers/gpio/gpio-zynq.c b/drivers/gpio/gpio-zynq.c > index e72794e..eae9d24 100644 > --- a/drivers/gpio/gpio-zynq.c > +++ b/drivers/gpio/gpio-zynq.c > @@ -96,6 +96,10 @@ > /* GPIO upper 16 bit mask */ > #define ZYNQ_GPIO_UPPER_MASK 0x > > +/* For GPIO quirks */ > +#define ZYNQ_GPIO BIT(0) > +#define ZYNQMP_GPIOBIT(1) if not can we remove ZYNQMP_GPIO?
Re: [PATCH 1/3] spi: spi-xilinx: Remove ISR race condition
On Thu, Oct 8, 2015 at 8:40 PM, Jean-Francois Dagenais wrote: > >> On Jun 4, 2013, at 1:32 PM, Mark Brown wrote: >> >> Applied but this is a bit sad, having to defer the refill to process >> context means that we're adding extra latency which takes us further >> away from being able to saturate the bus. There ought to be a way to >> avoid the issue though I can't think of a non-racy one - I guess level >> triggered interrupts aren't an option? > > Hi all, > > We've been using an improved version of this driver in production for years > here > in the 3.4 tree. I had to intervene in order to improve performance. I managed > to double it (not bad). Thats cool. > > Like the other threads I've seen about this, my strategy involved limiting the > reads to the registers, which, through a pci-e link were kind of long. Here's > the yet un-submitted commit header I carry in my clone: Why not send the patches. > > = > spi: xilinx - minimize iomem reads > > If this IP core is accessed through bridges like PCI-e, reads are rather > costly. Doing many reads or read-modify-writes is thus long and strenuous > on the CPU (active waiting). > > The transfer workflow of this driver allows some assumptions to be made > and > exploited to minimize reads as much as possible. > > These two assumptions are made: > - since we are in control of the CR register, cache it so we don't have to > read it all the time to modify it. Makes sense. > - FIFO (either depth of 1 or 16) are always maxed out, unless the > remaining > bytes are less than the FIFO depth. For this reason, we can predict the > state of the FIFOs without checking with the status register to check if > they are empty or full. Can you explain more details. > > Reading 32Mb flash at 32MHz on a core with 8bits/word and FIFO enabled > (16), > has dropped from ~60s to ~30s. Still high, but better. Most of the delay > still > comes from emptying the RX FIFO one "word" at a time. > === > -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [[PATCH v2] 2/2] Altera Modular ADC driver support
> +static int alt_modular_adc_probe(struct platform_device *pdev) > +{ > + struct altera_adc *adc; > + struct device_node *np = pdev->dev.of_node; > + struct iio_dev *indio_dev; > + struct resource *mem; > + int ret; > + > + if (!np) > + return -ENODEV; > + > + indio_dev = iio_device_alloc(sizeof(struct altera_adc)); > + if (!indio_dev) { > + dev_err(&pdev->dev, "failed allocating iio device\n"); > + return -ENOMEM; > + } > + > + adc = iio_priv(indio_dev); > + > + mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, > + "sequencer_csr"); > + adc->seq_regs = devm_ioremap_resource(&pdev->dev, mem); > + if (IS_ERR(adc->seq_regs)) { > + ret = PTR_ERR(adc->seq_regs); > + goto err_iio; > + } > + > + mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, > + "sample_store_csr"); > + adc->sample_regs = devm_ioremap_resource(&pdev->dev, mem); > + if (IS_ERR(adc->sample_regs)) { > + ret = PTR_ERR(adc->sample_regs); > + goto err_iio; > + } > + > + ret = alt_modular_adc_parse_dt(indio_dev, &pdev->dev); > + if (ret < 0) { > + dev_err(&pdev->dev, "failed to parse device tree\n"); > + goto err_iio; > + } > + > + ret = alt_modular_adc_channel_init(indio_dev); > + if (ret < 0) { > + dev_err(&pdev->dev, "failed initialize ADC channels\n"); > + goto err_iio; > + } > + > + platform_set_drvdata(pdev, indio_dev); > + > + indio_dev->name = dev_name(&pdev->dev); > + indio_dev->dev.parent = &pdev->dev; > + indio_dev->dev.of_node = pdev->dev.of_node; > + indio_dev->info = &adc_iio_info; > + indio_dev->modes = INDIO_DIRECT_MODE; > + indio_dev->num_channels = adc->slot_count; > + > + ret = iio_device_register(indio_dev); > + if (ret) > + goto err_iio; > + > + /* Disable Interrupt */ > + writel_relaxed(0, (adc->sample_regs + ADC_IER_REG)); Why disable interrupts? > + > + /* Start Continuous Sampling */ > + writel_relaxed((ADC_RUN_MSK), (adc->seq_regs + ADC_CMD_REG)); > + > + return 0; > + > + > +err_iio: > + iio_device_free(indio_dev); > + return ret; > +} > + > +static int alt_modular_adc_remove(struct platform_device *pdev) > +{ > + struct iio_dev *indio_dev = platform_get_drvdata(pdev); > + struct altera_adc *adc = iio_priv(indio_dev); > + > + /* Stop ADC */ > + writel((ADC_STOP_MSK), (adc->seq_regs + ADC_CMD_REG)); > + > + /* Unregister ADC */ > + iio_device_unregister(indio_dev); > + > + return 0; > +} > + > +static struct platform_driver altr_modular_adc_driver = { > + .probe = alt_modular_adc_probe, > + .remove = alt_modular_adc_remove, > + .driver = { > + .name = "alt-modular-adc", > + .owner = THIS_MODULE, > + .of_match_table = alt_modular_adc_match, > + }, > +}; > + > + > +module_platform_driver(altr_modular_adc_driver); > + > +MODULE_DESCRIPTION("Altera Modular ADC Driver"); > +MODULE_AUTHOR("Chee Nouk Phoon "); > +MODULE_LICENSE("GPL v2"); > -- > 1.7.1 > > -- > To unsubscribe from this list: send the line "unsubscribe linux-kernel" in > the body of a message to majord...@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html > Please read the FAQ at http://www.tux.org/lkml/ -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH v3 2/4] drivers: firmware: xilinx: Add ZynqMP firmware driver
Hi, Thanks for the patch. A few questions below. On Thu, Jan 25, 2018 at 4:51 AM, Jolly Shah wrote: > This patch is adding communication layer with firmware. > Firmware driver provides an interface to firmware APIs. > Interface APIs can be used by any driver to communicate to > PMUFW(Platform Management Unit). All requests go through ATF. > > Signed-off-by: Jolly Shah > Signed-off-by: Rajan Vaja > --- > > +/** > + * zynqmp_pm_clock_enable - Enable the clock for given id > + * @clock_id: ID of the clock to be enabled Does it enable all the parents also if they are disabled? > + * > + * This function is used by master to enable the clock > + * including peripherals and PLL clocks. > + * > + * Return: Returns status, either success or error+reason. > + */ > +static int zynqmp_pm_clock_enable(u32 clock_id) > +{ > + return invoke_pm_fn(PM_CLOCK_ENABLE, clock_id, 0, 0, 0, NULL); > +} > + > +/** > + * zynqmp_pm_clock_disable - Disable the clock for given id > + * @clock_id: ID of the clock to be disable > + * > + * This function is used by master to disable the clock > + * including peripherals and PLL clocks. > + * > + * Return: Returns status, either success or error+reason. > + */ > +static int zynqmp_pm_clock_disable(u32 clock_id) > +{ > + return invoke_pm_fn(PM_CLOCK_DISABLE, clock_id, 0, 0, 0, NULL); > +} > + > +/** > + * zynqmp_pm_clock_getstate - Get the clock state for given id > + * @clock_id: ID of the clock to be queried > + * @state: 1/0 (Enabled/Disabled) > + * > + * This function is used by master to get the state of clock > + * including peripherals and PLL clocks. > + * > + * Return: Returns status, either success or error+reason. > + */ > +static int zynqmp_pm_clock_getstate(u32 clock_id, u32 *state) > +{ > + u32 ret_payload[PAYLOAD_ARG_CNT]; > + int ret; > + > + ret = invoke_pm_fn(PM_CLOCK_GETSTATE, clock_id, 0, 0, 0, ret_payload); > + *state = ret_payload[1]; > + > + return ret; > +} > + > +/** > + * zynqmp_pm_clock_setdivider - Set the clock divider for given id > + * @clock_id: ID of the clock > + * @div_type: TYPE_DIV1: div1 > + * TYPE_DIV2: div2 div type didnt see in the signature. > + * @divider: divider value. > + * > + * This function is used by master to set divider for any clock > + * to achieve desired rate. > + * > + * Return: Returns status, either success or error+reason. > + */ > +static int zynqmp_pm_clock_setdivider(u32 clock_id, u32 divider) > +{ > + return invoke_pm_fn(PM_CLOCK_SETDIVIDER, clock_id, divider, 0, 0, > NULL); > +} > + > +/** > + * zynqmp_pm_clock_getdivider - Get the clock divider for given id > + * @clock_id: ID of the clock > + * @div_type: TYPE_DIV1: div1 > + * TYPE_DIV2: div2 didnt see this below. > + * @divider: divider value. > + * > + * This function is used by master to get divider values > + * for any clock. > + * > + * Return: Returns status, either success or error+reason. > + */ > +static int zynqmp_pm_clock_getdivider(u32 clock_id, u32 *divider) > +{ > + u32 ret_payload[PAYLOAD_ARG_CNT]; > + int ret; > + > + ret = invoke_pm_fn(PM_CLOCK_GETDIVIDER, clock_id, 0, 0, 0, > ret_payload); > + *divider = ret_payload[1]; > + > + return ret; > +} > + > +/** > + * zynqmp_pm_clock_setrate - Set the clock rate for given id > + * @clock_id: ID of the clock > + * @rate: rate value in hz > + * > + * This function is used by master to set rate for any clock. > + * > + * Return: Returns status, either success or error+reason. > + */ So this can set rate only 4G max ? > +static int zynqmp_pm_clock_setrate(u32 clock_id, u32 rate) > +{ > + return invoke_pm_fn(PM_CLOCK_SETRATE, clock_id, rate, 0, 0, NULL); > +} > + > +/** > + * zynqmp_pm_clock_getrate - Get the clock rate for given id > + * @clock_id: ID of the clock > + * @rate: rate value in hz > + * > + * This function is used by master to get rate > + * for any clock. > + * > + * Return: Returns status, either success or error+reason. > + */ Same question here? > +static int zynqmp_pm_clock_getrate(u32 clock_id, u32 *rate) > +{ > + u32 ret_payload[PAYLOAD_ARG_CNT]; > + int ret; > + > + ret = invoke_pm_fn(PM_CLOCK_GETRATE, clock_id, 0, 0, 0, ret_payload); > + *rate = ret_payload[1]; > + > + return ret; > +} > + Also what is the difference between set rate and set divider?
Re: [PATCH v2 2/2] dma: Add Xilinx zynqmp dma engine driver support
On Mon, Jun 15, 2015 at 8:06 PM, Punnaiah Choudary Kalluri wrote: > Added the basic driver for zynqmp dma engine used in Zynq > UltraScale+ MPSoC. The initial release of this driver supports > only memory to memory transfers. > > Signed-off-by: Punnaiah Choudary Kalluri > --- > +/** > + * zynqmp_dma_chan_is_idle - Provides the channel idle status > + * @chan: ZynqMP DMA DMA channel pointer > + * > + * Return: '1' if the channel is idle otherwise '0' > + */ > +static int zynqmp_dma_chan_is_idle(struct zynqmp_dma_chan *chan) maybe this could return bool. > +{ > + u32 regval; > + > + regval = readl(chan->regs + STATUS); > + if (regval & STATUS_BUSY) > + return 0; > + > + return 1; > +} > + -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [LINUX RFC V2 2/2] spi: Add support for Zynq Ultrascale+ MPSoC GQSPI controller
hi, Some minor comments. On Fri, Jun 5, 2015 at 6:37 PM, Ranjit Waghmode wrote: > This patch adds support for GQSPI controller driver used by > Zynq Ultrascale+ MPSoC > > Signed-off-by: Ranjit Waghmode > --- > Here is the v2 series. > + */ > +static void zynqmp_qspi_chipselect(struct spi_device *qspi, bool is_high) > +{ > + struct zynqmp_qspi *xqspi = spi_master_get_devdata(qspi->master); > + u32 genfifoentry = 0x0, statusreg, timeout; > + > + genfifoentry |= GQSPI_GENFIFO_MODE_SPI; > + genfifoentry |= xqspi->genfifobus; > + > + if (!is_high) { > + genfifoentry |= xqspi->genfifocs; > + genfifoentry |= GQSPI_GENFIFO_CS_SETUP; > + } else { > + genfifoentry |= GQSPI_GENFIFO_CS_HOLD; > + } > + > + zynqmp_gqspi_write(xqspi, GQSPI_GEN_FIFO_OFST, genfifoentry); > + > + /* Dummy generic FIFO entry */ > + zynqmp_gqspi_write(xqspi, GQSPI_GEN_FIFO_OFST, 0x0); > + > + /* Manually start the generic FIFO command */ > + zynqmp_gqspi_write(xqspi, GQSPI_CONFIG_OFST, > + zynqmp_gqspi_read(xqspi, GQSPI_CONFIG_OFST) | > + GQSPI_CFG_START_GEN_FIFO_MASK); > + timeout = 1; > + /* Wait until the generic FIFO command is empty */ > + do { > + statusreg = zynqmp_gqspi_read(xqspi, GQSPI_ISR_OFST); > + timeout--; Can this be not busy. > + } while (!(statusreg & > + GQSPI_ISR_GENFIFOEMPTY_MASK) && > +(statusreg & GQSPI_ISR_TXEMPTY_MASK) && timeout); > + if (!timeout) > + dev_err(xqspi->dev, "Chip select timed out\n"); > +} > + > +/** > + * zynqmp_qspi_setup_transfer: Configure QSPI controller for specified > + * transfer > + * @qspi: Pointer to the spi_device structure > + * @transfer: Pointer to the spi_transfer structure which provides > + * information about next transfer setup parameters > + * > + * Sets the operational mode of QSPI controller for the next QSPI transfer > and > + * sets the requested clock frequency. > + * > + * Return: Always 0 > + * > + * Note: > + * If the requested frequency is not an exact match with what can be > + * obtained using the pre-scalar value, the driver sets the clock > + * frequency which is lower than the requested frequency (maximum lower) > + * for the transfer. > + * > + * If the requested frequency is higher or lower than that is supported > + * by the QSPI controller the driver will set the highest or lowest > + * frequency supported by controller. > + */ > +static int zynqmp_qspi_setup_transfer(struct spi_device *qspi, > + struct spi_transfer *transfer) > +{ > + struct zynqmp_qspi *xqspi = spi_master_get_devdata(qspi->master); > + ulong clk_rate; > + u32 config_reg, req_hz, baud_rate_val = 0; > + > + if (transfer) > + req_hz = transfer->speed_hz; > + else > + req_hz = qspi->max_speed_hz; > + > + /* Set the clock frequency */ > + /* If req_hz == 0, default to lowest speed */ > + clk_rate = clk_get_rate(xqspi->refclk); > + > + while ((baud_rate_val < GQSPI_BAUD_DIV_MAX) && > + (clk_rate / > + (GQSPI_BAUD_DIV_SHIFT << baud_rate_val)) > req_hz) > + baud_rate_val++; > + > + config_reg = zynqmp_gqspi_read(xqspi, GQSPI_CONFIG_OFST); > + > + /* Set the QSPI clock phase and clock polarity */ > + config_reg &= (~GQSPI_CFG_CLK_PHA_MASK) & (~GQSPI_CFG_CLK_POL_MASK); > + > + if (qspi->mode & SPI_CPHA) > + config_reg |= GQSPI_CFG_CLK_PHA_MASK; > + if (qspi->mode & SPI_CPOL) > + config_reg |= GQSPI_CFG_CLK_POL_MASK; > + > + config_reg &= ~GQSPI_CFG_BAUD_RATE_DIV_MASK; > + config_reg |= (baud_rate_val << GQSPI_CFG_BAUD_RATE_DIV_SHIFT); > + zynqmp_gqspi_write(xqspi, GQSPI_CONFIG_OFST, config_reg); > + return 0; > +} > + > +/** > + * zynqmp_qspi_setup: Configure the QSPI controller > + * @qspi: Pointer to the spi_device structure > + * > + * Sets the operational mode of QSPI controller for the next QSPI transfer, > + * baud rate and divisor value to setup the requested qspi clock. > + * > + * Return: 0 Always doesnt seem to be true > + */ > +static int zynqmp_qspi_setup(struct spi_device *qspi) > +{ > + if (qspi->master->busy) > + return -EBUSY; > + return 0; > +} > + > +/** > + * zynqmp_qspi_filltxfifo: Fills the TX FIFO as long as there is room in > + * the FIFO or the bytes required to be > + * transmitted. > + * @xqspi: Pointer to the zynqmp_qspi structure > + * @size: Number of bytes to be copied from TX buffer to TX FIFO > + */ > +static void zynqmp_qspi_filltxfifo(struct zynqmp_qspi *xqspi, int size) > +{ > +
Re: [PATCH v3] iio: adc: xilinx-xadc: Push interrupts into threaded context
On Fri, Jul 24, 2015 at 6:08 PM, Lars-Peter Clausen wrote: > Hi, > > Sorry, but I don't think this patch has been sufficiently tested against a > mainline kernel. The driver wont even probe the way it is right now. > > On 07/21/2015 01:14 AM, Xander Huff wrote: >> >> The driver currently registers a pair of irq handlers using >> request_threaded_irq(), however the synchronization mechanism between the >> hardirq and the threadedirq handler is a regular spinlock. > > > If everything runs in threaded context we don't really need the spinlock > anymore and can use the mutex throughout. that should be better from the performance point of view. > >> >> Unfortunately, this breaks PREEMPT_RT builds, where a spinlock can sleep, >> and is thus not able to be acquired from a hardirq handler. This patch >> gets >> rid of the hardirq handler and pushes all interrupt handling into the >> threaded context. > > > We actually might as well run everything in the hardirq handler (which will > be threaded in PREEMPT_RT). The reason why we have the threaded handler is > because xadc_handle_event() used to sleep, but it doesn't do this anymore. The point is why have the hard irq. If we use hardirq then not mutex can be used and spinlock will be busy. is there something i may be missing? > > -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH-v5 2/5] i2c: pxa: enable/disable i2c module across msg xfer
hi , On Tue, Jul 21, 2015 at 6:11 PM, Vaibhav Hiremath wrote: > From: Yi Zhang > > Enable i2c module/unit before transmission and disable when it > finishes. > > why? > It's because the i2c bus may be disturbed if the slave device, > typically a touch, powers on. Why should that be an issue? Is it an errata. In which mode it is an issue slave / master or both? > > As we do not want to break slave mode support, this patch introduces > DT property to control disable of the I2C module after xfer in master > mode of operation. > > i2c-disable-after-xfer : If set, driver will disable I2C module after > msg xfer > > Signed-off-by: Yi Zhang > Signed-off-by: Vaibhav Hiremath > --- -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH v2] ARM64: zynqmp: Add eeprom memories on i2c bus
On Wed, Jul 29, 2015 at 7:49 PM, Michal Simek wrote: > Add i2c eeprom memories on i2c bus. > Thanks for the patch. Feel free to add Reviewed-by: Shubhrajyoti Datta > Signed-off-by: Michal Simek > --- > > Changes in v2: > - Change eeprom max freq from 100k to 400k > > --- > arch/arm64/boot/dts/xilinx/zynqmp-ep108.dts | 18 ++ > 1 file changed, 18 insertions(+) > > diff --git a/arch/arm64/boot/dts/xilinx/zynqmp-ep108.dts > b/arch/arm64/boot/dts/xilinx/zynqmp-ep108.dts > index c5cc8dbd0968..3b1011169756 100644 > --- a/arch/arm64/boot/dts/xilinx/zynqmp-ep108.dts > +++ b/arch/arm64/boot/dts/xilinx/zynqmp-ep108.dts > @@ -50,6 +50,24 @@ > status = "okay"; > }; > > +&i2c0 { > + status = "okay"; > + clock-frequency = <40>; > + eeprom@54 { > + compatible = "at,24c64"; > + reg = <0x54>; > + }; > +}; > + > +&i2c1 { > + status = "okay"; > + clock-frequency = <40>; > + eeprom@55 { > + compatible = "at,24c64"; > + reg = <0x55>; > + }; > +}; > + > &sata { > status = "okay"; > ceva,broken-gen2; > -- > 2.3.5 > > > ___ > linux-arm-kernel mailing list > linux-arm-ker...@lists.infradead.org > http://lists.infradead.org/mailman/listinfo/linux-arm-kernel -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH v3] iio: adc: xilinx-xadc: Push interrupts into threaded context
On Tue, Aug 4, 2015 at 1:35 PM, Lars-Peter Clausen wrote: > > Well there is no need to use a threaded IRQ. The interrupt handler is quite > small and doesn't take too much time and doesn't have any delays or sleeps > in it either. > > Ok thanks for the explanation. -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 7/7] ARM64: zynqmp: Add eeprom memories on i2c bus
Hi, On Mon, Jul 27, 2015 at 3:18 PM, Michal Simek wrote: > Add i2c eeprom memories on i2c bus. > > Signed-off-by: Michal Simek > --- > > arch/arm64/boot/dts/xilinx/zynqmp-ep108.dts | 18 ++ > 1 file changed, 18 insertions(+) > > diff --git a/arch/arm64/boot/dts/xilinx/zynqmp-ep108.dts > b/arch/arm64/boot/dts/xilinx/zynqmp-ep108.dts > index 206e18eca2fb..47debdcbefbf 100644 > --- a/arch/arm64/boot/dts/xilinx/zynqmp-ep108.dts > +++ b/arch/arm64/boot/dts/xilinx/zynqmp-ep108.dts > @@ -36,6 +36,24 @@ > status = "okay"; > }; > > +&i2c0 { > + status = "okay"; > + clock-frequency = <10>; If I am not wrong eeprom could work at 400k Could we make that as the speed. > + eeprom@54 { > + compatible = "at,24c64"; > + reg = <0x54>; > + }; > +}; > + > +&i2c1 { > + status = "okay"; > + clock-frequency = <10>; > + eeprom@55 { > + compatible = "at,24c64"; > + reg = <0x55>; > + }; > +}; > + > &gem0 { > status = "okay"; > phy-handle = <&phy0>; > -- > 2.3.5 > > > ___ > linux-arm-kernel mailing list > linux-arm-ker...@lists.infradead.org > http://lists.infradead.org/mailman/listinfo/linux-arm-kernel -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH] spi: zynqmp: disable clocks in error paths
The if pclk enable fails the refclk is not disabled. Fix the same. Signed-off-by: Shubhrajyoti Datta --- drivers/spi/spi-zynqmp-gqspi.c |3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/drivers/spi/spi-zynqmp-gqspi.c b/drivers/spi/spi-zynqmp-gqspi.c index aab9b49..18aeace 100644 --- a/drivers/spi/spi-zynqmp-gqspi.c +++ b/drivers/spi/spi-zynqmp-gqspi.c @@ -360,7 +360,7 @@ static int zynqmp_prepare_transfer_hardware(struct spi_master *master) ret = clk_enable(xqspi->refclk); if (ret) - goto clk_err; + return ret; ret = clk_enable(xqspi->pclk); if (ret) @@ -369,6 +369,7 @@ static int zynqmp_prepare_transfer_hardware(struct spi_master *master) zynqmp_gqspi_write(xqspi, GQSPI_EN_OFST, GQSPI_EN_MASK); return 0; clk_err: + clk_disable(xqspi->refclk); return ret; } -- 1.7.1
Re: [PATCH 1/3] spi: spi-xilinx: Remove ISR race condition
> >> >> = >> spi: xilinx - minimize iomem reads >> >> If this IP core is accessed through bridges like PCI-e, reads are rather >> costly. Doing many reads or read-modify-writes is thus long and strenuous >> on the CPU (active waiting). >> >> The transfer workflow of this driver allows some assumptions to be made >> and >> exploited to minimize reads as much as possible. >> >> These two assumptions are made: >> - since we are in control of the CR register, cache it so we don't have >> to >> read it all the time to modify it. > > Makes sense. I have made an attempt at it can you check if you get any performance improvemets on your setup. http://www.spinics.net/lists/linux-spi/msg05963.html Thanks, Shubhrajyoti -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v2] i2c: cadence: Move to sensible power management
Currently the clocks are enabled at probe and disabled at remove. Which keeps the clocks enabled even if no transaction is going on. This patch enables the clocks at the start of transfer and disables after it. Also adapts to runtime pm. Remove xi2c->suspended and use pm runtime status instead. converts dev pm to const to silence a checkpatch warning. Signed-off-by: Shubhrajyoti Datta --- changes since v2 update the cc list drivers/i2c/busses/i2c-cadence.c | 73 -- 1 files changed, 46 insertions(+), 27 deletions(-) diff --git a/drivers/i2c/busses/i2c-cadence.c b/drivers/i2c/busses/i2c-cadence.c index 84deed6..6b08d16 100644 --- a/drivers/i2c/busses/i2c-cadence.c +++ b/drivers/i2c/busses/i2c-cadence.c @@ -18,6 +18,7 @@ #include #include #include +#include /* Register offsets for the I2C device. */ #define CDNS_I2C_CR_OFFSET 0x00 /* Control Register, RW */ @@ -96,6 +97,8 @@ CDNS_I2C_IXR_COMP) #define CDNS_I2C_TIMEOUT msecs_to_jiffies(1000) +/* timeout for pm runtime autosuspend */ +#define CNDS_I2C_PM_TIMEOUT1000/* ms */ #define CDNS_I2C_FIFO_DEPTH16 /* FIFO depth at which the DATA interrupt occurs */ @@ -128,7 +131,6 @@ * @xfer_done: Transfer complete status * @p_send_buf:Pointer to transmit buffer * @p_recv_buf:Pointer to receive buffer - * @suspended: Flag holding the device's PM status * @send_count:Number of bytes still expected to send * @recv_count:Number of bytes still expected to receive * @curr_recv_count: Number of bytes to be received in current transfer @@ -141,6 +143,7 @@ * @quirks:flag for broken hold bit usage in r1p10 */ struct cdns_i2c { + struct device *dev; void __iomem *membase; struct i2c_adapter adap; struct i2c_msg *p_msg; @@ -148,7 +151,6 @@ struct cdns_i2c { struct completion xfer_done; unsigned char *p_send_buf; unsigned char *p_recv_buf; - u8 suspended; unsigned int send_count; unsigned int recv_count; unsigned int curr_recv_count; @@ -569,9 +571,14 @@ static int cdns_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, struct cdns_i2c *id = adap->algo_data; bool hold_quirk; + ret = pm_runtime_get_sync(id->dev); + if (ret < 0) + return ret; /* Check if the bus is free */ - if (cdns_i2c_readreg(CDNS_I2C_SR_OFFSET) & CDNS_I2C_SR_BA) - return -EAGAIN; + if (cdns_i2c_readreg(CDNS_I2C_SR_OFFSET) & CDNS_I2C_SR_BA) { + ret = -EAGAIN; + goto out; + } hold_quirk = !!(id->quirks & CDNS_I2C_BROKEN_HOLD_BIT); /* @@ -590,7 +597,8 @@ static int cdns_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, if (msgs[count].flags & I2C_M_RD) { dev_warn(adap->dev.parent, "Can't do repeated start after a receive message\n"); - return -EOPNOTSUPP; + ret = -EOPNOTSUPP; + goto out; } } id->bus_hold_flag = 1; @@ -608,20 +616,26 @@ static int cdns_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, ret = cdns_i2c_process_msg(id, msgs, adap); if (ret) - return ret; + goto out; /* Report the other error interrupts to application */ if (id->err_status) { cdns_i2c_master_reset(adap); - if (id->err_status & CDNS_I2C_IXR_NACK) - return -ENXIO; - - return -EIO; + if (id->err_status & CDNS_I2C_IXR_NACK) { + ret = -ENXIO; + goto out; + } + ret = -EIO; + goto out; } } - return num; + ret = num; +out: + pm_runtime_mark_last_busy(id->dev); + pm_runtime_put_autosuspend(id->dev); + return ret; } /** @@ -760,7 +774,7 @@ static int cdns_i2c_clk_notifier_cb(struct notifier_block *nb, unsigned long struct clk_notifier_data *ndata = data; struct cdns_i2c *id = to_cdns_i2c(nb); - if (id->suspended) + if (pm_runtime_suspended(id->dev)) return NOTIFY_OK; switch (event) { @@ -808,14 +822,12 @@ static int cdns_i2c_clk_notifier_cb(struct notifier_block *nb, unsigned long * * Return: 0 always */ -stat
Re: [PATCHv2] i2c: cadence: Enable power management
On Wed, Oct 28, 2015 at 11:34 AM, Shubhrajyoti Datta wrote: > Currently the clocks are enabled at probe and disabled at remove. > This patch enables the clocks at the start of transfer and disables > after it. > > Also adapts to runtime pm. > Remove xi2c->suspended and use pm runtime status instead. > > converts dev pm to const to silence a checkpatch warning. > Please ignore this patch -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCHv2] i2c: cadence: Enable power management
Currently the clocks are enabled at probe and disabled at remove. This patch enables the clocks at the start of transfer and disables after it. Also adapts to runtime pm. Remove xi2c->suspended and use pm runtime status instead. converts dev pm to const to silence a checkpatch warning. Signed-off-by: Shubhrajyoti Datta --- changes since v1: update the cc list. drivers/i2c/busses/i2c-cadence.c | 74 -- 1 files changed, 47 insertions(+), 27 deletions(-) diff --git a/drivers/i2c/busses/i2c-cadence.c b/drivers/i2c/busses/i2c-cadence.c index f5227c5..ba3c67c 100644 --- a/drivers/i2c/busses/i2c-cadence.c +++ b/drivers/i2c/busses/i2c-cadence.c @@ -18,6 +18,7 @@ #include #include #include +#include /* Register offsets for the I2C device. */ #define CDNS_I2C_CR_OFFSET 0x00 /* Control Register, RW */ @@ -98,6 +99,8 @@ CDNS_I2C_IXR_COMP) #define CDNS_I2C_TIMEOUT msecs_to_jiffies(1000) +/* timeout for pm runtime autosuspend */ +#define CNDS_I2C_PM_TIMEOUT1000/* ms */ #define CDNS_I2C_FIFO_DEPTH16 /* FIFO depth at which the DATA interrupt occurs */ @@ -130,7 +133,6 @@ * @xfer_done: Transfer complete status * @p_send_buf:Pointer to transmit buffer * @p_recv_buf:Pointer to receive buffer - * @suspended: Flag holding the device's PM status * @send_count:Number of bytes still expected to send * @recv_count:Number of bytes still expected to receive * @curr_recv_count: Number of bytes to be received in current transfer @@ -143,6 +145,7 @@ * @quirks:flag for broken hold bit usage in r1p10 */ struct cdns_i2c { + struct device *dev; void __iomem *membase; struct i2c_adapter adap; struct i2c_msg *p_msg; @@ -150,7 +153,6 @@ struct cdns_i2c { struct completion xfer_done; unsigned char *p_send_buf; unsigned char *p_recv_buf; - u8 suspended; unsigned int send_count; unsigned int recv_count; unsigned int curr_recv_count; @@ -623,10 +625,16 @@ static int cdns_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, u32 reg; struct cdns_i2c *id = adap->algo_data; bool hold_quirk; + + ret = pm_runtime_get_sync(id->dev); + if (ret < 0) + return ret; /* Check if the bus is free */ if (msgs->len) - if (cdns_i2c_readreg(CDNS_I2C_SR_OFFSET) & CDNS_I2C_SR_BA) - return -EAGAIN; + if (cdns_i2c_readreg(CDNS_I2C_SR_OFFSET) & CDNS_I2C_SR_BA) { + ret = -EAGAIN; + goto out; + } hold_quirk = !!(id->quirks & CDNS_I2C_BROKEN_HOLD_BIT); /* @@ -645,7 +653,8 @@ static int cdns_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, if (msgs[count].flags & I2C_M_RD) { dev_warn(adap->dev.parent, "Can't do repeated start after a receive message\n"); - return -EOPNOTSUPP; + ret = -EOPNOTSUPP; + goto out; } } id->bus_hold_flag = 1; @@ -663,20 +672,26 @@ static int cdns_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, ret = cdns_i2c_process_msg(id, msgs, adap); if (ret) - return ret; + goto out; /* Report the other error interrupts to application */ if (id->err_status) { cdns_i2c_master_reset(adap); - if (id->err_status & CDNS_I2C_IXR_NACK) - return -ENXIO; - - return -EIO; + if (id->err_status & CDNS_I2C_IXR_NACK) { + ret = -ENXIO; + goto out; + } + ret = -EIO; + goto out; } } - return num; + ret = num; +out: + pm_runtime_mark_last_busy(id->dev); + pm_runtime_put_autosuspend(id->dev); + return ret; } /** @@ -815,7 +830,7 @@ static int cdns_i2c_clk_notifier_cb(struct notifier_block *nb, unsigned long struct clk_notifier_data *ndata = data; struct cdns_i2c *id = to_cdns_i2c(nb); - if (id->suspended) + if (pm_runtime_suspended(id->dev)) return NOTIFY_OK; switch (event) { @@ -863,14 +878,12 @@ static int cdns_i2c_clk_notifier_cb(struct notifier_block *nb, unsigned long * * Return: 0
Re: [PATCH v2] i2c: cadence: Move to sensible power management
On Wed, Oct 28, 2015 at 9:48 PM, Sören Brinkmann wrote: > Hi Shubhrajyoti, > > > On Wed, 2015-10-28 at 12:56PM +0530, Shubhrajyoti Datta wrote: >> Currently the clocks are enabled at probe and disabled at remove. >> Which keeps the clocks enabled even if no transaction is going on. >> This patch enables the clocks at the start of transfer and disables >> after it. >> >> Also adapts to runtime pm. >> Remove xi2c->suspended and use pm runtime status instead. >> >> converts dev pm to const to silence a checkpatch warning. >> >> Signed-off-by: Shubhrajyoti Datta > > To me, this looks all good. Just one small concern below. Thanks for the review. > >> --- >> changes since v2 >> update the cc list >> >> drivers/i2c/busses/i2c-cadence.c | 73 >> -- >> 1 files changed, 46 insertions(+), 27 deletions(-) >> >> diff --git a/drivers/i2c/busses/i2c-cadence.c >> b/drivers/i2c/busses/i2c-cadence.c >> index 84deed6..6b08d16 100644 >> --- a/drivers/i2c/busses/i2c-cadence.c >> +++ b/drivers/i2c/busses/i2c-cadence.c >> @@ -18,6 +18,7 @@ >> #include >> #include >> #include >> +#include >> >> /* Register offsets for the I2C device. */ >> #define CDNS_I2C_CR_OFFSET 0x00 /* Control Register, RW */ >> @@ -96,6 +97,8 @@ >>CDNS_I2C_IXR_COMP) >> >> #define CDNS_I2C_TIMEOUT msecs_to_jiffies(1000) >> +/* timeout for pm runtime autosuspend */ >> +#define CNDS_I2C_PM_TIMEOUT 1000/* ms */ >> >> #define CDNS_I2C_FIFO_DEPTH 16 >> /* FIFO depth at which the DATA interrupt occurs */ >> @@ -128,7 +131,6 @@ >> * @xfer_done: Transfer complete status >> * @p_send_buf: Pointer to transmit buffer >> * @p_recv_buf: Pointer to receive buffer >> - * @suspended: Flag holding the device's PM status >> * @send_count: Number of bytes still expected to send >> * @recv_count: Number of bytes still expected to receive >> * @curr_recv_count: Number of bytes to be received in current transfer >> @@ -141,6 +143,7 @@ >> * @quirks: flag for broken hold bit usage in r1p10 >> */ >> struct cdns_i2c { >> + struct device *dev; >> void __iomem *membase; >> struct i2c_adapter adap; >> struct i2c_msg *p_msg; >> @@ -148,7 +151,6 @@ struct cdns_i2c { >> struct completion xfer_done; >> unsigned char *p_send_buf; >> unsigned char *p_recv_buf; >> - u8 suspended; > > There might have been a reason to store this flag here. Did you test > this with lockdep and CONFIG_DEBUG_ATOMIC_SLEEP? Just to make sure that > nothing that can sleep is called from atomic context. Done now. Essentially this is a flag is set in suspend routine. and checked in the isr I use pm_runtime_suspended(id->dev) instead. > > Sören > -- > To unsubscribe from this list: send the line "unsubscribe linux-kernel" in > the body of a message to majord...@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html > Please read the FAQ at http://www.tux.org/lkml/ -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 1/3] mailbox: Adding driver for Xilinx LogiCORE IP mailbox.
Hi Moritz, Overall looks good some nitpicks below. On Fri, May 22, 2015 at 5:07 AM, Moritz Fischer wrote: > The Xilinx LogiCORE IP mailbox is a FPGA core that allows for > interprocessor communication via AXI4 memory mapped / AXI4 stream > interfaces. > > It is single channel per core and allows for transmit and receive. > > Signed-off-by: Moritz Fischer > --- > drivers/mailbox/Kconfig | 8 + > drivers/mailbox/Makefile | 2 + > drivers/mailbox/mailbox-xilinx.c | 339 ++ > 3 files changed, 349 insertions(+) > > diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig > index 84b0a2d..e11e4b2 100644 > --- a/drivers/mailbox/Kconfig > +++ b/drivers/mailbox/Kconfig > @@ -60,4 +60,12 @@ config ALTERA_MBOX > An implementation of the Altera Mailbox soft core. It is used > to send message between processors. Say Y here if you want to use > the > Altera mailbox support. > + > +config XILINX_MBOX > + tristate "Xilinx Mailbox" > + help > + An implementation of the Xilinx Mailbox soft core. It is used > + to send message between processors. Say Y here if you want to use > the > + Xilinx mailbox support. > + > endif > diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile > index b18201e..d28a028 100644 > --- a/drivers/mailbox/Makefile > +++ b/drivers/mailbox/Makefile > @@ -11,3 +11,5 @@ obj-$(CONFIG_OMAP2PLUS_MBOX) += omap-mailbox.o > obj-$(CONFIG_PCC) += pcc.o > > obj-$(CONFIG_ALTERA_MBOX) += mailbox-altera.o > + > +obj-$(CONFIG_XILINX_MBOX) += mailbox-xilinx.o > diff --git a/drivers/mailbox/mailbox-xilinx.c > b/drivers/mailbox/mailbox-xilinx.c > new file mode 100644 > index 000..8d8aa17 > --- /dev/null > +++ b/drivers/mailbox/mailbox-xilinx.c > @@ -0,0 +1,339 @@ > +/* > + * Copyright (c) 2015, National Instruments Corp. All rights reserved. > + * > + * Driver for the Xilinx Logicore mailbox IP block > + * > + * 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; version 2 of the License. > + * > + * 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. > + */ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +#define DRIVER_NAME "xilinx-mailbox" > + > +/* register offsets */ > +#define MAILBOX_REG_WRDATA 0x00 > +#define MAILBOX_REG_RDDATA 0x08 > +#define MAILBOX_REG_STATUS 0x10 > +#define MAILBOX_REG_ERROR 0x14 > +#define MAILBOX_REG_SIT 0x18 > +#define MAILBOX_REG_RIT 0x1c > +#define MAILBOX_REG_IS 0x20 > +#define MAILBOX_REG_IE 0x24 > +#define MAILBOX_REG_IP 0x28 > + > +/* status register */ > +#define STS_RTA BIT(3) > +#define STS_STA BIT(2) > +#define STS_FULL BIT(1) > +#define STS_EMPTY BIT(0) > + > +/* error register */ > +#define ERR_FULL BIT(1) > +#define ERR_EMPTY BIT(0) > + > +/* mailbox interrupt status register */ > +#define INT_STATUS_ERR BIT(2) > +#define INT_STATUS_RTI BIT(1) > +#define INT_STATUS_STI BIT(0) > + > +/* mailbox interrupt enable register */ > +#define INT_ENABLE_ERR BIT(2) > +#define INT_ENABLE_RTI BIT(1) > +#define INT_ENABLE_STI BIT(0) > + > +#define MBOX_POLLING_MS5 /* polling interval 5ms */ > + > +struct xilinx_mbox { > + bool intr_mode; > + int irq; > + void __iomem *mbox_base; > + struct device *dev; > + struct mbox_controller controller; > + > + /* if the controller supports only RX polling mode */ > + struct timer_list rxpoll_timer; > +}; > + > +static struct xilinx_mbox *mbox_chan_to_xilinx_mbox(struct mbox_chan *chan) > +{ > + if (!chan || !chan->con_priv) > + return NULL; > + > + return (struct xilinx_mbox *)chan->con_priv; > +} > + > +static inline int xilinx_mbox_full(struct xilinx_mbox *mbox) Should this be a bool ? > +{ > + u32 status; > + > + status = readl_relaxed(mbox->mbox_base + MAILBOX_REG_STATUS); > + return status & STS_FULL; > +} > + > +static inline int xilinx_mbox_pending(struct xilinx_mbox *mbox) > +{ > + u32 status; > + > + status = readl_relaxed(mbox->mbox_base + MAILBOX_REG_STATUS); > + return !(status & STS_EMPTY); > +} > + > +static void xilinx_mbox_rx_intmask(struct xilinx_mbox *mbox, bool enable) > +{ > + u32 mask; > + > + mask = readl_relaxed(mbox->mbox_base + MAILBOX_REG_IE); > + if (enable) > + mask |= INT_ENABLE_RTI; > + else > + mask &= ~INT_ENABLE_RTI; > + writel_relaxed(mask, mbox->mbox_base + MAILBOX_REG_IE); > +} > + > +static void xilinx_mbox_tx_intmask(struct xilinx_mbox *mbox, bool enable) > +{ > + u3
Re: [PATCH 02/12] net: axienet: Handle 0 packet receive gracefully
On Tue, May 5, 2015 at 2:55 PM, Michal Simek wrote: > From: Peter Crosthwaite > > The AXI-DMA rx-delay interrupt can sometimes be triggered > when there are 0 outstanding packets received. This is due > to the fact that the receive function will greedily consume > as many packets as possible on interrupt. So if two packets > (with a very particular timing) arrive in succession they > will each cause the rx-delay interrupt, but the first interrupt > will consume both packets. > This means the second interrupt is a 0 packet receive. > > This is mostly OK, except that the tail pointer register is > updated unconditionally on receive. Currently the tail pointer > is always set to the current bd-ring descriptor under > the assumption that the hardware has moved onto the next > descriptor. What this means for length 0 recv is the current > descriptor that the hardware is potentially yet to use will > be marked as the tail. This causes the hardware to think > its run out of descriptors deadlocking the whole rx path. > Should it marked to stable ? > Fixed by updating the tail pointer to the most recent > successfully consumed descriptor. > > Reported-by: Wendy Liang > Signed-off-by: Peter Crosthwaite > Tested-by: Jason Wu > Acked-by: Michal Simek > Signed-off-by: Michal Simek > --- > -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 1/2] Documentation: DT: vdma: Add clock support for vdma
On Wed, Apr 20, 2016 at 12:49 PM, Kedareswara rao Appana wrote: > This patch updates the binding doc with clock description > for vdma. > > Signed-off-by: Kedareswara rao Appana > --- > Documentation/devicetree/bindings/dma/xilinx/xilinx_vdma.txt | 6 ++ > 1 file changed, 6 insertions(+) > > diff --git a/Documentation/devicetree/bindings/dma/xilinx/xilinx_vdma.txt > b/Documentation/devicetree/bindings/dma/xilinx/xilinx_vdma.txt > index fcc2b65..e1c9019 100644 > --- a/Documentation/devicetree/bindings/dma/xilinx/xilinx_vdma.txt > +++ b/Documentation/devicetree/bindings/dma/xilinx/xilinx_vdma.txt > @@ -21,6 +21,10 @@ Required properties: > - dma-channel child node: Should have at least one channel and can have up to > two channels per device. This node specifies the properties of each > DMA channel (see child node properties below). > +- clocks: Input clock specifier. Refer to common clock bindings. > +- clock-names: List of input clocks "axi_clk", "tx_clk", "txs_clk" (list of > input > + cloks may vary based on the ip configuration. see clock > bindings > + for more info). > > Required properties for VDMA: > - xlnx,num-fstores: Should be the number of framebuffers as configured in > h/w. > @@ -60,6 +64,8 @@ axi_vdma_0: axivdma@4003 { > xlnx,num-fstores = <0x8>; > xlnx,flush-fsync = <0x1>; > xlnx,addrwidth = <0x20>; > + clocks = <&clk 0>, <&clk 1>, <&clk 2>; > + clock-names = "axi_clk", "tx_clk", "txs_clk"; the module has s_axi_lite_aclk Clock I AXI VDMA AXI4-Lite interface clock m_axi_mm2s_aclk Clock I AXI VDMA MM2S clock m_axi_s2mm_aclk Clock I AXI VDMA S2MM clock m_axis_mm2s_aclk Clock I AXI VDMA MM2S AXIS clock s_axis_s2mm_aclk Clock I AXI VDMA S2MM AXIS clock I think a partial support is not wrong. however we should keep the names same as the TRM. > dma-channel@4003 { > compatible = "xlnx,axi-vdma-mm2s-channel"; > interrupts = < 0 54 4 >; > -- > 2.1.2 > > > ___ > linux-arm-kernel mailing list > linux-arm-ker...@lists.infradead.org > http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Re: [PATCH v2 2/2] dmaengine: vdma: Add clock support
On Wed, Apr 20, 2016 at 5:13 PM, Kedareswara rao Appana wrote: > Added basic clock support. The clocks are requested at probe > and released at remove. > > Signed-off-by: Kedareswara rao Appana Reviewed-by: Shubhrajyoti Datta
[PATCH 5/7] spi: cadence: Runtime pm adaptation
Currently the clocks are enabled at probe and disabled at remove. This patch moves the clock enable to the start of transaction and disables at the end. Signed-off-by: Shubhrajyoti Datta --- drivers/spi/spi-cadence.c | 70 +++- 1 files changed, 68 insertions(+), 2 deletions(-) diff --git a/drivers/spi/spi-cadence.c b/drivers/spi/spi-cadence.c index 8a6fee9..3b94063 100644 --- a/drivers/spi/spi-cadence.c +++ b/drivers/spi/spi-cadence.c @@ -19,6 +19,7 @@ #include #include #include +#include #include /* Name of this driver */ @@ -37,6 +38,7 @@ #define CDNS_SPI_SICR 0x24 /* Slave Idle Count Register, RW */ #define CDNS_SPI_THLD 0x28 /* Transmit FIFO Watermark Register,RW */ +#define SPI_AUTOSUSPEND_TIMEOUT3000 /* * SPI Configuration Register bit Masks * @@ -509,6 +511,11 @@ static int cdns_spi_probe(struct platform_device *pdev) goto clk_dis_apb; } + pm_runtime_enable(&pdev->dev); + pm_runtime_use_autosuspend(&pdev->dev); + pm_runtime_set_autosuspend_delay(&pdev->dev, SPI_AUTOSUSPEND_TIMEOUT); + pm_runtime_set_active(&pdev->dev); + ret = of_property_read_u32(pdev->dev.of_node, "num-cs", &num_cs); if (ret < 0) master->num_chipselect = CDNS_SPI_DEFAULT_NUM_CS; @@ -523,6 +530,9 @@ static int cdns_spi_probe(struct platform_device *pdev) /* SPI controller initializations */ cdns_spi_init_hw(xspi); + pm_runtime_mark_last_busy(&pdev->dev); + pm_runtime_put_autosuspend(&pdev->dev); + irq = platform_get_irq(pdev, 0); if (irq <= 0) { ret = -ENXIO; @@ -543,6 +553,7 @@ static int cdns_spi_probe(struct platform_device *pdev) master->transfer_one = cdns_transfer_one; master->unprepare_transfer_hardware = cdns_unprepare_transfer_hardware; master->set_cs = cdns_spi_chipselect; + master->auto_runtime_pm = true; master->mode_bits = SPI_CPOL | SPI_CPHA; /* Set to default valid value */ @@ -560,6 +571,8 @@ static int cdns_spi_probe(struct platform_device *pdev) return ret; clk_dis_all: + pm_runtime_set_suspended(&pdev->dev); + pm_runtime_disable(&pdev->dev); clk_disable_unprepare(xspi->ref_clk); clk_dis_apb: clk_disable_unprepare(xspi->pclk); @@ -587,6 +600,8 @@ static int cdns_spi_remove(struct platform_device *pdev) clk_disable_unprepare(xspi->ref_clk); clk_disable_unprepare(xspi->pclk); + pm_runtime_set_suspended(&pdev->dev); + pm_runtime_disable(&pdev->dev); spi_unregister_master(master); @@ -649,8 +664,59 @@ static int __maybe_unused cdns_spi_resume(struct device *dev) return 0; } -static SIMPLE_DEV_PM_OPS(cdns_spi_dev_pm_ops, cdns_spi_suspend, -cdns_spi_resume); +/** + * cdns_spi_runtime_resume - Runtime resume method for the SPI driver + * @dev: Address of the platform_device structure + * + * This function enables the clocks + * + * Return: 0 on success and error value on error + */ +static int cnds_runtime_resume(struct device *dev) +{ + struct spi_master *master = dev_get_drvdata(dev); + struct cdns_spi *xspi = spi_master_get_devdata(master); + int ret; + + ret = clk_prepare_enable(xspi->pclk); + if (ret) { + dev_err(dev, "Cannot enable APB clock.\n"); + return ret; + } + + ret = clk_prepare_enable(xspi->ref_clk); + if (ret) { + dev_err(dev, "Cannot enable device clock.\n"); + clk_disable(xspi->pclk); + return ret; + } + return 0; +} + +/** + * cdns_spi_runtime_suspend - Runtime suspend method for the SPI driver + * @dev: Address of the platform_device structure + * + * This function disables the clocks + * + * Return: Always 0 + */ +static int cnds_runtime_suspend(struct device *dev) +{ + struct spi_master *master = dev_get_drvdata(dev); + struct cdns_spi *xspi = spi_master_get_devdata(master); + + clk_disable_unprepare(xspi->ref_clk); + clk_disable_unprepare(xspi->pclk); + + return 0; +} + +static const struct dev_pm_ops cdns_spi_dev_pm_ops = { + SET_RUNTIME_PM_OPS(cnds_runtime_suspend, + cnds_runtime_resume, NULL) + SET_SYSTEM_SLEEP_PM_OPS(cdns_spi_suspend, cdns_spi_resume) +}; static const struct of_device_id cdns_spi_of_match[] = { { .compatible = "xlnx,zynq-spi-r1p6" }, -- 1.7.1
[PATCH 7/7] spi: cadence: Return the error code for cdns_spi_suspend and cdns_spi_resume
Return the error code for cdns_spi_suspend and cdns_spi_resume. Also fixes a comment where which claims that the error code is returned. Signed-off-by: Shubhrajyoti Datta --- drivers/spi/spi-cadence.c | 10 +++--- 1 files changed, 3 insertions(+), 7 deletions(-) diff --git a/drivers/spi/spi-cadence.c b/drivers/spi/spi-cadence.c index d0cdd18..07481e1 100644 --- a/drivers/spi/spi-cadence.c +++ b/drivers/spi/spi-cadence.c @@ -615,16 +615,14 @@ static int cdns_spi_remove(struct platform_device *pdev) * This function disables the SPI controller and * changes the driver state to "suspend" * - * Return: Always 0 + * Return: 0 on success and error value on error */ static int __maybe_unused cdns_spi_suspend(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); struct spi_master *master = platform_get_drvdata(pdev); - spi_master_suspend(master); - - return 0; + return spi_master_suspend(master); } /** @@ -640,9 +638,7 @@ static int __maybe_unused cdns_spi_resume(struct device *dev) struct platform_device *pdev = to_platform_device(dev); struct spi_master *master = platform_get_drvdata(pdev); - spi_master_resume(master); - - return 0; + return spi_master_resume(master); } /** -- 1.7.1
[PATCH 2/7] spi: cadence: Remove _MASK and _OFFSET suffix
Remove the _MASK and _OFFSET from the macros. It improves readability, removes some checkpatch error for exceeding 80 chars and also prevents some linebreaks. Signed-off-by: Shubhrajyoti Datta --- drivers/spi/spi-cadence.c | 161 + 1 files changed, 74 insertions(+), 87 deletions(-) diff --git a/drivers/spi/spi-cadence.c b/drivers/spi/spi-cadence.c index 3acaac3..97a3bf6 100644 --- a/drivers/spi/spi-cadence.c +++ b/drivers/spi/spi-cadence.c @@ -25,17 +25,17 @@ #define CDNS_SPI_NAME "cdns-spi" /* Register offset definitions */ -#define CDNS_SPI_CR_OFFSET 0x00 /* Configuration Register, RW */ -#define CDNS_SPI_ISR_OFFSET0x04 /* Interrupt Status Register, RO */ -#define CDNS_SPI_IER_OFFSET0x08 /* Interrupt Enable Register, WO */ -#define CDNS_SPI_IDR_OFFSET0x0c /* Interrupt Disable Register, WO */ -#define CDNS_SPI_IMR_OFFSET0x10 /* Interrupt Enabled Mask Register, RO */ -#define CDNS_SPI_ER_OFFSET 0x14 /* Enable/Disable Register, RW */ -#define CDNS_SPI_DR_OFFSET 0x18 /* Delay Register, RW */ -#define CDNS_SPI_TXD_OFFSET0x1C /* Data Transmit Register, WO */ -#define CDNS_SPI_RXD_OFFSET0x20 /* Data Receive Register, RO */ -#define CDNS_SPI_SICR_OFFSET 0x24 /* Slave Idle Count Register, RW */ -#define CDNS_SPI_THLD_OFFSET 0x28 /* Transmit FIFO Watermark Register,RW */ +#define CDNS_SPI_CR0x00 /* Configuration Register, RW */ +#define CDNS_SPI_ISR 0x04 /* Interrupt Status Register, RO */ +#define CDNS_SPI_IER 0x08 /* Interrupt Enable Register, WO */ +#define CDNS_SPI_IDR 0x0c /* Interrupt Disable Register, WO */ +#define CDNS_SPI_IMR 0x10 /* Interrupt Enabled Mask Register, RO */ +#define CDNS_SPI_ER0x14 /* Enable/Disable Register, RW */ +#define CDNS_SPI_DR0x18 /* Delay Register, RW */ +#define CDNS_SPI_TXD 0x1C /* Data Transmit Register, WO */ +#define CDNS_SPI_RXD 0x20 /* Data Receive Register, RO */ +#define CDNS_SPI_SICR 0x24 /* Slave Idle Count Register, RW */ +#define CDNS_SPI_THLD 0x28 /* Transmit FIFO Watermark Register,RW */ /* * SPI Configuration Register bit Masks @@ -43,20 +43,20 @@ * This register contains various control bits that affect the operation * of the SPI controller */ -#define CDNS_SPI_CR_MANSTRT_MASK 0x0001 /* Manual TX Start */ -#define CDNS_SPI_CR_CPHA_MASK 0x0004 /* Clock Phase Control */ -#define CDNS_SPI_CR_CPOL_MASK 0x0002 /* Clock Polarity Control */ -#define CDNS_SPI_CR_SSCTRL_MASK0x3C00 /* Slave Select Mask */ -#define CDNS_SPI_CR_PERI_SEL_MASK 0x0200 /* Peripheral Select Decode */ -#define CDNS_SPI_CR_BAUD_DIV_MASK 0x0038 /* Baud Rate Divisor Mask */ -#define CDNS_SPI_CR_MSTREN_MASK0x0001 /* Master Enable Mask */ -#define CDNS_SPI_CR_MANSTRTEN_MASK 0x8000 /* Manual TX Enable Mask */ -#define CDNS_SPI_CR_SSFORCE_MASK 0x4000 /* Manual SS Enable Mask */ -#define CDNS_SPI_CR_BAUD_DIV_4_MASK0x0008 /* Default Baud Div Mask */ -#define CDNS_SPI_CR_DEFAULT_MASK (CDNS_SPI_CR_MSTREN_MASK | \ - CDNS_SPI_CR_SSCTRL_MASK | \ - CDNS_SPI_CR_SSFORCE_MASK | \ - CDNS_SPI_CR_BAUD_DIV_4_MASK) +#define CDNS_SPI_CR_MANSTRT0x0001 /* Manual TX Start */ +#define CDNS_SPI_CR_CPHA 0x0004 /* Clock Phase Control */ +#define CDNS_SPI_CR_CPOL 0x0002 /* Clock Polarity Control */ +#define CDNS_SPI_CR_SSCTRL 0x3C00 /* Slave Select Mask */ +#define CDNS_SPI_CR_PERI_SEL 0x0200 /* Peripheral Select Decode */ +#define CDNS_SPI_CR_BAUD_DIV 0x0038 /* Baud Rate Divisor Mask */ +#define CDNS_SPI_CR_MSTREN 0x0001 /* Master Enable Mask */ +#define CDNS_SPI_CR_MANSTRTEN 0x8000 /* Manual TX Enable Mask */ +#define CDNS_SPI_CR_SSFORCE0x4000 /* Manual SS Enable Mask */ +#define CDNS_SPI_CR_BAUD_DIV_4 0x0008 /* Default Baud Div Mask */ +#define CDNS_SPI_CR_DEFAULT(CDNS_SPI_CR_MSTREN | \ + CDNS_SPI_CR_SSCTRL | \ + CDNS_SPI_CR_SSFORCE | \ + CDNS_SPI_CR_BAUD_DIV_4) /* * SPI Configuration Register - Baud rate and slave select @@ -77,21 +77,21 @@ * All the four interrupt registers (Status/Mask/Enable/Disable) have the same * bit definitions. */ -#define CDNS_SPI_IXR_TXOW_MASK 0x0004 /* SPI TX FIFO Overwater */ -#define CDNS_SPI_IXR_MODF_MASK 0x0002 /* SPI Mode Fault */ -#define CDNS_SPI_IXR_RXNEMTY_MASK 0x0010 /* SPI RX FIFO Not Empty */ -#define CDNS_SPI_IXR_DEFAULT_MASK (CDNS_SPI_IXR_TXOW_MASK | \ - CDNS_SPI_IXR_MODF_MASK) -#define CDNS_SPI_IXR_TXFULL_MASK 0x0008 /* SPI TX Full */ -#define CDNS_SPI_IXR_ALL_MASK 0x007F /* SPI all interrupts *
[PATCH 3/7] spi: cadence: Fix probe error handling
The clock disabling is missed out in some error cases at probe. Fix the same. Signed-off-by: Shubhrajyoti Datta --- drivers/spi/spi-cadence.c |4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/spi/spi-cadence.c b/drivers/spi/spi-cadence.c index 97a3bf6..2915b25 100644 --- a/drivers/spi/spi-cadence.c +++ b/drivers/spi/spi-cadence.c @@ -527,7 +527,7 @@ static int cdns_spi_probe(struct platform_device *pdev) if (irq <= 0) { ret = -ENXIO; dev_err(&pdev->dev, "irq number is invalid\n"); - goto remove_master; + goto clk_dis_all; } ret = devm_request_irq(&pdev->dev, irq, cdns_spi_irq, @@ -535,7 +535,7 @@ static int cdns_spi_probe(struct platform_device *pdev) if (ret != 0) { ret = -ENXIO; dev_err(&pdev->dev, "request_irq failed\n"); - goto remove_master; + goto clk_dis_all; } master->prepare_transfer_hardware = cdns_prepare_transfer_hardware; -- 1.7.1
[PATCH 6/7] spi: cadence: Remove the clock enable and disable from suspend and resume
Now that the clocks are enabled and disabled per transaction , remove the clock enable and disable from resume and suspend hooks. Signed-off-by: Shubhrajyoti Datta --- drivers/spi/spi-cadence.c | 19 --- 1 files changed, 0 insertions(+), 19 deletions(-) diff --git a/drivers/spi/spi-cadence.c b/drivers/spi/spi-cadence.c index 3b94063..d0cdd18 100644 --- a/drivers/spi/spi-cadence.c +++ b/drivers/spi/spi-cadence.c @@ -621,14 +621,9 @@ static int __maybe_unused cdns_spi_suspend(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); struct spi_master *master = platform_get_drvdata(pdev); - struct cdns_spi *xspi = spi_master_get_devdata(master); spi_master_suspend(master); - clk_disable_unprepare(xspi->ref_clk); - - clk_disable_unprepare(xspi->pclk); - return 0; } @@ -644,21 +639,7 @@ static int __maybe_unused cdns_spi_resume(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); struct spi_master *master = platform_get_drvdata(pdev); - struct cdns_spi *xspi = spi_master_get_devdata(master); - int ret = 0; - - ret = clk_prepare_enable(xspi->pclk); - if (ret) { - dev_err(dev, "Cannot enable APB clock.\n"); - return ret; - } - ret = clk_prepare_enable(xspi->ref_clk); - if (ret) { - dev_err(dev, "Cannot enable device clock.\n"); - clk_disable(xspi->pclk); - return ret; - } spi_master_resume(master); return 0; -- 1.7.1
[PATCH 4/7] spi: cadance: Fix the Documentation
cdns_spi_chipselect has parameter is_high however the comment describes it as is_on. Also fixes the below warning. drivers/spi/spi-cadence.c:182: warning: No description found for parameter 'is_high' drivers/spi/spi-cadence.c:182: warning: Excess function parameter 'is_on' description in 'cdns_spi_chipselect' Signed-off-by: Shubhrajyoti Datta --- drivers/spi/spi-cadence.c |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/drivers/spi/spi-cadence.c b/drivers/spi/spi-cadence.c index 2915b25..8a6fee9 100644 --- a/drivers/spi/spi-cadence.c +++ b/drivers/spi/spi-cadence.c @@ -169,7 +169,7 @@ static void cdns_spi_init_hw(struct cdns_spi *xspi) /** * cdns_spi_chipselect - Select or deselect the chip select line * @spi: Pointer to the spi_device structure - * @is_on: Select(0) or deselect (1) the chip select line + * @is_high: Select(0) or deselect (1) the chip select line */ static void cdns_spi_chipselect(struct spi_device *spi, bool is_high) { -- 1.7.1
[PATCH 1/7] spi: cadence: Fix a check patch warning
CHECK: Comparison to NULL could be written "!master" + if (master == NULL) Signed-off-by: Shubhrajyoti Datta --- drivers/spi/spi-cadence.c |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/drivers/spi/spi-cadence.c b/drivers/spi/spi-cadence.c index 121a413..3acaac3 100644 --- a/drivers/spi/spi-cadence.c +++ b/drivers/spi/spi-cadence.c @@ -481,7 +481,7 @@ static int cdns_spi_probe(struct platform_device *pdev) u32 num_cs; master = spi_alloc_master(&pdev->dev, sizeof(*xspi)); - if (master == NULL) + if (!master) return -ENOMEM; xspi = spi_master_get_devdata(master); -- 1.7.1
[PATCH] spi: cadence: Fix some checkpatch warnings
No functional change. Fixing some style related issues CHECK: multiple assignments should be avoided + new_ctrl_reg = ctrl_reg = cdns_spi_read(xspi, CDNS_SPI_CR); CHECK: Alignment should match open parenthesis +static void cdns_spi_config_clock_freq(struct spi_device *spi, + struct spi_transfer *transfer) CHECK: Please use a blank line after function/struct/union/enum declarations +} +static int cdns_prepare_message(struct spi_master *master, Signed-off-by: Shubhrajyoti Datta --- drivers/spi/spi-cadence.c |6 -- 1 files changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/spi/spi-cadence.c b/drivers/spi/spi-cadence.c index 07481e1..8a0bd62 100644 --- a/drivers/spi/spi-cadence.c +++ b/drivers/spi/spi-cadence.c @@ -209,7 +209,8 @@ static void cdns_spi_config_clock_mode(struct spi_device *spi) struct cdns_spi *xspi = spi_master_get_devdata(spi->master); u32 ctrl_reg, new_ctrl_reg; - new_ctrl_reg = ctrl_reg = cdns_spi_read(xspi, CDNS_SPI_CR); + new_ctrl_reg = cdns_spi_read(xspi, CDNS_SPI_CR); + ctrl_reg = new_ctrl_reg; /* Set the SPI clock phase and clock polarity */ new_ctrl_reg &= ~(CDNS_SPI_CR_CPHA | CDNS_SPI_CR_CPOL); @@ -246,7 +247,7 @@ static void cdns_spi_config_clock_mode(struct spi_device *spi) * controller. */ static void cdns_spi_config_clock_freq(struct spi_device *spi, - struct spi_transfer *transfer) + struct spi_transfer *transfer) { struct cdns_spi *xspi = spi_master_get_devdata(spi->master); u32 ctrl_reg, baud_rate_val; @@ -380,6 +381,7 @@ static irqreturn_t cdns_spi_irq(int irq, void *dev_id) return status; } + static int cdns_prepare_message(struct spi_master *master, struct spi_message *msg) { -- 1.7.1
Re: [PATCH] spi: cadence: mark pm functions __maybe_unused
On Sun, Apr 17, 2016 at 2:09 AM, Arnd Bergmann wrote: > The newly added runtime PM support for the cadence spi driver > causes harmless warnings when PM is disabled: > > drivers/spi/spi-cadence.c:681:12: warning: 'cnds_runtime_suspend' defined but > not used > drivers/spi/spi-cadence.c:652:12: warning: 'cnds_runtime_resume' defined but > not used > > This adds __maybe_unused annotations to the respective functions > to shut up the warnings, while leaving the code in place for > compile testing and avoiding ugly #ifdefs. Thanks for the patch. Feel free to add my ack. Acked-by: Shubhrajyoti Datta > > Signed-off-by: Arnd Bergmann > Fixes: d36ccd9f7ea4 ("spi: cadence: Runtime pm adaptation") > ---
[PATCH] gpio: zynq: Fix the error path
pm_runtime_disable is called only in remove it is missed out in the error path. Fix the same. Signed-off-by: Shubhrajyoti Datta --- drivers/gpio/gpio-zynq.c |4 +++- 1 files changed, 3 insertions(+), 1 deletions(-) diff --git a/drivers/gpio/gpio-zynq.c b/drivers/gpio/gpio-zynq.c index 66d3d24..75c6355 100644 --- a/drivers/gpio/gpio-zynq.c +++ b/drivers/gpio/gpio-zynq.c @@ -713,7 +713,7 @@ static int zynq_gpio_probe(struct platform_device *pdev) pm_runtime_enable(&pdev->dev); ret = pm_runtime_get_sync(&pdev->dev); if (ret < 0) - return ret; + goto err_pm_dis; /* report a bug if gpio chip registration fails */ ret = gpiochip_add_data(chip, gpio); @@ -745,6 +745,8 @@ err_rm_gpiochip: gpiochip_remove(chip); err_pm_put: pm_runtime_put(&pdev->dev); +err_pm_dis: + pm_runtime_disable(&pdev->dev); return ret; } -- 1.7.1
Re: [PATCH v2] i2c: cadence: Move to sensible power management
On Thu, Oct 29, 2015 at 8:27 PM, Shubhrajyoti Datta wrote: > On Wed, Oct 28, 2015 at 9:48 PM, Sören Brinkmann > wrote: >> Hi Shubhrajyoti, >> >> >> On Wed, 2015-10-28 at 12:56PM +0530, Shubhrajyoti Datta wrote: >>> Currently the clocks are enabled at probe and disabled at remove. >>> Which keeps the clocks enabled even if no transaction is going on. >>> This patch enables the clocks at the start of transfer and disables >>> after it. >>> >>> Also adapts to runtime pm. >>> Remove xi2c->suspended and use pm runtime status instead. >>> >>> converts dev pm to const to silence a checkpatch warning. >>> >>> Signed-off-by: Shubhrajyoti Datta >> >> To me, this looks all good. Just one small concern below. > > Thanks for the review. Soren , Do are you ok with the change or do you want me to resend without the suspended flag change. <> >> >> There might have been a reason to store this flag here. Did you test >> this with lockdep and CONFIG_DEBUG_ATOMIC_SLEEP? Just to make sure that >> nothing that can sleep is called from atomic context. > Done now. > > > Essentially this is a flag is set in suspend routine. and checked in > the isr I use > pm_runtime_suspended(id->dev) instead. > >> >> Sören >> -- >> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in >> the body of a message to majord...@vger.kernel.org >> More majordomo info at http://vger.kernel.org/majordomo-info.html >> Please read the FAQ at http://www.tux.org/lkml/ -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH v2] i2c: cadence: Move to sensible power management
On Tue, Nov 24, 2015 at 12:17 AM, Sören Brinkmann wrote: > On Sat, 2015-11-21 at 07:00PM +0530, Shubhrajyoti Datta wrote: >> On Thu, Oct 29, 2015 at 8:27 PM, Shubhrajyoti Datta >> wrote: >> > On Wed, Oct 28, 2015 at 9:48 PM, Sören Brinkmann >> > wrote: >> >> Hi Shubhrajyoti, >> >> >> >> >> >> On Wed, 2015-10-28 at 12:56PM +0530, Shubhrajyoti Datta wrote: >> >>> Currently the clocks are enabled at probe and disabled at remove. >> >>> Which keeps the clocks enabled even if no transaction is going on. >> >>> This patch enables the clocks at the start of transfer and disables >> >>> after it. >> >>> >> >>> Also adapts to runtime pm. >> >>> Remove xi2c->suspended and use pm runtime status instead. >> >>> >> >>> converts dev pm to const to silence a checkpatch warning. >> >>> >> >>> Signed-off-by: Shubhrajyoti Datta >> >> >> >> To me, this looks all good. Just one small concern below. >> > >> > Thanks for the review. >> Soren , >> Do are you ok with the change or do you want me to resend without the >> suspended flag change. > > I'm always for removing code that is not needed. If things are tested > and well and work without throwing any warnings I'm OK with it. It should be also having a suspended book-keeping in the driver is not needed the pm does that for us. I will spilt the patch and resend. Thanks, > > Sören -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH] mtd: spi-nor: Only set Micron quad-read mode when controller in 4-lane TX mode
On Tue, Jun 30, 2015 at 4:47 PM, Mike Looijmans wrote: > Micron QUAD mode expects command, address and data on 4 lanes instead of just > one for command (extended SPI mode). This requires the controller to be in a > special mode, so check first if the controller could be in that mode. If a > controller does not have the SPI_TX_QUAD mode set, this setting has no chance > of being valid at all, so don't try to enable it then, and just keep using > the extended SPI mode. > > Tested on a Zynq 7000 with a n25q256a flash chip, this failed to function > because of the introduction of: > "driver:mtd:spi-nor: Add quad I/O support for Micron spi nor" > This commit sets QUAD mode for most Micron chips without asking the controller > whether it's possible to do so, and without telling the controller that a > different mode is required, so it couldn't work. > > Signed-off-by: Mike Looijmans > --- > drivers/mtd/spi-nor/spi-nor.c | 2 ++ > 1 file changed, 2 insertions(+) > > diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c > index e8f6131..10ba94f 100644 > --- a/drivers/mtd/spi-nor/spi-nor.c > +++ b/drivers/mtd/spi-nor/spi-nor.c > @@ -1398,6 +1398,8 @@ static int set_quad_mode(struct spi_nor *nor, struct > flash_info *info) > } > return status; > case CFI_MFR_ST: > + if (!(nor->spi->mode & SPI_TX_QUAD)) > + return 0; Should we return 0 ? > status = micron_quad_enable(nor); > if (status) { > dev_err(nor->dev, "Micron quad-read not enabled\n"); > -- > 1.9.1 > > -- > To unsubscribe from this list: send the line "unsubscribe linux-kernel" in > the body of a message to majord...@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html > Please read the FAQ at http://www.tux.org/lkml/ -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH] gpio: zynq: properly support runtime PM for GPIO used as interrupts
Hi Thomas, Thanks for the patch. On Fri, Feb 8, 2019 at 4:13 PM Thomas Petazzoni wrote: > > The Zynq GPIO driver currently implements runtime PM by: > > - Enabling runtime PM support in ->probe() and letting the runtime PM >reference counter drop to zero at the end of ->probe(). > > - Increasing the runtime PM reference counter in ->request() and >decreasing it in ->free(). > > However, the latter is not sufficient: when a GPIO is used as an > interrupt, ->request() and ->free() are not called. Due to this, the > runtime PM counter remains to zero when the only GPIOs in use are used > as interrupts, causing them to simply not work. > > To address this problem, this commit implement the > ->irq_request_resources() and ->irq_release_resources() hooks, > ensuring that the runtime PM counter is properly > incremented/decremented. Since we override the default hooks, we keep > the existing behavior by making sure they call gpiochip_reqres_irq() / > gpiochip_relres_irq() respectively. > > Signed-off-by: Thomas Petazzoni > --- Reviewed-by: Shubhrajyoti Datta >
[RFC PATCH 1/2] dt-bindings: misc: Add dt bindings for flex noc Performance Monitor
Add dt bindings for flexnoc Performance Monitor. The flexnoc counters for read and write response and requests are supported. Signed-off-by: Shubhrajyoti Datta --- .../devicetree/bindings/misc/xlnx,flexnoc.txt | 24 ++ 1 file changed, 24 insertions(+) create mode 100644 Documentation/devicetree/bindings/misc/xlnx,flexnoc.txt diff --git a/Documentation/devicetree/bindings/misc/xlnx,flexnoc.txt b/Documentation/devicetree/bindings/misc/xlnx,flexnoc.txt new file mode 100644 index 000..6b533bc --- /dev/null +++ b/Documentation/devicetree/bindings/misc/xlnx,flexnoc.txt @@ -0,0 +1,24 @@ +* Xilinx Flexnoc Performance Monitor driver + +The FlexNoc Performance Monitor has counters for monitoring +the read and the write transaction counter. + +Required properties: +- compatible: "xlnx,flexnoc-pm-2.7" +- reg : Address and length of register sets for each device in + "reg-names" +- reg-names : The names of the register addresses corresponding to the + registers filled in "reg" + - funnel: base address of the funnel registers + - baselpd: base address of the LPD PM registers + - basefpd: base address FPD PM registers + +Example: + +performance-monitor@f092 { + compatible = "xlnx,flexnoc-pm-2.7"; + reg-names = "funnel", "baselpd", "basefpd"; + reg = <0x0 0xf092 0x0 0x1000>, + <0x0 0xf098 0x0 0x9000>, + <0x0 0xf0b8 0x0 0x9000>; +}; -- 2.1.1 This email and any attachments are intended for the sole use of the named recipient(s) and contain(s) confidential information that may be proprietary, privileged or copyrighted under applicable law. If you are not the intended recipient, do not read, copy, or forward this email message or any attachments. Delete this email message and any attachments immediately.
[RFC PATCH 2/2] misc: xilinx_flex: Add support for the flex noc Performance Monitor
Add support for the FlexNoc Performance Monitor. Adds support for various port setting and monitoring the packets transactions. It supports LPD and FPD monitoring counters for read and write transaction requests and responses. Signed-off-by: Shubhrajyoti Datta --- drivers/misc/Kconfig | 9 + drivers/misc/Makefile | 1 + drivers/misc/xilinx_flex_pm.c | 644 ++ 3 files changed, 654 insertions(+) create mode 100644 drivers/misc/xilinx_flex_pm.c diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index c55b637..1e9a6fa 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -454,6 +454,15 @@ config XILINX_SDFEC If unsure, say N. +config XILINX_FLEX_PM + tristate "Xilinx Flexnoc Performance Monitor" + help + This option enables support for the Xilinx Flex Noc Performance Monitor driver. + It monitors the read and write transactions. It has counters for the LPD and + FPD domains. + + If unsure, say N + config MISC_RTSX tristate default MISC_RTSX_PCI || MISC_RTSX_USB diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index c1860d3..1f1c34d 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -57,3 +57,4 @@ obj-y += cardreader/ obj-$(CONFIG_PVPANIC) += pvpanic.o obj-$(CONFIG_HABANA_AI)+= habanalabs/ obj-$(CONFIG_XILINX_SDFEC) += xilinx_sdfec.o +obj-$(CONFIG_XILINX_FLEX_PM) += xilinx_flex_pm.o diff --git a/drivers/misc/xilinx_flex_pm.c b/drivers/misc/xilinx_flex_pm.c new file mode 100644 index 000..891ab3a --- /dev/null +++ b/drivers/misc/xilinx_flex_pm.c @@ -0,0 +1,644 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Xilinx Flex Noc Performance Monitor driver. + * Copyright (c) 2019 Xilinx Inc. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Macro */ +#define to_xflex_dev_info(n) ((struct xflex_dev_info *)dev_get_drvdata(n)) + +#define FPM_LAR_OFFSET 0xFB0 +#define FPM_UNLOCK 0xC5ACCE55 + +#define FPM_RD_REQ_OFFSET 0x1000 +#define FPM_RD_RES_OFFSET 0x2000 +#define FPM_WR_REQ_OFFSET 0x3000 +#define FPM_WR_RES_OFFSET 0x4000 + +#define FPM_PORT_SEL_OFFSET0x134 +#define FPM_MAIN_CTRL_OFFSET 0x008 +#define FPM_SRC_SEL_OFFSET 0x138 +#define FPM_STATPERIOD 0x24 +#define FPM_CFGCTRL0x0C +#define FPM_LPD0x4210002 +#define FPM_FPD0x420c003 + +#define FPM_VAL0x300 +#define FPM_SRC0x200 +#define FPM_WRRSP_L0x7 +#define FPM_WRREQ_L0x6 +#define FPM_RDRSP_L0x5 +#define FPM_RDREQ_L0x4 +#define FPM_PROBE_SHIFT16 +#define FPM_COUNTER_OFFSET 0x14 +#define FPM_GLOBALEN BIT(0) +#define FPM_STATEN BIT(3) +#define FPM_STATCOND_DUMP BIT(5) +#define FPM_NUM_COUNTERS 4 +#define FPM_MAINCTL_DIS0 + +#define FPM_SRC_OFF0x0 +#define FPM_SRC_CYCLE 0x1 +#define FPM_SRC_IDLE 0x2 +#define FPM_SRC_XFER 0x3 +#define FPM_SRC_BUSY 0x4 +#define FPM_SRC_WAIT 0x5 +#define FPM_SRC_PACKET 0x6 + +/*Port values */ +#define FPM_PORT_LPD_AFIFS_AXI 0x0 +#define FPM_PORT_LPD_OCM 0x1 +#define FPM_PORT_LPD_OCMEXT0x2 +#define FPM_PORT_PMC_RPU_AXI0 0x3 + +#define FPM_PORT_FPDAXI0x1 +#define FPM_PORT_PROTXPPU 0x2 + +/** + * struct xflex_dev_info - Global Driver structure + * @dev: Device structure + * @baselpd: Iomapped LPD base address + * @basefpd: Iomapped FPD base address + * @funnel: Iomapped funnel register base address + * @counterid_lpd: LPD counter id + * @counterid_fpd: FPD counter id + */ +struct xflex_dev_info { + struct device *dev; + void __iomem *baselpd; + void __iomem *basefpd; + void __iomem *funnel; + u32 counterid_fpd; + u32 counterid_lpd; +}; + +/** + * enum xflex_sysfs_cmd_codes - sysfs command codes + * @XFLEX_GET_COUNTER_FPD: get the FPD counter value + * @XFLEX_SET_COUNTER_FPD: set the FPD counter value + * @XFLEX_GET_COUNTER_FPD_RDREQ: get the FPD read request count + * @XFLEX_GET_COUNTER_FPD_RDRSP: get the FPD read response count + * @XFLEX_GET_COUNTER_FPD_WRREQ: get the FPD write request count + * @XFLEX_GET_COUNTER_FPD_WRRSP: get the FPD write response count + * @XFLEX_GET_COUNTER_LPD_RDREQ: get the LPD read request count + * @XFLEX_GET_COUNTER_LPD_RDRSP: get the LPD read resp
[RFC PATCHv2 1/3] dt-bindings: misc: Add dt bindings for flex noc Performance Monitor
Add dt bindings for flexnoc Performance Monitor. The flexnoc counters for read and write response and requests are supported. Signed-off-by: Shubhrajyoti Datta --- .../devicetree/bindings/misc/xlnx,flexnoc.txt | 24 ++ 1 file changed, 24 insertions(+) create mode 100644 Documentation/devicetree/bindings/misc/xlnx,flexnoc.txt diff --git a/Documentation/devicetree/bindings/misc/xlnx,flexnoc.txt b/Documentation/devicetree/bindings/misc/xlnx,flexnoc.txt new file mode 100644 index 000..6b533bc --- /dev/null +++ b/Documentation/devicetree/bindings/misc/xlnx,flexnoc.txt @@ -0,0 +1,24 @@ +* Xilinx Flexnoc Performance Monitor driver + +The FlexNoc Performance Monitor has counters for monitoring +the read and the write transaction counter. + +Required properties: +- compatible: "xlnx,flexnoc-pm-2.7" +- reg : Address and length of register sets for each device in + "reg-names" +- reg-names : The names of the register addresses corresponding to the + registers filled in "reg" + - funnel: base address of the funnel registers + - baselpd: base address of the LPD PM registers + - basefpd: base address FPD PM registers + +Example: + +performance-monitor@f092 { + compatible = "xlnx,flexnoc-pm-2.7"; + reg-names = "funnel", "baselpd", "basefpd"; + reg = <0x0 0xf092 0x0 0x1000>, + <0x0 0xf098 0x0 0x9000>, + <0x0 0xf0b8 0x0 0x9000>; +}; -- 2.1.1 This email and any attachments are intended for the sole use of the named recipient(s) and contain(s) confidential information that may be proprietary, privileged or copyrighted under applicable law. If you are not the intended recipient, do not read, copy, or forward this email message or any attachments. Delete this email message and any attachments immediately.
[RFC PATCHv2 3/3] Documentation: short descriptions for Flexnoc Performance Monitor driver
Add short documentation for FlexNoc Performance Monitor driver. Signed-off-by: Shubhrajyoti Datta --- v2: patch added Documentation/misc-devices/xilinx_flex.txt | 66 ++ 1 file changed, 66 insertions(+) create mode 100644 Documentation/misc-devices/xilinx_flex.txt diff --git a/Documentation/misc-devices/xilinx_flex.txt b/Documentation/misc-devices/xilinx_flex.txt new file mode 100644 index 000..c075934 --- /dev/null +++ b/Documentation/misc-devices/xilinx_flex.txt @@ -0,0 +1,66 @@ +Kernel driver xilinx_flex + + +Supported chips: +Versal SOC + +Author: + Shubhrajyoti Datta + +Description +--- + +Versal uses the Arteris FlexNoC interconnect instead of the ARM NIC. FlexNoC +provides the capability to integrate performance counters in the interconnect. +It has configurable probe points to monitor the packet and forwards it to +observer for logging. It supports read and write transaction counts for +request and response. + +Features: +---> Run-time programmable selection of packet probe points. +---> Recording of traffic and link statistics. +---> Separate read and write response and request count. + +SYSFS: + +counteridfpd + RW - shows the counter number selected for the FPD Flexnoc. + +counterfpd_rdreq + RO - shows the read request count for the FPD counters. + +counterfpdsrc + WO - sets the source of the FPD counter. + +counterfpd_wrrsp + RO - shows the write response count for the FPD counters. + +counterfpd_rdrsp + RO - shows the read response count for the FPD counters. + +counterfpd_wrreq + RO - shows the write request count for the FPD counters. + +counterfpdport + WO - sets the port number selected for the FPD Flexnoc. + +counteridlpd + RW - shows the counter number selected for the LPD Flexnoc. + +counterlpdport + WO - sets the port number selected for the LPD Flexnoc. + +counterlpd_rdreq + RO - shows the read request count for the LPD counters. + +counterlpd_wrreq + RO - shows the write request count for the LPD counters. + +counterlpd_wrrsp + RO - shows the write response count for the LPD counters. + +counterlpdsrc + WO - sets the source of the LPD counter. + +counterlpd_rdrsp + RO - shows the read response count for the LPD counters. -- 2.1.1 This email and any attachments are intended for the sole use of the named recipient(s) and contain(s) confidential information that may be proprietary, privileged or copyrighted under applicable law. If you are not the intended recipient, do not read, copy, or forward this email message or any attachments. Delete this email message and any attachments immediately.
[RFC PATCHv2 2/3] misc: xilinx_flex: Add support for the flex noc Performance Monitor
Add support for the FlexNoc Performance Monitor. Adds support for various port setting and monitoring the packets transactions. It supports LPD and FPD monitoring counters for read and write transaction requests and responses. Signed-off-by: Shubhrajyoti Datta --- v2: Add a mutex to prevent race --- drivers/misc/Kconfig | 9 + drivers/misc/Makefile | 1 + drivers/misc/xilinx_flex_pm.c | 653 ++ 3 files changed, 663 insertions(+) create mode 100644 drivers/misc/xilinx_flex_pm.c diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index c55b637..1e9a6fa 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -454,6 +454,15 @@ config XILINX_SDFEC If unsure, say N. +config XILINX_FLEX_PM + tristate "Xilinx Flexnoc Performance Monitor" + help + This option enables support for the Xilinx Flex Noc Performance Monitor driver. + It monitors the read and write transactions. It has counters for the LPD and + FPD domains. + + If unsure, say N + config MISC_RTSX tristate default MISC_RTSX_PCI || MISC_RTSX_USB diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index c1860d3..1f1c34d 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -57,3 +57,4 @@ obj-y += cardreader/ obj-$(CONFIG_PVPANIC) += pvpanic.o obj-$(CONFIG_HABANA_AI)+= habanalabs/ obj-$(CONFIG_XILINX_SDFEC) += xilinx_sdfec.o +obj-$(CONFIG_XILINX_FLEX_PM) += xilinx_flex_pm.o diff --git a/drivers/misc/xilinx_flex_pm.c b/drivers/misc/xilinx_flex_pm.c new file mode 100644 index 000..e7684d1 --- /dev/null +++ b/drivers/misc/xilinx_flex_pm.c @@ -0,0 +1,653 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Xilinx Flex Noc Performance Monitor driver. + * Copyright (c) 2019 Xilinx Inc. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define to_xflex_dev_info(n) ((struct xflex_dev_info *)dev_get_drvdata(n)) + +#define FPM_LAR_OFFSET 0xFB0 +#define FPM_UNLOCK 0xC5ACCE55 + +#define FPM_RD_REQ_OFFSET 0x1000 +#define FPM_RD_RES_OFFSET 0x2000 +#define FPM_WR_REQ_OFFSET 0x3000 +#define FPM_WR_RES_OFFSET 0x4000 + +#define FPM_PORT_SEL_OFFSET0x134 +#define FPM_MAIN_CTRL_OFFSET 0x008 +#define FPM_SRC_SEL_OFFSET 0x138 +#define FPM_STATPERIOD 0x24 +#define FPM_CFGCTRL0x0C +#define FPM_LPD0x4210002 +#define FPM_FPD0x420c003 + +#define FPM_VAL0x300 +#define FPM_SRC0x200 +#define FPM_WRRSP_L0x7 +#define FPM_WRREQ_L0x6 +#define FPM_RDRSP_L0x5 +#define FPM_RDREQ_L0x4 +#define FPM_PROBE_SHIFT16 +#define FPM_COUNTER_OFFSET 0x14 +#define FPM_GLOBALEN BIT(0) +#define FPM_STATEN BIT(3) +#define FPM_STATCOND_DUMP BIT(5) +#define FPM_NUM_COUNTERS 4 +#define FPM_MAINCTL_DIS0 + +#define FPM_SRC_OFF0x0 +#define FPM_SRC_CYCLE 0x1 +#define FPM_SRC_IDLE 0x2 +#define FPM_SRC_XFER 0x3 +#define FPM_SRC_BUSY 0x4 +#define FPM_SRC_WAIT 0x5 +#define FPM_SRC_PACKET 0x6 + +/* Port values */ +#define FPM_PORT_LPD_AFIFS_AXI 0x0 +#define FPM_PORT_LPD_OCM 0x1 +#define FPM_PORT_LPD_OCMEXT0x2 +#define FPM_PORT_PMC_RPU_AXI0 0x3 + +#define FPM_PORT_FPDAXI0x1 +#define FPM_PORT_PROTXPPU 0x2 + +/** + * struct xflex_dev_info - Global Driver structure + * @dev: Device structure + * @baselpd: Iomapped LPD base address + * @basefpd: Iomapped FPD base address + * @funnel: Iomapped funnel register base address + * @counterid_lpd: LPD counter id + * @counterid_fpd: FPD counter id + */ +struct xflex_dev_info { + struct device *dev; + void __iomem *baselpd; + void __iomem *basefpd; + void __iomem *funnel; + u32 counterid_fpd; + u32 counterid_lpd; + struct mutex mutex; /* avoid parallel access to device */ +}; + +/** + * enum xflex_sysfs_cmd_codes - sysfs command codes + * @XFLEX_GET_COUNTER_FPD: get the FPD counter value + * @XFLEX_SET_COUNTER_FPD: set the FPD counter value + * @XFLEX_GET_COUNTER_FPD_RDREQ: get the FPD read request count + * @XFLEX_GET_COUNTER_FPD_RDRSP: get the FPD read response count + * @XFLEX_GET_COUNTER_FPD_WRREQ: get the FPD write request count + * @XFLEX_GET_COUNTER_FPD_WRRSP: get the FPD write response count + * @XFLEX_GET_COUNTER_LPD_RDREQ: get th
Re: [PATCH] i2c: cadence: try reset when master receive error interrupts
Hi Sxauwsk, On Wed, Jan 30, 2019 at 3:13 PM sxauwsk wrote: > > When the adapter receive error interrupts, such as NACK, arbitration lost, > cdns_i2c_master_xfer return to the caller directly instead of resuming > the adapter which resulted in the adapter being out of control. > > So when driver detect err_status then try to repair and fix it. > > Signed-off-by: sxauwsk > --- > drivers/i2c/busses/i2c-cadence.c | 12 +++- > 1 file changed, 7 insertions(+), 5 deletions(-) > > diff --git a/drivers/i2c/busses/i2c-cadence.c > b/drivers/i2c/busses/i2c-cadence.c > index b13605718291..e10048d7524a 100644 > --- a/drivers/i2c/busses/i2c-cadence.c > +++ b/drivers/i2c/busses/i2c-cadence.c > @@ -548,10 +548,6 @@ static int cdns_i2c_process_msg(struct cdns_i2c *id, > struct i2c_msg *msg, > cdns_i2c_writereg(CDNS_I2C_IXR_ALL_INTR_MASK, > CDNS_I2C_IDR_OFFSET); > > - /* If it is bus arbitration error, try again */ > - if (id->err_status & CDNS_I2C_IXR_ARB_LOST) > - return -EAGAIN; > - > return 0; > } > > @@ -617,13 +613,19 @@ static int cdns_i2c_master_xfer(struct i2c_adapter > *adap, struct i2c_msg *msgs, > id->bus_hold_flag = 0; > > ret = cdns_i2c_process_msg(id, msgs, adap); > - if (ret) > + if (!ret) > goto out; > In case the Arbitration error happend the cdns_i2c_process_msg would return 0 and we will miss the check below. Am I missing something ? > /* Report the other error interrupts to application */ > if (id->err_status) { > cdns_i2c_master_reset(adap); > > + /* If it is bus arbitration error, try again */ > + if (id->err_status & CDNS_I2C_IXR_ARB_LOST) { > + ret = -EAGAIN; > + goto out; > + } > + > if (id->err_status & CDNS_I2C_IXR_NACK) { > ret = -ENXIO; > goto out; > -- > 2.19.2 > >
Re: [PATCH 2/8] gpio: zynq: Wakeup gpio controller when it is used as IRQ controller
On Fri, Jan 11, 2019 at 8:26 PM Linus Walleij wrote: > > On Fri, Jan 11, 2019 at 1:54 PM Thomas Petazzoni > wrote: > > On Fri, 11 Jan 2019 10:54:20 +0100, Linus Walleij wrote: > > > > > My stance is that the driver is responsible of enabling and managing > > > runtime PM for its hardware block(s). > > > > > > Runtime PM in the core should only be added if the core needs to > > > be aware about it, such as is the case when e.g. a block device > > > needs to drain its write buffer before going to runtime sleep. > > > > > > I fail so see why the GPIO core need to be aware about this. > > > > In this very same thread at > > https://www.spinics.net/lists/arm-kernel/msg600515.html, you kind of I was not abloe to open the link could you please let me know if I am missing something?
Re: [PATCH] i2c: cadence: try reset when master receive error interrupts
Hi , On Sat, Feb 16, 2019 at 1:21 PM sxau...@163.com wrote: > > >Hi Sxauwsk, > > > >On Wed, Jan 30, 2019 at 3:13 PM sxauwsk wrote: > >> > >> When the adapter receive error interrupts, such as NACK, arbitration lost, > >> cdns_i2c_master_xfer return to the caller directly instead of resuming > >> the adapter which resulted in the adapter being out of control. > >> > >> So when driver detect err_status then try to repair and fix it. > >> > >> Signed-off-by: sxauwsk > >> --- > >> drivers/i2c/busses/i2c-cadence.c | 12 +++- > >> 1 file changed, 7 insertions(+), 5 deletions(-) > >> > >> diff --git a/drivers/i2c/busses/i2c-cadence.c > >> b/drivers/i2c/busses/i2c-cadence.c > >> index b13605718291..e10048d7524a 100644 > >> --- a/drivers/i2c/busses/i2c-cadence.c > >> +++ b/drivers/i2c/busses/i2c-cadence.c > >> @@ -548,10 +548,6 @@ static int cdns_i2c_process_msg(struct cdns_i2c *id, > >> struct i2c_msg *msg, > >> cdns_i2c_writereg(CDNS_I2C_IXR_ALL_INTR_MASK, > >> CDNS_I2C_IDR_OFFSET); > >> > >> - /* If it is bus arbitration error, try again */ > >> - if (id->err_status & CDNS_I2C_IXR_ARB_LOST) > >> - return -EAGAIN; > >> - > >> return 0; > >> } > >> > >> @@ -617,13 +613,19 @@ static int cdns_i2c_master_xfer(struct i2c_adapter > >> *adap, struct i2c_msg *msgs, > >> id->bus_hold_flag = 0; > >> > >> ret = cdns_i2c_process_msg(id, msgs, adap); > >> - if (ret) > >> + if (!ret) > >> goto out; > >> > >In case the Arbitration error happend the cdns_i2c_process_msg would > >return 0 > >and we will miss the check below. > > > >Am I missing something ? > > > >> /* Report the other error interrupts to application */ > >> if (id->err_status) { > >> cdns_i2c_master_reset(adap); > >> > >> + /* If it is bus arbitration error, try again */ > >> + if (id->err_status & CDNS_I2C_IXR_ARB_LOST) { > >> + ret = -EAGAIN; > >> + goto out; > >> + } > >> + > >> if (id->err_status & CDNS_I2C_IXR_NACK) { > >> ret = -ENXIO; > >> goto out; > >> -- > >> 2.19.2 > >> > >> > > In cdns_i2c_process_msg process, when detect arbitration lost error return > -EAGAIN to cdns_i2c_master_xfer, not return 0 > that mean cdns_i2c_process_msg just go out ignore error check and problem > occur, So we should do something when arbitration error detect. Arbitration lost is fine how about other errors like NACK.
Re: Re: [PATCH] i2c: cadence: try reset when master receive error interrupts
On Mon, Feb 18, 2019 at 12:48 PM sxau...@163.com wrote: > > Hi , Shubhrajyoti > > >Hi , > >On Sat, Feb 16, 2019 at 1:21 PM sxau...@163.com wrote: > >> > >> >Hi Sxauwsk, > >> > > >> >On Wed, Jan 30, 2019 at 3:13 PM sxauwsk wrote: > >> >> > >> >> When the adapter receive error interrupts, such as NACK, arbitration > >> >> lost, > >> >> cdns_i2c_master_xfer return to the caller directly instead of resuming > >> >> the adapter which resulted in the adapter being out of control. > >> >> > >> >> So when driver detect err_status then try to repair and fix it. > >> >> > >> >> Signed-off-by: sxauwsk > >> >> --- > >> >> drivers/i2c/busses/i2c-cadence.c | 12 +++- > >> >> 1 file changed, 7 insertions(+), 5 deletions(-) > >> >> > >> >> diff --git a/drivers/i2c/busses/i2c-cadence.c > >> >> b/drivers/i2c/busses/i2c-cadence.c > >> >> index b13605718291..e10048d7524a 100644 > >> >> --- a/drivers/i2c/busses/i2c-cadence.c > >> >> +++ b/drivers/i2c/busses/i2c-cadence.c > >> >> @@ -548,10 +548,6 @@ static int cdns_i2c_process_msg(struct cdns_i2c > >> >> *id, struct i2c_msg *msg, > >> >> cdns_i2c_writereg(CDNS_I2C_IXR_ALL_INTR_MASK, > >> >> CDNS_I2C_IDR_OFFSET); > >> >> > >> >> - /* If it is bus arbitration error, try again */ > >> >> - if (id->err_status & CDNS_I2C_IXR_ARB_LOST) > >> >> - return -EAGAIN; > >> >> - > >> >> return 0; > >> >> } > >> >> > >> >> @@ -617,13 +613,19 @@ static int cdns_i2c_master_xfer(struct > >> >> i2c_adapter *adap, struct i2c_msg *msgs, > >> >> id->bus_hold_flag = 0; > >> >> > >> >> ret = cdns_i2c_process_msg(id, msgs, adap); > >> >> - if (ret) > >> >> + if (!ret) > >> >> goto out; > >> >> > >> >In case the Arbitration error happend the cdns_i2c_process_msg would > >> >return 0 > >> >and we will miss the check below. > >> > > >> >Am I missing something ? > >> > > >> >> /* Report the other error interrupts to application */ > >> >> if (id->err_status) { > >> >> cdns_i2c_master_reset(adap); > >> >> > >> >> + /* If it is bus arbitration error, try again */ > >> >> + if (id->err_status & CDNS_I2C_IXR_ARB_LOST) { > >> >> + ret = -EAGAIN; > >> >> + goto out; > >> >> + } > >> >> + > >> >> if (id->err_status & CDNS_I2C_IXR_NACK) { > >> >> ret = -ENXIO; > >> >> goto out; > >> >> -- > >> >> 2.19.2 > >> >> > >> >> > >> > >> In cdns_i2c_process_msg process, when detect arbitration lost error return > >> -EAGAIN to cdns_i2c_master_xfer, not return 0 > >> that mean cdns_i2c_process_msg just go out ignore error check and > >> problem occur, So we should do something when arbitration error detect. > > > >Arbitration lost is fine how about other errors like NACK. > > >> >> ret = cdns_i2c_process_msg(id, msgs, adap); > >> >> - if (ret) > >> >> + if (!ret) > >> >> goto out; > > Yes, you're right, This place I should't make any change, perfect solution! > > >> >> > >> >> - /* If it is bus arbitration error, try again */ > >> >> - if (id->err_status & CDNS_I2C_IXR_ARB_LOST) > >> >> - return -EAGAIN; > >> >> - > >> >> return 0; > >> >> } > > > >> >> /* Report the other error interrupts to application */ > >> >> if (id->err_status) { > >> >> cdns_i2c_master_reset(adap); > >> >> > >> >> + /* If it is bus arbitration error, try again */ > >> >> + if (id->err_status & CDNS_I2C_IXR_ARB_LOST) { > >> >> + ret = -EAGAIN; > >> >> + goto out; > >> >> + } > >> >> + > > Maybe Just remove Arbitration lost Detect part from cdns_i2c_process_msg > function, then add to cdns_i2c_master_xfer, Do you think? I agree. > > > >
Re: [PATCH] i2c: xiic: Make the start and the byte count write atomic
Hi, On Tue, Sep 4, 2018 at 9:41 PM Wolfram Sang wrote: > > On Mon, Sep 03, 2018 at 03:11:11PM +0530, shubhrajyoti.da...@gmail.com wrote: > > From: Shubhrajyoti Datta > > > > Disable interrupts while configuring the transfer and enable them back. > > > > We have below as the programming sequence > > 1. start and slave address > > 2. byte count and stop > > > > In some customer platform there was a lot of interrupts between 1 and 2 > > and after slave address (around 7 clock cyles) if 2 is not executed > > then the transaction is nacked. > > > > To fix this case make the 2 writes atomic. > > > > Signed-off-by: Shubhrajyoti Datta > > Signed-off-by: Michal Simek > > I assume simply changing the order of the register writes won't fix it? No that is not possible. > > I also assume this is stable material? > Yes let me know if you want me to resend with the stable tag?
Re: [PATCH v9 2/2] dmaengine: Add Xilinx zynqmp dma engine driver support
> + */ > +static void zynqmp_dma_update_desc_to_ctrlr(struct zynqmp_dma_chan *chan, > + struct zynqmp_dma_desc_sw *desc) > +{ > + dma_addr_t addr; > + > + addr = desc->src_p; > + writel(addr, chan->regs + ZYNQMP_DMA_SRC_START_LSB); > + writel(upper_32_bits(addr), chan->regs + ZYNQMP_DMA_SRC_START_MSB); Can we combine the two writes to a 64bit write. It may be helpful on 64-bit systems. > + addr = desc->dst_p; > + writel(addr, chan->regs + ZYNQMP_DMA_DST_START_LSB); > + writel(upper_32_bits(addr), chan->regs + ZYNQMP_DMA_DST_START_MSB); > +}
Re: [PATCH v4] Axi-usb: Add support for 64-bit addressing.
On Mon, May 30, 2016 at 10:16 PM, Nava kishore Manne wrote: > This patch updates the driver to support 64-bit DMA addressing. > > Signed-off-by: Nava kishore Manne > --- > Changes for v4: > -Used boolen property insted of addrwith property in the DT > as suggested by Arnd Bergmann. > -Adopt the DT relevant changes into the driver. > > Changes for v3: > -Added new compatable string for 5.00 IP version as suggested > by > Arnd Bergmann. > -Used write_fn() insted of lo_hi_writeq() as suggested by > Arnd Bergmann. > > Changes for v2: > -Added dma-ranges property in device tree as suggested by > Arnd Bergmann. > -Modified the driver code based on the xlnx,addrwidth. > > .../devicetree/bindings/usb/udc-xilinx.txt | 5 ++- > drivers/usb/gadget/udc/udc-xilinx.c| 52 > +- > 2 files changed, 54 insertions(+), 3 deletions(-) > > diff --git a/Documentation/devicetree/bindings/usb/udc-xilinx.txt > b/Documentation/devicetree/bindings/usb/udc-xilinx.txt > index 47b4e39..d08d972 100644 > --- a/Documentation/devicetree/bindings/usb/udc-xilinx.txt > +++ b/Documentation/devicetree/bindings/usb/udc-xilinx.txt > @@ -1,12 +1,14 @@ > Xilinx USB2 device controller > > Required properties: > -- compatible : Should be "xlnx,usb2-device-4.00.a" > +- compatible : Should be "xlnx,usb2-device-4.00.a" or > + "xlnx,usb2-device-5.00" > - reg : Physical base address and size of the USB2 > device registers map. > - interrupts : Should contain single irq line of USB2 device > controller > - xlnx,has-builtin-dma : if DMA is included > +- xlnx,has-64bit-dma : if DMA is included 64-bit addressing support. > > Example: > axi-usb2-device@42e0 { > @@ -14,5 +16,6 @@ Example: > interrupts = <0x0 0x39 0x1>; > reg = <0x42e0 0x1>; > xlnx,has-builtin-dma; > + xlnx,has-64bit-dma; > }; > > diff --git a/drivers/usb/gadget/udc/udc-xilinx.c > b/drivers/usb/gadget/udc/udc-xilinx.c > index 1cbb0ac..6fb80c6 100644 > --- a/drivers/usb/gadget/udc/udc-xilinx.c > +++ b/drivers/usb/gadget/udc/udc-xilinx.c > @@ -47,6 +47,15 @@ > #define XUSB_DMA_LENGTH_OFFSET 0x0210 /* DMA Length Register */ > #define XUSB_DMA_STATUS_OFFSET 0x0214 /* DMA Status Register */ > > +/* DMA source Address Reg for LSB */ > +#define XUSB_DMA_DSAR_ADDR_OFFSET_LSB 0x0308 > +/* DMA source Address Reg for MSB */ > +#define XUSB_DMA_DSAR_ADDR_OFFSET_MSB 0x030C > +/* DMA destination Addr Reg LSB */ > +#define XUSB_DMA_DDAR_ADDR_OFFSET_LSB 0x0310 > +/* DMA destination Addr Reg MSB */ > +#define XUSB_DMA_DDAR_ADDR_OFFSET_MSB 0x0314 > + > /* Endpoint Configuration Space offsets */ > #define XUSB_EP_CFGSTATUS_OFFSET 0x00/* Endpoint Config Status */ > #define XUSB_EP_BUF0COUNT_OFFSET 0x08/* Buffer 0 Count */ > @@ -169,6 +178,7 @@ struct xusb_ep { > * @setup: usb_ctrlrequest structure for control requests > * @req: pointer to dummy request for get status command > * @dev: pointer to device structure in gadget > + * @is_extend_dma: flag indiacting whether the dma is 64-bit support or not. > * @usb_state: device in suspended state or not > * @remote_wkp: remote wakeup enabled by host > * @setupseqtx: tx status > @@ -186,6 +196,7 @@ struct xusb_udc { > struct usb_ctrlrequest setup; > struct xusb_req *req; > struct device *dev; > + bool is_extend_dma; > u32 usb_state; > u32 remote_wkp; > u32 setupseqtx; > @@ -215,6 +226,20 @@ static const struct usb_endpoint_descriptor > config_bulk_out_desc = { > }; > > /** > + * xudc_write64 - write 64bit value to device registers > + * @ep: pointer to the usb device endpoint structure. > + * @offset: register offset > + * @val: data to be written > + **/ > +static void xudc_write64(struct xusb_ep *ep, u32 offset, u64 val) > +{ > + struct xusb_udc *udc = ep->udc; > + > + udc->write_fn(udc->addr, offset, lower_32_bits(val)); > + udc->write_fn(udc->addr, offset+0x04, upper_32_bits(val)); can we move this to a single 64 bit write? > +} > + > +/**
Re: Reset implementation for Zynq
On Fri, Oct 21, 2016 at 10:34 PM, Moritz Fischer wrote: > Iztok, > > On Fri, Oct 21, 2016 at 03:08:47AM -0700, iztok.je...@redpitaya.com wrote: >> Hi Moritz, >> >> I was looking at your reset implementation for Zynq: >> https://github.com/Xilinx/linux-xlnx/blob/629041605b93343ad2e8971ceaac3edcef0b043b/drivers/reset/reset-zynq.c >> I went through related mailing list posts (including earlier versions of the >> patch) so I kind of understand what to change in the device tree. > > Please look at the upstream kernel sources and use the mailing list > (lkml) if you want to report bugs. Xilinx' vendor tree might or might > not be up to date. > >> I would like to use this driver to reset the Zynq I2C controller, since we >> have trouble with it getting into a lock up state. Can you explain what you are facing and what is meant by lockup state.
Re: Re: Reset implementation for Zynq
Hi Iztok, On Tue, Nov 8, 2016 at 3:10 PM, wrote: > Hi Shubhrajyoti, > > By lockup state, I mean an undefined/unhandled state of the HW logic state > machine, > or something similar in the software driver. > Based on symptoms I assume it is a HW lockup. > In practice asking the driver for a new I2C transfer would result in > nothing happening on the I2C bus (signals remain in hi-Z state). > Driver or userspace tool reports a transfer error, but I did not copy it. > And I did not check the state of the driver. > > To enter this mode it was enough to connect an oscilloscope probe to the SDA > signal. > The capacitance of the probe causes a deep voltage fall, which is quickly > corrected by the pullup. > I did not time the glitch, and the shape was partially defined by an I2C > level shifter. > The issue can be repeated with about 80% probability. > > There are two ways to get back to a working state: > 1. create a longer zero pulse (about 50ms manual grounding) on SDA > 2. reset the HW, this was done with a patched driver. Thanks for the explaination. May be recovery mechanism implementation could be considered. > > Regards, > Iztok Jeras > >
Re: i2c: xiic: Strange clk_prepare_enable() in xiic_i2c_remove()
On Sat, Dec 17, 2016 at 3:24 AM, Alexey Khoroshilov wrote: > Dear Shubhrajyoti, > > Looking at 36ecbcab84d0 ("i2c: xiic: Implement power management") > it is not clear why clk_prepare_enable(i2c->clk) is required in > xiic_i2c_remove()? 834 ret = clk_prepare_enable(i2c->clk); 835 if (ret) { 836 dev_err(&pdev->dev, "Unable to enable clock.\n"); 837 return ret; 838 } 839 xiic_deinit(i2c); 840 clk_disable_unprepare(i2c->clk); so it is enabled and disabled after xiic_deinit. > > It is enabled in xiic_i2c_probe() and disabled/enabled in > cdns_i2c_runtime_suspend()/cdns_i2c_runtime_resume(). > > Could you please clarify the point. > > -- > Alexey Khoroshilov > Linux Verification Center, ISPRAS > web: http://linuxtesting.org > > -- > To unsubscribe from this list: send the line "unsubscribe linux-i2c" in > the body of a message to majord...@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v4] Axi-usb: Add support for 64-bit addressing.
On Tue, May 31, 2016 at 10:45 AM, Nava kishore Manne wrote: > Hi Shubhrajyoti, > > > Thanks for the review... > >> > /** >> > + * xudc_write64 - write 64bit value to device registers >> > + * @ep: pointer to the usb device endpoint structure. >> > + * @offset: register offset >> > + * @val: data to be written >> > + **/ >> > +static void xudc_write64(struct xusb_ep *ep, u32 offset, u64 val) { >> > + struct xusb_udc *udc = ep->udc; >> > + >> > + udc->write_fn(udc->addr, offset, lower_32_bits(val)); >> > + udc->write_fn(udc->addr, offset+0x04, upper_32_bits(val)); >> >> can we move this to a single 64 bit write? > > Initially I sent the patches with writeq() ,lo_hi_writeq() later we decided > to replace with write_fun(). > The reason for this is lo_hi_writeq() always assumes a little-endian > register, so it's broken if anyone builds this device with big-endian > registers. > So replaced the 64bit calls with write_fun() as suggested by Arnd Bergmann. > Hope it clears your query. > Please refer to the below thread > > http://lkml.iu.edu/hypermail/linux/kernel/1604.2/02046.html missed that discurssion. thanks > > > Regards, > Navakishore. >
[PATCH v4 8/8] staging: clocking-wizard: Delete the driver from the staging
Delete the driver from the staging as it is in drivers/clk. Signed-off-by: Shubhrajyoti Datta --- drivers/staging/Kconfig| 2 - drivers/staging/Makefile | 1 - drivers/staging/clocking-wizard/Kconfig| 10 - drivers/staging/clocking-wizard/Makefile | 2 - drivers/staging/clocking-wizard/TODO | 12 - .../clocking-wizard/clk-xlnx-clock-wizard.c| 333 - drivers/staging/clocking-wizard/dt-binding.txt | 30 -- 7 files changed, 390 deletions(-) delete mode 100644 drivers/staging/clocking-wizard/Kconfig delete mode 100644 drivers/staging/clocking-wizard/Makefile delete mode 100644 drivers/staging/clocking-wizard/TODO delete mode 100644 drivers/staging/clocking-wizard/clk-xlnx-clock-wizard.c delete mode 100644 drivers/staging/clocking-wizard/dt-binding.txt diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index 4ec5528..cdb5422 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -78,8 +78,6 @@ source "drivers/staging/gs_fpgaboot/Kconfig" source "drivers/staging/unisys/Kconfig" -source "drivers/staging/clocking-wizard/Kconfig" - source "drivers/staging/fbtft/Kconfig" source "drivers/staging/fsl-dpaa2/Kconfig" diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index 4d34198..14570e5 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -29,7 +29,6 @@ obj-$(CONFIG_FIREWIRE_SERIAL) += fwserial/ obj-$(CONFIG_GOLDFISH) += goldfish/ obj-$(CONFIG_GS_FPGABOOT) += gs_fpgaboot/ obj-$(CONFIG_UNISYSSPAR) += unisys/ -obj-$(CONFIG_COMMON_CLK_XLNX_CLKWZRD) += clocking-wizard/ obj-$(CONFIG_FB_TFT) += fbtft/ obj-$(CONFIG_FSL_DPAA2)+= fsl-dpaa2/ obj-$(CONFIG_WILC1000) += wilc1000/ diff --git a/drivers/staging/clocking-wizard/Kconfig b/drivers/staging/clocking-wizard/Kconfig deleted file mode 100644 index 04be22d..000 --- a/drivers/staging/clocking-wizard/Kconfig +++ /dev/null @@ -1,10 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -# -# Xilinx Clocking Wizard Driver -# - -config COMMON_CLK_XLNX_CLKWZRD - tristate "Xilinx Clocking Wizard" - depends on COMMON_CLK && OF - help - Support for the Xilinx Clocking Wizard IP core clock generator. diff --git a/drivers/staging/clocking-wizard/Makefile b/drivers/staging/clocking-wizard/Makefile deleted file mode 100644 index b1f9152..000 --- a/drivers/staging/clocking-wizard/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -obj-$(CONFIG_COMMON_CLK_XLNX_CLKWZRD) += clk-xlnx-clock-wizard.o diff --git a/drivers/staging/clocking-wizard/TODO b/drivers/staging/clocking-wizard/TODO deleted file mode 100644 index ebe99db..000 --- a/drivers/staging/clocking-wizard/TODO +++ /dev/null @@ -1,12 +0,0 @@ -TODO: - - support for fractional multiplier - - support for fractional divider (output 0 only) - - support for set_rate() operations (may benefit from Stephen Boyd's - refactoring of the clk primitives: https://lkml.org/lkml/2014/9/5/766) - - review arithmetic - - overflow after multiplication? - - maximize accuracy before divisions - -Patches to: - Greg Kroah-Hartman - Sören Brinkmann diff --git a/drivers/staging/clocking-wizard/clk-xlnx-clock-wizard.c b/drivers/staging/clocking-wizard/clk-xlnx-clock-wizard.c deleted file mode 100644 index e52a64b..000 --- a/drivers/staging/clocking-wizard/clk-xlnx-clock-wizard.c +++ /dev/null @@ -1,333 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Xilinx 'Clocking Wizard' driver - * - * Copyright (C) 2013 - 2014 Xilinx - * - * Sören Brinkmann - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#define WZRD_NUM_OUTPUTS 7 -#define WZRD_ACLK_MAX_FREQ 25000UL - -#define WZRD_CLK_CFG_REG(n)(0x200 + 4 * (n)) - -#define WZRD_CLKOUT0_FRAC_EN BIT(18) -#define WZRD_CLKFBOUT_FRAC_EN BIT(26) - -#define WZRD_CLKFBOUT_MULT_SHIFT 8 -#define WZRD_CLKFBOUT_MULT_MASK(0xff << WZRD_CLKFBOUT_MULT_SHIFT) -#define WZRD_DIVCLK_DIVIDE_SHIFT 0 -#define WZRD_DIVCLK_DIVIDE_MASK(0xff << WZRD_DIVCLK_DIVIDE_SHIFT) -#define WZRD_CLKOUT_DIVIDE_SHIFT 0 -#define WZRD_CLKOUT_DIVIDE_MASK(0xff << WZRD_DIVCLK_DIVIDE_SHIFT) - -enum clk_wzrd_int_clks { - wzrd_clk_mul, - wzrd_clk_mul_div, - wzrd_clk_int_max -}; - -/** - * struct clk_wzrd: - * @clk_data: Clock data - * @nb:Notifier block - * @base: Memory base - * @clk_in1: Handle to input clock 'clk_in1' - * @axi_clk: Handle to input clock 's_axi_aclk' - * @clks_internal: Internal clocks - * @clkout:O
[PATCH v4 2/8] clk: clock-wizard: Add the clockwizard to clk directory
Add clocking wizard driver to clk. Signed-off-by: Shubhrajyoti Datta --- drivers/clk/Kconfig | 9 + drivers/clk/Makefile| 1 + drivers/clk/clk-xlnx-clock-wizard.c | 338 3 files changed, 348 insertions(+) create mode 100644 drivers/clk/clk-xlnx-clock-wizard.c diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index 69934c0..5f66076 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -360,6 +360,15 @@ config COMMON_CLK_FIXED_MMIO help Support for Memory Mapped IO Fixed clocks +config COMMON_CLK_XLNX_CLKWZRD + tristate "Xilinx Clocking Wizard" + depends on COMMON_CLK && OF + help + Support for the Xilinx Clocking Wizard IP core clock generator. + Adds support for clocking wizard and compatible. + This driver supports the Xilinx clocking wizard programmable clock + synthesizer. The number of output is configurable in the design. + source "drivers/clk/actions/Kconfig" source "drivers/clk/analogbits/Kconfig" source "drivers/clk/baikal-t1/Kconfig" diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index ca9af11..f41287859 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -68,6 +68,7 @@ obj-$(CONFIG_ARCH_VT8500) += clk-vt8500.o obj-$(CONFIG_COMMON_CLK_VC5) += clk-versaclock5.o obj-$(CONFIG_COMMON_CLK_WM831X)+= clk-wm831x.o obj-$(CONFIG_COMMON_CLK_XGENE) += clk-xgene.o +obj-$(CONFIG_COMMON_CLK_XLNX_CLKWZRD) += clk-xlnx-clock-wizard.o # please keep this section sorted lexicographically by directory path name obj-y += actions/ diff --git a/drivers/clk/clk-xlnx-clock-wizard.c b/drivers/clk/clk-xlnx-clock-wizard.c new file mode 100644 index 000..b31524a --- /dev/null +++ b/drivers/clk/clk-xlnx-clock-wizard.c @@ -0,0 +1,338 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Xilinx 'Clocking Wizard' driver + * + * Copyright (C) 2013 - 2020 Xilinx + * + * Sören Brinkmann + * Shubhrajyoti Datta + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define WZRD_NUM_OUTPUTS 7 +#define WZRD_ACLK_MAX_FREQ 25000UL + +#define WZRD_CLK_CFG_REG(n)(0x200 + 4 * (n)) + +#define WZRD_CLKOUT0_FRAC_EN BIT(18) +#define WZRD_CLKFBOUT_FRAC_EN BIT(26) + +#define WZRD_CLKFBOUT_MULT_SHIFT 8 +#define WZRD_CLKFBOUT_MULT_MASK(0xff << WZRD_CLKFBOUT_MULT_SHIFT) +#define WZRD_DIVCLK_DIVIDE_SHIFT 0 +#define WZRD_DIVCLK_DIVIDE_MASK(0xff << WZRD_DIVCLK_DIVIDE_SHIFT) +#define WZRD_CLKOUT_DIVIDE_SHIFT 0 +#define WZRD_CLKOUT_DIVIDE_MASK(0xff << WZRD_DIVCLK_DIVIDE_SHIFT) + +enum clk_wzrd_int_clks { + wzrd_clk_mul, + wzrd_clk_mul_div, + wzrd_clk_int_max +}; + +/** + * struct clk_wzrd: + * @clk_data: Clock data + * @nb:Notifier block + * @base: Memory base + * @clk_in1: Handle to input clock 'clk_in1' + * @axi_clk: Handle to input clock 's_axi_aclk' + * @clks_internal: Internal clocks + * @clkout:Output clocks + * @speed_grade: Speed grade of the device + * @suspended: Flag indicating power state of the device + */ +struct clk_wzrd { + struct clk_onecell_data clk_data; + struct notifier_block nb; + void __iomem *base; + struct clk *clk_in1; + struct clk *axi_clk; + struct clk *clks_internal[wzrd_clk_int_max]; + struct clk *clkout[WZRD_NUM_OUTPUTS]; + unsigned int speed_grade; + bool suspended; +}; + +#define to_clk_wzrd(_nb) container_of(_nb, struct clk_wzrd, nb) + +/* maximum frequencies for input/output clocks per speed grade */ +static const unsigned long clk_wzrd_max_freq[] = { + 8UL, + 93300UL, + 106600UL +}; + +static int clk_wzrd_clk_notifier(struct notifier_block *nb, unsigned long event, +void *data) +{ + unsigned long max; + struct clk_notifier_data *ndata = data; + struct clk_wzrd *clk_wzrd = to_clk_wzrd(nb); + + if (clk_wzrd->suspended) + return NOTIFY_OK; + + if (ndata->clk == clk_wzrd->clk_in1) + max = clk_wzrd_max_freq[clk_wzrd->speed_grade - 1]; + else if (ndata->clk == clk_wzrd->axi_clk) + max = WZRD_ACLK_MAX_FREQ; + else + return NOTIFY_DONE; /* should never happen */ + + switch (event) { + case PRE_RATE_CHANGE: + if (ndata->new_rate > max) + return NOTIFY_BAD; + return NOTIFY_OK; + case POST_RATE_CHANGE: + case ABORT_RATE_CHANGE: + default: + return NOTIFY_DONE; + } +} + +s
[PATCH v4 6/8] clk: clock-wizard: Remove the hardcoding of the clock outputs
The number of output clocks are configurable in the hardware. Currently the driver registers the maximum number of outputs. Fix the same by registering only the outputs that are there. Signed-off-by: Shubhrajyoti Datta --- v4: Assign output in this patch drivers/clk/clk-xlnx-clock-wizard.c | 6 -- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/clk/clk-xlnx-clock-wizard.c b/drivers/clk/clk-xlnx-clock-wizard.c index 8a7f9bb..28bbaa0 100644 --- a/drivers/clk/clk-xlnx-clock-wizard.c +++ b/drivers/clk/clk-xlnx-clock-wizard.c @@ -495,6 +495,7 @@ static int clk_wzrd_probe(struct platform_device *pdev) const char *clk_name; struct clk_wzrd *clk_wzrd; struct resource *mem; + int outputs; struct device_node *np = pdev->dev.of_node; clk_wzrd = devm_kzalloc(&pdev->dev, sizeof(*clk_wzrd), GFP_KERNEL); @@ -565,6 +566,7 @@ static int clk_wzrd_probe(struct platform_device *pdev) goto err_disable_clk; } + outputs = of_property_count_strings(np, "clock-output-names"); /* register div */ reg = (readl(clk_wzrd->base + WZRD_CLK_CFG_REG(0)) & WZRD_DIVCLK_DIVIDE_MASK) >> WZRD_DIVCLK_DIVIDE_SHIFT; @@ -586,7 +588,7 @@ static int clk_wzrd_probe(struct platform_device *pdev) } /* register div per output */ - for (i = WZRD_NUM_OUTPUTS - 1; i >= 0 ; i--) { + for (i = outputs - 1; i >= 0 ; i--) { const char *clkout_name; if (of_property_read_string_index(np, "clock-output-names", i, @@ -617,7 +619,7 @@ static int clk_wzrd_probe(struct platform_device *pdev) if (IS_ERR(clk_wzrd->clkout[i])) { int j; - for (j = i + 1; j < WZRD_NUM_OUTPUTS; j++) + for (j = i + 1; j < outputs; j++) clk_unregister(clk_wzrd->clkout[j]); dev_err(&pdev->dev, "unable to register divider clock\n"); -- 2.1.1
[PATCH v4 1/8] dt-bindings: add documentation of xilinx clocking wizard
Add the devicetree binding for the xilinx clocking wizard. Signed-off-by: Shubhrajyoti Datta --- v4: Move to yaml format .../bindings/clock/xlnx,clocking-wizard.yaml | 71 ++ 1 file changed, 71 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/xlnx,clocking-wizard.yaml diff --git a/Documentation/devicetree/bindings/clock/xlnx,clocking-wizard.yaml b/Documentation/devicetree/bindings/clock/xlnx,clocking-wizard.yaml new file mode 100644 index 000..5a8e991 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/xlnx,clocking-wizard.yaml @@ -0,0 +1,71 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/xlnx,clocking-wiz.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Xilinx clocking wizard + +maintainers: + - Shubhrajyoti Datta + +description: | + The clocking wizard is a soft ip clocking block of Xilinx versal. It + reads required input clock frequencies from the devicetree and acts as clock + clock output. + +select: false + +properties: + compatible: +items: + - enum: + - xlnx,clocking-wizard + - xlnx,clocking-wizard-6.0 + + "#clock-cells": +const: 1 + + clocks: +description: List of clock specifiers which are external input + clocks to the given clock controller. +items: + - description: clock input + - description: axi clock + + clock-names: +items: + - const: clk_in1 + - const: s_axi_aclk + + speed-grade: +allOf: + - $ref: /schemas/types.yaml#/definitions/uint32 + - enum: [1, 2, 3] +description: + Speed grade of the device. +maxItems: 1 + +required: + - compatible + - "#clock-cells" + - clocks + - clock-names + - speed-grade + +additionalProperties: false + +examples: + - | +clock-generator@4004 { +#clock-cells = <1>; +reg = <0x4004 0x1000>; +compatible = "xlnx,clk-wizard-1.0"; +speed-grade = <1>; +clock-names = "clk_in1", "s_axi_aclk"; +clocks = <&clkc 15>, <&clkc 15>; +clock-output-names = "clk_out1", "clk_out2", +"clk_out3", "clk_out4", "clk_out5", +"clk_out6", "clk_out7"; +}; +... -- 2.1.1
[PATCH v4 7/8] clk: clock-wizard: Update the fixed factor divisors
Update the fixed factor clock registration to register the divisors. Signed-off-by: Shubhrajyoti Datta --- drivers/clk/clk-xlnx-clock-wizard.c | 13 - 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/clk/clk-xlnx-clock-wizard.c b/drivers/clk/clk-xlnx-clock-wizard.c index 28bbaa0..333ada78 100644 --- a/drivers/clk/clk-xlnx-clock-wizard.c +++ b/drivers/clk/clk-xlnx-clock-wizard.c @@ -493,9 +493,11 @@ static int clk_wzrd_probe(struct platform_device *pdev) u32 reg, reg_f, mult; unsigned long rate; const char *clk_name; + void __iomem *ctrl_reg; struct clk_wzrd *clk_wzrd; struct resource *mem; int outputs; + unsigned long flags = 0; struct device_node *np = pdev->dev.of_node; clk_wzrd = devm_kzalloc(&pdev->dev, sizeof(*clk_wzrd), GFP_KERNEL); @@ -567,16 +569,17 @@ static int clk_wzrd_probe(struct platform_device *pdev) } outputs = of_property_count_strings(np, "clock-output-names"); - /* register div */ - reg = (readl(clk_wzrd->base + WZRD_CLK_CFG_REG(0)) & - WZRD_DIVCLK_DIVIDE_MASK) >> WZRD_DIVCLK_DIVIDE_SHIFT; + if (outputs == 1) + flags = CLK_SET_RATE_PARENT; clk_name = kasprintf(GFP_KERNEL, "%s_mul_div", dev_name(&pdev->dev)); if (!clk_name) { ret = -ENOMEM; goto err_rm_int_clk; } - clk_wzrd->clks_internal[wzrd_clk_mul_div] = clk_register_fixed_factor + ctrl_reg = clk_wzrd->base + WZRD_CLK_CFG_REG(0); + /* register div */ + clk_wzrd->clks_internal[wzrd_clk_mul_div] = clk_register_divider (&pdev->dev, clk_name, __clk_get_name(clk_wzrd->clks_internal[wzrd_clk_mul]), flags, ctrl_reg, 0, 8, CLK_DIVIDER_ONE_BASED | @@ -601,7 +604,7 @@ static int clk_wzrd_probe(struct platform_device *pdev) if (!i) clk_wzrd->clkout[i] = clk_wzrd_register_divf (&pdev->dev, clkout_name, - clk_name, 0, + clk_name, flags, clk_wzrd->base, (WZRD_CLK_CFG_REG(2) + i * 12), WZRD_CLKOUT_DIVIDE_SHIFT, WZRD_CLKOUT_DIVIDE_WIDTH, -- 2.1.1
[PATCH v4 3/8] clk: clock-wizard: Fix kernel-doc warning
Update description for the clocking wizard structure Signed-off-by: Shubhrajyoti Datta --- drivers/clk/clk-xlnx-clock-wizard.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/clk/clk-xlnx-clock-wizard.c b/drivers/clk/clk-xlnx-clock-wizard.c index b31524a..d6577c8 100644 --- a/drivers/clk/clk-xlnx-clock-wizard.c +++ b/drivers/clk/clk-xlnx-clock-wizard.c @@ -40,7 +40,8 @@ enum clk_wzrd_int_clks { }; /** - * struct clk_wzrd: + * struct clk_wzrd - Clock wizard private data structure + * * @clk_data: Clock data * @nb:Notifier block * @base: Memory base -- 2.1.1
[PATCH v4 0/8] clk: clockwizard: Driver updates
Greg suggested that we move the driver to the clk from the staging. Add patches to address the concerns regarding the fractional and set rate support in the TODO. The patch set does the following - Trivial fixes for kernel doc. - Move the driver to the clk folder - Add capability to set rate. - Add fractional support. - Add support for configurable outputs. Changes in the v3: Added the cover-letter. Add patches for rate setting and fractional support Add patches for warning. Remove the driver from staging as suggested v4: Reorder the patches. Merge the CLK_IS_BASIC patch. Add the yaml form of binding document Shubhrajyoti Datta (8): dt-bindings: add documentation of xilinx clocking wizard clk: clock-wizard: Add the clockwizard to clk directory clk: clock-wizard: Fix kernel-doc warning clk: clock-wizard: Add support for dynamic reconfiguration clk: clock-wizard: Add support for fractional support clk: clock-wizard: Remove the hardcoding of the clock outputs clk: clock-wizard: Update the fixed factor divisors staging: clocking-wizard: Delete the driver from the staging .../bindings/clock/xlnx,clocking-wizard.yaml | 71 +++ drivers/clk/Kconfig| 9 + drivers/clk/Makefile | 1 + drivers/clk/clk-xlnx-clock-wizard.c| 710 + drivers/staging/Kconfig| 2 - drivers/staging/Makefile | 1 - drivers/staging/clocking-wizard/Kconfig| 10 - drivers/staging/clocking-wizard/Makefile | 2 - drivers/staging/clocking-wizard/TODO | 12 - .../clocking-wizard/clk-xlnx-clock-wizard.c| 333 -- drivers/staging/clocking-wizard/dt-binding.txt | 30 - 11 files changed, 791 insertions(+), 390 deletions(-) create mode 100644 Documentation/devicetree/bindings/clock/xlnx,clocking-wizard.yaml create mode 100644 drivers/clk/clk-xlnx-clock-wizard.c delete mode 100644 drivers/staging/clocking-wizard/Kconfig delete mode 100644 drivers/staging/clocking-wizard/Makefile delete mode 100644 drivers/staging/clocking-wizard/TODO delete mode 100644 drivers/staging/clocking-wizard/clk-xlnx-clock-wizard.c delete mode 100644 drivers/staging/clocking-wizard/dt-binding.txt -- 2.1.1
[PATCH v4 5/8] clk: clock-wizard: Add support for fractional support
Currently the set rate granularity is to integral divisors. Add support for the fractional divisors. Only the first output0 is fractional in the hardware. Signed-off-by: Shubhrajyoti Datta --- drivers/clk/clk-xlnx-clock-wizard.c | 192 +--- 1 file changed, 179 insertions(+), 13 deletions(-) diff --git a/drivers/clk/clk-xlnx-clock-wizard.c b/drivers/clk/clk-xlnx-clock-wizard.c index 4b563f3..8a7f9bb 100644 --- a/drivers/clk/clk-xlnx-clock-wizard.c +++ b/drivers/clk/clk-xlnx-clock-wizard.c @@ -28,11 +28,15 @@ #define WZRD_CLKFBOUT_MULT_SHIFT 8 #define WZRD_CLKFBOUT_MULT_MASK(0xff << WZRD_CLKFBOUT_MULT_SHIFT) +#define WZRD_CLKFBOUT_FRAC_SHIFT 16 +#define WZRD_CLKFBOUT_FRAC_MASK(0x3ff << WZRD_CLKFBOUT_FRAC_SHIFT) #define WZRD_DIVCLK_DIVIDE_SHIFT 0 #define WZRD_DIVCLK_DIVIDE_MASK(0xff << WZRD_DIVCLK_DIVIDE_SHIFT) #define WZRD_CLKOUT_DIVIDE_SHIFT 0 #define WZRD_CLKOUT_DIVIDE_WIDTH 8 #define WZRD_CLKOUT_DIVIDE_MASK(0xff << WZRD_DIVCLK_DIVIDE_SHIFT) +#define WZRD_CLKOUT_FRAC_SHIFT 8 +#define WZRD_CLKOUT_FRAC_MASK 0x3ff #define WZRD_DR_MAX_INT_DIV_VALUE 255 #define WZRD_DR_NUM_RETRIES1 @@ -51,6 +55,7 @@ enum clk_wzrd_int_clks { wzrd_clk_mul, wzrd_clk_mul_div, + wzrd_clk_mul_frac, wzrd_clk_int_max }; @@ -212,6 +217,161 @@ static const struct clk_ops clk_wzrd_clk_divider_ops = { .recalc_rate = clk_wzrd_recalc_rate, }; +static unsigned long clk_wzrd_recalc_ratef(struct clk_hw *hw, + unsigned long parent_rate) +{ + unsigned int val; + u32 div, frac; + struct clk_wzrd_divider *divider = to_clk_wzrd_divider(hw); + void __iomem *div_addr = + (void __iomem *)((u64)divider->base + divider->offset); + + val = readl(div_addr); + div = val & div_mask(divider->width); + frac = (val >> WZRD_CLKOUT_FRAC_SHIFT) & WZRD_CLKOUT_FRAC_MASK; + + return ((parent_rate * 1000) / ((div * 1000) + frac)); +} + +static int clk_wzrd_dynamic_reconfig_f(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + int err = 0; + u16 retries; + u32 value, pre; + unsigned long flags = 0; + unsigned long rate_div, f, clockout0_div; + struct clk_wzrd_divider *divider = to_clk_wzrd_divider(hw); + void __iomem *div_addr = + (void __iomem *)((u64)divider->base + divider->offset); + + if (divider->lock) + spin_lock_irqsave(divider->lock, flags); + else + __acquire(divider->lock); + + rate_div = ((parent_rate * 1000) / rate); + clockout0_div = rate_div / 1000; + + pre = DIV_ROUND_CLOSEST((parent_rate * 1000), rate); + f = (u32)(pre - (clockout0_div * 1000)); + f = f & WZRD_CLKOUT_FRAC_MASK; + + value = ((f << WZRD_CLKOUT_DIVIDE_WIDTH) | (clockout0_div & + WZRD_CLKOUT_DIVIDE_MASK)); + + /* Set divisor and clear phase offset */ + writel(value, div_addr); + writel(0x0, div_addr + WZRD_DR_DIV_TO_PHASE_OFFSET); + + /* Check status register */ + retries = WZRD_DR_NUM_RETRIES; + while (retries--) { + if (readl(divider->base + WZRD_DR_STATUS_REG_OFFSET) & + WZRD_DR_LOCK_BIT_MASK) + break; + } + + if (!retries) { + err = -ETIMEDOUT; + goto err_reconfig; + } + + /* Initiate reconfiguration */ + writel(WZRD_DR_BEGIN_DYNA_RECONF, + divider->base + WZRD_DR_INIT_REG_OFFSET); + + /* Check status register */ + retries = WZRD_DR_NUM_RETRIES; + while (retries--) { + if (readl(divider->base + WZRD_DR_STATUS_REG_OFFSET) & + WZRD_DR_LOCK_BIT_MASK) + break; + } + + if (!retries) + err = -ETIMEDOUT; + +err_reconfig: + if (divider->lock) + spin_unlock_irqrestore(divider->lock, flags); + else + __release(divider->lock); + + return err; +} + +static long clk_wzrd_round_rate_f(struct clk_hw *hw, unsigned long rate, + unsigned long *prate) +{ + return rate; +} + +static const struct clk_ops clk_wzrd_clk_divider_ops_f = { + .round_rate = clk_wzrd_round_rate_f, + .set_rate = clk_wzrd_dynamic_reconfig_f, + .recalc_rate = clk_wzrd_recalc_ratef, +}; + +static struct clk *clk_wzrd_register_divf(struct device *dev, + const char *name, +
[PATCH v4 4/8] clk: clock-wizard: Add support for dynamic reconfiguration
The patch adds support for dynamic reconfiguration of clock output rate. Output clocks are registered as dividers and set rate callback function is used for dynamic reconfiguration. Based on the initial work from Chirag. Signed-off-by: Chirag Parekh Signed-off-by: Shubhrajyoti Datta --- drivers/clk/clk-xlnx-clock-wizard.c | 212 +++- 1 file changed, 206 insertions(+), 6 deletions(-) diff --git a/drivers/clk/clk-xlnx-clock-wizard.c b/drivers/clk/clk-xlnx-clock-wizard.c index d6577c8..4b563f3 100644 --- a/drivers/clk/clk-xlnx-clock-wizard.c +++ b/drivers/clk/clk-xlnx-clock-wizard.c @@ -31,8 +31,23 @@ #define WZRD_DIVCLK_DIVIDE_SHIFT 0 #define WZRD_DIVCLK_DIVIDE_MASK(0xff << WZRD_DIVCLK_DIVIDE_SHIFT) #define WZRD_CLKOUT_DIVIDE_SHIFT 0 +#define WZRD_CLKOUT_DIVIDE_WIDTH 8 #define WZRD_CLKOUT_DIVIDE_MASK(0xff << WZRD_DIVCLK_DIVIDE_SHIFT) +#define WZRD_DR_MAX_INT_DIV_VALUE 255 +#define WZRD_DR_NUM_RETRIES1 +#define WZRD_DR_STATUS_REG_OFFSET 0x04 +#define WZRD_DR_LOCK_BIT_MASK 0x0001 +#define WZRD_DR_INIT_REG_OFFSET0x25C +#define WZRD_DR_DIV_TO_PHASE_OFFSET4 +#define WZRD_DR_BEGIN_DYNA_RECONF 0x03 + +/* Get the mask from width */ +#define div_mask(width)((1 << (width)) - 1) + +/* Extract divider instance from clock hardware instance */ +#define to_clk_wzrd_divider(_hw) container_of(_hw, struct clk_wzrd_divider, hw) + enum clk_wzrd_int_clks { wzrd_clk_mul, wzrd_clk_mul_div, @@ -64,6 +79,29 @@ struct clk_wzrd { bool suspended; }; +/** + * struct clk_wzrd_divider - clock divider specific to clk_wzrd + * + * @hw:handle between common and hardware-specific interfaces + * @base: base address of register containing the divider + * @offset:offset address of register containing the divider + * @shift: shift to the divider bit field + * @width: width of the divider bit field + * @flags: clk_wzrd divider flags + * @table: array of value/divider pairs, last entry should have div = 0 + * @lock: register lock + */ +struct clk_wzrd_divider { + struct clk_hw hw; + void __iomem *base; + u16 offset; + u8 shift; + u8 width; + u8 flags; + const struct clk_div_table *table; + spinlock_t *lock; /* divider lock */ +}; + #define to_clk_wzrd(_nb) container_of(_nb, struct clk_wzrd, nb) /* maximum frequencies for input/output clocks per speed grade */ @@ -73,6 +111,164 @@ static const unsigned long clk_wzrd_max_freq[] = { 106600UL }; +/* spin lock variable for clk_wzrd */ +static DEFINE_SPINLOCK(clkwzrd_lock); + +static unsigned long clk_wzrd_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct clk_wzrd_divider *divider = to_clk_wzrd_divider(hw); + void __iomem *div_addr = + (void __iomem *)((u64)divider->base + divider->offset); + unsigned int val; + + val = readl(div_addr) >> divider->shift; + val &= div_mask(divider->width); + + return divider_recalc_rate(hw, parent_rate, val, divider->table, + divider->flags); +} + +static int clk_wzrd_dynamic_reconfig(struct clk_hw *hw, unsigned long rate, +unsigned long parent_rate) +{ + int err = 0; + u16 retries; + u32 value; + unsigned long flags = 0; + struct clk_wzrd_divider *divider = to_clk_wzrd_divider(hw); + void __iomem *div_addr = + (void __iomem *)((u64)divider->base + divider->offset); + + if (divider->lock) + spin_lock_irqsave(divider->lock, flags); + else + __acquire(divider->lock); + + value = DIV_ROUND_CLOSEST(parent_rate, rate); + + /* Cap the value to max */ + if (value > WZRD_DR_MAX_INT_DIV_VALUE) + value = WZRD_DR_MAX_INT_DIV_VALUE; + + /* Set divisor and clear phase offset */ + writel(value, div_addr); + writel(0x00, div_addr + WZRD_DR_DIV_TO_PHASE_OFFSET); + + /* Check status register */ + retries = WZRD_DR_NUM_RETRIES; + while (retries--) { + if (readl(divider->base + WZRD_DR_STATUS_REG_OFFSET) & + WZRD_DR_LOCK_BIT_MASK) + break; + } + + if (retries == 0) { + err = -ETIMEDOUT; + goto err_reconfig; + } + + /* Initiate reconfiguration */ + writel(WZRD_DR_BEGIN_DYNA_RECONF, + divider->base + WZRD_DR_INIT_REG_OFFSET); + + /* Check status register */ + retries = WZRD_DR_NUM_RETRIES; + while (retries--) { + if (readl(divider->base + WZRD_DR_STATUS_REG_OFFSET) &a
[PATCH v6 0/8] clk: clk-wizard: clock-wizard: Driver updates
In the thread [1] Greg suggested that we move the driver to the clk from the staging. Add patches to address the concerns regarding the fractional and set rate support in the TODO. The patch set does the following - Trivial fixes for kernel doc. - Move the driver to the clk folder - Add capability to set rate. - Add fractional support. - Add support for configurable outputs. - Make the output names unique so that multiple instances do not crib. Changes in the v3: Added the cover-letter. Add patches for rate setting and fractional support Add patches for warning. Remove the driver from staging as suggested v4: Reorder the patches. Merge the CLK_IS_BASIC patch. Add the yaml form of binding document v5: Fix a mismerge v6: Fix the yaml warning use poll timedout [1] https://spinics.net/lists/linux-driver-devel/msg117326.html Shubhrajyoti Datta (8): dt-bindings: add documentation of xilinx clocking wizard clk: clock-wizard: Add the clockwizard to clk directory clk: clock-wizard: Fix kernel-doc warning clk: clock-wizard: Add support for dynamic reconfiguration clk: clock-wizard: Add support for fractional support clk: clock-wizard: Remove the hardcoding of the clock outputs clk: clock-wizard: Update the fixed factor divisors staging: clocking-wizard: Delete the driver from the staging .../bindings/clock/xlnx,clocking-wizard.yaml | 71 +++ drivers/clk/Kconfig| 9 + drivers/clk/Makefile | 1 + drivers/clk/clk-xlnx-clock-wizard.c| 657 + drivers/staging/Kconfig| 2 - drivers/staging/Makefile | 1 - drivers/staging/clocking-wizard/Kconfig| 10 - drivers/staging/clocking-wizard/Makefile | 2 - drivers/staging/clocking-wizard/TODO | 12 - .../clocking-wizard/clk-xlnx-clock-wizard.c| 333 --- drivers/staging/clocking-wizard/dt-binding.txt | 30 - 11 files changed, 738 insertions(+), 390 deletions(-) create mode 100644 Documentation/devicetree/bindings/clock/xlnx,clocking-wizard.yaml create mode 100644 drivers/clk/clk-xlnx-clock-wizard.c delete mode 100644 drivers/staging/clocking-wizard/Kconfig delete mode 100644 drivers/staging/clocking-wizard/Makefile delete mode 100644 drivers/staging/clocking-wizard/TODO delete mode 100644 drivers/staging/clocking-wizard/clk-xlnx-clock-wizard.c delete mode 100644 drivers/staging/clocking-wizard/dt-binding.txt -- 2.1.1
[PATCH v6 8/8] staging: clocking-wizard: Delete the driver from the staging
Delete the driver from the staging as it is in drivers/clk. Signed-off-by: Shubhrajyoti Datta Acked-by: Greg Kroah-Hartman --- drivers/staging/Kconfig| 2 - drivers/staging/Makefile | 1 - drivers/staging/clocking-wizard/Kconfig| 10 - drivers/staging/clocking-wizard/Makefile | 2 - drivers/staging/clocking-wizard/TODO | 12 - .../clocking-wizard/clk-xlnx-clock-wizard.c| 333 - drivers/staging/clocking-wizard/dt-binding.txt | 30 -- 7 files changed, 390 deletions(-) delete mode 100644 drivers/staging/clocking-wizard/Kconfig delete mode 100644 drivers/staging/clocking-wizard/Makefile delete mode 100644 drivers/staging/clocking-wizard/TODO delete mode 100644 drivers/staging/clocking-wizard/clk-xlnx-clock-wizard.c delete mode 100644 drivers/staging/clocking-wizard/dt-binding.txt diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index e6c831c..bae49c6 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -76,8 +76,6 @@ source "drivers/staging/gs_fpgaboot/Kconfig" source "drivers/staging/unisys/Kconfig" -source "drivers/staging/clocking-wizard/Kconfig" - source "drivers/staging/fbtft/Kconfig" source "drivers/staging/fsl-dpaa2/Kconfig" diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index a3b1fd0..f5a3e57 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -28,7 +28,6 @@ obj-$(CONFIG_FIREWIRE_SERIAL) += fwserial/ obj-$(CONFIG_GOLDFISH) += goldfish/ obj-$(CONFIG_GS_FPGABOOT) += gs_fpgaboot/ obj-$(CONFIG_UNISYSSPAR) += unisys/ -obj-$(CONFIG_COMMON_CLK_XLNX_CLKWZRD) += clocking-wizard/ obj-$(CONFIG_FB_TFT) += fbtft/ obj-$(CONFIG_FSL_DPAA2)+= fsl-dpaa2/ obj-$(CONFIG_MOST) += most/ diff --git a/drivers/staging/clocking-wizard/Kconfig b/drivers/staging/clocking-wizard/Kconfig deleted file mode 100644 index 69cf514..000 --- a/drivers/staging/clocking-wizard/Kconfig +++ /dev/null @@ -1,10 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -# -# Xilinx Clocking Wizard Driver -# - -config COMMON_CLK_XLNX_CLKWZRD - tristate "Xilinx Clocking Wizard" - depends on COMMON_CLK && OF && IOMEM - help - Support for the Xilinx Clocking Wizard IP core clock generator. diff --git a/drivers/staging/clocking-wizard/Makefile b/drivers/staging/clocking-wizard/Makefile deleted file mode 100644 index b1f9152..000 --- a/drivers/staging/clocking-wizard/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -obj-$(CONFIG_COMMON_CLK_XLNX_CLKWZRD) += clk-xlnx-clock-wizard.o diff --git a/drivers/staging/clocking-wizard/TODO b/drivers/staging/clocking-wizard/TODO deleted file mode 100644 index ebe99db..000 --- a/drivers/staging/clocking-wizard/TODO +++ /dev/null @@ -1,12 +0,0 @@ -TODO: - - support for fractional multiplier - - support for fractional divider (output 0 only) - - support for set_rate() operations (may benefit from Stephen Boyd's - refactoring of the clk primitives: https://lkml.org/lkml/2014/9/5/766) - - review arithmetic - - overflow after multiplication? - - maximize accuracy before divisions - -Patches to: - Greg Kroah-Hartman - Sören Brinkmann diff --git a/drivers/staging/clocking-wizard/clk-xlnx-clock-wizard.c b/drivers/staging/clocking-wizard/clk-xlnx-clock-wizard.c deleted file mode 100644 index e52a64b..000 --- a/drivers/staging/clocking-wizard/clk-xlnx-clock-wizard.c +++ /dev/null @@ -1,333 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Xilinx 'Clocking Wizard' driver - * - * Copyright (C) 2013 - 2014 Xilinx - * - * Sören Brinkmann - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#define WZRD_NUM_OUTPUTS 7 -#define WZRD_ACLK_MAX_FREQ 25000UL - -#define WZRD_CLK_CFG_REG(n)(0x200 + 4 * (n)) - -#define WZRD_CLKOUT0_FRAC_EN BIT(18) -#define WZRD_CLKFBOUT_FRAC_EN BIT(26) - -#define WZRD_CLKFBOUT_MULT_SHIFT 8 -#define WZRD_CLKFBOUT_MULT_MASK(0xff << WZRD_CLKFBOUT_MULT_SHIFT) -#define WZRD_DIVCLK_DIVIDE_SHIFT 0 -#define WZRD_DIVCLK_DIVIDE_MASK(0xff << WZRD_DIVCLK_DIVIDE_SHIFT) -#define WZRD_CLKOUT_DIVIDE_SHIFT 0 -#define WZRD_CLKOUT_DIVIDE_MASK(0xff << WZRD_DIVCLK_DIVIDE_SHIFT) - -enum clk_wzrd_int_clks { - wzrd_clk_mul, - wzrd_clk_mul_div, - wzrd_clk_int_max -}; - -/** - * struct clk_wzrd: - * @clk_data: Clock data - * @nb:Notifier block - * @base: Memory base - * @clk_in1: Handle to input clock 'clk_in1' - * @axi_clk: Handle to input clock 's_axi_aclk' - * @clks_internal: Int
[PATCH v6 6/8] clk: clock-wizard: Remove the hardcoding of the clock outputs
The number of output clocks are configurable in the hardware. Currently the driver registers the maximum number of outputs. Fix the same by registering only the outputs that are there. Signed-off-by: Shubhrajyoti Datta --- v4: Assign output in this patch drivers/clk/clk-xlnx-clock-wizard.c | 6 -- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/clk/clk-xlnx-clock-wizard.c b/drivers/clk/clk-xlnx-clock-wizard.c index 1af59a4..ded4cdd 100644 --- a/drivers/clk/clk-xlnx-clock-wizard.c +++ b/drivers/clk/clk-xlnx-clock-wizard.c @@ -442,6 +442,7 @@ static int clk_wzrd_probe(struct platform_device *pdev) const char *clk_name; struct clk_wzrd *clk_wzrd; struct resource *mem; + int outputs; struct device_node *np = pdev->dev.of_node; clk_wzrd = devm_kzalloc(&pdev->dev, sizeof(*clk_wzrd), GFP_KERNEL); @@ -512,6 +513,7 @@ static int clk_wzrd_probe(struct platform_device *pdev) goto err_disable_clk; } + outputs = of_property_count_strings(np, "clock-output-names"); /* register div */ reg = (readl(clk_wzrd->base + WZRD_CLK_CFG_REG(0)) & WZRD_DIVCLK_DIVIDE_MASK) >> WZRD_DIVCLK_DIVIDE_SHIFT; @@ -533,7 +535,7 @@ static int clk_wzrd_probe(struct platform_device *pdev) } /* register div per output */ - for (i = WZRD_NUM_OUTPUTS - 1; i >= 0 ; i--) { + for (i = outputs - 1; i >= 0 ; i--) { const char *clkout_name; if (of_property_read_string_index(np, "clock-output-names", i, @@ -564,7 +566,7 @@ static int clk_wzrd_probe(struct platform_device *pdev) if (IS_ERR(clk_wzrd->clkout[i])) { int j; - for (j = i + 1; j < WZRD_NUM_OUTPUTS; j++) + for (j = i + 1; j < outputs; j++) clk_unregister(clk_wzrd->clkout[j]); dev_err(&pdev->dev, "unable to register divider clock\n"); -- 2.1.1
[PATCH v6 7/8] clk: clock-wizard: Update the fixed factor divisors
Update the fixed factor clock registration to register the divisors. Signed-off-by: Shubhrajyoti Datta --- drivers/clk/clk-xlnx-clock-wizard.c | 13 - 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/clk/clk-xlnx-clock-wizard.c b/drivers/clk/clk-xlnx-clock-wizard.c index ded4cdd..fd69eb0 100644 --- a/drivers/clk/clk-xlnx-clock-wizard.c +++ b/drivers/clk/clk-xlnx-clock-wizard.c @@ -440,9 +440,11 @@ static int clk_wzrd_probe(struct platform_device *pdev) u32 reg, reg_f, mult; unsigned long rate; const char *clk_name; + void __iomem *ctrl_reg; struct clk_wzrd *clk_wzrd; struct resource *mem; int outputs; + unsigned long flags = 0; struct device_node *np = pdev->dev.of_node; clk_wzrd = devm_kzalloc(&pdev->dev, sizeof(*clk_wzrd), GFP_KERNEL); @@ -514,16 +516,17 @@ static int clk_wzrd_probe(struct platform_device *pdev) } outputs = of_property_count_strings(np, "clock-output-names"); - /* register div */ - reg = (readl(clk_wzrd->base + WZRD_CLK_CFG_REG(0)) & - WZRD_DIVCLK_DIVIDE_MASK) >> WZRD_DIVCLK_DIVIDE_SHIFT; + if (outputs == 1) + flags = CLK_SET_RATE_PARENT; clk_name = kasprintf(GFP_KERNEL, "%s_mul_div", dev_name(&pdev->dev)); if (!clk_name) { ret = -ENOMEM; goto err_rm_int_clk; } - clk_wzrd->clks_internal[wzrd_clk_mul_div] = clk_register_fixed_factor + ctrl_reg = clk_wzrd->base + WZRD_CLK_CFG_REG(0); + /* register div */ + clk_wzrd->clks_internal[wzrd_clk_mul_div] = clk_register_divider (&pdev->dev, clk_name, __clk_get_name(clk_wzrd->clks_internal[wzrd_clk_mul]), flags, ctrl_reg, 0, 8, CLK_DIVIDER_ONE_BASED | @@ -548,7 +551,7 @@ static int clk_wzrd_probe(struct platform_device *pdev) if (!i) clk_wzrd->clkout[i] = clk_wzrd_register_divf (&pdev->dev, clkout_name, - clk_name, 0, + clk_name, flags, clk_wzrd->base, (WZRD_CLK_CFG_REG(2) + i * 12), WZRD_CLKOUT_DIVIDE_SHIFT, WZRD_CLKOUT_DIVIDE_WIDTH, -- 2.1.1
[PATCH v6 1/8] dt-bindings: add documentation of xilinx clocking wizard
Add the devicetree binding for the xilinx clocking wizard. Signed-off-by: Shubhrajyoti Datta --- v6: Fix a yaml warning .../bindings/clock/xlnx,clocking-wizard.yaml | 71 ++ 1 file changed, 71 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/xlnx,clocking-wizard.yaml diff --git a/Documentation/devicetree/bindings/clock/xlnx,clocking-wizard.yaml b/Documentation/devicetree/bindings/clock/xlnx,clocking-wizard.yaml new file mode 100644 index 000..ca63593 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/xlnx,clocking-wizard.yaml @@ -0,0 +1,71 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/xlnx,clocking-wizard.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Xilinx clocking wizard + +maintainers: + - Shubhrajyoti Datta + +description: | + The clocking wizard is a soft ip clocking block of Xilinx versal. It + reads required input clock frequencies from the devicetree and acts as clock + clock output. + +select: false + +properties: + compatible: +items: + - enum: + - xlnx,clocking-wizard + - xlnx,clocking-wizard-6.0 + + "#clock-cells": +const: 1 + + clocks: +description: List of clock specifiers which are external input + clocks to the given clock controller. +items: + - description: clock input + - description: axi clock + + clock-names: +items: + - const: clk_in1 + - const: s_axi_aclk + + speed-grade: +allOf: + - $ref: /schemas/types.yaml#/definitions/uint32 + - enum: [1, 2, 3] +description: + Speed grade of the device. +maxItems: 1 + +required: + - compatible + - "#clock-cells" + - clocks + - clock-names + - speed-grade + +additionalProperties: false + +examples: + - | +clock-generator@4004 { +#clock-cells = <1>; +reg = <0x4004 0x1000>; +compatible = "xlnx,clk-wizard-1.0"; +speed-grade = <1>; +clock-names = "clk_in1", "s_axi_aclk"; +clocks = <&clkc 15>, <&clkc 15>; +clock-output-names = "clk_out1", "clk_out2", +"clk_out3", "clk_out4", "clk_out5", +"clk_out6", "clk_out7"; +}; +... -- 2.1.1
[PATCH v6 4/8] clk: clock-wizard: Add support for dynamic reconfiguration
The patch adds support for dynamic reconfiguration of clock output rate. Output clocks are registered as dividers and set rate callback function is used for dynamic reconfiguration. Based on the initial work from Chirag. Signed-off-by: Chirag Parekh Signed-off-by: Shubhrajyoti Datta --- v6: Remove the typecast. use min for capping frequency. use polled timeout drivers/clk/clk-xlnx-clock-wizard.c | 185 ++-- 1 file changed, 179 insertions(+), 6 deletions(-) diff --git a/drivers/clk/clk-xlnx-clock-wizard.c b/drivers/clk/clk-xlnx-clock-wizard.c index d6577c8..8dfcec8 100644 --- a/drivers/clk/clk-xlnx-clock-wizard.c +++ b/drivers/clk/clk-xlnx-clock-wizard.c @@ -17,6 +17,7 @@ #include #include #include +#include #define WZRD_NUM_OUTPUTS 7 #define WZRD_ACLK_MAX_FREQ 25000UL @@ -31,8 +32,23 @@ #define WZRD_DIVCLK_DIVIDE_SHIFT 0 #define WZRD_DIVCLK_DIVIDE_MASK(0xff << WZRD_DIVCLK_DIVIDE_SHIFT) #define WZRD_CLKOUT_DIVIDE_SHIFT 0 +#define WZRD_CLKOUT_DIVIDE_WIDTH 8 #define WZRD_CLKOUT_DIVIDE_MASK(0xff << WZRD_DIVCLK_DIVIDE_SHIFT) +#define WZRD_DR_MAX_INT_DIV_VALUE 255 +#define WZRD_DR_NUM_RETRIES1 +#define WZRD_DR_STATUS_REG_OFFSET 0x04 +#define WZRD_DR_LOCK_BIT_MASK 0x0001 +#define WZRD_DR_INIT_REG_OFFSET0x25C +#define WZRD_DR_DIV_TO_PHASE_OFFSET4 +#define WZRD_DR_BEGIN_DYNA_RECONF 0x03 + +/* Get the mask from width */ +#define div_mask(width)((1 << (width)) - 1) + +/* Extract divider instance from clock hardware instance */ +#define to_clk_wzrd_divider(_hw) container_of(_hw, struct clk_wzrd_divider, hw) + enum clk_wzrd_int_clks { wzrd_clk_mul, wzrd_clk_mul_div, @@ -64,6 +80,29 @@ struct clk_wzrd { bool suspended; }; +/** + * struct clk_wzrd_divider - clock divider specific to clk_wzrd + * + * @hw:handle between common and hardware-specific interfaces + * @base: base address of register containing the divider + * @offset:offset address of register containing the divider + * @shift: shift to the divider bit field + * @width: width of the divider bit field + * @flags: clk_wzrd divider flags + * @table: array of value/divider pairs, last entry should have div = 0 + * @lock: register lock + */ +struct clk_wzrd_divider { + struct clk_hw hw; + void __iomem *base; + u16 offset; + u8 shift; + u8 width; + u8 flags; + const struct clk_div_table *table; + spinlock_t *lock; /* divider lock */ +}; + #define to_clk_wzrd(_nb) container_of(_nb, struct clk_wzrd, nb) /* maximum frequencies for input/output clocks per speed grade */ @@ -73,6 +112,136 @@ static const unsigned long clk_wzrd_max_freq[] = { 106600UL }; +/* spin lock variable for clk_wzrd */ +static DEFINE_SPINLOCK(clkwzrd_lock); + +static unsigned long clk_wzrd_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct clk_wzrd_divider *divider = to_clk_wzrd_divider(hw); + void __iomem *div_addr = divider->base + divider->offset; + unsigned int val; + + val = readl(div_addr) >> divider->shift; + val &= div_mask(divider->width); + + return divider_recalc_rate(hw, parent_rate, val, divider->table, + divider->flags, divider->width); +} + +static int clk_wzrd_dynamic_reconfig(struct clk_hw *hw, unsigned long rate, +unsigned long parent_rate) +{ + int err = 0; + u32 value; + struct clk_wzrd_divider *divider = to_clk_wzrd_divider(hw); + void __iomem *div_addr = divider->base + divider->offset; + + value = DIV_ROUND_CLOSEST(parent_rate, rate); + + /* Cap the value to max */ + min(value, (u32)WZRD_DR_MAX_INT_DIV_VALUE); + + /* Set divisor and clear phase offset */ + writel(value, div_addr); + writel(0x00, div_addr + WZRD_DR_DIV_TO_PHASE_OFFSET); + + /* Check status register */ + err = readl_poll_timeout(divider->base + WZRD_DR_STATUS_REG_OFFSET, value, + value & WZRD_DR_LOCK_BIT_MASK, + WZRD_USEC_POLL, WZRD_TIMEOUT_POLL); + if (err) + return err; + + /* Initiate reconfiguration */ + writel(WZRD_DR_BEGIN_DYNA_RECONF, + divider->base + WZRD_DR_INIT_REG_OFFSET); + + /* Check status register */ + err = readl_poll_timeout(divider->base + WZRD_DR_STATUS_REG_OFFSET, value, + value & WZRD_DR_LOCK_BIT_MASK, + WZRD_USEC_POLL, WZRD_TIMEOUT_POLL); + + return err; +} + +static long clk_wzrd_round_rate(struct clk_hw *hw, unsigned long rate, + u
[PATCH v6 2/8] clk: clock-wizard: Add the clockwizard to clk directory
Add clocking wizard driver to clk. Signed-off-by: Shubhrajyoti Datta --- drivers/clk/Kconfig | 9 + drivers/clk/Makefile| 1 + drivers/clk/clk-xlnx-clock-wizard.c | 338 3 files changed, 348 insertions(+) create mode 100644 drivers/clk/clk-xlnx-clock-wizard.c diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index 4026fac..a0e29dd 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -359,6 +359,15 @@ config COMMON_CLK_FIXED_MMIO help Support for Memory Mapped IO Fixed clocks +config COMMON_CLK_XLNX_CLKWZRD + tristate "Xilinx Clocking Wizard" + depends on COMMON_CLK && OF + help + Support for the Xilinx Clocking Wizard IP core clock generator. + Adds support for clocking wizard and compatible. + This driver supports the Xilinx clocking wizard programmable clock + synthesizer. The number of output is configurable in the design. + source "drivers/clk/actions/Kconfig" source "drivers/clk/analogbits/Kconfig" source "drivers/clk/baikal-t1/Kconfig" diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index da8fcf1..1ad6414 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -69,6 +69,7 @@ obj-$(CONFIG_ARCH_VT8500) += clk-vt8500.o obj-$(CONFIG_COMMON_CLK_VC5) += clk-versaclock5.o obj-$(CONFIG_COMMON_CLK_WM831X)+= clk-wm831x.o obj-$(CONFIG_COMMON_CLK_XGENE) += clk-xgene.o +obj-$(CONFIG_COMMON_CLK_XLNX_CLKWZRD) += clk-xlnx-clock-wizard.o # please keep this section sorted lexicographically by directory path name obj-y += actions/ diff --git a/drivers/clk/clk-xlnx-clock-wizard.c b/drivers/clk/clk-xlnx-clock-wizard.c new file mode 100644 index 000..b31524a --- /dev/null +++ b/drivers/clk/clk-xlnx-clock-wizard.c @@ -0,0 +1,338 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Xilinx 'Clocking Wizard' driver + * + * Copyright (C) 2013 - 2020 Xilinx + * + * Sören Brinkmann + * Shubhrajyoti Datta + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define WZRD_NUM_OUTPUTS 7 +#define WZRD_ACLK_MAX_FREQ 25000UL + +#define WZRD_CLK_CFG_REG(n)(0x200 + 4 * (n)) + +#define WZRD_CLKOUT0_FRAC_EN BIT(18) +#define WZRD_CLKFBOUT_FRAC_EN BIT(26) + +#define WZRD_CLKFBOUT_MULT_SHIFT 8 +#define WZRD_CLKFBOUT_MULT_MASK(0xff << WZRD_CLKFBOUT_MULT_SHIFT) +#define WZRD_DIVCLK_DIVIDE_SHIFT 0 +#define WZRD_DIVCLK_DIVIDE_MASK(0xff << WZRD_DIVCLK_DIVIDE_SHIFT) +#define WZRD_CLKOUT_DIVIDE_SHIFT 0 +#define WZRD_CLKOUT_DIVIDE_MASK(0xff << WZRD_DIVCLK_DIVIDE_SHIFT) + +enum clk_wzrd_int_clks { + wzrd_clk_mul, + wzrd_clk_mul_div, + wzrd_clk_int_max +}; + +/** + * struct clk_wzrd: + * @clk_data: Clock data + * @nb:Notifier block + * @base: Memory base + * @clk_in1: Handle to input clock 'clk_in1' + * @axi_clk: Handle to input clock 's_axi_aclk' + * @clks_internal: Internal clocks + * @clkout:Output clocks + * @speed_grade: Speed grade of the device + * @suspended: Flag indicating power state of the device + */ +struct clk_wzrd { + struct clk_onecell_data clk_data; + struct notifier_block nb; + void __iomem *base; + struct clk *clk_in1; + struct clk *axi_clk; + struct clk *clks_internal[wzrd_clk_int_max]; + struct clk *clkout[WZRD_NUM_OUTPUTS]; + unsigned int speed_grade; + bool suspended; +}; + +#define to_clk_wzrd(_nb) container_of(_nb, struct clk_wzrd, nb) + +/* maximum frequencies for input/output clocks per speed grade */ +static const unsigned long clk_wzrd_max_freq[] = { + 8UL, + 93300UL, + 106600UL +}; + +static int clk_wzrd_clk_notifier(struct notifier_block *nb, unsigned long event, +void *data) +{ + unsigned long max; + struct clk_notifier_data *ndata = data; + struct clk_wzrd *clk_wzrd = to_clk_wzrd(nb); + + if (clk_wzrd->suspended) + return NOTIFY_OK; + + if (ndata->clk == clk_wzrd->clk_in1) + max = clk_wzrd_max_freq[clk_wzrd->speed_grade - 1]; + else if (ndata->clk == clk_wzrd->axi_clk) + max = WZRD_ACLK_MAX_FREQ; + else + return NOTIFY_DONE; /* should never happen */ + + switch (event) { + case PRE_RATE_CHANGE: + if (ndata->new_rate > max) + return NOTIFY_BAD; + return NOTIFY_OK; + case POST_RATE_CHANGE: + case ABORT_RATE_CHANGE: + default: + return NOTIFY_DONE; + } +} + +s
[PATCH v6 3/8] clk: clock-wizard: Fix kernel-doc warning
Update description for the clocking wizard structure Signed-off-by: Shubhrajyoti Datta --- drivers/clk/clk-xlnx-clock-wizard.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/clk/clk-xlnx-clock-wizard.c b/drivers/clk/clk-xlnx-clock-wizard.c index b31524a..d6577c8 100644 --- a/drivers/clk/clk-xlnx-clock-wizard.c +++ b/drivers/clk/clk-xlnx-clock-wizard.c @@ -40,7 +40,8 @@ enum clk_wzrd_int_clks { }; /** - * struct clk_wzrd: + * struct clk_wzrd - Clock wizard private data structure + * * @clk_data: Clock data * @nb:Notifier block * @base: Memory base -- 2.1.1
[PATCH v6 5/8] clk: clock-wizard: Add support for fractional support
Currently the set rate granularity is to integral divisors. Add support for the fractional divisors. Only the first output0 is fractional in the hardware. Signed-off-by: Shubhrajyoti Datta --- v6: remove unnecessary typecast remove unnecessary locks use polled timeout drivers/clk/clk-xlnx-clock-wizard.c | 166 +--- 1 file changed, 153 insertions(+), 13 deletions(-) diff --git a/drivers/clk/clk-xlnx-clock-wizard.c b/drivers/clk/clk-xlnx-clock-wizard.c index 8dfcec8..1af59a4 100644 --- a/drivers/clk/clk-xlnx-clock-wizard.c +++ b/drivers/clk/clk-xlnx-clock-wizard.c @@ -29,20 +29,25 @@ #define WZRD_CLKFBOUT_MULT_SHIFT 8 #define WZRD_CLKFBOUT_MULT_MASK(0xff << WZRD_CLKFBOUT_MULT_SHIFT) +#define WZRD_CLKFBOUT_FRAC_SHIFT 16 +#define WZRD_CLKFBOUT_FRAC_MASK(0x3ff << WZRD_CLKFBOUT_FRAC_SHIFT) #define WZRD_DIVCLK_DIVIDE_SHIFT 0 #define WZRD_DIVCLK_DIVIDE_MASK(0xff << WZRD_DIVCLK_DIVIDE_SHIFT) #define WZRD_CLKOUT_DIVIDE_SHIFT 0 #define WZRD_CLKOUT_DIVIDE_WIDTH 8 #define WZRD_CLKOUT_DIVIDE_MASK(0xff << WZRD_DIVCLK_DIVIDE_SHIFT) +#define WZRD_CLKOUT_FRAC_SHIFT 8 +#define WZRD_CLKOUT_FRAC_MASK 0x3ff #define WZRD_DR_MAX_INT_DIV_VALUE 255 -#define WZRD_DR_NUM_RETRIES1 #define WZRD_DR_STATUS_REG_OFFSET 0x04 #define WZRD_DR_LOCK_BIT_MASK 0x0001 #define WZRD_DR_INIT_REG_OFFSET0x25C #define WZRD_DR_DIV_TO_PHASE_OFFSET4 #define WZRD_DR_BEGIN_DYNA_RECONF 0x03 +#define WZRD_USEC_POLL 10 +#define WZRD_TIMEOUT_POLL 1000 /* Get the mask from width */ #define div_mask(width)((1 << (width)) - 1) @@ -52,6 +57,7 @@ enum clk_wzrd_int_clks { wzrd_clk_mul, wzrd_clk_mul_div, + wzrd_clk_mul_frac, wzrd_clk_int_max }; @@ -185,6 +191,134 @@ static const struct clk_ops clk_wzrd_clk_divider_ops = { .recalc_rate = clk_wzrd_recalc_rate, }; +static unsigned long clk_wzrd_recalc_ratef(struct clk_hw *hw, + unsigned long parent_rate) +{ + unsigned int val; + u32 div, frac; + struct clk_wzrd_divider *divider = to_clk_wzrd_divider(hw); + void __iomem *div_addr = divider->base + divider->offset; + + val = readl(div_addr); + div = val & div_mask(divider->width); + frac = (val >> WZRD_CLKOUT_FRAC_SHIFT) & WZRD_CLKOUT_FRAC_MASK; + + return ((parent_rate * 1000) / ((div * 1000) + frac)); +} + +static int clk_wzrd_dynamic_reconfig_f(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + int err; + u32 value, pre; + unsigned long rate_div, f, clockout0_div; + struct clk_wzrd_divider *divider = to_clk_wzrd_divider(hw); + void __iomem *div_addr = divider->base + divider->offset; + + rate_div = ((parent_rate * 1000) / rate); + clockout0_div = rate_div / 1000; + + pre = DIV_ROUND_CLOSEST((parent_rate * 1000), rate); + f = (u32)(pre - (clockout0_div * 1000)); + f = f & WZRD_CLKOUT_FRAC_MASK; + + value = ((f << WZRD_CLKOUT_DIVIDE_WIDTH) | (clockout0_div & + WZRD_CLKOUT_DIVIDE_MASK)); + + /* Set divisor and clear phase offset */ + writel(value, div_addr); + writel(0x0, div_addr + WZRD_DR_DIV_TO_PHASE_OFFSET); + + /* Check status register */ + err= readl_poll_timeout(divider->base + WZRD_DR_STATUS_REG_OFFSET, value, + value & WZRD_DR_LOCK_BIT_MASK, + WZRD_USEC_POLL, WZRD_TIMEOUT_POLL); + if (err) + return err; + + /* Initiate reconfiguration */ + writel(WZRD_DR_BEGIN_DYNA_RECONF, + divider->base + WZRD_DR_INIT_REG_OFFSET); + + /* Check status register */ + err= readl_poll_timeout(divider->base + WZRD_DR_STATUS_REG_OFFSET, value, + value & WZRD_DR_LOCK_BIT_MASK, + WZRD_USEC_POLL, WZRD_TIMEOUT_POLL); + + return err; +} + +static long clk_wzrd_round_rate_f(struct clk_hw *hw, unsigned long rate, + unsigned long *prate) +{ + return rate; +} + +static const struct clk_ops clk_wzrd_clk_divider_ops_f = { + .round_rate = clk_wzrd_round_rate_f, + .set_rate = clk_wzrd_dynamic_reconfig_f, + .recalc_rate = clk_wzrd_recalc_ratef, +}; + +static struct clk *clk_wzrd_register_divf(struct device *dev, + const char *name, + const char *parent_name, + unsigned long flags, + void __iomem *base, u16 offset, +
RE: [PATCH v6 2/8] clk: clock-wizard: Add the clockwizard to clk directory
Hi Stephen, Thanks for the review. > -Original Message- > From: Stephen Boyd > Sent: Tuesday, September 22, 2020 2:52 AM > To: Shubhrajyoti Datta ; linux-...@vger.kernel.org > Cc: devicet...@vger.kernel.org; linux-kernel@vger.kernel.org; > de...@driverdev.osuosl.org; robh...@kernel.org; > gre...@linuxfoundation.org; mturque...@baylibre.com; Shubhrajyoti > Datta > Subject: Re: [PATCH v6 2/8] clk: clock-wizard: Add the clockwizard to clk > directory > > Quoting Stephen Boyd (2020-09-21 14:19:59) > > Quoting Shubhrajyoti Datta (2020-08-28 06:39:50) > > > Add clocking wizard driver to clk. > > > > > > Signed-off-by: Shubhrajyoti Datta > > > --- > > > > Can this be combined with patch #6? > > Sorry, I meant patch #8. Did not get the comment. Do you want to split the makefile and the driver parts of the patch. Or the whole of the patch to be merged. Or do you want the staging patch merged with here? [PATCH v6 8/8] staging: clocking-wizard: Delete the driver from the staging
Re: [PATCH V2 3/3] MAINTAINERS: add fragment for xilinx GPIO drivers
On Thu, Jul 23, 2020 at 7:37 PM Srinivas Neeli wrote: > > Added entry for xilinx GPIO drivers. > > Signed-off-by: Srinivas Neeli > --- Acked-by: : Shubhrajyoti Datta
RE: [PATCH v6 5/8] clk: clock-wizard: Add support for fractional support
Hi , Thanks for the review. > -Original Message- > From: Stephen Boyd > Sent: Tuesday, September 22, 2020 2:48 AM > To: Shubhrajyoti Datta ; linux-...@vger.kernel.org > Cc: devicet...@vger.kernel.org; linux-kernel@vger.kernel.org; > de...@driverdev.osuosl.org; robh...@kernel.org; > gre...@linuxfoundation.org; mturque...@baylibre.com; Shubhrajyoti > Datta > Subject: Re: [PATCH v6 5/8] clk: clock-wizard: Add support for fractional > support > > Quoting Shubhrajyoti Datta (2020-08-28 06:39:53) > > Currently the set rate granularity is to integral divisors. > > Add support for the fractional divisors. > > Only the first output0 is fractional in the hardware. > > > > Signed-off-by: Shubhrajyoti Datta > > Getting closer. > > > diff --git a/drivers/clk/clk-xlnx-clock-wizard.c > > b/drivers/clk/clk-xlnx-clock-wizard.c > > index 8dfcec8..1af59a4 100644 > > --- a/drivers/clk/clk-xlnx-clock-wizard.c > > +++ b/drivers/clk/clk-xlnx-clock-wizard.c > > @@ -185,6 +191,134 @@ static const struct clk_ops > clk_wzrd_clk_divider_ops = { > > .recalc_rate = clk_wzrd_recalc_rate, }; > > > > +static unsigned long clk_wzrd_recalc_ratef(struct clk_hw *hw, > > + unsigned long parent_rate) > > +{ > > + unsigned int val; > > + u32 div, frac; > > + struct clk_wzrd_divider *divider = to_clk_wzrd_divider(hw); > > + void __iomem *div_addr = divider->base + divider->offset; > > + > > + val = readl(div_addr); > > + div = val & div_mask(divider->width); > > + frac = (val >> WZRD_CLKOUT_FRAC_SHIFT) & > > + WZRD_CLKOUT_FRAC_MASK; > > + > > + return ((parent_rate * 1000) / ((div * 1000) + frac)); > > Please remove extra parenthesis. And is this mult_frac()? > Will fix > > +} > > + > > +static int clk_wzrd_dynamic_reconfig_f(struct clk_hw *hw, unsigned long > rate, > > + unsigned long parent_rate) { > > + int err; > > + u32 value, pre; > > + unsigned long rate_div, f, clockout0_div; > > + struct clk_wzrd_divider *divider = to_clk_wzrd_divider(hw); > > + void __iomem *div_addr = divider->base + divider->offset; > > + > > + rate_div = ((parent_rate * 1000) / rate); > > + clockout0_div = rate_div / 1000; > > + > > + pre = DIV_ROUND_CLOSEST((parent_rate * 1000), rate); > > + f = (u32)(pre - (clockout0_div * 1000)); > > + f = f & WZRD_CLKOUT_FRAC_MASK; > > + > > + value = ((f << WZRD_CLKOUT_DIVIDE_WIDTH) | (clockout0_div & > > + WZRD_CLKOUT_DIVIDE_MASK)); > > Please split this to multiple lines. Will fix > > > + > > + /* Set divisor and clear phase offset */ > > + writel(value, div_addr); > > + writel(0x0, div_addr + WZRD_DR_DIV_TO_PHASE_OFFSET); > > + > > + /* Check status register */ > > + err= readl_poll_timeout(divider->base + > WZRD_DR_STATUS_REG_OFFSET, value, > > + value & WZRD_DR_LOCK_BIT_MASK, > > + WZRD_USEC_POLL, WZRD_TIMEOUT_POLL); > > + if (err) > > + return err; > > + > > + /* Initiate reconfiguration */ > > + writel(WZRD_DR_BEGIN_DYNA_RECONF, > > + divider->base + WZRD_DR_INIT_REG_OFFSET); > > + > > + /* Check status register */ > > + err= readl_poll_timeout(divider->base + > WZRD_DR_STATUS_REG_OFFSET, value, > > + value & WZRD_DR_LOCK_BIT_MASK, > > + WZRD_USEC_POLL, WZRD_TIMEOUT_POLL); > > + > > + return err; > > Just return readl_poll_timeout() please. Will fix > > > +} > > + > > +static long clk_wzrd_round_rate_f(struct clk_hw *hw, unsigned long > rate, > > + unsigned long *prate) { > > + return rate; > > Can every rate be supported? This function is supposed to tell the clk > framework what rate will be achieved if we call clk_set_rate() with 'rate' > passed to this function. Almost always returning 'rate' is not the case. > We can support rate upto 3 decimal places to prevent truncation here we are Returning rate. > > > > + > > +static const struct clk_ops clk_wzrd_clk_divider_ops_f = { > > + .round_rate = clk_wzrd_round_rate_f, > > + .set_rate
Re: [PATCH] serial-uartlite: Fix null-ptr-deref in ulite_exit
Hi YueHaibing, Thanks for the patch. On Thu, May 16, 2019 at 9:42 AM YueHaibing wrote: > > If ulite_probe is not called or failed to registed s/registed/register > uart_register_driver, unload the module will call > uart_unregister_driver, which will tigger NULL s/tigger/trigger > pointer dereference like this: > > BUG: KASAN: null-ptr-deref in tty_unregister_driver+0x19/0x100 > Read of size 4 at addr 0034 by task syz-executor.0/4246 > > CPU: 0 PID: 4246 Comm: syz-executor.0 Tainted: G C5.1.0+ #26 > Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.10.2-1ubuntu1 > 04/01/2014 > Call Trace: > dump_stack+0xa9/0x10e > ? tty_unregister_driver+0x19/0x100 > ? tty_unregister_driver+0x19/0x100 > __kasan_report+0x171/0x18d > ? tty_unregister_driver+0x19/0x100 > kasan_report+0xe/0x20 > tty_unregister_driver+0x19/0x100 > uart_unregister_driver+0x30/0xc0 > __x64_sys_delete_module+0x244/0x330 > ? __ia32_sys_delete_module+0x330/0x330 > ? __x64_sys_clock_gettime+0xe3/0x160 > ? trace_hardirqs_on_thunk+0x1a/0x1c > ? trace_hardirqs_off_caller+0x3e/0x130 > ? lockdep_hardirqs_off+0xb5/0x100 > ? mark_held_locks+0x1a/0x90 > ? do_syscall_64+0x14/0x2a0 > do_syscall_64+0x72/0x2a0 > entry_SYSCALL_64_after_hwframe+0x49/0xbe > > This patch fix this by moving uart_unregister_driver > to ulite_remove. > Reviewed-by: Shubhrajyoti Datta > Reported-by: Hulk Robot > Fixes: 415b43bdb008 ("tty: serial: uartlite: Move uart register to probe") > Signed-off-by: YueHaibing > --- > drivers/tty/serial/uartlite.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/drivers/tty/serial/uartlite.c b/drivers/tty/serial/uartlite.c > index b8b912b..2e49fb6 100644 > --- a/drivers/tty/serial/uartlite.c > +++ b/drivers/tty/serial/uartlite.c > @@ -867,6 +867,7 @@ static int ulite_remove(struct platform_device *pdev) > pm_runtime_disable(&pdev->dev); > pm_runtime_set_suspended(&pdev->dev); > pm_runtime_dont_use_autosuspend(&pdev->dev); > + uart_unregister_driver(&ulite_uart_driver); > return rc; > } > > @@ -897,7 +898,6 @@ static int __init ulite_init(void) > static void __exit ulite_exit(void) > { > platform_driver_unregister(&ulite_platform_driver); > - uart_unregister_driver(&ulite_uart_driver); > } > > module_init(ulite_init); > -- > 1.8.3.1 > >
[PATCH v4 0/8] clk: clockwizard: Driver updates
Greg suggested that we move the driver to the clk from the staging. Add patches to address the concerns regarding the fractional and set rate support in the TODO. The patch set does the following - Trivial fixes for kernel doc. - Move the driver to the clk folder - Add capability to set rate. - Add fractional support. - Add support for configurable outputs. Changes in the v3: Added the cover-letter. Add patches for rate setting and fractional support Add patches for warning. Remove the driver from staging as suggested v4: Reorder the patches. Merge the CLK_IS_BASIC patch. Add the yaml form of binding document v5: Fix a mismerge Shubhrajyoti Datta (8): dt-bindings: add documentation of xilinx clocking wizard clk: clock-wizard: Add the clockwizard to clk directory clk: clock-wizard: Fix kernel-doc warning clk: clock-wizard: Add support for dynamic reconfiguration clk: clock-wizard: Add support for fractional support clk: clock-wizard: Remove the hardcoding of the clock outputs clk: clock-wizard: Update the fixed factor divisors staging: clocking-wizard: Delete the driver from the staging .../bindings/clock/xlnx,clocking-wizard.yaml | 71 +++ drivers/clk/Kconfig| 9 + drivers/clk/Makefile | 1 + drivers/clk/clk-xlnx-clock-wizard.c| 710 + drivers/staging/Kconfig| 2 - drivers/staging/Makefile | 1 - drivers/staging/clocking-wizard/Kconfig| 10 - drivers/staging/clocking-wizard/Makefile | 2 - drivers/staging/clocking-wizard/TODO | 12 - .../clocking-wizard/clk-xlnx-clock-wizard.c| 333 -- drivers/staging/clocking-wizard/dt-binding.txt | 30 - 11 files changed, 791 insertions(+), 390 deletions(-) create mode 100644 Documentation/devicetree/bindings/clock/xlnx,clocking-wizard.yaml create mode 100644 drivers/clk/clk-xlnx-clock-wizard.c delete mode 100644 drivers/staging/clocking-wizard/Kconfig delete mode 100644 drivers/staging/clocking-wizard/Makefile delete mode 100644 drivers/staging/clocking-wizard/TODO delete mode 100644 drivers/staging/clocking-wizard/clk-xlnx-clock-wizard.c delete mode 100644 drivers/staging/clocking-wizard/dt-binding.txt -- 2.1.1
[PATCH v5 1/8] dt-bindings: add documentation of xilinx clocking wizard
Add the devicetree binding for the xilinx clocking wizard. Signed-off-by: Shubhrajyoti Datta --- v4: change to yaml format .../bindings/clock/xlnx,clocking-wizard.yaml | 71 ++ 1 file changed, 71 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/xlnx,clocking-wizard.yaml diff --git a/Documentation/devicetree/bindings/clock/xlnx,clocking-wizard.yaml b/Documentation/devicetree/bindings/clock/xlnx,clocking-wizard.yaml new file mode 100644 index 000..5a8e991 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/xlnx,clocking-wizard.yaml @@ -0,0 +1,71 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/xlnx,clocking-wiz.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Xilinx clocking wizard + +maintainers: + - Shubhrajyoti Datta + +description: | + The clocking wizard is a soft ip clocking block of Xilinx versal. It + reads required input clock frequencies from the devicetree and acts as clock + clock output. + +select: false + +properties: + compatible: +items: + - enum: + - xlnx,clocking-wizard + - xlnx,clocking-wizard-6.0 + + "#clock-cells": +const: 1 + + clocks: +description: List of clock specifiers which are external input + clocks to the given clock controller. +items: + - description: clock input + - description: axi clock + + clock-names: +items: + - const: clk_in1 + - const: s_axi_aclk + + speed-grade: +allOf: + - $ref: /schemas/types.yaml#/definitions/uint32 + - enum: [1, 2, 3] +description: + Speed grade of the device. +maxItems: 1 + +required: + - compatible + - "#clock-cells" + - clocks + - clock-names + - speed-grade + +additionalProperties: false + +examples: + - | +clock-generator@4004 { +#clock-cells = <1>; +reg = <0x4004 0x1000>; +compatible = "xlnx,clk-wizard-1.0"; +speed-grade = <1>; +clock-names = "clk_in1", "s_axi_aclk"; +clocks = <&clkc 15>, <&clkc 15>; +clock-output-names = "clk_out1", "clk_out2", +"clk_out3", "clk_out4", "clk_out5", +"clk_out6", "clk_out7"; +}; +... -- 2.1.1
[PATCH v5 2/8] clk: clock-wizard: Add the clockwizard to clk directory
Add clocking wizard driver to clk. Signed-off-by: Shubhrajyoti Datta --- drivers/clk/Kconfig | 9 + drivers/clk/Makefile| 1 + drivers/clk/clk-xlnx-clock-wizard.c | 338 3 files changed, 348 insertions(+) create mode 100644 drivers/clk/clk-xlnx-clock-wizard.c diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index 69934c0..5f66076 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -360,6 +360,15 @@ config COMMON_CLK_FIXED_MMIO help Support for Memory Mapped IO Fixed clocks +config COMMON_CLK_XLNX_CLKWZRD + tristate "Xilinx Clocking Wizard" + depends on COMMON_CLK && OF + help + Support for the Xilinx Clocking Wizard IP core clock generator. + Adds support for clocking wizard and compatible. + This driver supports the Xilinx clocking wizard programmable clock + synthesizer. The number of output is configurable in the design. + source "drivers/clk/actions/Kconfig" source "drivers/clk/analogbits/Kconfig" source "drivers/clk/baikal-t1/Kconfig" diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index ca9af11..f41287859 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -68,6 +68,7 @@ obj-$(CONFIG_ARCH_VT8500) += clk-vt8500.o obj-$(CONFIG_COMMON_CLK_VC5) += clk-versaclock5.o obj-$(CONFIG_COMMON_CLK_WM831X)+= clk-wm831x.o obj-$(CONFIG_COMMON_CLK_XGENE) += clk-xgene.o +obj-$(CONFIG_COMMON_CLK_XLNX_CLKWZRD) += clk-xlnx-clock-wizard.o # please keep this section sorted lexicographically by directory path name obj-y += actions/ diff --git a/drivers/clk/clk-xlnx-clock-wizard.c b/drivers/clk/clk-xlnx-clock-wizard.c new file mode 100644 index 000..b31524a --- /dev/null +++ b/drivers/clk/clk-xlnx-clock-wizard.c @@ -0,0 +1,338 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Xilinx 'Clocking Wizard' driver + * + * Copyright (C) 2013 - 2020 Xilinx + * + * Sören Brinkmann + * Shubhrajyoti Datta + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define WZRD_NUM_OUTPUTS 7 +#define WZRD_ACLK_MAX_FREQ 25000UL + +#define WZRD_CLK_CFG_REG(n)(0x200 + 4 * (n)) + +#define WZRD_CLKOUT0_FRAC_EN BIT(18) +#define WZRD_CLKFBOUT_FRAC_EN BIT(26) + +#define WZRD_CLKFBOUT_MULT_SHIFT 8 +#define WZRD_CLKFBOUT_MULT_MASK(0xff << WZRD_CLKFBOUT_MULT_SHIFT) +#define WZRD_DIVCLK_DIVIDE_SHIFT 0 +#define WZRD_DIVCLK_DIVIDE_MASK(0xff << WZRD_DIVCLK_DIVIDE_SHIFT) +#define WZRD_CLKOUT_DIVIDE_SHIFT 0 +#define WZRD_CLKOUT_DIVIDE_MASK(0xff << WZRD_DIVCLK_DIVIDE_SHIFT) + +enum clk_wzrd_int_clks { + wzrd_clk_mul, + wzrd_clk_mul_div, + wzrd_clk_int_max +}; + +/** + * struct clk_wzrd: + * @clk_data: Clock data + * @nb:Notifier block + * @base: Memory base + * @clk_in1: Handle to input clock 'clk_in1' + * @axi_clk: Handle to input clock 's_axi_aclk' + * @clks_internal: Internal clocks + * @clkout:Output clocks + * @speed_grade: Speed grade of the device + * @suspended: Flag indicating power state of the device + */ +struct clk_wzrd { + struct clk_onecell_data clk_data; + struct notifier_block nb; + void __iomem *base; + struct clk *clk_in1; + struct clk *axi_clk; + struct clk *clks_internal[wzrd_clk_int_max]; + struct clk *clkout[WZRD_NUM_OUTPUTS]; + unsigned int speed_grade; + bool suspended; +}; + +#define to_clk_wzrd(_nb) container_of(_nb, struct clk_wzrd, nb) + +/* maximum frequencies for input/output clocks per speed grade */ +static const unsigned long clk_wzrd_max_freq[] = { + 8UL, + 93300UL, + 106600UL +}; + +static int clk_wzrd_clk_notifier(struct notifier_block *nb, unsigned long event, +void *data) +{ + unsigned long max; + struct clk_notifier_data *ndata = data; + struct clk_wzrd *clk_wzrd = to_clk_wzrd(nb); + + if (clk_wzrd->suspended) + return NOTIFY_OK; + + if (ndata->clk == clk_wzrd->clk_in1) + max = clk_wzrd_max_freq[clk_wzrd->speed_grade - 1]; + else if (ndata->clk == clk_wzrd->axi_clk) + max = WZRD_ACLK_MAX_FREQ; + else + return NOTIFY_DONE; /* should never happen */ + + switch (event) { + case PRE_RATE_CHANGE: + if (ndata->new_rate > max) + return NOTIFY_BAD; + return NOTIFY_OK; + case POST_RATE_CHANGE: + case ABORT_RATE_CHANGE: + default: + return NOTIFY_DONE; + } +} + +s
[PATCH v5 3/8] clk: clock-wizard: Fix kernel-doc warning
Update description for the clocking wizard structure Signed-off-by: Shubhrajyoti Datta --- drivers/clk/clk-xlnx-clock-wizard.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/clk/clk-xlnx-clock-wizard.c b/drivers/clk/clk-xlnx-clock-wizard.c index b31524a..d6577c8 100644 --- a/drivers/clk/clk-xlnx-clock-wizard.c +++ b/drivers/clk/clk-xlnx-clock-wizard.c @@ -40,7 +40,8 @@ enum clk_wzrd_int_clks { }; /** - * struct clk_wzrd: + * struct clk_wzrd - Clock wizard private data structure + * * @clk_data: Clock data * @nb:Notifier block * @base: Memory base -- 2.1.1
[PATCH v5 8/8] staging: clocking-wizard: Delete the driver from the staging
Delete the driver from the staging as it is in drivers/clk. Signed-off-by: Shubhrajyoti Datta Acked-by: Greg Kroah-Hartman --- drivers/staging/Kconfig| 2 - drivers/staging/Makefile | 1 - drivers/staging/clocking-wizard/Kconfig| 10 - drivers/staging/clocking-wizard/Makefile | 2 - drivers/staging/clocking-wizard/TODO | 12 - .../clocking-wizard/clk-xlnx-clock-wizard.c| 333 - drivers/staging/clocking-wizard/dt-binding.txt | 30 -- 7 files changed, 390 deletions(-) delete mode 100644 drivers/staging/clocking-wizard/Kconfig delete mode 100644 drivers/staging/clocking-wizard/Makefile delete mode 100644 drivers/staging/clocking-wizard/TODO delete mode 100644 drivers/staging/clocking-wizard/clk-xlnx-clock-wizard.c delete mode 100644 drivers/staging/clocking-wizard/dt-binding.txt diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index 4ec5528..cdb5422 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -78,8 +78,6 @@ source "drivers/staging/gs_fpgaboot/Kconfig" source "drivers/staging/unisys/Kconfig" -source "drivers/staging/clocking-wizard/Kconfig" - source "drivers/staging/fbtft/Kconfig" source "drivers/staging/fsl-dpaa2/Kconfig" diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index 4d34198..14570e5 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -29,7 +29,6 @@ obj-$(CONFIG_FIREWIRE_SERIAL) += fwserial/ obj-$(CONFIG_GOLDFISH) += goldfish/ obj-$(CONFIG_GS_FPGABOOT) += gs_fpgaboot/ obj-$(CONFIG_UNISYSSPAR) += unisys/ -obj-$(CONFIG_COMMON_CLK_XLNX_CLKWZRD) += clocking-wizard/ obj-$(CONFIG_FB_TFT) += fbtft/ obj-$(CONFIG_FSL_DPAA2)+= fsl-dpaa2/ obj-$(CONFIG_WILC1000) += wilc1000/ diff --git a/drivers/staging/clocking-wizard/Kconfig b/drivers/staging/clocking-wizard/Kconfig deleted file mode 100644 index 04be22d..000 --- a/drivers/staging/clocking-wizard/Kconfig +++ /dev/null @@ -1,10 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -# -# Xilinx Clocking Wizard Driver -# - -config COMMON_CLK_XLNX_CLKWZRD - tristate "Xilinx Clocking Wizard" - depends on COMMON_CLK && OF - help - Support for the Xilinx Clocking Wizard IP core clock generator. diff --git a/drivers/staging/clocking-wizard/Makefile b/drivers/staging/clocking-wizard/Makefile deleted file mode 100644 index b1f9152..000 --- a/drivers/staging/clocking-wizard/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -obj-$(CONFIG_COMMON_CLK_XLNX_CLKWZRD) += clk-xlnx-clock-wizard.o diff --git a/drivers/staging/clocking-wizard/TODO b/drivers/staging/clocking-wizard/TODO deleted file mode 100644 index ebe99db..000 --- a/drivers/staging/clocking-wizard/TODO +++ /dev/null @@ -1,12 +0,0 @@ -TODO: - - support for fractional multiplier - - support for fractional divider (output 0 only) - - support for set_rate() operations (may benefit from Stephen Boyd's - refactoring of the clk primitives: https://lkml.org/lkml/2014/9/5/766) - - review arithmetic - - overflow after multiplication? - - maximize accuracy before divisions - -Patches to: - Greg Kroah-Hartman - Sören Brinkmann diff --git a/drivers/staging/clocking-wizard/clk-xlnx-clock-wizard.c b/drivers/staging/clocking-wizard/clk-xlnx-clock-wizard.c deleted file mode 100644 index e52a64b..000 --- a/drivers/staging/clocking-wizard/clk-xlnx-clock-wizard.c +++ /dev/null @@ -1,333 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Xilinx 'Clocking Wizard' driver - * - * Copyright (C) 2013 - 2014 Xilinx - * - * Sören Brinkmann - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#define WZRD_NUM_OUTPUTS 7 -#define WZRD_ACLK_MAX_FREQ 25000UL - -#define WZRD_CLK_CFG_REG(n)(0x200 + 4 * (n)) - -#define WZRD_CLKOUT0_FRAC_EN BIT(18) -#define WZRD_CLKFBOUT_FRAC_EN BIT(26) - -#define WZRD_CLKFBOUT_MULT_SHIFT 8 -#define WZRD_CLKFBOUT_MULT_MASK(0xff << WZRD_CLKFBOUT_MULT_SHIFT) -#define WZRD_DIVCLK_DIVIDE_SHIFT 0 -#define WZRD_DIVCLK_DIVIDE_MASK(0xff << WZRD_DIVCLK_DIVIDE_SHIFT) -#define WZRD_CLKOUT_DIVIDE_SHIFT 0 -#define WZRD_CLKOUT_DIVIDE_MASK(0xff << WZRD_DIVCLK_DIVIDE_SHIFT) - -enum clk_wzrd_int_clks { - wzrd_clk_mul, - wzrd_clk_mul_div, - wzrd_clk_int_max -}; - -/** - * struct clk_wzrd: - * @clk_data: Clock data - * @nb:Notifier block - * @base: Memory base - * @clk_in1: Handle to input clock 'clk_in1' - * @axi_clk: Handle to input clock 's_axi_aclk' - * @clks_internal: Internal cl
[PATCH v5 7/8] clk: clock-wizard: Update the fixed factor divisors
Update the fixed factor clock registration to register the divisors. Signed-off-by: Shubhrajyoti Datta --- drivers/clk/clk-xlnx-clock-wizard.c | 13 - 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/clk/clk-xlnx-clock-wizard.c b/drivers/clk/clk-xlnx-clock-wizard.c index 0c57ca0..5f53bfd0 100644 --- a/drivers/clk/clk-xlnx-clock-wizard.c +++ b/drivers/clk/clk-xlnx-clock-wizard.c @@ -493,9 +493,11 @@ static int clk_wzrd_probe(struct platform_device *pdev) u32 reg, reg_f, mult; unsigned long rate; const char *clk_name; + void __iomem *ctrl_reg; struct clk_wzrd *clk_wzrd; struct resource *mem; int outputs; + unsigned long flags = 0; struct device_node *np = pdev->dev.of_node; clk_wzrd = devm_kzalloc(&pdev->dev, sizeof(*clk_wzrd), GFP_KERNEL); @@ -567,16 +569,17 @@ static int clk_wzrd_probe(struct platform_device *pdev) } outputs = of_property_count_strings(np, "clock-output-names"); - /* register div */ - reg = (readl(clk_wzrd->base + WZRD_CLK_CFG_REG(0)) & - WZRD_DIVCLK_DIVIDE_MASK) >> WZRD_DIVCLK_DIVIDE_SHIFT; + if (outputs == 1) + flags = CLK_SET_RATE_PARENT; clk_name = kasprintf(GFP_KERNEL, "%s_mul_div", dev_name(&pdev->dev)); if (!clk_name) { ret = -ENOMEM; goto err_rm_int_clk; } - clk_wzrd->clks_internal[wzrd_clk_mul_div] = clk_register_fixed_factor + ctrl_reg = clk_wzrd->base + WZRD_CLK_CFG_REG(0); + /* register div */ + clk_wzrd->clks_internal[wzrd_clk_mul_div] = clk_register_divider (&pdev->dev, clk_name, __clk_get_name(clk_wzrd->clks_internal[wzrd_clk_mul]), flags, ctrl_reg, 0, 8, CLK_DIVIDER_ONE_BASED | @@ -601,7 +604,7 @@ static int clk_wzrd_probe(struct platform_device *pdev) if (!i) clk_wzrd->clkout[i] = clk_wzrd_register_divf (&pdev->dev, clkout_name, - clk_name, 0, + clk_name, flags, clk_wzrd->base, (WZRD_CLK_CFG_REG(2) + i * 12), WZRD_CLKOUT_DIVIDE_SHIFT, WZRD_CLKOUT_DIVIDE_WIDTH, -- 2.1.1
[PATCH v5 6/8] clk: clock-wizard: Remove the hardcoding of the clock outputs
The number of output clocks are configurable in the hardware. Currently the driver registers the maximum number of outputs. Fix the same by registering only the outputs that are there. Signed-off-by: Shubhrajyoti Datta --- v4: Assign output in this patch drivers/clk/clk-xlnx-clock-wizard.c | 6 -- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/clk/clk-xlnx-clock-wizard.c b/drivers/clk/clk-xlnx-clock-wizard.c index 1cf381c..0c57ca0 100644 --- a/drivers/clk/clk-xlnx-clock-wizard.c +++ b/drivers/clk/clk-xlnx-clock-wizard.c @@ -495,6 +495,7 @@ static int clk_wzrd_probe(struct platform_device *pdev) const char *clk_name; struct clk_wzrd *clk_wzrd; struct resource *mem; + int outputs; struct device_node *np = pdev->dev.of_node; clk_wzrd = devm_kzalloc(&pdev->dev, sizeof(*clk_wzrd), GFP_KERNEL); @@ -565,6 +566,7 @@ static int clk_wzrd_probe(struct platform_device *pdev) goto err_disable_clk; } + outputs = of_property_count_strings(np, "clock-output-names"); /* register div */ reg = (readl(clk_wzrd->base + WZRD_CLK_CFG_REG(0)) & WZRD_DIVCLK_DIVIDE_MASK) >> WZRD_DIVCLK_DIVIDE_SHIFT; @@ -586,7 +588,7 @@ static int clk_wzrd_probe(struct platform_device *pdev) } /* register div per output */ - for (i = WZRD_NUM_OUTPUTS - 1; i >= 0 ; i--) { + for (i = outputs - 1; i >= 0 ; i--) { const char *clkout_name; if (of_property_read_string_index(np, "clock-output-names", i, @@ -617,7 +619,7 @@ static int clk_wzrd_probe(struct platform_device *pdev) if (IS_ERR(clk_wzrd->clkout[i])) { int j; - for (j = i + 1; j < WZRD_NUM_OUTPUTS; j++) + for (j = i + 1; j < outputs; j++) clk_unregister(clk_wzrd->clkout[j]); dev_err(&pdev->dev, "unable to register divider clock\n"); -- 2.1.1
[PATCH v5 4/8] clk: clock-wizard: Add support for dynamic reconfiguration
The patch adds support for dynamic reconfiguration of clock output rate. Output clocks are registered as dividers and set rate callback function is used for dynamic reconfiguration. Based on the initial work from Chirag. Signed-off-by: Chirag Parekh Signed-off-by: Shubhrajyoti Datta --- drivers/clk/clk-xlnx-clock-wizard.c | 212 +++- 1 file changed, 206 insertions(+), 6 deletions(-) diff --git a/drivers/clk/clk-xlnx-clock-wizard.c b/drivers/clk/clk-xlnx-clock-wizard.c index d6577c8..aaffb04 100644 --- a/drivers/clk/clk-xlnx-clock-wizard.c +++ b/drivers/clk/clk-xlnx-clock-wizard.c @@ -31,8 +31,23 @@ #define WZRD_DIVCLK_DIVIDE_SHIFT 0 #define WZRD_DIVCLK_DIVIDE_MASK(0xff << WZRD_DIVCLK_DIVIDE_SHIFT) #define WZRD_CLKOUT_DIVIDE_SHIFT 0 +#define WZRD_CLKOUT_DIVIDE_WIDTH 8 #define WZRD_CLKOUT_DIVIDE_MASK(0xff << WZRD_DIVCLK_DIVIDE_SHIFT) +#define WZRD_DR_MAX_INT_DIV_VALUE 255 +#define WZRD_DR_NUM_RETRIES1 +#define WZRD_DR_STATUS_REG_OFFSET 0x04 +#define WZRD_DR_LOCK_BIT_MASK 0x0001 +#define WZRD_DR_INIT_REG_OFFSET0x25C +#define WZRD_DR_DIV_TO_PHASE_OFFSET4 +#define WZRD_DR_BEGIN_DYNA_RECONF 0x03 + +/* Get the mask from width */ +#define div_mask(width)((1 << (width)) - 1) + +/* Extract divider instance from clock hardware instance */ +#define to_clk_wzrd_divider(_hw) container_of(_hw, struct clk_wzrd_divider, hw) + enum clk_wzrd_int_clks { wzrd_clk_mul, wzrd_clk_mul_div, @@ -64,6 +79,29 @@ struct clk_wzrd { bool suspended; }; +/** + * struct clk_wzrd_divider - clock divider specific to clk_wzrd + * + * @hw:handle between common and hardware-specific interfaces + * @base: base address of register containing the divider + * @offset:offset address of register containing the divider + * @shift: shift to the divider bit field + * @width: width of the divider bit field + * @flags: clk_wzrd divider flags + * @table: array of value/divider pairs, last entry should have div = 0 + * @lock: register lock + */ +struct clk_wzrd_divider { + struct clk_hw hw; + void __iomem *base; + u16 offset; + u8 shift; + u8 width; + u8 flags; + const struct clk_div_table *table; + spinlock_t *lock; /* divider lock */ +}; + #define to_clk_wzrd(_nb) container_of(_nb, struct clk_wzrd, nb) /* maximum frequencies for input/output clocks per speed grade */ @@ -73,6 +111,164 @@ static const unsigned long clk_wzrd_max_freq[] = { 106600UL }; +/* spin lock variable for clk_wzrd */ +static DEFINE_SPINLOCK(clkwzrd_lock); + +static unsigned long clk_wzrd_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct clk_wzrd_divider *divider = to_clk_wzrd_divider(hw); + void __iomem *div_addr = + (void __iomem *)((u64)divider->base + divider->offset); + unsigned int val; + + val = readl(div_addr) >> divider->shift; + val &= div_mask(divider->width); + + return divider_recalc_rate(hw, parent_rate, val, divider->table, + divider->flags, divider->width); +} + +static int clk_wzrd_dynamic_reconfig(struct clk_hw *hw, unsigned long rate, +unsigned long parent_rate) +{ + int err = 0; + u16 retries; + u32 value; + unsigned long flags = 0; + struct clk_wzrd_divider *divider = to_clk_wzrd_divider(hw); + void __iomem *div_addr = + (void __iomem *)((u64)divider->base + divider->offset); + + if (divider->lock) + spin_lock_irqsave(divider->lock, flags); + else + __acquire(divider->lock); + + value = DIV_ROUND_CLOSEST(parent_rate, rate); + + /* Cap the value to max */ + if (value > WZRD_DR_MAX_INT_DIV_VALUE) + value = WZRD_DR_MAX_INT_DIV_VALUE; + + /* Set divisor and clear phase offset */ + writel(value, div_addr); + writel(0x00, div_addr + WZRD_DR_DIV_TO_PHASE_OFFSET); + + /* Check status register */ + retries = WZRD_DR_NUM_RETRIES; + while (retries--) { + if (readl(divider->base + WZRD_DR_STATUS_REG_OFFSET) & + WZRD_DR_LOCK_BIT_MASK) + break; + } + + if (retries == 0) { + err = -ETIMEDOUT; + goto err_reconfig; + } + + /* Initiate reconfiguration */ + writel(WZRD_DR_BEGIN_DYNA_RECONF, + divider->base + WZRD_DR_INIT_REG_OFFSET); + + /* Check status register */ + retries = WZRD_DR_NUM_RETRIES; + while (ret
[PATCH v5 5/8] clk: clock-wizard: Add support for fractional support
Currently the set rate granularity is to integral divisors. Add support for the fractional divisors. Only the first output0 is fractional in the hardware. Signed-off-by: Shubhrajyoti Datta --- drivers/clk/clk-xlnx-clock-wizard.c | 190 +--- 1 file changed, 178 insertions(+), 12 deletions(-) diff --git a/drivers/clk/clk-xlnx-clock-wizard.c b/drivers/clk/clk-xlnx-clock-wizard.c index aaffb04..1cf381c 100644 --- a/drivers/clk/clk-xlnx-clock-wizard.c +++ b/drivers/clk/clk-xlnx-clock-wizard.c @@ -28,11 +28,15 @@ #define WZRD_CLKFBOUT_MULT_SHIFT 8 #define WZRD_CLKFBOUT_MULT_MASK(0xff << WZRD_CLKFBOUT_MULT_SHIFT) +#define WZRD_CLKFBOUT_FRAC_SHIFT 16 +#define WZRD_CLKFBOUT_FRAC_MASK(0x3ff << WZRD_CLKFBOUT_FRAC_SHIFT) #define WZRD_DIVCLK_DIVIDE_SHIFT 0 #define WZRD_DIVCLK_DIVIDE_MASK(0xff << WZRD_DIVCLK_DIVIDE_SHIFT) #define WZRD_CLKOUT_DIVIDE_SHIFT 0 #define WZRD_CLKOUT_DIVIDE_WIDTH 8 #define WZRD_CLKOUT_DIVIDE_MASK(0xff << WZRD_DIVCLK_DIVIDE_SHIFT) +#define WZRD_CLKOUT_FRAC_SHIFT 8 +#define WZRD_CLKOUT_FRAC_MASK 0x3ff #define WZRD_DR_MAX_INT_DIV_VALUE 255 #define WZRD_DR_NUM_RETRIES1 @@ -51,6 +55,7 @@ enum clk_wzrd_int_clks { wzrd_clk_mul, wzrd_clk_mul_div, + wzrd_clk_mul_frac, wzrd_clk_int_max }; @@ -212,6 +217,161 @@ static const struct clk_ops clk_wzrd_clk_divider_ops = { .recalc_rate = clk_wzrd_recalc_rate, }; +static unsigned long clk_wzrd_recalc_ratef(struct clk_hw *hw, + unsigned long parent_rate) +{ + unsigned int val; + u32 div, frac; + struct clk_wzrd_divider *divider = to_clk_wzrd_divider(hw); + void __iomem *div_addr = + (void __iomem *)((u64)divider->base + divider->offset); + + val = readl(div_addr); + div = val & div_mask(divider->width); + frac = (val >> WZRD_CLKOUT_FRAC_SHIFT) & WZRD_CLKOUT_FRAC_MASK; + + return ((parent_rate * 1000) / ((div * 1000) + frac)); +} + +static int clk_wzrd_dynamic_reconfig_f(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + int err = 0; + u16 retries; + u32 value, pre; + unsigned long flags = 0; + unsigned long rate_div, f, clockout0_div; + struct clk_wzrd_divider *divider = to_clk_wzrd_divider(hw); + void __iomem *div_addr = + (void __iomem *)((u64)divider->base + divider->offset); + + if (divider->lock) + spin_lock_irqsave(divider->lock, flags); + else + __acquire(divider->lock); + + rate_div = ((parent_rate * 1000) / rate); + clockout0_div = rate_div / 1000; + + pre = DIV_ROUND_CLOSEST((parent_rate * 1000), rate); + f = (u32)(pre - (clockout0_div * 1000)); + f = f & WZRD_CLKOUT_FRAC_MASK; + + value = ((f << WZRD_CLKOUT_DIVIDE_WIDTH) | (clockout0_div & + WZRD_CLKOUT_DIVIDE_MASK)); + + /* Set divisor and clear phase offset */ + writel(value, div_addr); + writel(0x0, div_addr + WZRD_DR_DIV_TO_PHASE_OFFSET); + + /* Check status register */ + retries = WZRD_DR_NUM_RETRIES; + while (retries--) { + if (readl(divider->base + WZRD_DR_STATUS_REG_OFFSET) & + WZRD_DR_LOCK_BIT_MASK) + break; + } + + if (!retries) { + err = -ETIMEDOUT; + goto err_reconfig; + } + + /* Initiate reconfiguration */ + writel(WZRD_DR_BEGIN_DYNA_RECONF, + divider->base + WZRD_DR_INIT_REG_OFFSET); + + /* Check status register */ + retries = WZRD_DR_NUM_RETRIES; + while (retries--) { + if (readl(divider->base + WZRD_DR_STATUS_REG_OFFSET) & + WZRD_DR_LOCK_BIT_MASK) + break; + } + + if (!retries) + err = -ETIMEDOUT; + +err_reconfig: + if (divider->lock) + spin_unlock_irqrestore(divider->lock, flags); + else + __release(divider->lock); + + return err; +} + +static long clk_wzrd_round_rate_f(struct clk_hw *hw, unsigned long rate, + unsigned long *prate) +{ + return rate; +} + +static const struct clk_ops clk_wzrd_clk_divider_ops_f = { + .round_rate = clk_wzrd_round_rate_f, + .set_rate = clk_wzrd_dynamic_reconfig_f, + .recalc_rate = clk_wzrd_recalc_ratef, +}; + +static struct clk *clk_wzrd_register_divf(struct device *dev, + const char *name, +
[PATCH] tty: xilinx_uartps: move to arch_initcall for earlier console
Signed-off-by: Shubhrajyoti Datta --- drivers/tty/serial/xilinx_uartps.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c index ff1b115..a239343 100644 --- a/drivers/tty/serial/xilinx_uartps.c +++ b/drivers/tty/serial/xilinx_uartps.c @@ -1647,7 +1647,7 @@ static void __exit cdns_uart_exit(void) uart_unregister_driver(&cdns_uart_uart_driver); } -module_init(cdns_uart_init); +arch_initcall(cdns_uart_init); module_exit(cdns_uart_exit); MODULE_DESCRIPTION("Driver for Cadence UART"); -- 2.1.1
Re: [PATCH] tty: xilinx_uartps: move to arch_initcall for earlier console
... >> >> I *guess* it is to get the console up really early, simply becaus it is >> quite helpful for spotting early boot problems. > > > ok. It means no concern about the move to arch_initcall. > Shubhrajyoti: Please send v2 with changelog. Will do thanks for the review. > > Thanks, > Michal
[PATCHv2] tty: xilinx_uartps: move to arch_initcall for earlier console
move to arch_initcall to get the console up really early, it is quite helpful for spotting early boot problems. Signed-off-by: Shubhrajyoti Datta --- drivers/tty/serial/xilinx_uartps.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c index fde55dc..96fda91 100644 --- a/drivers/tty/serial/xilinx_uartps.c +++ b/drivers/tty/serial/xilinx_uartps.c @@ -1673,7 +1673,7 @@ static void __exit cdns_uart_exit(void) uart_unregister_driver(&cdns_uart_uart_driver); } -module_init(cdns_uart_init); +arch_initcall(cdns_uart_init); module_exit(cdns_uart_exit); MODULE_DESCRIPTION("Driver for Cadence UART"); -- 2.1.1