* Re: [PATCH linux 2/6] hwmon: occ: Add sysfs interface
From: Andrew Jeffery @ 2017-01-08 23:52 UTC (permalink / raw)
To: Guenter Roeck, Edward James
Cc: corbet, devicetree, eajames.ibm, jdelvare, joel, linux-doc,
linux-hwmon, linux-i2c, linux-kernel, mark.rutland, robh+dt, wsa
In-Reply-To: <8b182766-32a0-9eb1-7917-14abf811cef5@roeck-us.net>
[-- Attachment #1: Type: text/plain, Size: 4017 bytes --]
On Sat, 2017-01-07 at 09:15 -0800, Guenter Roeck wrote:
> On 01/06/2017 02:17 PM, Edward James wrote:
>
> [ ... ]
>
> > > > +}
> > > > +
> > > > +static DEVICE_ATTR(online, S_IWUSR | S_IRUGO, show_occ_online,
> > > > + store_occ_online);
> > > > +
> > > > +struct occ_sysfs *occ_sysfs_start(struct device *dev, struct occ *occ,
> > > > + struct occ_sysfs_config *config)
> > > > +{
> > > > + struct occ_sysfs *hwmon = devm_kzalloc(dev, sizeof(struct occ_sysfs),
> > > > + GFP_KERNEL);
> > > > + int rc;
> > > > +
> > > > + if (!hwmon)
> > > > + return ERR_PTR(-ENOMEM);
> > > > +
> > > > + hwmon->occ = occ;
> > > > + hwmon->num_caps_fields = config->num_caps_fields;
> > > > + hwmon->caps_names = config->caps_names;
> > > > +
> > > > + dev_set_drvdata(dev, hwmon);
> > > > +
> > > > + rc = device_create_file(dev, &dev_attr_online);
> > > > + if (rc)
> > > > + return ERR_PTR(rc);
> > > > +
> > > > + return hwmon;
> > > > +}
> > > > +EXPORT_SYMBOL(occ_sysfs_start);
> > > > +
> > > > +int occ_sysfs_stop(struct device *dev, struct occ_sysfs *driver)
> > > > +{
> > > > + if (driver->dev) {
> > > > + occ_remove_hwmon_attrs(driver);
> > > > + hwmon_device_unregister(driver->dev);
> > > > + }
> > > > +
> > > > + device_remove_file(driver->dev, &dev_attr_online);
> > > > +
> > > > + devm_kfree(dev, driver);
> > >
> > > Thw point of using devm_ functions is not to require remove/free functions.
> > > Something is completely wrong here if you need that call.
> > >
> > > Overall, this is architectually completely wrong. One does not register
> > > or instantiate drivers based on writing into sysfs attributes. Please
> > > reconsider your approach.
> >
> > We had some trouble designing this driver because the BMC only has
> > access to the OCC once the processor is powered on. This will happen
> > sometime after the BMC boots (this driver runs only on the BMC). With
> > no access to the OCC, we don't know what sensors are present on the
> > system without a large static enumeration. Also any sysfs files created
> > before we have OCC access won't be able to return any data.
> >
> > Instead of the "online" attribute, what do you think about using the
> > "bind"/"unbind" API to probe the device from user space once the system
> > is powered on? All the hwmon registration would take place in the probe
> > function, it would just occur some time after boot.
> >
>
> A more common approach would be to have a platform driver. That platform
> driver would need a means to detect if the OCC is up and running, and
> instantiate everything else once it is.
>
> A trigger from user space is problematic because there is no guarantee
> that the OCC is really up (or that it even exists).
This is true in general, but for the BMC case we have more information:
The host CPU power supply is controlled by several GPIOs from
userspace. Once we receive the "power-good" signal for the host CPU we
can bind the OCC driver and trigger the probe.
Alternatively, in the style of your first para, we could push the host
CPU state management into the kernel and expose a boot/reboot/power-off
API to userspace. That would give us a place to hook calls for
configuring and cleaning up any host-dependent drivers on the BMC.
The solution to the host-power-state problem is also applicable to the
OpenFSI patches that were recently sent out:
https://lkml.org/lkml/2016/12/6/732
The OpenFSI infra needs to re-scan for CFAMs when the host is powered
up.
>
> An alternative might be to have the hwmon driver poll for the OCC,
> but that would be a bit more difficult and might require a kernel thread
> or maybe asynchronous probing.
This was our thought as a fallback solution.
Andrew
>
> Guenter
>
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 801 bytes --]
^ permalink raw reply
* Re: [PATCH 1/5] drivers: mmc: sunxi: fix A64 calibration routine
From: André Przywara @ 2017-01-08 23:56 UTC (permalink / raw)
To: Maxime Ripard
Cc: Ulf Hansson, Chen-Yu Tsai, Hans De Goede, Icenowy Zheng,
Mark Rutland, Rob Herring, devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-mmc-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-sunxi-/JYPxA39Uh5TLH3MbocFFw,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20170105174725.kmr25iodjnjozqjm@lukather>
On 05/01/17 17:47, Maxime Ripard wrote:
Hi,
> On Mon, Jan 02, 2017 at 11:03:42PM +0000, Andre Przywara wrote:
>> The calibration facility in the A64 MMC block seems to have been
>> misunderstood: the result value is not the value to program into the
>> delay bits, but is the number of delay cells that result in a full clock
>> cycle delay. So this value has to be scaled by the desired phase, which
>> we still have to know and program.
>> Change the calibration routine to take a phase parameter and scale the
>> calibration value accordingly.
>> Also introduce sun50i-a64 delay parameters to store the required phase.
>> Looking at the BSP kernel the sample delay for anything below HS200 is
>> 0, so we go with that value.
>> Once the driver supports HS200 and faster modes, we can enter confirmed
>> working values in there.
>>
>> Signed-off-by: Andre Przywara <andre.przywara-5wv7dgnIgG8@public.gmane.org>
>
> Exactly how that works hasn't been confirmed, and the only thing that
> this patch actually do is... nothing, since the delay is always 0. If
> and when we get HS400 to work and we know for a fact how the
> calibration works, then we'll be able to use it. Until then, we can
> just clear those bits.
Fair enough, though I am a bit puzzled as what to do here now:
Dropping this patch here entirely causes the wrong calibration settings
to degrade the BananaPi eMMC performance by up to 50% (20 MB/s vs.
40MB/s in hdparm, and 25% longer execution time for a "find / -type f |
xargs md5sum > /dev/null" run). So this is not an option.
1) Shall I simply revert Icenowy's original patch that introduced the
calibration function? That should leave the values at their reset value
of 0. But do we want to make sure that these values are set to 0 by
explicitly zeroing the bits?
Also I guess your HS-400 support will need to write some values in
there, so we will need some code later again?
2) Changing the calibration function to don't do any calibration really
and just write 0 into the delay bits seems like an option, but looks a
bit weird. Also I guess your faster transfer modes support will need to
write _something_, though I don't know what those values are and where
they will come from.
So I am leaning towards 1) for now, unless you send your MMC patches and
we at least merge the patch dealing with the calibration part for the
next release.
Any recommendations? I would love to see the MMC support go into 4.11.
Cheers,
Andre.
^ permalink raw reply
* ATTENTION !
From: Kamal Ali Mohamed @ 2017-01-09 0:03 UTC (permalink / raw)
In-Reply-To: <2061243689.1489900.1483920231155.ref@mail.yahoo.com>
Greetings to you and your families,
I never want to disturb you at all but will like you give me your attention. I need a matured and capable hand in a business deal of $8, 500, 000.00 (Eight Million Five Hundred Thousand USA Dollars).I belief you are suitable to handle such project perfectly .Please answer me.For more details.All details shall be sent to you once I hear from you.Sorry if you received this letter in your spam, Due to recent connection error here in my country.
Thanks and best regards,
Mr.Kamal Ali Mohamed.
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* RE: [PATCH 1/3] ARM: at91: flush the L2 cache before entering cpu idle
From: Wenyou.Yang-UWL1GkI3JZL3oGB3hsPCZA @ 2017-01-09 1:47 UTC (permalink / raw)
To: alexandre.belloni-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8
Cc: linux-lFZ/pmaqli7XmaaqVzeoHQ,
nicolas.ferre-AIFe0yeh4nAAvxtiuMwx3w,
robh+dt-DgEjT+Ai2ygdnm+yROfE0A, mark.rutland-5wv7dgnIgG8,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
In-Reply-To: <20170106090517.txcoukisnx43cfqq-m++hUPXGwpdeoWH0uzbU5w@public.gmane.org>
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset="gb2312", Size: 2150 bytes --]
Hi Alexandre,
> -----Original Message-----
> From: Alexandre Belloni [mailto:alexandre.belloni@free-electrons.com]
> Sent: 2017Äê1ÔÂ6ÈÕ 17:05
> To: Wenyou Yang - A41535 <Wenyou.Yang@microchip.com>
> Cc: Russell King <linux@arm.linux.org.uk>; Nicolas Ferre
> <nicolas.ferre@atmel.com>; Rob Herring <robh+dt@kernel.org>; Mark Rutland
> <mark.rutland@arm.com>; linux-kernel@vger.kernel.org; Wenyou Yang - A41535
> <Wenyou.Yang@microchip.com>; devicetree@vger.kernel.org; linux-arm-
> kernel@lists.infradead.org
> Subject: Re: [PATCH 1/3] ARM: at91: flush the L2 cache before entering cpu idle
>
> Hi,
>
> On 06/01/2017 at 14:59:45 +0800, Wenyou Yang wrote :
> > For the SoCs such as SAMA5D2 and SAMA5D4 which have L2 cache, flush
> > the L2 cache first before entering the cpu idle.
> >
> > Signed-off-by: Wenyou Yang <wenyou.yang@atmel.com>
> > ---
> >
> > arch/arm/mach-at91/pm.c | 19 +++++++++++++++++++
> > drivers/memory/atmel-sdramc.c | 1 +
> > 2 files changed, 20 insertions(+)
> >
> > diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c index
> > b4332b727e9c..1a60dede1a01 100644
> > --- a/arch/arm/mach-at91/pm.c
> > +++ b/arch/arm/mach-at91/pm.c
> > @@ -289,6 +289,24 @@ static void at91_ddr_standby(void)
> > at91_ramc_write(1, AT91_DDRSDRC_LPR, saved_lpr1); }
> >
> > +static void at91_ddr_cache_standby(void) {
> > + u32 saved_lpr;
> > +
> > + flush_cache_all();
> > + outer_disable();
> > +
> > + saved_lpr = at91_ramc_read(0, AT91_DDRSDRC_LPR);
> > + at91_ramc_write(0, AT91_DDRSDRC_LPR, (saved_lpr &
> > + (~AT91_DDRSDRC_LPCB)) |
> AT91_DDRSDRC_LPCB_SELF_REFRESH);
> > +
> > + cpu_do_idle();
> > +
> > + at91_ramc_write(0, AT91_DDRSDRC_LPR, saved_lpr);
> > +
> > + outer_resume();
> > +}
> > +
>
> Seems good to me. Did you measure the added latency on sama5d3 if you add the
> cache operations in at91_ddr_standby instead of having a new function?
No, I didn't. How to measure it?
Best Regards,
Wenyou Yang
N§²æìr¸yúèØb²X¬¶Ç§vØ^)Þº{.nÇ+·zøzÚÞz)í
æèw*\x1fjg¬±¨\x1e¶Ý¢j.ïÛ°\½½MúgjÌæa×\x02' ©Þ¢¸\f¢·¦j:+v¨wèjØm¶ÿ¾\a«êçzZ+ùÝ¢j"ú!¶i
^ permalink raw reply
* Re: [PATCH v3] iio:temperature: Add support for TI TMP007 sensor
From: Mani Sadhasivam @ 2017-01-09 2:06 UTC (permalink / raw)
To: Jonathan Cameron
Cc: pmeerw-jW+XmwGofnusTnJN9+BGXg, linux-iio-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <9efdb51f-1b15-d8b7-8c3d-777cae4c382b-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
On Sun, Jan 08, 2017 at 10:56:14AM +0000, Jonathan Cameron wrote:
> On 06/01/17 02:50, Mani Sadhasivam wrote:
> > This patch adds support for TI TMP007 - 16 bit IR thermopile sensor with integrated Math engine.
> > Sensor takes care of calculating the object temperature with the help of calibrated constants stored in non-volatile memory,
> > thereby reducing the calculation overhead.
> >
> > Signed-off-by: Manivannan Sadhasivam <manivannanece23-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> Pretty good. A few minor comments inline. It 'might' be worth using
> regmap for this part to avoid hand rolling masked partial register writes
> and caching of register values. Perhaps it's not worth it for such a
> simple interface however.
>
> Jonathan
Thanks Jonathan for your review.
> > ---
> >
> > Changes in v3 (based on suggestions from Peter):
> >
> > 1. Added data validity check for TObj
> > 2. Modified the comment style
> > 3. Added powerdown function
> > 4. Some code cleanups
> >
> > .../devicetree/bindings/iio/temperature/tmp007.txt | 16 +
> > drivers/iio/temperature/Kconfig | 10 +
> > drivers/iio/temperature/Makefile | 1 +
> > drivers/iio/temperature/tmp007.c | 345 +++++++++++++++++++++
> > 4 files changed, 372 insertions(+)
> > create mode 100644 Documentation/devicetree/bindings/iio/temperature/tmp007.txt
> > create mode 100644 drivers/iio/temperature/tmp007.c
> >
> > diff --git a/Documentation/devicetree/bindings/iio/temperature/tmp007.txt b/Documentation/devicetree/bindings/iio/temperature/tmp007.txt
> > new file mode 100644
> > index 0000000..9ae0519
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/iio/temperature/tmp007.txt
> > @@ -0,0 +1,16 @@
> > +* TI TMP007 - IR thermopile sensor with integrated math engine
> > +
> > +Link to datasheet: http://www.ti.com/lit/ds/symlink/tmp007.pdf
> > +
> > +Required properties:
> > +
> > + - compatible: should be "ti,tmp007"
> > + - reg: the I2C address of the sensor (changeable via ADR pins)
> Perhaps list the options that are possible?
ACK.
> > +
> > +Example:
> > +
> > +tmp007@40 {
> > + compatible = "ti,tmp007";
> > + reg = <0x40>;
> > +};
> > +
> > diff --git a/drivers/iio/temperature/Kconfig b/drivers/iio/temperature/Kconfig
> > index c4664e5..538ce9e 100644
> > --- a/drivers/iio/temperature/Kconfig
> > +++ b/drivers/iio/temperature/Kconfig
> > @@ -23,6 +23,16 @@ config TMP006
> > This driver can also be built as a module. If so, the module will
> > be called tmp006.
> >
> > +config TMP007
> > + tristate "TMP007 infrared thermopile sensor with Integrated Math Engine"
> > + depends on I2C
> > + help
> > + If you say yes here you get support for the Texas Instruments
> > + TMP007 infrared thermopile sensor with Integrated Math Engine.
> > +
> > + This driver can also be built as a module. If so, the module will
> > + be called tmp007.
> > +
> > config TSYS01
> > tristate "Measurement Specialties TSYS01 temperature sensor using I2C bus connection"
> > depends on I2C
> > diff --git a/drivers/iio/temperature/Makefile b/drivers/iio/temperature/Makefile
> > index 02bc79d..f0cf5c5 100644
> > --- a/drivers/iio/temperature/Makefile
> > +++ b/drivers/iio/temperature/Makefile
> > @@ -4,5 +4,6 @@
> >
> > obj-$(CONFIG_MLX90614) += mlx90614.o
> > obj-$(CONFIG_TMP006) += tmp006.o
> > +obj-$(CONFIG_TMP007) += tmp007.o
> > obj-$(CONFIG_TSYS01) += tsys01.o
> > obj-$(CONFIG_TSYS02D) += tsys02d.o
> > diff --git a/drivers/iio/temperature/tmp007.c b/drivers/iio/temperature/tmp007.c
> > new file mode 100644
> > index 0000000..a385ef5
> > --- /dev/null
> > +++ b/drivers/iio/temperature/tmp007.c
> > @@ -0,0 +1,345 @@
> > +/*
> > + * tmp007.c - Support for TI TMP007 IR thermopile sensor with integrated math engine
> > + *
> > + * Copyright (c) 2017 Manivannan Sadhasivam <manivannanece23-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> > + *
> > + * This file is subject to the terms and conditions of version 2 of
> > + * the GNU General Public License. See the file COPYING in the main
> > + * directory of this archive for more details.
> > + *
> > + * Driver for the Texas Instruments I2C 16-bit IR thermopile sensor
> > + *
> > + * (7-bit I2C slave address (0x40 - 0x47), changeable via ADR pins)
> > + *
> > + * Note: This driver assumes that the sensor has been calibrated beforehand
> > + *
> > + * TODO: ALERT irq, limit threshold events
> > + *
> > + */
> > +
> > +#include <linux/err.h>
> > +#include <linux/i2c.h>
> > +#include <linux/delay.h>
> > +#include <linux/module.h>
> > +#include <linux/pm.h>
> > +#include <linux/bitops.h>
> > +#include <linux/of.h>
> > +
> > +#include <linux/iio/iio.h>
> > +#include <linux/iio/sysfs.h>
> > +
> > +#define TMP007_TDIE 0x01
> > +#define TMP007_CONFIG 0x02
> > +#define TMP007_TOBJECT 0x03
> > +#define TMP007_STATUS 0x04
> > +#define TMP007_STATUS_MASK 0x05
> > +#define TMP007_MANUFACTURER_ID 0x1e
> > +#define TMP007_DEVICE_ID 0x1f
> > +
> > +#define TMP007_CONFIG_CONV_EN BIT(12)
> > +#define TMP007_CONFIG_COMP_EN BIT(5)
> > +#define TMP007_CONFIG_TC_EN BIT(6)
> > +#define TMP007_CONFIG_CR_MASK GENMASK(11, 9)
> > +#define TMP007_CONFIG_CR_SHIFT 9
> > +
> > +#define TMP007_STATUS_CONV_READY BIT(14)
> > +#define TMP007_STATUS_DATA_VALID BIT(9)
> > +
> > +#define TMP007_MANUFACTURER_MAGIC 0x5449
> > +#define TMP007_DEVICE_MAGIC 0x0078
> > +
> > +#define TMP007_TEMP_SHIFT 2
> > +
> > +struct tmp007_data {
> > + struct i2c_client *client;
>
> The fact you are caching values here and that everything is register
> based suggests to me that it might make sense to use regmap and take
> advantage of it's built in caching and masked write functions.
>
> If you pefer to stick to direct smbus calls that is fine.
I'd prefer to use smbus calls over regmap here. As the usage is quite less and I don't think it'll be needed for such
simple interface.
>
> > + u16 config;
>
> > + u16 status_mask;
> Why cache this register? It is directly read then written
> whenever used.
ACK.
>
> > +};
> > +
> > +static const int tmp007_avgs[5][2] = { {4, 0}, {2, 0}, {1, 0},
> > + {0, 500000}, {0, 250000} };
> > +
> > +static int tmp007_read_temperature(struct tmp007_data *data, u8 reg)
> > +{
> > + s32 ret;
> > + int tries = 50;
> > +
> > + while (tries-- > 0) {
> > + ret = i2c_smbus_read_word_swapped(data->client,
> > + TMP007_STATUS);
> > + if (ret < 0)
> > + return ret;
> > + if ((ret & TMP007_STATUS_CONV_READY) &&
> > + !(ret & TMP007_STATUS_DATA_VALID))
> > + break;
> > + msleep(100);
> > + }
> > +
> > + if (tries < 0)
> > + return -EIO;
> > +
> > + return i2c_smbus_read_word_swapped(data->client, reg);
> > +}
> > +
> > +static int tmp007_powerdown(struct tmp007_data *data)
> > +{
> > + return i2c_smbus_write_word_swapped(data->client, TMP007_CONFIG,
> > + data->config & ~TMP007_CONFIG_CONV_EN);
> > +}
> > +
> > +static int tmp007_read_raw(struct iio_dev *indio_dev,
> > + struct iio_chan_spec const *channel, int *val,
> > + int *val2, long mask)
> > +{
> > + struct tmp007_data *data = iio_priv(indio_dev);
> > + s32 ret;
> > + int conv_rate;
> > +
> > + switch (mask) {
> > + case IIO_CHAN_INFO_RAW:
> > + switch (channel->channel2) {
> > + case IIO_MOD_TEMP_AMBIENT: /* LSB: 0.03125 degree Celsius */
> > + ret = i2c_smbus_read_word_swapped(data->client, TMP007_TDIE);
> > + if (ret < 0)
> > + return ret;
> > + break;
> > + case IIO_MOD_TEMP_OBJECT:
> > + ret = tmp007_read_temperature(data, TMP007_TOBJECT);
> > + if (ret < 0)
> > + return ret;
> > + break;
> > + default:
> > + return -EINVAL;
> > + }
> > +
> > + *val = sign_extend32(ret, 15) >> TMP007_TEMP_SHIFT;
> > +
> > + return IIO_VAL_INT;
> > + case IIO_CHAN_INFO_SCALE:
> > + *val = 31;
> > + *val2 = 250000;
> > +
> > + return IIO_VAL_INT_PLUS_MICRO;
> > + case IIO_CHAN_INFO_SAMP_FREQ:
> > + conv_rate = (data->config & TMP007_CONFIG_CR_MASK)
> > + >> TMP007_CONFIG_CR_SHIFT;
> > + *val = tmp007_avgs[conv_rate][0];
> > + *val2 = tmp007_avgs[conv_rate][1];
> > +
> > + return IIO_VAL_INT_PLUS_MICRO;
> > + default:
> > + return -EINVAL;
> > + }
> > +}
> > +
> > +static int tmp007_write_raw(struct iio_dev *indio_dev,
> > + struct iio_chan_spec const *channel, int val,
> > + int val2, long mask)
> > +{
> > + struct tmp007_data *data = iio_priv(indio_dev);
> > + int i;
> > + u16 tmp;
> > +
> > + if (mask == IIO_CHAN_INFO_SAMP_FREQ) {
> > + for (i = 0; i < ARRAY_SIZE(tmp007_avgs); i++) {
> > + if ((val == tmp007_avgs[i][0]) &&
> > + (val2 == tmp007_avgs[i][1])) {
> > + tmp = data->config & ~TMP007_CONFIG_CR_MASK;
> > + tmp |= (i << TMP007_CONFIG_CR_SHIFT);
> > +
> > + return i2c_smbus_write_word_swapped(data->client,
> > + TMP007_CONFIG,
> > + data->config = tmp);
> > + }
> > + }
> > + }
> > +
> > + return -EINVAL;
> > +}
> > +
> > +static IIO_CONST_ATTR(sampling_frequency_available, "4 2 1 0.5 0.25");
> > +
> > +static struct attribute *tmp007_attributes[] = {
> > + &iio_const_attr_sampling_frequency_available.dev_attr.attr,
> > + NULL
> > +};
> > +
> > +static const struct attribute_group tmp007_attribute_group = {
> > + .attrs = tmp007_attributes,
> > +};
> > +
> > +static const struct iio_chan_spec tmp007_channels[] = {
> > + {
> > + .type = IIO_TEMP,
> > + .modified = 1,
> > + .channel2 = IIO_MOD_TEMP_AMBIENT,
> > + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
> > + BIT(IIO_CHAN_INFO_SCALE),
> > + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),
> > + },
> > + {
> > + .type = IIO_TEMP,
> > + .modified = 1,
> > + .channel2 = IIO_MOD_TEMP_OBJECT,
> > + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
> > + BIT(IIO_CHAN_INFO_SCALE),
> > + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),
> > + }
> > +};
> > +
> > +static const struct iio_info tmp007_info = {
> > + .read_raw = tmp007_read_raw,
> > + .write_raw = tmp007_write_raw,
> > + .attrs = &tmp007_attribute_group,
> > + .driver_module = THIS_MODULE,
> > +};
> > +
> > +static bool tmp007_identify(struct i2c_client *client)
> > +{
> > + int manf_id, dev_id;
> > +
> > + manf_id = i2c_smbus_read_word_swapped(client, TMP007_MANUFACTURER_ID);
> > + if (manf_id < 0)
> > + return false;
> > +
> > + dev_id = i2c_smbus_read_word_swapped(client, TMP007_DEVICE_ID);
> > + if (dev_id < 0)
> > + return false;
> > +
> > + return (manf_id == TMP007_MANUFACTURER_MAGIC && dev_id == TMP007_DEVICE_MAGIC);
> > +}
> > +
> > +static int tmp007_probe(struct i2c_client *client,
> > + const struct i2c_device_id *tmp007_id)
> > +{
> > + struct tmp007_data *data;
> > + struct iio_dev *indio_dev;
> > + int ret;
> > +
> > + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WORD_DATA))
> > + return -EOPNOTSUPP;
> > +
> > + if (!tmp007_identify(client)) {
> > + dev_err(&client->dev, "TMP007 not found\n");
> > + return -ENODEV;
> > + }
> > +
> > + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
> > + if (!indio_dev)
> > + return -ENOMEM;
> > +
> > + data = iio_priv(indio_dev);
> > + i2c_set_clientdata(client, indio_dev);
> > + data->client = client;
> > +
> > + indio_dev->dev.parent = &client->dev;
> > + indio_dev->name = dev_name(&client->dev);
> > + indio_dev->modes = INDIO_DIRECT_MODE;
> > + indio_dev->info = &tmp007_info;
> > +
> > + indio_dev->channels = tmp007_channels;
> > + indio_dev->num_channels = ARRAY_SIZE(tmp007_channels);
> > +
> > + /*
> > + * Set Configuration register:
> > + * 1. Conversion ON
> > + * 2. Comparator mode
> > + * 3. Transient correction enable
> > + */
> > +
> > + ret = i2c_smbus_read_word_swapped(data->client, TMP007_CONFIG);
> > + if (ret < 0)
> > + return ret;
> > +
> > + data->config = ret;
> > + data->config |= (TMP007_CONFIG_CONV_EN | TMP007_CONFIG_COMP_EN | TMP007_CONFIG_TC_EN);
> > +
> > + ret = i2c_smbus_write_word_swapped(data->client, TMP007_CONFIG,
> > + data->config);
> > + if (ret < 0)
> > + return ret;
> > +
> > + /*
> > + * Set Status Mask register:
> > + * 1. Conversion ready enable
> 2. Data valid?
ACK.
> > + */
> > +
> > + ret = i2c_smbus_read_word_swapped(data->client, TMP007_STATUS_MASK);
> > + if (ret < 0)
> > + goto error_powerdown;
> > +
> > + data->status_mask = ret;
> > + data->status_mask |= (TMP007_STATUS_CONV_READY | TMP007_STATUS_DATA_VALID);
> > +
> > + ret = i2c_smbus_write_word_swapped(data->client, TMP007_STATUS_MASK,
> > + data->status_mask);
> > + if (ret < 0)
> > + goto error_powerdown;
> > +
> > + return iio_device_register(indio_dev);
> > +
> > +error_powerdown:
> > + tmp007_powerdown(data);
> > +
> > + return ret;
> > +}
> > +
> > +static int tmp007_remove(struct i2c_client *client)
> > +{
> > + struct iio_dev *indio_dev = i2c_get_clientdata(client);
> > + struct tmp007_data *data = iio_priv(indio_dev);
> > +
> > + iio_device_unregister(indio_dev);
> > + tmp007_powerdown(data);
> > +
> > + return 0;
> > +}
> > +
> > +#ifdef CONFIG_PM_SLEEP
> > +static int tmp007_suspend(struct device *dev)
> > +{
> > + struct tmp007_data *data = iio_priv(i2c_get_clientdata(
> > + to_i2c_client(dev)));
> > +
> > + return tmp007_powerdown(data);
> > +}
> > +
> > +static int tmp007_resume(struct device *dev)
> > +{
> > + struct tmp007_data *data = iio_priv(i2c_get_clientdata(
> > + to_i2c_client(dev)));
> > +
> > + return i2c_smbus_write_word_swapped(data->client, TMP007_CONFIG,
> > + data->config | TMP007_CONFIG_CONV_EN);
> > +}
> > +#endif
> > +
> > +static SIMPLE_DEV_PM_OPS(tmp007_pm_ops, tmp007_suspend, tmp007_resume);
> > +
> > +static const struct of_device_id tmp007_of_match[] = {
> > + { .compatible = "ti,tmp007", },
> > + { },
> > +};
> > +MODULE_DEVICE_TABLE(of, tmp007_of_match);
> > +
> > +static const struct i2c_device_id tmp007_id[] = {
> > + { "tmp007", 0 },
> > + { }
> > +};
> > +MODULE_DEVICE_TABLE(i2c, tmp007_id);
> > +
> > +static struct i2c_driver tmp007_driver = {
> > + .driver = {
> > + .name = "tmp007",
> > + .of_match_table = of_match_ptr(tmp007_of_match),
> > + .pm = &tmp007_pm_ops,
> > + },
> > + .probe = tmp007_probe,
> > + .remove = tmp007_remove,
> > + .id_table = tmp007_id,
> > +};
> > +module_i2c_driver(tmp007_driver);
> > +
> > +MODULE_AUTHOR("Manivannan Sadhasivam <manivannanece23-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>");
> > +MODULE_DESCRIPTION("TI TMP007 IR thermopile sensor driver");
> > +MODULE_LICENSE("GPL");
> >
>
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH v7 1/5] dt-bindings: zte: add bindings document for zx2967 power domain controller
From: Shawn Guo @ 2017-01-09 2:09 UTC (permalink / raw)
To: Baoyou Xie, robh+dt-DgEjT+Ai2ygdnm+yROfE0A
Cc: jun.nie-QSEj5FYQhm4dnm+yROfE0A, mark.rutland-5wv7dgnIgG8,
gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r,
davem-fT/PcQaiUtIeIZ0/mPfg9Q,
geert+renesas-gXvu3+zWzMSzQB+pC5nmwQ,
akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b,
mchehab-DgEjT+Ai2ygdnm+yROfE0A, krzk-DgEjT+Ai2ygdnm+yROfE0A,
arnd-r2nGTMty4D4, claudiu.manoil-3arQi8VN3Tc,
amitdanielk-Re5JQEeQqe8AvxtiuMwx3w,
pankaj.dubey-Sze3O3UU22JBDgjK7y7TUQ, yangbo.lu-3arQi8VN3Tc,
scott.branden-dY08KVG/lbpWk0Htik3J/w,
simon.horman-wFxRvT7yatFl57MIdRCFDg,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
In-Reply-To: <1483694164-7668-1-git-send-email-baoyou.xie-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
On Fri, Jan 06, 2017 at 05:16:00PM +0800, Baoyou Xie wrote:
> This patch adds device tree bindings document for ZTE zx2967
> family power domain controller.
>
> Signed-off-by: Baoyou Xie <baoyou.xie-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
Hi Rob,
Are you happy with the bindings? I plan to merge the series through
arm-soc tree with your ACK on this patch.
Shawn
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH v7 5/5] soc: zte: pm_domains: Add support for zx296718
From: Shawn Guo @ 2017-01-09 2:16 UTC (permalink / raw)
To: Baoyou Xie
Cc: jun.nie, robh+dt, mark.rutland, gregkh, davem, geert+renesas,
akpm, mchehab, krzk, arnd, claudiu.manoil, amitdanielk,
pankaj.dubey, yangbo.lu, scott.branden, simon.horman, devicetree,
linux-kernel, linux-arm-kernel
In-Reply-To: <1483694164-7668-5-git-send-email-baoyou.xie@linaro.org>
On Fri, Jan 06, 2017 at 05:16:04PM +0800, Baoyou Xie wrote:
> This patch introduces the power domain driver of zx296718
> which belongs to zte's zx2967 family.
>
> Signed-off-by: Baoyou Xie <baoyou.xie@linaro.org>
> Reviewed-by: Jun Nie <jun.nie@linaro.org>
Except the need of PCU_DM_xxx enum (I'm not strong on that,so would
leave it to author's decision), the patch series looks good to me.
I'm going to queue it up for 4.11 after getting Rob's ACK on bindings.
Let me know if anyone has any objections.
Shawn
^ permalink raw reply
* RE: [PATCH v2 05/12] Document: dt: binding: imx: update pinctrl doc for imx6sll
From: Jacky Bai @ 2017-01-09 2:32 UTC (permalink / raw)
To: Linus Walleij
Cc: Shawn Guo, Michael Turquette, Stephen Boyd, Rob Herring,
Mark Rutland, Sascha Hauer, Fabio Estevam, Daniel Lezcano,
Thomas Gleixner, Philipp Zabel, linux-clk,
devicetree@vger.kernel.org, linux-gpio@vger.kernel.org,
linux-arm-kernel@lists.infradead.org, jacky.baip@gmail.com
In-Reply-To: <CACRpkdYUME8K+JusA0ORRKqxyBuhDdyei8eg7UZbHidKw9=bQw@mail.gmail.com>
> Subject: Re: [PATCH v2 05/12] Document: dt: binding: imx: update pinctrl doc
> for imx6sll
>
> On Tue, Dec 27, 2016 at 10:47 AM, Bai Ping <ping.bai@nxp.com> wrote:
>
> > Add pinctrl binding doc update for imx6sll.
> >
> > Signed-off-by: Bai Ping <ping.bai@nxp.com>
>
> I have to push back on this a bit.
>
> > +Please refer to fsl,imx-pinctrl.txt in this directory for common
> > +binding part and usage.
>
> I understand that it is building on top of the old i.MX bindings and that it has
> some kind of "tradition" coming with it.
>
> At the same time, the i.MX bindings came about before we had the generic pin
> control bindings defined.
>
> > +CONFIG bits definition:
> > +PAD_CTL_LVE (1 << 22)
> > +PAD_CTL_HYS (1 << 16)
> > +PAD_CTL_PUS_100K_DOWN (0 << 14)
> > +PAD_CTL_PUS_47K_UP (1 << 14)
> > +PAD_CTL_PUS_100K_UP (2 << 14)
> > +PAD_CTL_PUS_22K_UP (3 << 14)
> > +PAD_CTL_PUE (1 << 13)
> > +PAD_CTL_PKE (1 << 12)
> > +PAD_CTL_ODE (1 << 11)
> > +PAD_CTL_SPEED_LOW (0 << 6)
> > +PAD_CTL_SPEED_MED (1 << 6)
> > +PAD_CTL_SPEED_HIGH (3 << 6)
> > +PAD_CTL_DSE_DISABLE (0 << 3)
> > +PAD_CTL_DSE_260ohm (1 << 3)
> > +PAD_CTL_DSE_130ohm (2 << 3)
> > +PAD_CTL_DSE_87ohm (3 << 3)
> > +PAD_CTL_DSE_65ohm (4 << 3)
> > +PAD_CTL_DSE_52ohm (5 << 3)
> > +PAD_CTL_DSE_43ohm (6 << 3)
> > +PAD_CTL_DSE_37ohm (7 << 3)
> > +PAD_CTL_SRE_FAST (1 << 0)
> > +PAD_CTL_SRE_SLOW (0 << 0)
>
> A whole slew of these if not all correspond to the generic bindings.
>
> I would consider augmenting the code in the driver to handle the generic
> bindings *in addition* to the old legacy bindings, and use those over these
> random custom bits.
>
> Read drivers using CONFIG_GENERIC_PINCONF as an inspiration.
>
> For example see commit
> cefbf1a1b29531a970bc2908a50a75d6474fcc38
> "pinctrl: sunxi: Support generic binding"
> from Maxime Ripard, where he does a similar thing for sunxi.
I have look into the above commit on using generic binding. But I think the generic pinconf
is not very easy to add in imx pinctrl Driver. imx pinctrl use a different way to parse the pin configure.
Each fsl,pin entry looks like <PIN_FUNC_ID CONFIG> in dts, the CONFIG is the pad setting value like
pull-up, open-drain, drive strength etc. The above config bit definition is specific to each SOC in the PAD CTL register.
If we want set the pin config to enable hysteresis, 47KOhm Pull Up, 50Mhz speed, 80Ohm driver strength
and Fast Slew Rate, then the CONFIG value should be 0x17059( ORs corresponding bit definition). This value will be set in
PAD CTL register to config the corresponding pin.
BR
Jacky Bai
>
> Yours,
> Linus Walleij
^ permalink raw reply
* Re: [PATCH v1 1/3] dt: bindings: add thermal device driver for zx2967
From: Shawn Guo @ 2017-01-09 2:41 UTC (permalink / raw)
To: Baoyou Xie
Cc: rui.zhang, edubezval, robh+dt, mark.rutland, jun.nie, gregkh,
davem, geert+renesas, akpm, mchehab, linux, linux-pm, devicetree,
linux-kernel, linux-arm-kernel, xie.baoyou, chen.chaokai,
wang.qiang01
In-Reply-To: <1483767488-19778-1-git-send-email-baoyou.xie@linaro.org>
On Sat, Jan 07, 2017 at 01:38:06PM +0800, Baoyou Xie wrote:
> This patch adds dt-binding documentation for zx2967 family thermal sensor.
>
> Signed-off-by: Baoyou Xie <baoyou.xie@linaro.org>
The patch subject is inappropriate. The patch adds a bindings not
device driver.
> ---
> .../devicetree/bindings/thermal/zx2967-thermal.txt | 22 ++++++++++++++++++++++
> 1 file changed, 22 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/thermal/zx2967-thermal.txt
>
> diff --git a/Documentation/devicetree/bindings/thermal/zx2967-thermal.txt b/Documentation/devicetree/bindings/thermal/zx2967-thermal.txt
> new file mode 100644
> index 0000000..2633964
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/thermal/zx2967-thermal.txt
> @@ -0,0 +1,22 @@
> +* ZTE zx2967 family Thermal
> +
> +Required Properties:
> +- compatible: should be one of the following.
> + * zte,zx2967-thermal
> + * zte,zx296718-thermal
We usually use specific SoC name in compatible string to specify the
programming model for the hardware. That said, I do not think we need
"zte,zx2967-thermal".
> +- reg: physical base address of the controller and length of memory mapped
> + region.
> +- clocks : Pairs of phandle and specifier referencing the controller's clocks.
> +- clock-names: "tempsensor_gate" for the topcrm clock.
> + "tempsensor_pclk" for the apb clock.
In the context of tempsensor device, the "tempsensor_" in the clock
names are not really necessary.
> +- #thermal-sensor-cells: must be 0.
> +
> +Example:
> +
> + tempsensor: tempsensor@148a000 {
> + compatible = "zte,zx2967-thermal";
"zte,zx296718-thermal"
Shawn
> + reg = <0x0148a000 0x20>;
> + clocks = <&topcrm TEMPSENSOR_GATE>, <&audiocrm AUDIO_TS_PCLK>;
> + clock-names = "tempsensor_gate", "tempsensor_pclk";
> + #thermal-sensor-cells = <0>;
> + };
> --
> 2.7.4
>
^ permalink raw reply
* [PATCH v4] iio:temperature: Add support for TI TMP007 sensor
From: Manivannan Sadhasivam @ 2017-01-09 2:55 UTC (permalink / raw)
To: jic23-DgEjT+Ai2ygdnm+yROfE0A, pmeerw-jW+XmwGofnusTnJN9+BGXg
Cc: linux-iio-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA
This patch adds support for TI TMP007 - 16 bit IR thermopile sensor with integrated Math engine.
Sensor takes care of calculating the object temperature with the help of calibrated constants stored in non-volatile memory,
thereby reducing the calculation overhead.
Signed-off-by: Manivannan Sadhasivam <manivannanece23-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
---
Changes since v3:
1. Removed caching of status register
2. Modified comments for data validity
3. Added possible address combinations in dTree bindings file
.../devicetree/bindings/iio/temperature/tmp007.txt | 27 ++
drivers/iio/temperature/Kconfig | 10 +
drivers/iio/temperature/Makefile | 1 +
drivers/iio/temperature/tmp007.c | 345 +++++++++++++++++++++
4 files changed, 383 insertions(+)
create mode 100644 Documentation/devicetree/bindings/iio/temperature/tmp007.txt
create mode 100644 drivers/iio/temperature/tmp007.c
diff --git a/Documentation/devicetree/bindings/iio/temperature/tmp007.txt b/Documentation/devicetree/bindings/iio/temperature/tmp007.txt
new file mode 100644
index 0000000..3b8f41f
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/temperature/tmp007.txt
@@ -0,0 +1,27 @@
+* TI TMP007 - IR thermopile sensor with integrated math engine
+
+Link to datasheet: http://www.ti.com/lit/ds/symlink/tmp007.pdf
+
+Required properties:
+
+ - compatible: should be "ti,tmp007"
+ - reg: the I2C address of the sensor (changeable via ADR pins)
+ ------------------------------
+ |ADR1 | ADR0 | Device Address|
+ ------------------------------
+ 0 0 0x40
+ 0 1 0x41
+ 0 SDA 0x42
+ 0 SCL 0x43
+ 1 0 0x44
+ 1 1 0x45
+ 1 SDA 0x46
+ 1 SCL 0x47
+
+Example:
+
+tmp007@40 {
+ compatible = "ti,tmp007";
+ reg = <0x40>;
+};
+
diff --git a/drivers/iio/temperature/Kconfig b/drivers/iio/temperature/Kconfig
index c4664e5..538ce9e 100644
--- a/drivers/iio/temperature/Kconfig
+++ b/drivers/iio/temperature/Kconfig
@@ -23,6 +23,16 @@ config TMP006
This driver can also be built as a module. If so, the module will
be called tmp006.
+config TMP007
+ tristate "TMP007 infrared thermopile sensor with Integrated Math Engine"
+ depends on I2C
+ help
+ If you say yes here you get support for the Texas Instruments
+ TMP007 infrared thermopile sensor with Integrated Math Engine.
+
+ This driver can also be built as a module. If so, the module will
+ be called tmp007.
+
config TSYS01
tristate "Measurement Specialties TSYS01 temperature sensor using I2C bus connection"
depends on I2C
diff --git a/drivers/iio/temperature/Makefile b/drivers/iio/temperature/Makefile
index 02bc79d..f0cf5c5 100644
--- a/drivers/iio/temperature/Makefile
+++ b/drivers/iio/temperature/Makefile
@@ -4,5 +4,6 @@
obj-$(CONFIG_MLX90614) += mlx90614.o
obj-$(CONFIG_TMP006) += tmp006.o
+obj-$(CONFIG_TMP007) += tmp007.o
obj-$(CONFIG_TSYS01) += tsys01.o
obj-$(CONFIG_TSYS02D) += tsys02d.o
diff --git a/drivers/iio/temperature/tmp007.c b/drivers/iio/temperature/tmp007.c
new file mode 100644
index 0000000..24c6c16
--- /dev/null
+++ b/drivers/iio/temperature/tmp007.c
@@ -0,0 +1,345 @@
+/*
+ * tmp007.c - Support for TI TMP007 IR thermopile sensor with integrated math engine
+ *
+ * Copyright (c) 2017 Manivannan Sadhasivam <manivannanece23-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
+ *
+ * This file is subject to the terms and conditions of version 2 of
+ * the GNU General Public License. See the file COPYING in the main
+ * directory of this archive for more details.
+ *
+ * Driver for the Texas Instruments I2C 16-bit IR thermopile sensor
+ *
+ * (7-bit I2C slave address (0x40 - 0x47), changeable via ADR pins)
+ *
+ * Note: This driver assumes that the sensor has been calibrated beforehand
+ *
+ * TODO: ALERT irq, limit threshold events
+ *
+ */
+
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/pm.h>
+#include <linux/bitops.h>
+#include <linux/of.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+
+#define TMP007_TDIE 0x01
+#define TMP007_CONFIG 0x02
+#define TMP007_TOBJECT 0x03
+#define TMP007_STATUS 0x04
+#define TMP007_STATUS_MASK 0x05
+#define TMP007_MANUFACTURER_ID 0x1e
+#define TMP007_DEVICE_ID 0x1f
+
+#define TMP007_CONFIG_CONV_EN BIT(12)
+#define TMP007_CONFIG_COMP_EN BIT(5)
+#define TMP007_CONFIG_TC_EN BIT(6)
+#define TMP007_CONFIG_CR_MASK GENMASK(11, 9)
+#define TMP007_CONFIG_CR_SHIFT 9
+
+#define TMP007_STATUS_CONV_READY BIT(14)
+#define TMP007_STATUS_DATA_VALID BIT(9)
+
+#define TMP007_MANUFACTURER_MAGIC 0x5449
+#define TMP007_DEVICE_MAGIC 0x0078
+
+#define TMP007_TEMP_SHIFT 2
+
+struct tmp007_data {
+ struct i2c_client *client;
+ u16 config;
+};
+
+static const int tmp007_avgs[5][2] = { {4, 0}, {2, 0}, {1, 0},
+ {0, 500000}, {0, 250000} };
+
+static int tmp007_read_temperature(struct tmp007_data *data, u8 reg)
+{
+ s32 ret;
+ int tries = 50;
+
+ while (tries-- > 0) {
+ ret = i2c_smbus_read_word_swapped(data->client,
+ TMP007_STATUS);
+ if (ret < 0)
+ return ret;
+ if ((ret & TMP007_STATUS_CONV_READY) &&
+ !(ret & TMP007_STATUS_DATA_VALID))
+ break;
+ msleep(100);
+ }
+
+ if (tries < 0)
+ return -EIO;
+
+ return i2c_smbus_read_word_swapped(data->client, reg);
+}
+
+static int tmp007_powerdown(struct tmp007_data *data)
+{
+ return i2c_smbus_write_word_swapped(data->client, TMP007_CONFIG,
+ data->config & ~TMP007_CONFIG_CONV_EN);
+}
+
+static int tmp007_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *channel, int *val,
+ int *val2, long mask)
+{
+ struct tmp007_data *data = iio_priv(indio_dev);
+ s32 ret;
+ int conv_rate;
+
+ switch (mask) {
+ case IIO_CHAN_INFO_RAW:
+ switch (channel->channel2) {
+ case IIO_MOD_TEMP_AMBIENT: /* LSB: 0.03125 degree Celsius */
+ ret = i2c_smbus_read_word_swapped(data->client, TMP007_TDIE);
+ if (ret < 0)
+ return ret;
+ break;
+ case IIO_MOD_TEMP_OBJECT:
+ ret = tmp007_read_temperature(data, TMP007_TOBJECT);
+ if (ret < 0)
+ return ret;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ *val = sign_extend32(ret, 15) >> TMP007_TEMP_SHIFT;
+
+ return IIO_VAL_INT;
+ case IIO_CHAN_INFO_SCALE:
+ *val = 31;
+ *val2 = 250000;
+
+ return IIO_VAL_INT_PLUS_MICRO;
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ conv_rate = (data->config & TMP007_CONFIG_CR_MASK)
+ >> TMP007_CONFIG_CR_SHIFT;
+ *val = tmp007_avgs[conv_rate][0];
+ *val2 = tmp007_avgs[conv_rate][1];
+
+ return IIO_VAL_INT_PLUS_MICRO;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int tmp007_write_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *channel, int val,
+ int val2, long mask)
+{
+ struct tmp007_data *data = iio_priv(indio_dev);
+ int i;
+ u16 tmp;
+
+ if (mask == IIO_CHAN_INFO_SAMP_FREQ) {
+ for (i = 0; i < ARRAY_SIZE(tmp007_avgs); i++) {
+ if ((val == tmp007_avgs[i][0]) &&
+ (val2 == tmp007_avgs[i][1])) {
+ tmp = data->config & ~TMP007_CONFIG_CR_MASK;
+ tmp |= (i << TMP007_CONFIG_CR_SHIFT);
+
+ return i2c_smbus_write_word_swapped(data->client,
+ TMP007_CONFIG,
+ data->config = tmp);
+ }
+ }
+ }
+
+ return -EINVAL;
+}
+
+static IIO_CONST_ATTR(sampling_frequency_available, "4 2 1 0.5 0.25");
+
+static struct attribute *tmp007_attributes[] = {
+ &iio_const_attr_sampling_frequency_available.dev_attr.attr,
+ NULL
+};
+
+static const struct attribute_group tmp007_attribute_group = {
+ .attrs = tmp007_attributes,
+};
+
+static const struct iio_chan_spec tmp007_channels[] = {
+ {
+ .type = IIO_TEMP,
+ .modified = 1,
+ .channel2 = IIO_MOD_TEMP_AMBIENT,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_SCALE),
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),
+ },
+ {
+ .type = IIO_TEMP,
+ .modified = 1,
+ .channel2 = IIO_MOD_TEMP_OBJECT,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_SCALE),
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),
+ }
+};
+
+static const struct iio_info tmp007_info = {
+ .read_raw = tmp007_read_raw,
+ .write_raw = tmp007_write_raw,
+ .attrs = &tmp007_attribute_group,
+ .driver_module = THIS_MODULE,
+};
+
+static bool tmp007_identify(struct i2c_client *client)
+{
+ int manf_id, dev_id;
+
+ manf_id = i2c_smbus_read_word_swapped(client, TMP007_MANUFACTURER_ID);
+ if (manf_id < 0)
+ return false;
+
+ dev_id = i2c_smbus_read_word_swapped(client, TMP007_DEVICE_ID);
+ if (dev_id < 0)
+ return false;
+
+ return (manf_id == TMP007_MANUFACTURER_MAGIC && dev_id == TMP007_DEVICE_MAGIC);
+}
+
+static int tmp007_probe(struct i2c_client *client,
+ const struct i2c_device_id *tmp007_id)
+{
+ struct tmp007_data *data;
+ struct iio_dev *indio_dev;
+ int ret;
+ u16 status;
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WORD_DATA))
+ return -EOPNOTSUPP;
+
+ if (!tmp007_identify(client)) {
+ dev_err(&client->dev, "TMP007 not found\n");
+ return -ENODEV;
+ }
+
+ indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
+ if (!indio_dev)
+ return -ENOMEM;
+
+ data = iio_priv(indio_dev);
+ i2c_set_clientdata(client, indio_dev);
+ data->client = client;
+
+ indio_dev->dev.parent = &client->dev;
+ indio_dev->name = dev_name(&client->dev);
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->info = &tmp007_info;
+
+ indio_dev->channels = tmp007_channels;
+ indio_dev->num_channels = ARRAY_SIZE(tmp007_channels);
+
+ /*
+ * Set Configuration register:
+ * 1. Conversion ON
+ * 2. Comparator mode
+ * 3. Transient correction enable
+ */
+
+ ret = i2c_smbus_read_word_swapped(data->client, TMP007_CONFIG);
+ if (ret < 0)
+ return ret;
+
+ data->config = ret;
+ data->config |= (TMP007_CONFIG_CONV_EN | TMP007_CONFIG_COMP_EN | TMP007_CONFIG_TC_EN);
+
+ ret = i2c_smbus_write_word_swapped(data->client, TMP007_CONFIG,
+ data->config);
+ if (ret < 0)
+ return ret;
+
+ /*
+ * Set Status Mask register:
+ * 1. Conversion ready enable
+ * 2. Data valid enable
+ */
+
+ ret = i2c_smbus_read_word_swapped(data->client, TMP007_STATUS_MASK);
+ if (ret < 0)
+ goto error_powerdown;
+
+ status = ret;
+ status |= (TMP007_STATUS_CONV_READY | TMP007_STATUS_DATA_VALID);
+
+ ret = i2c_smbus_write_word_swapped(data->client, TMP007_STATUS_MASK, status);
+ if (ret < 0)
+ goto error_powerdown;
+
+ return iio_device_register(indio_dev);
+
+error_powerdown:
+ tmp007_powerdown(data);
+
+ return ret;
+}
+
+static int tmp007_remove(struct i2c_client *client)
+{
+ struct iio_dev *indio_dev = i2c_get_clientdata(client);
+ struct tmp007_data *data = iio_priv(indio_dev);
+
+ iio_device_unregister(indio_dev);
+ tmp007_powerdown(data);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int tmp007_suspend(struct device *dev)
+{
+ struct tmp007_data *data = iio_priv(i2c_get_clientdata(
+ to_i2c_client(dev)));
+
+ return tmp007_powerdown(data);
+}
+
+static int tmp007_resume(struct device *dev)
+{
+ struct tmp007_data *data = iio_priv(i2c_get_clientdata(
+ to_i2c_client(dev)));
+
+ return i2c_smbus_write_word_swapped(data->client, TMP007_CONFIG,
+ data->config | TMP007_CONFIG_CONV_EN);
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(tmp007_pm_ops, tmp007_suspend, tmp007_resume);
+
+static const struct of_device_id tmp007_of_match[] = {
+ { .compatible = "ti,tmp007", },
+ { },
+};
+MODULE_DEVICE_TABLE(of, tmp007_of_match);
+
+static const struct i2c_device_id tmp007_id[] = {
+ { "tmp007", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, tmp007_id);
+
+static struct i2c_driver tmp007_driver = {
+ .driver = {
+ .name = "tmp007",
+ .of_match_table = of_match_ptr(tmp007_of_match),
+ .pm = &tmp007_pm_ops,
+ },
+ .probe = tmp007_probe,
+ .remove = tmp007_remove,
+ .id_table = tmp007_id,
+};
+module_i2c_driver(tmp007_driver);
+
+MODULE_AUTHOR("Manivannan Sadhasivam <manivannanece23-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>");
+MODULE_DESCRIPTION("TI TMP007 IR thermopile sensor driver");
+MODULE_LICENSE("GPL");
--
2.7.4
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH v7 1/2] mtd: arasan: Add device tree binding documentation
From: Punnaiah Choudary Kalluri @ 2017-01-09 2:58 UTC (permalink / raw)
To: dwmw2-wEGCiKHe2LqWVfeAwA7xHQ,
computersforpeace-Re5JQEeQqe8AvxtiuMwx3w,
boris.brezillon-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8,
marek.vasut-Re5JQEeQqe8AvxtiuMwx3w, richard-/L3Ra7n9ekc,
cyrille.pitchen-AIFe0yeh4nAAvxtiuMwx3w,
robh+dt-DgEjT+Ai2ygdnm+yROfE0A, mark.rutland-5wv7dgnIgG8
Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
devicetree-u79uwXL29TY76Z2rM5mHXA, michals-gjFFaj9aHVfQT0dZR+AlfA,
kalluripunnaiahchoudary-Re5JQEeQqe8AvxtiuMwx3w,
kpc528-Re5JQEeQqe8AvxtiuMwx3w, Punnaiah Choudary Kalluri
This patch adds the dts binding document for arasan nand flash
controller.
Signed-off-by: Punnaiah Choudary Kalluri <punnaia-gjFFaj9aHVfQT0dZR+AlfA@public.gmane.org>
---
Changes in v7:
- Corrected the acronyms those should be in caps
changes in v6:
- Removed num-cs property
- Separated nandchip from nand controller
changes in v5:
- None
Changes in v4:
- Added num-cs property
- Added clock support
Changes in v3:
- None
Changes in v2:
- None
---
.../devicetree/bindings/mtd/arasan_nfc.txt | 38 ++++++++++++++++++++++
1 file changed, 38 insertions(+)
create mode 100644 Documentation/devicetree/bindings/mtd/arasan_nfc.txt
diff --git a/Documentation/devicetree/bindings/mtd/arasan_nfc.txt b/Documentation/devicetree/bindings/mtd/arasan_nfc.txt
new file mode 100644
index 0000000..f20adfc
--- /dev/null
+++ b/Documentation/devicetree/bindings/mtd/arasan_nfc.txt
@@ -0,0 +1,38 @@
+Arasan NAND Flash Controller with ONFI 3.1 support
+
+Required properties:
+- compatible: Should be "arasan,nfc-v3p10"
+- reg: Memory map for module access
+- interrupt-parent: Interrupt controller the interrupt is routed through
+- interrupts: Should contain the interrupt for the device
+- clock-name: List of input clocks - "clk_sys", "clk_flash"
+ (See clock bindings for details)
+- clocks: Clock phandles (see clock bindings for details)
+
+Optional properties:
+- arasan,has-mdma: Enables DMA support
+
+For NAND partition information please refer the below file
+Documentation/devicetree/bindings/mtd/partition.txt
+
+Example:
+ nand0: nand@ff100000 {
+ compatible = "arasan,nfc-v3p10"
+ reg = <0x0 0xff100000 0x1000>;
+ clock-name = "clk_sys", "clk_flash"
+ clocks = <&misc_clk &misc_clk>;
+ interrupt-parent = <&gic>;
+ interrupts = <0 14 4>;
+ arasan,has-mdma;
+ #address-cells = <1>;
+ #size-cells = <0>
+
+ nand@0 {
+ reg = <0>
+ partition@0 {
+ label = "filesystem";
+ reg = <0x0 0x0 0x1000000>;
+ };
+ (...)
+ };
+ };
--
2.7.4
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH v7 2/2] mtd: nand: Add support for Arasan NAND Flash Controller
From: Punnaiah Choudary Kalluri @ 2017-01-09 2:58 UTC (permalink / raw)
To: dwmw2-wEGCiKHe2LqWVfeAwA7xHQ,
computersforpeace-Re5JQEeQqe8AvxtiuMwx3w,
boris.brezillon-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8,
marek.vasut-Re5JQEeQqe8AvxtiuMwx3w, richard-/L3Ra7n9ekc,
cyrille.pitchen-AIFe0yeh4nAAvxtiuMwx3w,
robh+dt-DgEjT+Ai2ygdnm+yROfE0A, mark.rutland-5wv7dgnIgG8
Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
devicetree-u79uwXL29TY76Z2rM5mHXA, michals-gjFFaj9aHVfQT0dZR+AlfA,
kalluripunnaiahchoudary-Re5JQEeQqe8AvxtiuMwx3w,
kpc528-Re5JQEeQqe8AvxtiuMwx3w, Punnaiah Choudary Kalluri
In-Reply-To: <1483930734-10309-1-git-send-email-punnaia-gjFFaj9aHVfQT0dZR+AlfA@public.gmane.org>
Added the basic driver for Arasan NAND Flash Controller used in
Zynq UltraScale+ MPSoC. It supports only Hw ECC and upto 24bit
correction.
Signed-off-by: Punnaiah Choudary Kalluri <punnaia-gjFFaj9aHVfQT0dZR+AlfA@public.gmane.org>
---
Changes in v7:
- Implemented Marek suggestions and comments
- Corrected the acronyms those should be in caps
- Modified kconfig/Make file to keep arasan entry in sorted order
- Added is_vmlloc_addr check
- Used ioread/write32_rep variants to avoid compilation error for intel
platforms
- separated PIO and DMA mode read/write functions
- Minor cleanup
Chnages in v6:
- Addressed most of the Brian and Boris comments
- Separated the nandchip from the nand controller
- Removed the ecc lookup table from driver
- Now use framework nand waitfunction and readoob
- Fixed the compiler warning
- Adapted the new frameowrk changes related to ecc and ooblayout
- Disabled the clocks after the nand_reelase
- Now using only one completion object
- Boris suggessions like adapting cmd_ctrl and rework on read/write byte
are not implemented and i will patch them later
- Also check_erased_ecc_chunk for erase and check for is_vmalloc_addr will
implement later once the basic driver is mainlined.
Changes in v5:
- Renamed the driver filei as arasan_nand.c
- Fixed all comments relaqted coding style
- Fixed comments related to propagating the errors
- Modified the anfc_write_page_hwecc as per the write_page
prototype
Changes in v4:
- Added support for onfi timing mode configuration
- Added clock supppport
- Added support for multiple chipselects
Changes in v3:
- Removed unused variables
- Avoided busy loop and used jifies based implementation
- Fixed compiler warnings "right shift count >= width of type"
- Removed unneeded codei and improved error reporting
- Added onfi version check to ensure reading the valid address cycles
Changes in v2:
- Added missing of.h to avoid kbuild system report erro
---
drivers/mtd/nand/Kconfig | 8 +
drivers/mtd/nand/Makefile | 1 +
drivers/mtd/nand/arasan_nand.c | 932 +++++++++++++++++++++++++++++++++++++++++
3 files changed, 941 insertions(+)
create mode 100644 drivers/mtd/nand/arasan_nand.c
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index 7b7a887..c4cfca2 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -41,6 +41,14 @@ config MTD_SM_COMMON
tristate
default n
+config MTD_NAND_ARASAN
+ tristate "Support for Arasan Nand Flash controller"
+ depends on HAS_IOMEM
+ depends on HAS_DMA
+ help
+ Enables the driver for the Arasan NAND Flash controller on
+ Zynq UltraScale+ MPSoC.
+
config MTD_NAND_DENALI
tristate
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index cafde6f..7754170 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_MTD_NAND_BCH) += nand_bch.o
obj-$(CONFIG_MTD_NAND_IDS) += nand_ids.o
obj-$(CONFIG_MTD_SM_COMMON) += sm_common.o
+obj-$(CONFIG_MTD_NAND_ARASAN) += arasan_nand.o
obj-$(CONFIG_MTD_NAND_CAFE) += cafe_nand.o
obj-$(CONFIG_MTD_NAND_AMS_DELTA) += ams-delta.o
obj-$(CONFIG_MTD_NAND_DENALI) += denali.o
diff --git a/drivers/mtd/nand/arasan_nand.c b/drivers/mtd/nand/arasan_nand.c
new file mode 100644
index 0000000..2103134
--- /dev/null
+++ b/drivers/mtd/nand/arasan_nand.c
@@ -0,0 +1,932 @@
+/*
+ * Arasan NAND Flash Controller Driver
+ *
+ * Copyright (C) 2014 - 2017 Xilinx, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License version 2 as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/interrupt.h>
+#include <linux/io-64-nonatomic-lo-hi.h>
+#include <linux/module.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/partitions.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+#define DRIVER_NAME "arasan_nand"
+#define EVNT_TIMEOUT_MSEC 1000
+
+#define PKT_OFST 0x00
+#define MEM_ADDR1_OFST 0x04
+#define MEM_ADDR2_OFST 0x08
+#define CMD_OFST 0x0C
+#define PROG_OFST 0x10
+#define INTR_STS_EN_OFST 0x14
+#define INTR_SIG_EN_OFST 0x18
+#define INTR_STS_OFST 0x1C
+#define READY_STS_OFST 0x20
+#define DMA_ADDR1_OFST 0x24
+#define FLASH_STS_OFST 0x28
+#define DATA_PORT_OFST 0x30
+#define ECC_OFST 0x34
+#define ECC_ERR_CNT_OFST 0x38
+#define ECC_SPR_CMD_OFST 0x3C
+#define ECC_ERR_CNT_1BIT_OFST 0x40
+#define ECC_ERR_CNT_2BIT_OFST 0x44
+#define DMA_ADDR0_OFST 0x50
+#define DATA_INTERFACE_OFST 0x6C
+
+#define PKT_CNT_SHIFT 12
+
+#define ECC_ENABLE BIT(31)
+#define DMA_EN_MASK GENMASK(27, 26)
+#define DMA_ENABLE 0x2
+#define DMA_EN_SHIFT 26
+#define REG_PAGE_SIZE_SHIFT 23
+#define REG_PAGE_SIZE_512 0
+#define REG_PAGE_SIZE_1K 5
+#define REG_PAGE_SIZE_2K 1
+#define REG_PAGE_SIZE_4K 2
+#define REG_PAGE_SIZE_8K 3
+#define REG_PAGE_SIZE_16K 4
+#define CMD2_SHIFT 8
+#define ADDR_CYCLES_SHIFT 28
+
+#define XFER_COMPLETE BIT(2)
+#define READ_READY BIT(1)
+#define WRITE_READY BIT(0)
+#define MBIT_ERROR BIT(3)
+
+#define PROG_PGRD BIT(0)
+#define PROG_ERASE BIT(2)
+#define PROG_STATUS BIT(3)
+#define PROG_PGPROG BIT(4)
+#define PROG_RDID BIT(6)
+#define PROG_RDPARAM BIT(7)
+#define PROG_RST BIT(8)
+#define PROG_GET_FEATURE BIT(9)
+#define PROG_SET_FEATURE BIT(10)
+
+#define PG_ADDR_SHIFT 16
+#define BCH_MODE_SHIFT 25
+#define BCH_EN_SHIFT 27
+#define ECC_SIZE_SHIFT 16
+
+#define MEM_ADDR_MASK GENMASK(7, 0)
+#define BCH_MODE_MASK GENMASK(27, 25)
+
+#define CS_MASK GENMASK(31, 30)
+#define CS_SHIFT 30
+
+#define PAGE_ERR_CNT_MASK GENMASK(16, 8)
+#define PKT_ERR_CNT_MASK GENMASK(7, 0)
+
+#define NVDDR_MODE BIT(9)
+#define NVDDR_TIMING_MODE_SHIFT 3
+
+#define ONFI_ID_LEN 8
+#define TEMP_BUF_SIZE 1024
+#define NVDDR_MODE_PACKET_SIZE 8
+#define SDR_MODE_PACKET_SIZE 4
+
+#define ONFI_DATA_INTERFACE_NVDDR BIT(4)
+#define EVENT_MASK (XFER_COMPLETE | READ_READY | WRITE_READY | MBIT_ERROR)
+
+/**
+ * struct anfc_nand_chip - Defines the nand chip related information
+ * @node: used to store NAND chips into a list.
+ * @chip: NAND chip information structure.
+ * @bch: Bch / Hamming mode enable/disable.
+ * @bchmode: Bch mode.
+ * @eccval: Ecc config value.
+ * @raddr_cycles: Row address cycle information.
+ * @caddr_cycles: Column address cycle information.
+ * @pktsize: Packet size for read / write operation.
+ * @csnum: chipselect number to be used.
+ * @spktsize: Packet size in ddr mode for status operation.
+ * @inftimeval Data interface and timing mode information
+ */
+struct anfc_nand_chip {
+ struct list_head node;
+ struct nand_chip chip;
+ bool bch;
+ u32 bchmode;
+ u32 eccval;
+ u16 raddr_cycles;
+ u16 caddr_cycles;
+ u32 pktsize;
+ int csnum;
+ u32 spktsize;
+ u32 inftimeval;
+};
+
+/**
+ * struct anfc - Defines the Arasan NAND flash driver instance
+ * @controller: base controller structure.
+ * @chips: list of all nand chips attached to the ctrler.
+ * @dev: Pointer to the device structure.
+ * @base: Virtual address of the NAND flash device.
+ * @curr_cmd: Current command issued.
+ * @clk_sys: Pointer to the system clock.
+ * @clk_flash: Pointer to the flash clock.
+ * @dma: Dma enable/disable.
+ * @iswriteoob: Identifies if oob write operation is required.
+ * @buf: Buffer used for read/write byte operations.
+ * @irq: irq number
+ * @bufshift: Variable used for indexing buffer operation
+ * @csnum: Chip select number currently inuse.
+ * @event: Completion event for nand status events.
+ */
+struct anfc {
+ struct nand_hw_control controller;
+ struct list_head chips;
+ struct device *dev;
+ void __iomem *base;
+ int curr_cmd;
+ struct clk *clk_sys;
+ struct clk *clk_flash;
+ bool dma;
+ bool iswriteoob;
+ u8 buf[TEMP_BUF_SIZE];
+ int irq;
+ u32 bufshift;
+ int csnum;
+ struct completion event;
+};
+
+static int anfc_ooblayout_ecc(struct mtd_info *mtd, int section,
+ struct mtd_oob_region *oobregion)
+{
+ struct nand_chip *nand = mtd_to_nand(mtd);
+
+ if (section)
+ return -ERANGE;
+
+ oobregion->length = nand->ecc.total;
+ oobregion->offset = mtd->oobsize - oobregion->length;
+
+ return 0;
+}
+
+static int anfc_ooblayout_free(struct mtd_info *mtd, int section,
+ struct mtd_oob_region *oobregion)
+{
+ struct nand_chip *nand = mtd_to_nand(mtd);
+
+ if (section)
+ return -ERANGE;
+
+ oobregion->offset = 2;
+ oobregion->length = mtd->oobsize - nand->ecc.total - 2;
+
+ return 0;
+}
+
+static const struct mtd_ooblayout_ops anfc_ooblayout_ops = {
+ .ecc = anfc_ooblayout_ecc,
+ .free = anfc_ooblayout_free,
+};
+
+static inline struct anfc_nand_chip *to_anfc_nand(struct nand_chip *nand)
+{
+ return container_of(nand, struct anfc_nand_chip, chip);
+}
+
+static inline struct anfc *to_anfc(struct nand_hw_control *ctrl)
+{
+ return container_of(ctrl, struct anfc, controller);
+}
+
+static u8 anfc_page(u32 pagesize)
+{
+ switch (pagesize) {
+ case 512:
+ return REG_PAGE_SIZE_512;
+ case 1024:
+ return REG_PAGE_SIZE_1K;
+ case 2048:
+ return REG_PAGE_SIZE_2K;
+ case 4096:
+ return REG_PAGE_SIZE_4K;
+ case 8192:
+ return REG_PAGE_SIZE_8K;
+ case 16384:
+ return REG_PAGE_SIZE_16K;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static inline void anfc_enable_intrs(struct anfc *nfc, u32 val)
+{
+ writel(val, nfc->base + INTR_STS_EN_OFST);
+ writel(val, nfc->base + INTR_SIG_EN_OFST);
+}
+
+static inline void anfc_config_ecc(struct anfc *nfc, int on)
+{
+ u32 val;
+
+ val = readl(nfc->base + CMD_OFST);
+ if (on)
+ val |= ECC_ENABLE;
+ else
+ val &= ~ECC_ENABLE;
+ writel(val, nfc->base + CMD_OFST);
+}
+
+static inline void anfc_config_dma(struct anfc *nfc, int on)
+{
+ u32 val;
+
+ val = readl(nfc->base + CMD_OFST);
+ val &= ~DMA_EN_MASK;
+ if (on)
+ val |= DMA_ENABLE << DMA_EN_SHIFT;
+ writel(val, nfc->base + CMD_OFST);
+}
+
+static inline int anfc_wait_for_event(struct anfc *nfc)
+{
+ return wait_for_completion_timeout(&nfc->event,
+ msecs_to_jiffies(EVNT_TIMEOUT_MSEC));
+}
+
+static inline void anfc_setpktszcnt(struct anfc *nfc, u32 pktsize,
+ u32 pktcount)
+{
+ writel(pktsize | (pktcount << PKT_CNT_SHIFT), nfc->base + PKT_OFST);
+}
+
+static inline void anfc_set_eccsparecmd(struct anfc *nfc,
+ struct anfc_nand_chip *achip, u8 cmd1, u8 cmd2)
+{
+ writel(cmd1 | (cmd2 << CMD2_SHIFT) |
+ (achip->caddr_cycles << ADDR_CYCLES_SHIFT),
+ nfc->base + ECC_SPR_CMD_OFST);
+}
+
+static void anfc_setpagecoladdr(struct anfc *nfc, u32 page, u16 col)
+{
+ u32 val;
+
+ writel(col | (page << PG_ADDR_SHIFT), nfc->base + MEM_ADDR1_OFST);
+
+ val = readl(nfc->base + MEM_ADDR2_OFST);
+ val = (val & ~MEM_ADDR_MASK) |
+ ((page >> PG_ADDR_SHIFT) & MEM_ADDR_MASK);
+ writel(val, nfc->base + MEM_ADDR2_OFST);
+}
+
+static void anfc_prepare_cmd(struct anfc *nfc, u8 cmd1, u8 cmd2, u8 dmamode,
+ u32 pagesize, u8 addrcycles)
+{
+ u32 regval;
+
+ regval = cmd1 | (cmd2 << CMD2_SHIFT);
+ if (dmamode && nfc->dma)
+ regval |= DMA_ENABLE << DMA_EN_SHIFT;
+ regval |= addrcycles << ADDR_CYCLES_SHIFT;
+ regval |= anfc_page(pagesize) << REG_PAGE_SIZE_SHIFT;
+ writel(regval, nfc->base + CMD_OFST);
+}
+
+static int anfc_write_oob(struct mtd_info *mtd, struct nand_chip *chip,
+ int page)
+{
+ struct anfc *nfc = to_anfc(chip->controller);
+
+ nfc->iswriteoob = true;
+ chip->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize, page);
+ chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
+ nfc->iswriteoob = false;
+
+ return 0;
+}
+
+static void anfc_rw_buf_dma(struct mtd_info *mtd, uint8_t *buf, int len,
+ int operation, u32 prog)
+{
+ dma_addr_t paddr;
+ struct nand_chip *chip = mtd_to_nand(mtd);
+ struct anfc *nfc = to_anfc(chip->controller);
+ struct anfc_nand_chip *achip = to_anfc_nand(chip);
+ u32 eccintr = 0, dir;
+ u32 pktsize = len, pktcount = 1;
+
+ if ((nfc->curr_cmd == NAND_CMD_READ0) ||
+ ((nfc->curr_cmd == NAND_CMD_SEQIN) && !nfc->iswriteoob)) {
+ pktsize = achip->pktsize;
+ pktcount = DIV_ROUND_UP(mtd->writesize, pktsize);
+ }
+ anfc_setpktszcnt(nfc, pktsize, pktcount);
+
+ if (!achip->bch && (nfc->curr_cmd == NAND_CMD_READ0))
+ eccintr = MBIT_ERROR;
+
+ if (operation)
+ dir = DMA_FROM_DEVICE;
+ else
+ dir = DMA_TO_DEVICE;
+
+ paddr = dma_map_single(nfc->dev, buf, len, dir);
+ if (dma_mapping_error(nfc->dev, paddr)) {
+ dev_err(nfc->dev, "Read buffer mapping error");
+ return;
+ }
+ lo_hi_writeq(paddr, nfc->base + DMA_ADDR0_OFST);
+ anfc_enable_intrs(nfc, (XFER_COMPLETE | eccintr));
+ writel(prog, nfc->base + PROG_OFST);
+ anfc_wait_for_event(nfc);
+ dma_unmap_single(nfc->dev, paddr, len, dir);
+}
+
+static void anfc_rw_buf_pio(struct mtd_info *mtd, uint8_t *buf, int len,
+ int operation, int prog)
+{
+ struct nand_chip *chip = mtd_to_nand(mtd);
+ struct anfc *nfc = to_anfc(chip->controller);
+ struct anfc_nand_chip *achip = to_anfc_nand(chip);
+ u32 *bufptr = (u32 *)buf;
+ u32 cnt = 0, intr = 0;
+ u32 pktsize = len, pktcount = 1;
+
+ anfc_config_dma(nfc, 0);
+
+ if ((nfc->curr_cmd == NAND_CMD_READ0) ||
+ ((nfc->curr_cmd == NAND_CMD_SEQIN) && !nfc->iswriteoob)) {
+ pktsize = achip->pktsize;
+ pktcount = DIV_ROUND_UP(mtd->writesize, pktsize);
+ }
+ anfc_setpktszcnt(nfc, pktsize, pktcount);
+
+ if (!achip->bch && (nfc->curr_cmd == NAND_CMD_READ0))
+ intr = MBIT_ERROR;
+
+ if (operation)
+ intr |= READ_READY;
+ else
+ intr |= WRITE_READY;
+
+ anfc_enable_intrs(nfc, intr);
+ writel(prog, nfc->base + PROG_OFST);
+
+ while (cnt < pktcount) {
+ anfc_wait_for_event(nfc);
+ cnt++;
+ if (cnt == pktcount)
+ anfc_enable_intrs(nfc, XFER_COMPLETE);
+ if (operation)
+ ioread32_rep(nfc->base + DATA_PORT_OFST, bufptr,
+ pktsize/4);
+ else
+ iowrite32_rep(nfc->base + DATA_PORT_OFST, bufptr,
+ pktsize/4);
+ bufptr += (pktsize / 4);
+ if (cnt < pktcount)
+ anfc_enable_intrs(nfc, intr);
+ }
+
+ anfc_wait_for_event(nfc);
+}
+
+static void anfc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
+{
+ struct nand_chip *chip = mtd_to_nand(mtd);
+ struct anfc *nfc = to_anfc(chip->controller);
+
+ if (nfc->dma && !is_vmalloc_addr(buf))
+ anfc_rw_buf_dma(mtd, buf, len, 1, PROG_PGRD);
+ else
+ anfc_rw_buf_pio(mtd, buf, len, 1, PROG_PGRD);
+}
+
+static void anfc_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
+{
+ struct nand_chip *chip = mtd_to_nand(mtd);
+ struct anfc *nfc = to_anfc(chip->controller);
+
+ if (nfc->dma && !is_vmalloc_addr(buf))
+ anfc_rw_buf_dma(mtd, (char *)buf, len, 0, PROG_PGPROG);
+ else
+ anfc_rw_buf_pio(mtd, (char *)buf, len, 0, PROG_PGPROG);
+}
+
+static int anfc_read_page_hwecc(struct mtd_info *mtd,
+ struct nand_chip *chip, uint8_t *buf,
+ int oob_required, int page)
+{
+ u32 val;
+ struct anfc *nfc = to_anfc(chip->controller);
+ struct anfc_nand_chip *achip = to_anfc_nand(chip);
+
+ anfc_set_eccsparecmd(nfc, achip, NAND_CMD_RNDOUT, NAND_CMD_RNDOUTSTART);
+ anfc_config_ecc(nfc, 1);
+
+ val = readl(nfc->base + CMD_OFST);
+ val = val | ECC_ENABLE;
+ writel(val, nfc->base + CMD_OFST);
+
+ chip->read_buf(mtd, buf, mtd->writesize);
+
+ val = readl(nfc->base + ECC_ERR_CNT_OFST);
+ if (achip->bch) {
+ mtd->ecc_stats.corrected += val & PAGE_ERR_CNT_MASK;
+ } else {
+ val = readl(nfc->base + ECC_ERR_CNT_1BIT_OFST);
+ mtd->ecc_stats.corrected += val;
+ val = readl(nfc->base + ECC_ERR_CNT_2BIT_OFST);
+ mtd->ecc_stats.failed += val;
+ /* Clear ecc error count register 1Bit, 2Bit */
+ writel(0x0, nfc->base + ECC_ERR_CNT_1BIT_OFST);
+ writel(0x0, nfc->base + ECC_ERR_CNT_2BIT_OFST);
+ }
+
+ if (oob_required)
+ chip->ecc.read_oob(mtd, chip, page);
+
+ return 0;
+}
+
+static int anfc_write_page_hwecc(struct mtd_info *mtd,
+ struct nand_chip *chip, const uint8_t *buf,
+ int oob_required, int page)
+{
+ int ret;
+ struct anfc *nfc = to_anfc(chip->controller);
+ struct anfc_nand_chip *achip = to_anfc_nand(chip);
+ uint8_t *ecc_calc = chip->buffers->ecccalc;
+
+ anfc_set_eccsparecmd(nfc, achip, NAND_CMD_RNDIN, 0);
+ anfc_config_ecc(nfc, 1);
+
+ chip->write_buf(mtd, buf, mtd->writesize);
+
+ if (oob_required) {
+ chip->waitfunc(mtd, chip);
+ chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page);
+ chip->read_buf(mtd, ecc_calc, mtd->oobsize);
+ ret = mtd_ooblayout_set_eccbytes(mtd, ecc_calc, chip->oob_poi,
+ 0, chip->ecc.total);
+ if (ret)
+ return ret;
+ chip->ecc.write_oob(mtd, chip, page);
+ }
+
+ return 0;
+}
+
+static u8 anfc_read_byte(struct mtd_info *mtd)
+{
+ struct nand_chip *chip = mtd_to_nand(mtd);
+ struct anfc *nfc = to_anfc(chip->controller);
+
+ return nfc->buf[nfc->bufshift++];
+}
+
+static int anfc_ecc_init(struct mtd_info *mtd,
+ struct nand_ecc_ctrl *ecc)
+{
+ u32 ecc_addr;
+ unsigned int bchmode, steps;
+ struct nand_chip *chip = mtd_to_nand(mtd);
+ struct anfc_nand_chip *achip = to_anfc_nand(chip);
+
+ ecc->mode = NAND_ECC_HW;
+ ecc->read_page = anfc_read_page_hwecc;
+ ecc->write_page = anfc_write_page_hwecc;
+ ecc->write_oob = anfc_write_oob;
+ mtd_set_ooblayout(mtd, &anfc_ooblayout_ops);
+
+ steps = mtd->writesize / chip->ecc_step_ds;
+
+ switch (chip->ecc_strength_ds) {
+ case 12:
+ bchmode = 0x1;
+ break;
+ case 8:
+ bchmode = 0x2;
+ break;
+ case 4:
+ bchmode = 0x3;
+ break;
+ case 24:
+ bchmode = 0x4;
+ break;
+ default:
+ bchmode = 0x0;
+ }
+
+ if (!bchmode)
+ ecc->total = 3 * steps;
+ else
+ ecc->total =
+ DIV_ROUND_UP(fls(8 * chip->ecc_step_ds) *
+ chip->ecc_strength_ds * steps, 8);
+
+ ecc->strength = chip->ecc_strength_ds;
+ ecc->size = chip->ecc_step_ds;
+ ecc->bytes = ecc->total / steps;
+ ecc->steps = steps;
+ achip->bchmode = bchmode;
+ achip->bch = achip->bchmode;
+ ecc_addr = mtd->writesize + (mtd->oobsize - ecc->total);
+
+ achip->eccval = ecc_addr | (ecc->total << ECC_SIZE_SHIFT) |
+ (achip->bch << BCH_EN_SHIFT);
+
+ if (chip->ecc_step_ds >= 1024)
+ achip->pktsize = 1024;
+ else
+ achip->pktsize = 512;
+
+ return 0;
+}
+
+static void anfc_cmd_function(struct mtd_info *mtd,
+ unsigned int cmd, int column, int page_addr)
+{
+ struct nand_chip *chip = mtd_to_nand(mtd);
+ struct anfc_nand_chip *achip = to_anfc_nand(chip);
+ struct anfc *nfc = to_anfc(chip->controller);
+ bool wait = false, read = false;
+ u32 addrcycles, prog;
+ u32 *bufptr = (u32 *)nfc->buf;
+
+ nfc->bufshift = 0;
+ nfc->curr_cmd = cmd;
+
+ if (page_addr == -1)
+ page_addr = 0;
+ if (column == -1)
+ column = 0;
+
+ switch (cmd) {
+ case NAND_CMD_RESET:
+ anfc_prepare_cmd(nfc, cmd, 0, 0, 0, 0);
+ prog = PROG_RST;
+ wait = true;
+ break;
+ case NAND_CMD_SEQIN:
+ addrcycles = achip->raddr_cycles + achip->caddr_cycles;
+ anfc_prepare_cmd(nfc, cmd, NAND_CMD_PAGEPROG, 1,
+ mtd->writesize, addrcycles);
+ anfc_setpagecoladdr(nfc, page_addr, column);
+ break;
+ case NAND_CMD_READOOB:
+ column += mtd->writesize;
+ case NAND_CMD_READ0:
+ case NAND_CMD_READ1:
+ addrcycles = achip->raddr_cycles + achip->caddr_cycles;
+ anfc_prepare_cmd(nfc, NAND_CMD_READ0, NAND_CMD_READSTART, 1,
+ mtd->writesize, addrcycles);
+ anfc_setpagecoladdr(nfc, page_addr, column);
+ break;
+ case NAND_CMD_RNDOUT:
+ anfc_prepare_cmd(nfc, cmd, NAND_CMD_RNDOUTSTART, 1,
+ mtd->writesize, 2);
+ anfc_setpagecoladdr(nfc, page_addr, column);
+ break;
+ case NAND_CMD_PARAM:
+ anfc_prepare_cmd(nfc, cmd, 0, 0, 0, 1);
+ anfc_setpagecoladdr(nfc, page_addr, column);
+ anfc_rw_buf_pio(mtd, nfc->buf,
+ (4 * sizeof(struct nand_onfi_params)),
+ 1, PROG_RDPARAM);
+ break;
+ case NAND_CMD_READID:
+ anfc_prepare_cmd(nfc, cmd, 0, 0, 0, 1);
+ anfc_setpagecoladdr(nfc, page_addr, column);
+ anfc_rw_buf_pio(mtd, nfc->buf, ONFI_ID_LEN, 1, PROG_RDID);
+ break;
+ case NAND_CMD_ERASE1:
+ addrcycles = achip->raddr_cycles;
+ prog = PROG_ERASE;
+ anfc_prepare_cmd(nfc, cmd, NAND_CMD_ERASE2, 0, 0, addrcycles);
+ column = page_addr & 0xffff;
+ page_addr = (page_addr >> PG_ADDR_SHIFT) & 0xffff;
+ anfc_setpagecoladdr(nfc, page_addr, column);
+ wait = true;
+ break;
+ case NAND_CMD_STATUS:
+ anfc_prepare_cmd(nfc, cmd, 0, 0, 0, 0);
+ anfc_setpktszcnt(nfc, achip->spktsize/4, 1);
+ anfc_setpagecoladdr(nfc, page_addr, column);
+ prog = PROG_STATUS;
+ wait = read = true;
+ break;
+ case NAND_CMD_GET_FEATURES:
+ anfc_prepare_cmd(nfc, cmd, 0, 0, 0, 1);
+ anfc_setpagecoladdr(nfc, page_addr, column);
+ anfc_rw_buf_pio(mtd, nfc->buf, achip->spktsize, 1,
+ PROG_GET_FEATURE);
+ break;
+ case NAND_CMD_SET_FEATURES:
+ anfc_prepare_cmd(nfc, cmd, 0, 0, 0, 1);
+ anfc_setpagecoladdr(nfc, page_addr, column);
+ break;
+ default:
+ return;
+ }
+
+ if (wait) {
+ anfc_enable_intrs(nfc, XFER_COMPLETE);
+ writel(prog, nfc->base + PROG_OFST);
+ anfc_wait_for_event(nfc);
+ }
+
+ if (read)
+ bufptr[0] = readl(nfc->base + FLASH_STS_OFST);
+}
+
+static void anfc_select_chip(struct mtd_info *mtd, int num)
+{
+ u32 val;
+ struct nand_chip *chip = mtd_to_nand(mtd);
+ struct anfc_nand_chip *achip = to_anfc_nand(chip);
+ struct anfc *nfc = to_anfc(chip->controller);
+
+ if (num == -1)
+ return;
+
+ val = readl(nfc->base + MEM_ADDR2_OFST);
+ val &= (val & ~(CS_MASK | BCH_MODE_MASK));
+ val |= (achip->csnum << CS_SHIFT) | (achip->bchmode << BCH_MODE_SHIFT);
+ writel(val, nfc->base + MEM_ADDR2_OFST);
+ nfc->csnum = achip->csnum;
+ writel(achip->eccval, nfc->base + ECC_OFST);
+ writel(achip->inftimeval, nfc->base + DATA_INTERFACE_OFST);
+}
+
+static irqreturn_t anfc_irq_handler(int irq, void *ptr)
+{
+ struct anfc *nfc = ptr;
+ u32 status;
+
+ status = readl(nfc->base + INTR_STS_OFST);
+ if (status & EVENT_MASK) {
+ complete(&nfc->event);
+ writel((status & EVENT_MASK), nfc->base + INTR_STS_OFST);
+ writel(0, nfc->base + INTR_STS_EN_OFST);
+ writel(0, nfc->base + INTR_SIG_EN_OFST);
+ return IRQ_HANDLED;
+ }
+
+ return IRQ_NONE;
+}
+
+static int anfc_onfi_set_features(struct mtd_info *mtd, struct nand_chip *chip,
+ int addr, uint8_t *subfeature_param)
+{
+ struct anfc_nand_chip *achip = to_anfc_nand(chip);
+ int status;
+
+ if (!chip->onfi_version)
+ return -EINVAL;
+
+ if (!(le16_to_cpu(chip->onfi_params.opt_cmd) &
+ ONFI_OPT_CMD_SET_GET_FEATURES))
+ return -EINVAL;
+
+ chip->cmdfunc(mtd, NAND_CMD_SET_FEATURES, addr, -1);
+ anfc_rw_buf_pio(mtd, subfeature_param, achip->spktsize,
+ 0, PROG_SET_FEATURE);
+ status = chip->waitfunc(mtd, chip);
+ if (status & NAND_STATUS_FAIL)
+ return -EIO;
+
+ return 0;
+}
+
+static int anfc_init_timing_mode(struct anfc *nfc,
+ struct anfc_nand_chip *achip)
+{
+ int mode, err;
+ unsigned int feature[2];
+ u32 inftimeval;
+ struct nand_chip *chip = &achip->chip;
+ struct mtd_info *mtd = nand_to_mtd(chip);
+
+ memset(feature, 0, NVDDR_MODE_PACKET_SIZE);
+ /* Get nvddr timing modes */
+ mode = onfi_get_sync_timing_mode(chip) & 0xff;
+ if (!mode) {
+ mode = fls(onfi_get_async_timing_mode(chip)) - 1;
+ inftimeval = mode;
+ } else {
+ mode = fls(mode) - 1;
+ inftimeval = NVDDR_MODE | (mode << NVDDR_TIMING_MODE_SHIFT);
+ mode |= ONFI_DATA_INTERFACE_NVDDR;
+ }
+
+ feature[0] = mode;
+ chip->select_chip(mtd, achip->csnum);
+ err = chip->onfi_set_features(mtd, chip, ONFI_FEATURE_ADDR_TIMING_MODE,
+ (uint8_t *)feature);
+ chip->select_chip(mtd, -1);
+ if (err)
+ return err;
+
+ achip->inftimeval = inftimeval;
+
+ if (mode & ONFI_DATA_INTERFACE_NVDDR)
+ achip->spktsize = NVDDR_MODE_PACKET_SIZE;
+
+ return 0;
+}
+
+static int anfc_nand_chip_init(struct anfc *nfc,
+ struct anfc_nand_chip *anand_chip,
+ struct device_node *np)
+{
+ struct nand_chip *chip = &anand_chip->chip;
+ struct mtd_info *mtd = nand_to_mtd(chip);
+ int ret;
+
+ ret = of_property_read_u32(np, "reg", &anand_chip->csnum);
+ if (ret) {
+ dev_err(nfc->dev, "can't get chip-select\n");
+ return -ENXIO;
+ }
+
+ mtd->name = devm_kasprintf(nfc->dev, GFP_KERNEL, "arasan_nand.%d",
+ anand_chip->csnum);
+ mtd->dev.parent = nfc->dev;
+
+ chip->cmdfunc = anfc_cmd_function;
+ chip->chip_delay = 30;
+ chip->controller = &nfc->controller;
+ chip->read_buf = anfc_read_buf;
+ chip->write_buf = anfc_write_buf;
+ chip->read_byte = anfc_read_byte;
+ chip->options = NAND_BUSWIDTH_AUTO | NAND_NO_SUBPAGE_WRITE;
+ chip->bbt_options = NAND_BBT_USE_FLASH;
+ chip->select_chip = anfc_select_chip;
+ chip->onfi_set_features = anfc_onfi_set_features;
+ nand_set_flash_node(chip, np);
+
+ anand_chip->spktsize = SDR_MODE_PACKET_SIZE;
+ ret = nand_scan_ident(mtd, 1, NULL);
+ if (ret) {
+ dev_err(nfc->dev, "nand_scan_ident for NAND failed\n");
+ return ret;
+ }
+ if (chip->onfi_version) {
+ anand_chip->raddr_cycles = chip->onfi_params.addr_cycles & 0xf;
+ anand_chip->caddr_cycles =
+ (chip->onfi_params.addr_cycles >> 4) & 0xf;
+ } else {
+ /* For non-ONFI devices, configuring the address cyles as 5 */
+ anand_chip->raddr_cycles = 3;
+ anand_chip->caddr_cycles = 2;
+ }
+
+ ret = anfc_init_timing_mode(nfc, anand_chip);
+ if (ret) {
+ dev_err(nfc->dev, "timing mode init failed\n");
+ return ret;
+ }
+
+ ret = anfc_ecc_init(mtd, &chip->ecc);
+ if (ret)
+ return ret;
+
+ ret = nand_scan_tail(mtd);
+ if (ret) {
+ dev_err(nfc->dev, "nand_scan_tail for NAND failed\n");
+ return ret;
+ }
+
+ return mtd_device_register(mtd, NULL, 0);
+}
+
+static int anfc_probe(struct platform_device *pdev)
+{
+ struct anfc *nfc;
+ struct anfc_nand_chip *anand_chip;
+ struct device_node *np = pdev->dev.of_node, *child;
+ struct resource *res;
+ int err;
+
+ nfc = devm_kzalloc(&pdev->dev, sizeof(*nfc), GFP_KERNEL);
+ if (!nfc)
+ return -ENOMEM;
+
+ init_waitqueue_head(&nfc->controller.wq);
+ INIT_LIST_HEAD(&nfc->chips);
+ init_completion(&nfc->event);
+ nfc->dev = &pdev->dev;
+ platform_set_drvdata(pdev, nfc);
+ nfc->csnum = -1;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ nfc->base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(nfc->base))
+ return PTR_ERR(nfc->base);
+ nfc->dma = of_property_read_bool(pdev->dev.of_node,
+ "arasan,has-mdma");
+ nfc->irq = platform_get_irq(pdev, 0);
+ if (nfc->irq < 0) {
+ dev_err(&pdev->dev, "platform_get_irq failed\n");
+ return -ENXIO;
+ }
+ err = devm_request_irq(&pdev->dev, nfc->irq, anfc_irq_handler,
+ 0, "arasannfc", nfc);
+ if (err)
+ return err;
+ nfc->clk_sys = devm_clk_get(&pdev->dev, "clk_sys");
+ if (IS_ERR(nfc->clk_sys)) {
+ dev_err(&pdev->dev, "sys clock not found.\n");
+ return PTR_ERR(nfc->clk_sys);
+ }
+
+ nfc->clk_flash = devm_clk_get(&pdev->dev, "clk_flash");
+ if (IS_ERR(nfc->clk_flash)) {
+ dev_err(&pdev->dev, "flash clock not found.\n");
+ return PTR_ERR(nfc->clk_flash);
+ }
+
+ err = clk_prepare_enable(nfc->clk_sys);
+ if (err) {
+ dev_err(&pdev->dev, "Unable to enable sys clock.\n");
+ return err;
+ }
+
+ err = clk_prepare_enable(nfc->clk_flash);
+ if (err) {
+ dev_err(&pdev->dev, "Unable to enable flash clock.\n");
+ goto clk_dis_sys;
+ }
+
+ for_each_available_child_of_node(np, child) {
+ anand_chip = devm_kzalloc(&pdev->dev, sizeof(*anand_chip),
+ GFP_KERNEL);
+ if (!anand_chip) {
+ of_node_put(child);
+ err = -ENOMEM;
+ goto nandchip_clean_up;
+ }
+
+ err = anfc_nand_chip_init(nfc, anand_chip, child);
+ if (err) {
+ devm_kfree(&pdev->dev, anand_chip);
+ continue;
+ }
+
+ list_add_tail(&anand_chip->node, &nfc->chips);
+ }
+
+ return 0;
+
+nandchip_clean_up:
+ list_for_each_entry(anand_chip, &nfc->chips, node)
+ nand_release(nand_to_mtd(&anand_chip->chip));
+ clk_disable_unprepare(nfc->clk_flash);
+clk_dis_sys:
+ clk_disable_unprepare(nfc->clk_sys);
+
+ return err;
+}
+
+static int anfc_remove(struct platform_device *pdev)
+{
+ struct anfc *nfc = platform_get_drvdata(pdev);
+ struct anfc_nand_chip *anand_chip;
+
+ list_for_each_entry(anand_chip, &nfc->chips, node)
+ nand_release(nand_to_mtd(&anand_chip->chip));
+
+ clk_disable_unprepare(nfc->clk_sys);
+ clk_disable_unprepare(nfc->clk_flash);
+
+ return 0;
+}
+
+static const struct of_device_id anfc_ids[] = {
+ { .compatible = "arasan,nfc-v3p10" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, anfc_ids);
+
+static struct platform_driver anfc_driver = {
+ .driver = {
+ .name = DRIVER_NAME,
+ .of_match_table = anfc_ids,
+ },
+ .probe = anfc_probe,
+ .remove = anfc_remove,
+};
+module_platform_driver(anfc_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Xilinx, Inc");
+MODULE_DESCRIPTION("Arasan NAND Flash Controller Driver");
--
2.7.4
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* Re: [PATCH v1 3/3] thermal: zx2967: add thermal driver for ZTE's zx2967 family
From: Shawn Guo @ 2017-01-09 3:00 UTC (permalink / raw)
To: Baoyou Xie
Cc: rui.zhang, edubezval, robh+dt, mark.rutland, jun.nie, gregkh,
davem, geert+renesas, akpm, mchehab, linux, linux-pm, devicetree,
linux-kernel, linux-arm-kernel, xie.baoyou, chen.chaokai,
wang.qiang01
In-Reply-To: <1483767488-19778-3-git-send-email-baoyou.xie@linaro.org>
On Sat, Jan 07, 2017 at 01:38:08PM +0800, Baoyou Xie wrote:
> This patch adds thermal driver for ZTE's zx2967 family.
>
> Signed-off-by: Baoyou Xie <baoyou.xie@linaro.org>
> ---
> drivers/thermal/Kconfig | 6 +
> drivers/thermal/Makefile | 1 +
> drivers/thermal/zx2967_thermal.c | 241 +++++++++++++++++++++++++++++++++++++++
> 3 files changed, 248 insertions(+)
> create mode 100644 drivers/thermal/zx2967_thermal.c
>
> diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
> index 18f2de6..0dd597e 100644
> --- a/drivers/thermal/Kconfig
> +++ b/drivers/thermal/Kconfig
> @@ -445,3 +445,9 @@ config BCM2835_THERMAL
> Support for thermal sensors on Broadcom bcm2835 SoCs.
>
> endif
> +
> +config ZX2967_THERMAL
> + tristate "Thermal sensors on zx2967 SoC"
> + depends on ARCH_ZX
> + help
> + Support for thermal sensors on ZTE zx2967 SoCs.
> diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
> index 677c6d9..c00c05e 100644
> --- a/drivers/thermal/Makefile
> +++ b/drivers/thermal/Makefile
> @@ -57,3 +57,4 @@ obj-$(CONFIG_HISI_THERMAL) += hisi_thermal.o
> obj-$(CONFIG_MTK_THERMAL) += mtk_thermal.o
> obj-$(CONFIG_GENERIC_ADC_THERMAL) += thermal-generic-adc.o
> obj-$(CONFIG_BCM2835_THERMAL) += bcm2835_thermal.o
> +obj-$(CONFIG_ZX2967_THERMAL) += zx2967_thermal.o
> diff --git a/drivers/thermal/zx2967_thermal.c b/drivers/thermal/zx2967_thermal.c
> new file mode 100644
> index 0000000..1aef070
> --- /dev/null
> +++ b/drivers/thermal/zx2967_thermal.c
> @@ -0,0 +1,241 @@
> +/*
> + * ZTE's zx2967 family thermal sensor driver
> + *
> + * Copyright (C) 2017 ZTE Ltd.
> + *
> + * Author: Baoyou Xie <baoyou.xie@linaro.org>
> + *
> + * License terms: GNU General Public License (GPL) version 2
> + */
> +
> +#include <linux/module.h>
> +#include <linux/device.h>
> +#include <linux/io.h>
> +#include <linux/err.h>
> +#include <linux/clk.h>
> +#include <linux/delay.h>
> +#include <linux/platform_device.h>
> +#include <linux/thermal.h>
> +
> +/* DCF Control Register */
> +#define ZX2967_THERMAL_DCF 0x4
> +
> +/* Selection Register */
> +#define ZX2967_THERMAL_SEL 0x8
> +
> +/* Control Register */
> +#define ZX2967_THERMAL_CTRL 0x10
> +
> +#define ZX2967_THERMAL_ID_MASK (0x18)
> +
> +struct zx2967_thermal_sensor {
> + struct zx2967_thermal_priv *priv;
> + struct thermal_zone_device *tzd;
> + int id;
> +};
> +
> +#define NUM_SENSORS 1
> +
> +struct zx2967_thermal_priv {
> + struct zx2967_thermal_sensor sensors[NUM_SENSORS];
What's the point of defining an array with only one element?
> + struct mutex lock;
> + struct clk *clk_gate;
> + struct clk *pclk;
> + void __iomem *regs;
> + struct pinctrl *pinmux_dvi0_d3;
> + struct pinctrl *pinmux_dvi0_d4;
> + struct pinctrl *pinmux_dvi0_d5;
These three pointers are not used.
> +};
> +
> +static int zx2967_thermal_suspend(struct device *dev)
> +{
> + struct platform_device *pdev = to_platform_device(dev);
> + struct zx2967_thermal_priv *priv = platform_get_drvdata(pdev);
> +
> + if (priv && priv->pclk)
> + clk_disable_unprepare(priv->pclk);
> +
> + if (priv && priv->clk_gate)
> + clk_disable_unprepare(priv->clk_gate);
> + dev_info(dev, "suspended\n");
Noisy message.
> +
> + return 0;
> +}
> +
> +static int zx2967_thermal_resume(struct device *dev)
> +{
> + struct platform_device *pdev = to_platform_device(dev);
> + struct zx2967_thermal_priv *priv = platform_get_drvdata(pdev);
> + int error;
> +
> + error = clk_prepare_enable(priv->clk_gate);
> + if (error)
> + return error;
> +
> + error = clk_prepare_enable(priv->pclk);
> + if (error)
> + return error;
clk_disable_unprepare() should be called for priv->clk_gate before
returning here.
> +
> + dev_info(dev, "resumed\n");
> +
> + return 0;
> +}
> +
> +static int zx2967_thermal_get_temp(void *data, int *temp)
> +{
> + void __iomem *regs;
> + struct zx2967_thermal_sensor *sensor = data;
> + struct zx2967_thermal_priv *priv = sensor->priv;
> + unsigned long timeout = jiffies + msecs_to_jiffies(100);
> + u32 val, sel_id;
> +
> + regs = priv->regs;
> + mutex_lock(&priv->lock);
> +
> + writel_relaxed(0, regs);
I suggest we have a macro for register at offset 0 as well to improve
the readability.
> + writel_relaxed(2, regs + ZX2967_THERMAL_DCF);
> +
> + val = readl_relaxed(regs + ZX2967_THERMAL_SEL);
> + val &= ~ZX2967_THERMAL_ID_MASK;
> + sel_id = sensor->id ? 8 : 0x10;
> + val |= sel_id;
> + writel_relaxed(val, regs + ZX2967_THERMAL_SEL);
> +
> + usleep_range(100, 300);
> + while (!(readl_relaxed(regs + ZX2967_THERMAL_CTRL) & 0x1000)) {
> + if (time_after(jiffies, timeout)) {
> + pr_err("*** Thermal sensor %d data timeout\n",
> + sensor->id);
dev_err? And drop "*** ".
> + mutex_unlock(&priv->lock);
> + return -EIO;
-ETIMEDOUT?
> + }
> + }
> +
> + writel_relaxed(3, regs + ZX2967_THERMAL_DCF);
> + val = readl_relaxed(regs + ZX2967_THERMAL_CTRL) & 0xfff;
> + writel_relaxed(1, regs);
> +
> + /** Calculate temperature */
> + *temp = DIV_ROUND_CLOSEST((val - 922) * 1000, 1951);
> +
> + mutex_unlock(&priv->lock);
> +
> + return 0;
> +}
> +
> +static struct thermal_zone_of_device_ops zx2967_of_thermal_ops = {
> + .get_temp = zx2967_thermal_get_temp,
> +};
> +
> +static int zx2967_thermal_probe(struct platform_device *pdev)
> +{
> + struct zx2967_thermal_priv *priv;
> + struct resource *res;
> + int ret, i;
> +
> + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
> + if (!priv)
> + return -ENOMEM;
> +
> + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> + priv->regs = devm_ioremap_resource(&pdev->dev, res);
> + if (IS_ERR(priv->regs))
> + return PTR_ERR(priv->regs);
> +
> + priv->clk_gate = devm_clk_get(&pdev->dev, "tempsensor_gate");
> + if (IS_ERR(priv->clk_gate)) {
> + ret = PTR_ERR(priv->clk_gate);
> + dev_err(&pdev->dev, "failed to get clock gate: %d\n", ret);
> + return ret;
> + }
> +
> + ret = clk_prepare_enable(priv->clk_gate);
> + if (ret) {
> + dev_err(&pdev->dev, "failed to enable converter clock: %d\n",
> + ret);
> + return ret;
> + }
> +
> + priv->pclk = devm_clk_get(&pdev->dev, "tempsensor_pclk");
> + if (IS_ERR(priv->pclk)) {
> + ret = PTR_ERR(priv->pclk);
> + dev_err(&pdev->dev, "failed to get apb clock: %d\n", ret);
> + return ret;
> + }
> +
> + ret = clk_prepare_enable(priv->pclk);
> + if (ret) {
> + dev_err(&pdev->dev, "failed to enable converter clock: %d\n",
> + ret);
> + return ret;
The use count of enable and prepare on priv->clk_gate will be
unbalanced.
> + }
> +
> + mutex_init(&priv->lock);
> + for (i = 0; i < NUM_SENSORS; i++) {
> + struct zx2967_thermal_sensor *sensor = &priv->sensors[i];
> +
> + sensor->priv = priv;
> + sensor->id = i;
> + sensor->tzd = thermal_zone_of_sensor_register(&pdev->dev,
> + i,
> + sensor,
> + &zx2967_of_thermal_ops);
> + if (IS_ERR(sensor->tzd)) {
> + ret = PTR_ERR(sensor->tzd);
> + dev_err(&pdev->dev, "failed to register sensor %d: %d\n",
> + i, ret);
> + goto remove_ts;
> + }
> + }
> + platform_set_drvdata(pdev, priv);
> +
> + return 0;
> +
> +remove_ts:
> + for (i--; i >= 0; i--)
> + thermal_zone_of_sensor_unregister(&pdev->dev,
> + priv->sensors[i].tzd);
> +
> + return ret;
Unbalanced clk_prepare_enable(priv->pclk).
Shawn
> +}
> +
> +static int zx2967_thermal_exit(struct platform_device *pdev)
> +{
> + struct zx2967_thermal_priv *priv = platform_get_drvdata(pdev);
> + int i;
> +
> + for (i = 0; i < NUM_SENSORS; i++) {
> + struct zx2967_thermal_sensor *sensor = &priv->sensors[i];
> +
> + thermal_zone_of_sensor_unregister(&pdev->dev, sensor->tzd);
> + }
> + clk_disable_unprepare(priv->pclk);
> + clk_disable_unprepare(priv->clk_gate);
> +
> + return 0;
> +}
> +
> +static const struct of_device_id zx2967_thermal_id_table[] = {
> + { .compatible = "zte,zx2967-thermal" },
> + { .compatible = "zte,zx296718-thermal" },
> + {}
> +};
> +MODULE_DEVICE_TABLE(of, zx2967_thermal_id_table);
> +
> +static SIMPLE_DEV_PM_OPS(zx2967_thermal_pm_ops,
> + zx2967_thermal_suspend, zx2967_thermal_resume);
> +
> +static struct platform_driver zx2967_thermal_driver = {
> + .probe = zx2967_thermal_probe,
> + .remove = zx2967_thermal_exit,
> + .driver = {
> + .name = "zx2967_thermal",
> + .of_match_table = zx2967_thermal_id_table,
> + .pm = &zx2967_thermal_pm_ops,
> + },
> +};
> +module_platform_driver(zx2967_thermal_driver);
> +
> +MODULE_AUTHOR("Baoyou Xie <baoyou.xie@linaro.org>");
> +MODULE_DESCRIPTION("ZTE zx2967 thermal driver");
> +MODULE_LICENSE("GPL");
> --
> 2.7.4
>
^ permalink raw reply
* Re: [PATCH v1 3/3] thermal: zx2967: add thermal driver for ZTE's zx2967 family
From: Jun Nie @ 2017-01-09 3:00 UTC (permalink / raw)
To: Baoyou Xie, rui.zhang, edubezval, robh+dt, mark.rutland, gregkh,
davem, geert+renesas, akpm, mchehab, linux
Cc: linux-pm, devicetree, linux-kernel, linux-arm-kernel, shawnguo,
xie.baoyou, chen.chaokai, wang.qiang01
In-Reply-To: <1483767488-19778-3-git-send-email-baoyou.xie@linaro.org>
On 2017年01月07日 13:38, Baoyou Xie wrote:
> This patch adds thermal driver for ZTE's zx2967 family.
>
> Signed-off-by: Baoyou Xie <baoyou.xie@linaro.org>
> ---
> drivers/thermal/Kconfig | 6 +
> drivers/thermal/Makefile | 1 +
> drivers/thermal/zx2967_thermal.c | 241 +++++++++++++++++++++++++++++++++++++++
> 3 files changed, 248 insertions(+)
> create mode 100644 drivers/thermal/zx2967_thermal.c
>
> diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
> index 18f2de6..0dd597e 100644
> --- a/drivers/thermal/Kconfig
> +++ b/drivers/thermal/Kconfig
> @@ -445,3 +445,9 @@ config BCM2835_THERMAL
> Support for thermal sensors on Broadcom bcm2835 SoCs.
>
> endif
> +
> +config ZX2967_THERMAL
> + tristate "Thermal sensors on zx2967 SoC"
> + depends on ARCH_ZX
> + help
> + Support for thermal sensors on ZTE zx2967 SoCs.
> diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
> index 677c6d9..c00c05e 100644
> --- a/drivers/thermal/Makefile
> +++ b/drivers/thermal/Makefile
> @@ -57,3 +57,4 @@ obj-$(CONFIG_HISI_THERMAL) += hisi_thermal.o
> obj-$(CONFIG_MTK_THERMAL) += mtk_thermal.o
> obj-$(CONFIG_GENERIC_ADC_THERMAL) += thermal-generic-adc.o
> obj-$(CONFIG_BCM2835_THERMAL) += bcm2835_thermal.o
> +obj-$(CONFIG_ZX2967_THERMAL) += zx2967_thermal.o
> diff --git a/drivers/thermal/zx2967_thermal.c b/drivers/thermal/zx2967_thermal.c
> new file mode 100644
> index 0000000..1aef070
> --- /dev/null
> +++ b/drivers/thermal/zx2967_thermal.c
> @@ -0,0 +1,241 @@
> +/*
> + * ZTE's zx2967 family thermal sensor driver
> + *
> + * Copyright (C) 2017 ZTE Ltd.
> + *
> + * Author: Baoyou Xie <baoyou.xie@linaro.org>
> + *
> + * License terms: GNU General Public License (GPL) version 2
> + */
> +
> +#include <linux/module.h>
Please follow alphabet sequence.
> +#include <linux/device.h>
> +#include <linux/io.h>
> +#include <linux/err.h>
> +#include <linux/clk.h>
> +#include <linux/delay.h>
> +#include <linux/platform_device.h>
> +#include <linux/thermal.h>
> +
> +/* DCF Control Register */
> +#define ZX2967_THERMAL_DCF 0x4
> +
> +/* Selection Register */
> +#define ZX2967_THERMAL_SEL 0x8
> +
> +/* Control Register */
> +#define ZX2967_THERMAL_CTRL 0x10
> +
> +#define ZX2967_THERMAL_ID_MASK (0x18)
> +
> +struct zx2967_thermal_sensor {
> + struct zx2967_thermal_priv *priv;
> + struct thermal_zone_device *tzd;
> + int id;
> +};
> +
> +#define NUM_SENSORS 1
> +
> +struct zx2967_thermal_priv {
> + struct zx2967_thermal_sensor sensors[NUM_SENSORS];
> + struct mutex lock;
> + struct clk *clk_gate;
> + struct clk *pclk;
> + void __iomem *regs;
> + struct pinctrl *pinmux_dvi0_d3;
> + struct pinctrl *pinmux_dvi0_d4;
> + struct pinctrl *pinmux_dvi0_d5;
I do not see usage of pinmux_div0_d*, please remove it.
> +};
> +
> +static int zx2967_thermal_suspend(struct device *dev)
> +{
> + struct platform_device *pdev = to_platform_device(dev);
> + struct zx2967_thermal_priv *priv = platform_get_drvdata(pdev);
> +
> + if (priv && priv->pclk)
> + clk_disable_unprepare(priv->pclk);
> +
> + if (priv && priv->clk_gate)
> + clk_disable_unprepare(priv->clk_gate);
> + dev_info(dev, "suspended\n");
> +
> + return 0;
> +}
> +
> +static int zx2967_thermal_resume(struct device *dev)
> +{
> + struct platform_device *pdev = to_platform_device(dev);
> + struct zx2967_thermal_priv *priv = platform_get_drvdata(pdev);
> + int error;
> +
> + error = clk_prepare_enable(priv->clk_gate);
> + if (error)
Use IS_ERR(ret) to check error.
> + return error;
> +
> + error = clk_prepare_enable(priv->pclk);
> + if (error)
Ditto.
> + return error;
> +
> + dev_info(dev, "resumed\n");
> +
> + return 0;
> +}
> +
> +static int zx2967_thermal_get_temp(void *data, int *temp)
> +{
> + void __iomem *regs;
> + struct zx2967_thermal_sensor *sensor = data;
> + struct zx2967_thermal_priv *priv = sensor->priv;
> + unsigned long timeout = jiffies + msecs_to_jiffies(100);
> + u32 val, sel_id;
> +
> + regs = priv->regs;
> + mutex_lock(&priv->lock);
> +
> + writel_relaxed(0, regs);
> + writel_relaxed(2, regs + ZX2967_THERMAL_DCF);
> +
> + val = readl_relaxed(regs + ZX2967_THERMAL_SEL);
> + val &= ~ZX2967_THERMAL_ID_MASK;
> + sel_id = sensor->id ? 8 : 0x10;
You can define a macro for 8 and 0x10. BTW: NUM_SENSORS is 1 currently,
you can change it to 2 if hardware support it. Or you can add TODO mark
for later work.
> + val |= sel_id;
> + writel_relaxed(val, regs + ZX2967_THERMAL_SEL);
> +
> + usleep_range(100, 300);
> + while (!(readl_relaxed(regs + ZX2967_THERMAL_CTRL) & 0x1000)) {
> + if (time_after(jiffies, timeout)) {
> + pr_err("*** Thermal sensor %d data timeout\n",
> + sensor->id);
> + mutex_unlock(&priv->lock);
> + return -EIO;
> + }
> + }
> +
> + writel_relaxed(3, regs + ZX2967_THERMAL_DCF);
> + val = readl_relaxed(regs + ZX2967_THERMAL_CTRL) & 0xfff;
Define 0xfff as a macro.
> + writel_relaxed(1, regs);
> +
> + /** Calculate temperature */
> + *temp = DIV_ROUND_CLOSEST((val - 922) * 1000, 1951);
> +
> + mutex_unlock(&priv->lock);
> +
> + return 0;
> +}
> +
> +static struct thermal_zone_of_device_ops zx2967_of_thermal_ops = {
> + .get_temp = zx2967_thermal_get_temp,
> +};
> +
> +static int zx2967_thermal_probe(struct platform_device *pdev)
> +{
> + struct zx2967_thermal_priv *priv;
> + struct resource *res;
> + int ret, i;
> +
> + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
> + if (!priv)
> + return -ENOMEM;
> +
> + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> + priv->regs = devm_ioremap_resource(&pdev->dev, res);
> + if (IS_ERR(priv->regs))
> + return PTR_ERR(priv->regs);
> +
> + priv->clk_gate = devm_clk_get(&pdev->dev, "tempsensor_gate");
> + if (IS_ERR(priv->clk_gate)) {
> + ret = PTR_ERR(priv->clk_gate);
> + dev_err(&pdev->dev, "failed to get clock gate: %d\n", ret);
> + return ret;
> + }
> +
> + ret = clk_prepare_enable(priv->clk_gate);
> + if (ret) {
Use IS_ERR(ret) to check error.
> + dev_err(&pdev->dev, "failed to enable converter clock: %d\n",
> + ret);
> + return ret;
> + }
> +
> + priv->pclk = devm_clk_get(&pdev->dev, "tempsensor_pclk");
> + if (IS_ERR(priv->pclk)) {
> + ret = PTR_ERR(priv->pclk);
> + dev_err(&pdev->dev, "failed to get apb clock: %d\n", ret);
> + return ret;
> + }
> +
> + ret = clk_prepare_enable(priv->pclk);
> + if (ret) {
Ditto.
> + dev_err(&pdev->dev, "failed to enable converter clock: %d\n",
> + ret);
> + return ret;
> + }
> +
> + mutex_init(&priv->lock);
> + for (i = 0; i < NUM_SENSORS; i++) {
> + struct zx2967_thermal_sensor *sensor = &priv->sensors[i];
> +
> + sensor->priv = priv;
> + sensor->id = i;
> + sensor->tzd = thermal_zone_of_sensor_register(&pdev->dev,
> + i,
> + sensor,
No need to create new line.
> + &zx2967_of_thermal_ops);
> + if (IS_ERR(sensor->tzd)) {
> + ret = PTR_ERR(sensor->tzd);
> + dev_err(&pdev->dev, "failed to register sensor %d: %d\n",
> + i, ret);
> + goto remove_ts;
> + }
> + }
> + platform_set_drvdata(pdev, priv);
> +
> + return 0;
> +
> +remove_ts:
> + for (i--; i >= 0; i--)
> + thermal_zone_of_sensor_unregister(&pdev->dev,
> + priv->sensors[i].tzd);
> +
> + return ret;
> +}
> +
> +static int zx2967_thermal_exit(struct platform_device *pdev)
> +{
> + struct zx2967_thermal_priv *priv = platform_get_drvdata(pdev);
> + int i;
> +
> + for (i = 0; i < NUM_SENSORS; i++) {
> + struct zx2967_thermal_sensor *sensor = &priv->sensors[i];
> +
> + thermal_zone_of_sensor_unregister(&pdev->dev, sensor->tzd);
> + }
> + clk_disable_unprepare(priv->pclk);
> + clk_disable_unprepare(priv->clk_gate);
> +
> + return 0;
> +}
> +
> +static const struct of_device_id zx2967_thermal_id_table[] = {
> + { .compatible = "zte,zx2967-thermal" },
> + { .compatible = "zte,zx296718-thermal" },
Does the sensors that maps to the two compatibles have any difference?
If yes, we can add the difference with data member. If not, we can use
the same compatible string.
> + {}
> +};
> +MODULE_DEVICE_TABLE(of, zx2967_thermal_id_table);
> +
> +static SIMPLE_DEV_PM_OPS(zx2967_thermal_pm_ops,
> + zx2967_thermal_suspend, zx2967_thermal_resume);
> +
> +static struct platform_driver zx2967_thermal_driver = {
> + .probe = zx2967_thermal_probe,
> + .remove = zx2967_thermal_exit,
> + .driver = {
> + .name = "zx2967_thermal",
> + .of_match_table = zx2967_thermal_id_table,
> + .pm = &zx2967_thermal_pm_ops,
> + },
> +};
> +module_platform_driver(zx2967_thermal_driver);
> +
> +MODULE_AUTHOR("Baoyou Xie <baoyou.xie@linaro.org>");
> +MODULE_DESCRIPTION("ZTE zx2967 thermal driver");
> +MODULE_LICENSE("GPL");
>
^ permalink raw reply
* Re: [PATCH 2/2] media: rc: add driver for IR remote receiver on MT7623 SoC
From: Sean Wang @ 2017-01-09 3:13 UTC (permalink / raw)
To: Sean Young
Cc: mchehab-JPH+aEBZ4P+UEJcrhfAQsw, hdegoede-H+wXaHxf7aLQT0dZR+AlfA,
hkallweit1-Re5JQEeQqe8AvxtiuMwx3w, robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
mark.rutland-5wv7dgnIgG8, matthias.bgg-Re5JQEeQqe8AvxtiuMwx3w,
andi.shyti-Sze3O3UU22JBDgjK7y7TUQ,
hverkuil-qWit8jRvyhVmR6Xm/wNWPw,
ivo.g.dimitrov.75-Re5JQEeQqe8AvxtiuMwx3w,
linux-media-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-mediatek-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
keyhaede-Re5JQEeQqe8AvxtiuMwx3w
In-Reply-To: <20170108211624.GB7866-3XSxi2G4b3iXFJAUJl40Xg@public.gmane.org>
On Sun, 2017-01-08 at 21:16 +0000, Sean Young wrote:
> Hi Sean,
>
> On Fri, Jan 06, 2017 at 03:31:25PM +0800, Sean Wang wrote:
> > On Thu, 2017-01-05 at 17:12 +0000, Sean Young wrote:
> > > On Fri, Jan 06, 2017 at 12:06:24AM +0800, sean.wang-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org wrote:
> > > > + /* Handle pulse and space until end of message */
> > > > + for (i = 0 ; i < MTK_CHKDATA_SZ ; i++) {
> > > > + val = mtk_r32(ir, MTK_CHKDATA_REG(i));
> > > > + dev_dbg(ir->dev, "@reg%d=0x%08x\n", i, val);
> > > > +
> > > > + for (j = 0 ; j < 4 ; j++) {
> > > > + wid = (val & (0xff << j * 8)) >> j * 8;
> > > > + rawir.pulse = !rawir.pulse;
> > > > + rawir.duration = wid * (MTK_IR_SAMPLE + 1);
> > > > + ir_raw_event_store_with_filter(ir->rc, &rawir);
> > > > +
> > > > + if (MTK_IR_END(wid))
> > > > + goto end_msg;
> > > > + }
> > > > + }
> > >
> > > If I read this correctly, there is a maximum of 17 * 4 = 68 edges per
> > > IR message. The rc6 mce key 0 (scancode 0x800f0400) is 69 edges, so that
> > > won't work.
> > >
> > Uh, this is related to hardware limitation. Maximum number hardware
> > holds indeed is only 68 edges as you said :(
> >
> > For the case, I will try change the logic into that the whole message
> > is dropped if no end of message is seen within 68 counts to avoid
> > wasting CPU for decoding.
>
> I'm not sure it is worthwhile dropping the IR in that case. The processing
> is minimal and it might be possible that we have just enough IR to decode
> a scancode even if the trailing end of message is missing. Note that
> the call to ir_raw_event_set_idle() will generate an timeout IR event, so
> there will always be an end of message marker.
1)
I agree with you :) The original logic I made already as you pointed out
is sent incomplete IR message to let ir-raw try to decode as possible.
2)
I had another question. I found multiple and same IR messages being
received when using SONY remote controller. Should driver needs to
report each message or only one of these to the upper layer ?
> All I wanted to do was point out a limitation in case there is a
> workaround; if there is not then we might as well make do with the IR
> we do have.
I also will leave some words about limitation we had in the comments.
> Thanks
> Sean
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH v4 1/2] power: reset: add linkstation-reset driver
From: Roger Shimizu @ 2017-01-09 3:31 UTC (permalink / raw)
To: Ryan Tandy
Cc: Andrew Lunn, Martin Michlmayr, Sylver Bruneau,
Herbert Valerio Riedel, Florian Fainelli, linux-pm, devicetree,
linux-arm-kernel
In-Reply-To: <20170108170209.GD573@kiwi.nardis.ca>
Dear Ryan,
Thanks for your comments!
On Mon, Jan 9, 2017 at 2:02 AM, Ryan Tandy <ryan@nardis.ca> wrote:
> On Sun, Jan 08, 2017 at 12:04:50AM +0900, Roger Shimizu wrote:
>>
>> +config POWER_RESET_LINKSTATION
>> + bool "Buffalo Linkstation and its variants reset driver"
>> + depends on OF_GPIO && PLAT_ORION
>> + help
>> + This driver supports power off Buffalo Linkstation / KuroBox Pro
>> + NAS and their variants by sending commands to the
>> micro-controller
>> + which controls the main power.
>
> Would it make sense to mention something about these being the ARM9/orion5x
> Linkstations? If I understand correctly, the older PPC Linkstations have a
> single-byte poweroff command. (Maybe they could even be supported by
> qnap-poweroff.)
>
> See arch/powerpc/platforms/embedded6xx/linkstation.c around line 123, and
> arch/powerpc/platforms/embedded6xx/ls_uart.c.
This driver, linkstation-reset, can also handle PPC Linkstation after
it's converted to DT.
I already considered this and mentioned in previous reply [0].
[0] http://marc.info/?l=linux-pm&m=148216908031283
Cheers,
--
Roger Shimizu, GMT +9 Tokyo
PGP/GPG: 4096R/6C6ACD6417B3ACB1
^ permalink raw reply
* gpio_key.c device tree question
From: noman pouigt @ 2017-01-09 3:42 UTC (permalink / raw)
To: dmitry.torokhov, linux-input; +Cc: devicetree, linux-kernel
Hello,
I am trying to see how to disable the sub device nodes in
gpio_keys device node.
I have this in my base dtsi file:
#include "vendor_file.dtsi"
gpio_keys {
compatible = "gpio-keys";
input-name = "gpio-keys";
pinctrl-names = "gpio_key_active","gpio_key_suspend";
pinctrl-0 = <&key_active>;
pinctrl-1 = <&key_suspend>;
camera_snapshot {
label = "camera_snapshot";
//snip
};
};
I have this in vendor_file.dtsi:
gpio_keys {
source_key_1 {
label = "source_key_1";
//snip
};
};
In my current consolidated dtb file all nodes are getting
added i.e. camera_snapshot and source_key_1. How
can i remove camera_snapshot node from the
gpio_keys device node or disable it?
Thanks,
^ permalink raw reply
* Re: [PATCH 4/4] mmc: pwrseq-simple: add disable-post-power-on option
From: Matt Ranostay @ 2017-01-09 4:53 UTC (permalink / raw)
To: Linus Walleij
Cc: Ulf Hansson, Rob Herring, devicetree@vger.kernel.org,
linux-mmc@vger.kernel.org, Tony Lindgren, Liam Breck
In-Reply-To: <CACRpkdad7JXzxYfuB_XYdo2vuZmEt5iWgq79Va5cWwTaJc6Y5Q@mail.gmail.com>
On Fri, Dec 30, 2016 at 12:05 AM, Linus Walleij
<linus.walleij@linaro.org> wrote:
> On Mon, Dec 19, 2016 at 1:01 AM, Matt Ranostay <matt@ranostay.consulting> wrote:
>
>> * SD8787 has a "powerdown" line, and CW1200 has a "powerup" line.. I
>> know this is a simple logic inversion.
>
> If this is a GPIO line, the GPIO subsystem can flag a line for
> inverted logic. GPIO_ACTIVE_LOW from device tree for example.
Slight ping on Ulf on this thread :).
I do understand the inverted logic flag but that doesn't help if there
are different logic states between various chipsets.
>
> Yours,
> Linus Walleij
^ permalink raw reply
* [PATCH 0/3][v3] Add QorIQ LS2088A platform support
From: Abhimanyu Saini @ 2017-01-09 5:14 UTC (permalink / raw)
To: devicetree-u79uwXL29TY76Z2rM5mHXA, robh-DgEjT+Ai2ygdnm+yROfE0A,
mark.rutland-5wv7dgnIgG8, shawnguo-DgEjT+Ai2ygdnm+yROfE0A
Cc: scott.wood-3arQi8VN3Tc, stuart.yoder-3arQi8VN3Tc,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
Abhimanyu Saini
This patchset adds support for the QorIQ LS2088A SoC.
LS2088A SoC is similar to LS2080A SoC with a few differences like it has A72 cores.
This patchset
- reorganize LS2088A DTS/DTSI for code reuseability
- adds LS2088A device dtsi and dts files.
Abhimanyu Saini (3):
dt-bindings: Add compatible for LS2088A QDS and RDB boards
arm64: freescale: ls2080a: Split devicetree for code resuability
arm64: Add DTS support for FSL's LS2088A SoC
Changes for v3:
- rename dts/dtsi files
Changes for v2:
- reorganize LS2088A device tree to use common
nodes from LS2080A device trees.
- Both LS2080A and LS2088A have same hardware
controllers, so separate dt-binding patches for
pcie, gpio, dspi, qspi are not required.
Abhimanyu Saini (3):
dt-bindings: Add compatible for LS2088A QDS and RDB board
arm64: freescale: ls2080a: Split devicetree for code resuability
arm64: freescale: ls2088a: Add DTS support for FSL's LS2088A SoC
Documentation/devicetree/bindings/arm/fsl.txt | 11 +
arch/arm64/boot/dts/freescale/Makefile | 2 +
arch/arm64/boot/dts/freescale/fsl-ls2080a-qds.dts | 154 +----
arch/arm64/boot/dts/freescale/fsl-ls2080a-rdb.dts | 106 +---
arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi | 715 +---------------------
arch/arm64/boot/dts/freescale/fsl-ls2088a-qds.dts | 65 ++
arch/arm64/boot/dts/freescale/fsl-ls2088a-rdb.dts | 65 ++
arch/arm64/boot/dts/freescale/fsl-ls2088a.dtsi | 162 +++++
8 files changed, 331 insertions(+), 949 deletions(-)
create mode 100644 arch/arm64/boot/dts/freescale/fsl-ls2088a-qds.dts
create mode 100644 arch/arm64/boot/dts/freescale/fsl-ls2088a-rdb.dts
create mode 100644 arch/arm64/boot/dts/freescale/fsl-ls2088a.dtsi
--
1.9.1
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [PATCH 1/3][v3] dt-bindings: Add compatible for LS2088A QDS and RDB board
From: Abhimanyu Saini @ 2017-01-09 5:14 UTC (permalink / raw)
To: devicetree-u79uwXL29TY76Z2rM5mHXA, robh-DgEjT+Ai2ygdnm+yROfE0A,
mark.rutland-5wv7dgnIgG8, shawnguo-DgEjT+Ai2ygdnm+yROfE0A
Cc: scott.wood-3arQi8VN3Tc, stuart.yoder-3arQi8VN3Tc,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
Abhimanyu Saini, Priyanka Jain, Ashish Kumar
In-Reply-To: <1483938896-2221-1-git-send-email-abhimanyu.saini-3arQi8VN3Tc@public.gmane.org>
Signed-off-by: Abhimanyu Saini <abhimanyu.saini-3arQi8VN3Tc@public.gmane.org>
Signed-off-by: Priyanka Jain <priyanka.jain-3arQi8VN3Tc@public.gmane.org>
Signed-off-by: Ashish Kumar <ashish.kumar-3arQi8VN3Tc@public.gmane.org>
Acked-by: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
---
Changes for v2:
- reorganize LS2088A device tree to use common
nodes from LS2080A device trees.
- Both LS2080A and LS2088A have same hardware
controllers, so separate dt-binding patches for
pcie, gpio, dspi, qspi are not required.
Documentation/devicetree/bindings/arm/fsl.txt | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/Documentation/devicetree/bindings/arm/fsl.txt b/Documentation/devicetree/bindings/arm/fsl.txt
index d6ee9c6..75ad8c5 100644
--- a/Documentation/devicetree/bindings/arm/fsl.txt
+++ b/Documentation/devicetree/bindings/arm/fsl.txt
@@ -179,3 +179,14 @@ LS2080A ARMv8 based RDB Board
Required root node properties:
- compatible = "fsl,ls2080a-rdb", "fsl,ls2080a";
+LS2088A SoC
+Required root node properties:
+ - compatible = "fsl,ls2088a";
+
+LS2088A ARMv8 based QDS Board
+Required root node properties:
+ - compatible = "fsl,ls2088a-qds", "fsl,ls2088a";
+
+LS2088A ARMv8 based RDB Board
+Required root node properties:
+ - compatible = "fsl,ls2088a-rdb", "fsl,ls2088a";
--
1.9.1
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH 2/3][v3] arm64: freescale: ls2080a: Split devicetree for code resuability
From: Abhimanyu Saini @ 2017-01-09 5:14 UTC (permalink / raw)
To: devicetree-u79uwXL29TY76Z2rM5mHXA, robh-DgEjT+Ai2ygdnm+yROfE0A,
mark.rutland-5wv7dgnIgG8, shawnguo-DgEjT+Ai2ygdnm+yROfE0A
Cc: scott.wood-3arQi8VN3Tc, stuart.yoder-3arQi8VN3Tc,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
Abhimanyu Saini, Priyanka Jain, Ashish Kumar
In-Reply-To: <1483938896-2221-1-git-send-email-abhimanyu.saini-3arQi8VN3Tc@public.gmane.org>
LS2088A and LS2080A are similar SoCs with a few differences like
ARM cores etc.
Reorganize the LS2080A device tree to move the common nodes to:
- fsl-ls208xa.dtsi
- fsl-ls208xa-rdb.dtsi
- fsl-ls208xa-qds.dtsi
Signed-off-by: Priyanka Jain <priyanka.jain-3arQi8VN3Tc@public.gmane.org>
Signed-off-by: Ashish Kumar <ashish.kumar-3arQi8VN3Tc@public.gmane.org>
Signed-off-by: Abhimanyu Saini <abhimanyu.saini-3arQi8VN3Tc@public.gmane.org>
---
Changes for v3:
- rename dts/dtsi files
arch/arm64/boot/dts/freescale/fsl-ls2080a-qds.dts | 154 +----
arch/arm64/boot/dts/freescale/fsl-ls2080a-rdb.dts | 106 +---
arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi | 715 +---------------------
3 files changed, 26 insertions(+), 949 deletions(-)
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls2080a-qds.dts b/arch/arm64/boot/dts/freescale/fsl-ls2080a-qds.dts
index 8bc1f8f..3cf4a5c 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls2080a-qds.dts
+++ b/arch/arm64/boot/dts/freescale/fsl-ls2080a-qds.dts
@@ -1,8 +1,9 @@
/*
* Device Tree file for Freescale LS2080a QDS Board.
*
- * Copyright (C) 2015, Freescale Semiconductor
+ * Copyright (C) 2015-17, Freescale Semiconductor
*
+ * Abhimanyu Saini <abhimanyu.saini-3arQi8VN3Tc@public.gmane.org>
* Bhupesh Sharma <bhupesh.sharma-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
*
* This file is dual-licensed: you can use it either under the terms
@@ -62,153 +63,4 @@
};
};
-&esdhc {
- status = "okay";
-};
-
-&ifc {
- status = "okay";
- #address-cells = <2>;
- #size-cells = <1>;
- ranges = <0x0 0x0 0x5 0x80000000 0x08000000
- 0x2 0x0 0x5 0x30000000 0x00010000
- 0x3 0x0 0x5 0x20000000 0x00010000>;
-
- nor@0,0 {
- #address-cells = <1>;
- #size-cells = <1>;
- compatible = "cfi-flash";
- reg = <0x0 0x0 0x8000000>;
- bank-width = <2>;
- device-width = <1>;
- };
-
- nand@2,0 {
- compatible = "fsl,ifc-nand";
- reg = <0x2 0x0 0x10000>;
- };
-
- cpld@3,0 {
- reg = <0x3 0x0 0x10000>;
- compatible = "fsl,ls2080aqds-fpga", "fsl,fpga-qixis";
- };
-};
-
-&i2c0 {
- status = "okay";
- pca9547@77 {
- compatible = "nxp,pca9547";
- reg = <0x77>;
- #address-cells = <1>;
- #size-cells = <0>;
- i2c@0 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <0x00>;
- rtc@68 {
- compatible = "dallas,ds3232";
- reg = <0x68>;
- };
- };
-
- i2c@2 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <0x02>;
-
- ina220@40 {
- compatible = "ti,ina220";
- reg = <0x40>;
- shunt-resistor = <500>;
- };
-
- ina220@41 {
- compatible = "ti,ina220";
- reg = <0x41>;
- shunt-resistor = <1000>;
- };
- };
-
- i2c@3 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <0x3>;
-
- adt7481@4c {
- compatible = "adi,adt7461";
- reg = <0x4c>;
- };
- };
- };
-};
-
-&i2c1 {
- status = "disabled";
-};
-
-&i2c2 {
- status = "disabled";
-};
-
-&i2c3 {
- status = "disabled";
-};
-
-&dspi {
- status = "okay";
- dflash0: n25q128a {
- #address-cells = <1>;
- #size-cells = <1>;
- compatible = "st,m25p80";
- spi-max-frequency = <3000000>;
- reg = <0>;
- };
- dflash1: sst25wf040b {
- #address-cells = <1>;
- #size-cells = <1>;
- compatible = "st,m25p80";
- spi-max-frequency = <3000000>;
- reg = <1>;
- };
- dflash2: en25s64 {
- #address-cells = <1>;
- #size-cells = <1>;
- compatible = "st,m25p80";
- spi-max-frequency = <3000000>;
- reg = <2>;
- };
-};
-
-&qspi {
- status = "okay";
- flash0: s25fl256s1@0 {
- #address-cells = <1>;
- #size-cells = <1>;
- compatible = "st,m25p80";
- spi-max-frequency = <20000000>;
- reg = <0>;
- };
- flash2: s25fl256s1@2 {
- #address-cells = <1>;
- #size-cells = <1>;
- compatible = "st,m25p80";
- spi-max-frequency = <20000000>;
- reg = <0>;
- };
-};
-
-&sata0 {
- status = "okay";
-};
-
-&sata1 {
- status = "okay";
-};
-
-&usb0 {
- status = "okay";
-};
-
-&usb1 {
- status = "okay";
-};
+#include "fsl-ls208xa-qds.dtsi"
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls2080a-rdb.dts b/arch/arm64/boot/dts/freescale/fsl-ls2080a-rdb.dts
index 2ff46ca..d5224fb 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls2080a-rdb.dts
+++ b/arch/arm64/boot/dts/freescale/fsl-ls2080a-rdb.dts
@@ -62,108 +62,4 @@
};
};
-&esdhc {
- status = "okay";
-};
-
-&ifc {
- status = "okay";
- #address-cells = <2>;
- #size-cells = <1>;
- ranges = <0x0 0x0 0x5 0x80000000 0x08000000
- 0x2 0x0 0x5 0x30000000 0x00010000
- 0x3 0x0 0x5 0x20000000 0x00010000>;
-
- nor@0,0 {
- #address-cells = <1>;
- #size-cells = <1>;
- compatible = "cfi-flash";
- reg = <0x0 0x0 0x8000000>;
- bank-width = <2>;
- device-width = <1>;
- };
-
- nand@2,0 {
- compatible = "fsl,ifc-nand";
- reg = <0x2 0x0 0x10000>;
- };
-
- cpld@3,0 {
- reg = <0x3 0x0 0x10000>;
- compatible = "fsl,ls2080aqds-fpga", "fsl,fpga-qixis";
- };
-
-};
-
-&i2c0 {
- status = "okay";
- pca9547@75 {
- compatible = "nxp,pca9547";
- reg = <0x75>;
- #address-cells = <1>;
- #size-cells = <0>;
- i2c@1 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <0x01>;
- rtc@68 {
- compatible = "dallas,ds3232";
- reg = <0x68>;
- };
- };
-
- i2c@3 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <0x3>;
-
- adt7481@4c {
- compatible = "adi,adt7461";
- reg = <0x4c>;
- };
- };
- };
-};
-
-&i2c1 {
- status = "disabled";
-};
-
-&i2c2 {
- status = "disabled";
-};
-
-&i2c3 {
- status = "disabled";
-};
-
-&dspi {
- status = "okay";
- dflash0: n25q512a {
- #address-cells = <1>;
- #size-cells = <1>;
- compatible = "st,m25p80";
- spi-max-frequency = <3000000>;
- reg = <0>;
- };
-};
-
-&qspi {
- status = "disabled";
-};
-
-&sata0 {
- status = "okay";
-};
-
-&sata1 {
- status = "okay";
-};
-
-&usb0 {
- status = "okay";
-};
-
-&usb1 {
- status = "okay";
-};
+#include "fsl-ls208xa-rdb.dtsi"
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi
index e5935f2..35801f3 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi
@@ -1,8 +1,9 @@
/*
* Device Tree Include file for Freescale Layerscape-2080A family SoC.
*
- * Copyright (C) 2014-2015, Freescale Semiconductor
+ * Copyright (C) 2014-2017, Freescale Semiconductor
*
+ * Abhimanyu Saini <abhimanyu.saini-3arQi8VN3Tc@public.gmane.org>
* Bhupesh Sharma <bhupesh.sharma-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
*
* This file is dual-licensed: you can use it either under the terms
@@ -149,697 +150,25 @@
};
};
- memory@80000000 {
- device_type = "memory";
- reg = <0x00000000 0x80000000 0 0x80000000>;
- /* DRAM space - 1, size : 2 GB DRAM */
- };
-
- sysclk: sysclk {
- compatible = "fixed-clock";
- #clock-cells = <0>;
- clock-frequency = <100000000>;
- clock-output-names = "sysclk";
- };
-
- gic: interrupt-controller@6000000 {
- compatible = "arm,gic-v3";
- reg = <0x0 0x06000000 0 0x10000>, /* GIC Dist */
- <0x0 0x06100000 0 0x100000>, /* GICR (RD_base + SGI_base) */
- <0x0 0x0c0c0000 0 0x2000>, /* GICC */
- <0x0 0x0c0d0000 0 0x1000>, /* GICH */
- <0x0 0x0c0e0000 0 0x20000>; /* GICV */
- #interrupt-cells = <3>;
- #address-cells = <2>;
- #size-cells = <2>;
- ranges;
- interrupt-controller;
- interrupts = <1 9 0x4>;
-
- its: gic-its@6020000 {
- compatible = "arm,gic-v3-its";
- msi-controller;
- reg = <0x0 0x6020000 0 0x20000>;
- };
- };
-
- rstcr: syscon@1e60000 {
- compatible = "fsl,ls2080a-rstcr", "syscon";
- reg = <0x0 0x1e60000 0x0 0x4>;
- };
-
- reboot {
- compatible ="syscon-reboot";
- regmap = <&rstcr>;
- offset = <0x0>;
- mask = <0x2>;
- };
-
- timer {
- compatible = "arm,armv8-timer";
- interrupts = <1 13 4>, /* Physical Secure PPI, active-low */
- <1 14 4>, /* Physical Non-Secure PPI, active-low */
- <1 11 4>, /* Virtual PPI, active-low */
- <1 10 4>; /* Hypervisor PPI, active-low */
- fsl,erratum-a008585;
- };
-
- pmu {
- compatible = "arm,armv8-pmuv3";
- interrupts = <1 7 0x8>; /* PMU PPI, Level low type */
- };
-
- soc {
- compatible = "simple-bus";
- #address-cells = <2>;
- #size-cells = <2>;
- ranges;
-
- clockgen: clocking@1300000 {
- compatible = "fsl,ls2080a-clockgen";
- reg = <0 0x1300000 0 0xa0000>;
- #clock-cells = <2>;
- clocks = <&sysclk>;
- };
-
- dcfg: dcfg@1e00000 {
- compatible = "fsl,ls2080a-dcfg", "syscon";
- reg = <0x0 0x1e00000 0x0 0x10000>;
- little-endian;
- };
-
- tmu: tmu@1f80000 {
- compatible = "fsl,qoriq-tmu";
- reg = <0x0 0x1f80000 0x0 0x10000>;
- interrupts = <0 23 0x4>;
- fsl,tmu-range = <0xb0000 0x9002a 0x6004c 0x30062>;
- fsl,tmu-calibration = <0x00000000 0x00000026
- 0x00000001 0x0000002d
- 0x00000002 0x00000032
- 0x00000003 0x00000039
- 0x00000004 0x0000003f
- 0x00000005 0x00000046
- 0x00000006 0x0000004d
- 0x00000007 0x00000054
- 0x00000008 0x0000005a
- 0x00000009 0x00000061
- 0x0000000a 0x0000006a
- 0x0000000b 0x00000071
-
- 0x00010000 0x00000025
- 0x00010001 0x0000002c
- 0x00010002 0x00000035
- 0x00010003 0x0000003d
- 0x00010004 0x00000045
- 0x00010005 0x0000004e
- 0x00010006 0x00000057
- 0x00010007 0x00000061
- 0x00010008 0x0000006b
- 0x00010009 0x00000076
-
- 0x00020000 0x00000029
- 0x00020001 0x00000033
- 0x00020002 0x0000003d
- 0x00020003 0x00000049
- 0x00020004 0x00000056
- 0x00020005 0x00000061
- 0x00020006 0x0000006d
-
- 0x00030000 0x00000021
- 0x00030001 0x0000002a
- 0x00030002 0x0000003c
- 0x00030003 0x0000004e>;
- little-endian;
- #thermal-sensor-cells = <1>;
- };
-
- thermal-zones {
- cpu_thermal: cpu-thermal {
- polling-delay-passive = <1000>;
- polling-delay = <5000>;
-
- thermal-sensors = <&tmu 4>;
-
- trips {
- cpu_alert: cpu-alert {
- temperature = <75000>;
- hysteresis = <2000>;
- type = "passive";
- };
- cpu_crit: cpu-crit {
- temperature = <85000>;
- hysteresis = <2000>;
- type = "critical";
- };
- };
-
- cooling-maps {
- map0 {
- trip = <&cpu_alert>;
- cooling-device =
- <&cpu0 THERMAL_NO_LIMIT
- THERMAL_NO_LIMIT>;
- };
- map1 {
- trip = <&cpu_alert>;
- cooling-device =
- <&cpu2 THERMAL_NO_LIMIT
- THERMAL_NO_LIMIT>;
- };
- map2 {
- trip = <&cpu_alert>;
- cooling-device =
- <&cpu4 THERMAL_NO_LIMIT
- THERMAL_NO_LIMIT>;
- };
- map3 {
- trip = <&cpu_alert>;
- cooling-device =
- <&cpu6 THERMAL_NO_LIMIT
- THERMAL_NO_LIMIT>;
- };
- };
- };
- };
-
- serial0: serial@21c0500 {
- compatible = "fsl,ns16550", "ns16550a";
- reg = <0x0 0x21c0500 0x0 0x100>;
- clocks = <&clockgen 4 3>;
- interrupts = <0 32 0x4>; /* Level high type */
- };
-
- serial1: serial@21c0600 {
- compatible = "fsl,ns16550", "ns16550a";
- reg = <0x0 0x21c0600 0x0 0x100>;
- clocks = <&clockgen 4 3>;
- interrupts = <0 32 0x4>; /* Level high type */
- };
-
- cluster1_core0_watchdog: wdt@c000000 {
- compatible = "arm,sp805-wdt", "arm,primecell";
- reg = <0x0 0xc000000 0x0 0x1000>;
- clocks = <&clockgen 4 3>, <&clockgen 4 3>;
- clock-names = "apb_pclk", "wdog_clk";
- };
-
- cluster1_core1_watchdog: wdt@c010000 {
- compatible = "arm,sp805-wdt", "arm,primecell";
- reg = <0x0 0xc010000 0x0 0x1000>;
- clocks = <&clockgen 4 3>, <&clockgen 4 3>;
- clock-names = "apb_pclk", "wdog_clk";
- };
-
- cluster2_core0_watchdog: wdt@c100000 {
- compatible = "arm,sp805-wdt", "arm,primecell";
- reg = <0x0 0xc100000 0x0 0x1000>;
- clocks = <&clockgen 4 3>, <&clockgen 4 3>;
- clock-names = "apb_pclk", "wdog_clk";
- };
-
- cluster2_core1_watchdog: wdt@c110000 {
- compatible = "arm,sp805-wdt", "arm,primecell";
- reg = <0x0 0xc110000 0x0 0x1000>;
- clocks = <&clockgen 4 3>, <&clockgen 4 3>;
- clock-names = "apb_pclk", "wdog_clk";
- };
-
- cluster3_core0_watchdog: wdt@c200000 {
- compatible = "arm,sp805-wdt", "arm,primecell";
- reg = <0x0 0xc200000 0x0 0x1000>;
- clocks = <&clockgen 4 3>, <&clockgen 4 3>;
- clock-names = "apb_pclk", "wdog_clk";
- };
-
- cluster3_core1_watchdog: wdt@c210000 {
- compatible = "arm,sp805-wdt", "arm,primecell";
- reg = <0x0 0xc210000 0x0 0x1000>;
- clocks = <&clockgen 4 3>, <&clockgen 4 3>;
- clock-names = "apb_pclk", "wdog_clk";
- };
-
- cluster4_core0_watchdog: wdt@c300000 {
- compatible = "arm,sp805-wdt", "arm,primecell";
- reg = <0x0 0xc300000 0x0 0x1000>;
- clocks = <&clockgen 4 3>, <&clockgen 4 3>;
- clock-names = "apb_pclk", "wdog_clk";
- };
-
- cluster4_core1_watchdog: wdt@c310000 {
- compatible = "arm,sp805-wdt", "arm,primecell";
- reg = <0x0 0xc310000 0x0 0x1000>;
- clocks = <&clockgen 4 3>, <&clockgen 4 3>;
- clock-names = "apb_pclk", "wdog_clk";
- };
-
- fsl_mc: fsl-mc@80c000000 {
- compatible = "fsl,qoriq-mc";
- reg = <0x00000008 0x0c000000 0 0x40>, /* MC portal base */
- <0x00000000 0x08340000 0 0x40000>; /* MC control reg */
- msi-parent = <&its>;
- #address-cells = <3>;
- #size-cells = <1>;
-
- /*
- * Region type 0x0 - MC portals
- * Region type 0x1 - QBMAN portals
- */
- ranges = <0x0 0x0 0x0 0x8 0x0c000000 0x4000000
- 0x1 0x0 0x0 0x8 0x18000000 0x8000000>;
-
- /*
- * Define the maximum number of MACs present on the SoC.
- */
- dpmacs {
- #address-cells = <1>;
- #size-cells = <0>;
-
- dpmac1: dpmac@1 {
- compatible = "fsl,qoriq-mc-dpmac";
- reg = <0x1>;
- };
-
- dpmac2: dpmac@2 {
- compatible = "fsl,qoriq-mc-dpmac";
- reg = <0x2>;
- };
-
- dpmac3: dpmac@3 {
- compatible = "fsl,qoriq-mc-dpmac";
- reg = <0x3>;
- };
-
- dpmac4: dpmac@4 {
- compatible = "fsl,qoriq-mc-dpmac";
- reg = <0x4>;
- };
-
- dpmac5: dpmac@5 {
- compatible = "fsl,qoriq-mc-dpmac";
- reg = <0x5>;
- };
-
- dpmac6: dpmac@6 {
- compatible = "fsl,qoriq-mc-dpmac";
- reg = <0x6>;
- };
-
- dpmac7: dpmac@7 {
- compatible = "fsl,qoriq-mc-dpmac";
- reg = <0x7>;
- };
-
- dpmac8: dpmac@8 {
- compatible = "fsl,qoriq-mc-dpmac";
- reg = <0x8>;
- };
-
- dpmac9: dpmac@9 {
- compatible = "fsl,qoriq-mc-dpmac";
- reg = <0x9>;
- };
-
- dpmac10: dpmac@a {
- compatible = "fsl,qoriq-mc-dpmac";
- reg = <0xa>;
- };
-
- dpmac11: dpmac@b {
- compatible = "fsl,qoriq-mc-dpmac";
- reg = <0xb>;
- };
-
- dpmac12: dpmac@c {
- compatible = "fsl,qoriq-mc-dpmac";
- reg = <0xc>;
- };
-
- dpmac13: dpmac@d {
- compatible = "fsl,qoriq-mc-dpmac";
- reg = <0xd>;
- };
-
- dpmac14: dpmac@e {
- compatible = "fsl,qoriq-mc-dpmac";
- reg = <0xe>;
- };
-
- dpmac15: dpmac@f {
- compatible = "fsl,qoriq-mc-dpmac";
- reg = <0xf>;
- };
-
- dpmac16: dpmac@10 {
- compatible = "fsl,qoriq-mc-dpmac";
- reg = <0x10>;
- };
- };
- };
-
- smmu: iommu@5000000 {
- compatible = "arm,mmu-500";
- reg = <0 0x5000000 0 0x800000>;
- #global-interrupts = <12>;
- interrupts = <0 13 4>, /* global secure fault */
- <0 14 4>, /* combined secure interrupt */
- <0 15 4>, /* global non-secure fault */
- <0 16 4>, /* combined non-secure interrupt */
- /* performance counter interrupts 0-7 */
- <0 211 4>, <0 212 4>,
- <0 213 4>, <0 214 4>,
- <0 215 4>, <0 216 4>,
- <0 217 4>, <0 218 4>,
- /* per context interrupt, 64 interrupts */
- <0 146 4>, <0 147 4>,
- <0 148 4>, <0 149 4>,
- <0 150 4>, <0 151 4>,
- <0 152 4>, <0 153 4>,
- <0 154 4>, <0 155 4>,
- <0 156 4>, <0 157 4>,
- <0 158 4>, <0 159 4>,
- <0 160 4>, <0 161 4>,
- <0 162 4>, <0 163 4>,
- <0 164 4>, <0 165 4>,
- <0 166 4>, <0 167 4>,
- <0 168 4>, <0 169 4>,
- <0 170 4>, <0 171 4>,
- <0 172 4>, <0 173 4>,
- <0 174 4>, <0 175 4>,
- <0 176 4>, <0 177 4>,
- <0 178 4>, <0 179 4>,
- <0 180 4>, <0 181 4>,
- <0 182 4>, <0 183 4>,
- <0 184 4>, <0 185 4>,
- <0 186 4>, <0 187 4>,
- <0 188 4>, <0 189 4>,
- <0 190 4>, <0 191 4>,
- <0 192 4>, <0 193 4>,
- <0 194 4>, <0 195 4>,
- <0 196 4>, <0 197 4>,
- <0 198 4>, <0 199 4>,
- <0 200 4>, <0 201 4>,
- <0 202 4>, <0 203 4>,
- <0 204 4>, <0 205 4>,
- <0 206 4>, <0 207 4>,
- <0 208 4>, <0 209 4>;
- mmu-masters = <&fsl_mc 0x300 0>;
- };
-
- dspi: dspi@2100000 {
- status = "disabled";
- compatible = "fsl,ls2080a-dspi", "fsl,ls2085a-dspi";
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <0x0 0x2100000 0x0 0x10000>;
- interrupts = <0 26 0x4>; /* Level high type */
- clocks = <&clockgen 4 3>;
- clock-names = "dspi";
- spi-num-chipselects = <5>;
- bus-num = <0>;
- };
-
- esdhc: esdhc@2140000 {
- status = "disabled";
- compatible = "fsl,ls2080a-esdhc", "fsl,esdhc";
- reg = <0x0 0x2140000 0x0 0x10000>;
- interrupts = <0 28 0x4>; /* Level high type */
- clock-frequency = <0>; /* Updated by bootloader */
- voltage-ranges = <1800 1800 3300 3300>;
- sdhci,auto-cmd12;
- little-endian;
- bus-width = <4>;
- };
-
- gpio0: gpio@2300000 {
- compatible = "fsl,ls2080a-gpio", "fsl,qoriq-gpio";
- reg = <0x0 0x2300000 0x0 0x10000>;
- interrupts = <0 36 0x4>; /* Level high type */
- gpio-controller;
- little-endian;
- #gpio-cells = <2>;
- interrupt-controller;
- #interrupt-cells = <2>;
- };
-
- gpio1: gpio@2310000 {
- compatible = "fsl,ls2080a-gpio", "fsl,qoriq-gpio";
- reg = <0x0 0x2310000 0x0 0x10000>;
- interrupts = <0 36 0x4>; /* Level high type */
- gpio-controller;
- little-endian;
- #gpio-cells = <2>;
- interrupt-controller;
- #interrupt-cells = <2>;
- };
-
- gpio2: gpio@2320000 {
- compatible = "fsl,ls2080a-gpio", "fsl,qoriq-gpio";
- reg = <0x0 0x2320000 0x0 0x10000>;
- interrupts = <0 37 0x4>; /* Level high type */
- gpio-controller;
- little-endian;
- #gpio-cells = <2>;
- interrupt-controller;
- #interrupt-cells = <2>;
- };
-
- gpio3: gpio@2330000 {
- compatible = "fsl,ls2080a-gpio", "fsl,qoriq-gpio";
- reg = <0x0 0x2330000 0x0 0x10000>;
- interrupts = <0 37 0x4>; /* Level high type */
- gpio-controller;
- little-endian;
- #gpio-cells = <2>;
- interrupt-controller;
- #interrupt-cells = <2>;
- };
-
- i2c0: i2c@2000000 {
- status = "disabled";
- compatible = "fsl,vf610-i2c";
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <0x0 0x2000000 0x0 0x10000>;
- interrupts = <0 34 0x4>; /* Level high type */
- clock-names = "i2c";
- clocks = <&clockgen 4 3>;
- };
-
- i2c1: i2c@2010000 {
- status = "disabled";
- compatible = "fsl,vf610-i2c";
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <0x0 0x2010000 0x0 0x10000>;
- interrupts = <0 34 0x4>; /* Level high type */
- clock-names = "i2c";
- clocks = <&clockgen 4 3>;
- };
-
- i2c2: i2c@2020000 {
- status = "disabled";
- compatible = "fsl,vf610-i2c";
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <0x0 0x2020000 0x0 0x10000>;
- interrupts = <0 35 0x4>; /* Level high type */
- clock-names = "i2c";
- clocks = <&clockgen 4 3>;
- };
-
- i2c3: i2c@2030000 {
- status = "disabled";
- compatible = "fsl,vf610-i2c";
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <0x0 0x2030000 0x0 0x10000>;
- interrupts = <0 35 0x4>; /* Level high type */
- clock-names = "i2c";
- clocks = <&clockgen 4 3>;
- };
-
- ifc: ifc@2240000 {
- compatible = "fsl,ifc", "simple-bus";
- reg = <0x0 0x2240000 0x0 0x20000>;
- interrupts = <0 21 0x4>; /* Level high type */
- little-endian;
- #address-cells = <2>;
- #size-cells = <1>;
-
- ranges = <0 0 0x5 0x80000000 0x08000000
- 2 0 0x5 0x30000000 0x00010000
- 3 0 0x5 0x20000000 0x00010000>;
- };
-
- qspi: quadspi@20c0000 {
- status = "disabled";
- compatible = "fsl,ls2080a-qspi", "fsl,ls1021a-qspi";
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <0x0 0x20c0000 0x0 0x10000>,
- <0x0 0x20000000 0x0 0x10000000>;
- reg-names = "QuadSPI", "QuadSPI-memory";
- interrupts = <0 25 0x4>; /* Level high type */
- clocks = <&clockgen 4 3>, <&clockgen 4 3>;
- clock-names = "qspi_en", "qspi";
- };
-
- pcie@3400000 {
- compatible = "fsl,ls2080a-pcie", "fsl,ls2085a-pcie",
- "snps,dw-pcie";
- reg = <0x00 0x03400000 0x0 0x00100000 /* controller registers */
- 0x10 0x00000000 0x0 0x00002000>; /* configuration space */
- reg-names = "regs", "config";
- interrupts = <0 108 0x4>; /* Level high type */
- interrupt-names = "intr";
- #address-cells = <3>;
- #size-cells = <2>;
- device_type = "pci";
- dma-coherent;
- num-lanes = <4>;
- bus-range = <0x0 0xff>;
- ranges = <0x81000000 0x0 0x00000000 0x10 0x00010000 0x0 0x00010000 /* downstream I/O */
- 0x82000000 0x0 0x40000000 0x10 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */
- msi-parent = <&its>;
- #interrupt-cells = <1>;
- interrupt-map-mask = <0 0 0 7>;
- interrupt-map = <0000 0 0 1 &gic 0 0 0 109 4>,
- <0000 0 0 2 &gic 0 0 0 110 4>,
- <0000 0 0 3 &gic 0 0 0 111 4>,
- <0000 0 0 4 &gic 0 0 0 112 4>;
- };
-
- pcie@3500000 {
- compatible = "fsl,ls2080a-pcie", "fsl,ls2085a-pcie",
- "snps,dw-pcie";
- reg = <0x00 0x03500000 0x0 0x00100000 /* controller registers */
- 0x12 0x00000000 0x0 0x00002000>; /* configuration space */
- reg-names = "regs", "config";
- interrupts = <0 113 0x4>; /* Level high type */
- interrupt-names = "intr";
- #address-cells = <3>;
- #size-cells = <2>;
- device_type = "pci";
- dma-coherent;
- num-lanes = <4>;
- bus-range = <0x0 0xff>;
- ranges = <0x81000000 0x0 0x00000000 0x12 0x00010000 0x0 0x00010000 /* downstream I/O */
- 0x82000000 0x0 0x40000000 0x12 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */
- msi-parent = <&its>;
- #interrupt-cells = <1>;
- interrupt-map-mask = <0 0 0 7>;
- interrupt-map = <0000 0 0 1 &gic 0 0 0 114 4>,
- <0000 0 0 2 &gic 0 0 0 115 4>,
- <0000 0 0 3 &gic 0 0 0 116 4>,
- <0000 0 0 4 &gic 0 0 0 117 4>;
- };
-
- pcie@3600000 {
- compatible = "fsl,ls2080a-pcie", "fsl,ls2085a-pcie",
- "snps,dw-pcie";
- reg = <0x00 0x03600000 0x0 0x00100000 /* controller registers */
- 0x14 0x00000000 0x0 0x00002000>; /* configuration space */
- reg-names = "regs", "config";
- interrupts = <0 118 0x4>; /* Level high type */
- interrupt-names = "intr";
- #address-cells = <3>;
- #size-cells = <2>;
- device_type = "pci";
- dma-coherent;
- num-lanes = <8>;
- bus-range = <0x0 0xff>;
- ranges = <0x81000000 0x0 0x00000000 0x14 0x00010000 0x0 0x00010000 /* downstream I/O */
- 0x82000000 0x0 0x40000000 0x14 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */
- msi-parent = <&its>;
- #interrupt-cells = <1>;
- interrupt-map-mask = <0 0 0 7>;
- interrupt-map = <0000 0 0 1 &gic 0 0 0 119 4>,
- <0000 0 0 2 &gic 0 0 0 120 4>,
- <0000 0 0 3 &gic 0 0 0 121 4>,
- <0000 0 0 4 &gic 0 0 0 122 4>;
- };
-
- pcie@3700000 {
- compatible = "fsl,ls2080a-pcie", "fsl,ls2085a-pcie",
- "snps,dw-pcie";
- reg = <0x00 0x03700000 0x0 0x00100000 /* controller registers */
- 0x16 0x00000000 0x0 0x00002000>; /* configuration space */
- reg-names = "regs", "config";
- interrupts = <0 123 0x4>; /* Level high type */
- interrupt-names = "intr";
- #address-cells = <3>;
- #size-cells = <2>;
- device_type = "pci";
- dma-coherent;
- num-lanes = <4>;
- bus-range = <0x0 0xff>;
- ranges = <0x81000000 0x0 0x00000000 0x16 0x00010000 0x0 0x00010000 /* downstream I/O */
- 0x82000000 0x0 0x40000000 0x16 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */
- msi-parent = <&its>;
- #interrupt-cells = <1>;
- interrupt-map-mask = <0 0 0 7>;
- interrupt-map = <0000 0 0 1 &gic 0 0 0 124 4>,
- <0000 0 0 2 &gic 0 0 0 125 4>,
- <0000 0 0 3 &gic 0 0 0 126 4>,
- <0000 0 0 4 &gic 0 0 0 127 4>;
- };
-
- sata0: sata@3200000 {
- status = "disabled";
- compatible = "fsl,ls2080a-ahci";
- reg = <0x0 0x3200000 0x0 0x10000>;
- interrupts = <0 133 0x4>; /* Level high type */
- clocks = <&clockgen 4 3>;
- dma-coherent;
- };
-
- sata1: sata@3210000 {
- status = "disabled";
- compatible = "fsl,ls2080a-ahci";
- reg = <0x0 0x3210000 0x0 0x10000>;
- interrupts = <0 136 0x4>; /* Level high type */
- clocks = <&clockgen 4 3>;
- dma-coherent;
- };
-
- usb0: usb3@3100000 {
- status = "disabled";
- compatible = "snps,dwc3";
- reg = <0x0 0x3100000 0x0 0x10000>;
- interrupts = <0 80 0x4>; /* Level high type */
- dr_mode = "host";
- snps,quirk-frame-length-adjustment = <0x20>;
- snps,dis_rxdet_inp3_quirk;
- };
-
- usb1: usb3@3110000 {
- status = "disabled";
- compatible = "snps,dwc3";
- reg = <0x0 0x3110000 0x0 0x10000>;
- interrupts = <0 81 0x4>; /* Level high type */
- dr_mode = "host";
- snps,quirk-frame-length-adjustment = <0x20>;
- snps,dis_rxdet_inp3_quirk;
- };
-
- ccn@4000000 {
- compatible = "arm,ccn-504";
- reg = <0x0 0x04000000 0x0 0x01000000>;
- interrupts = <0 12 4>;
- };
- };
-
- ddr1: memory-controller@1080000 {
- compatible = "fsl,qoriq-memory-controller";
- reg = <0x0 0x1080000 0x0 0x1000>;
- interrupts = <0 17 0x4>;
- little-endian;
- };
+ #include "fsl-ls208xa.dtsi"
+};
- ddr2: memory-controller@1090000 {
- compatible = "fsl,qoriq-memory-controller";
- reg = <0x0 0x1090000 0x0 0x1000>;
- interrupts = <0 18 0x4>;
- little-endian;
- };
+&pcie1 {
+ ranges = <0x81000000 0x0 0x00000000 0x10 0x00010000 0x0 0x00010000 /* downstream I/O */
+ 0x82000000 0x0 0x40000000 0x10 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */
+};
+
+&pcie2 {
+ ranges = <0x81000000 0x0 0x00000000 0x12 0x00010000 0x0 0x00010000 /* downstream I/O */
+ 0x82000000 0x0 0x40000000 0x12 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */
+};
+
+&pcie3 {
+ ranges = <0x81000000 0x0 0x00000000 0x14 0x00010000 0x0 0x00010000 /* downstream I/O */
+ 0x82000000 0x0 0x40000000 0x14 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */
};
+
+&pcie4 {
+ ranges = <0x81000000 0x0 0x00000000 0x16 0x00010000 0x0 0x00010000 /* downstream I/O */
+ 0x82000000 0x0 0x40000000 0x16 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */
+ };
--
1.9.1
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH 3/3][v3] arm64: freescale: ls2088a: Add DTS support for FSL's LS2088A SoC
From: Abhimanyu Saini @ 2017-01-09 5:14 UTC (permalink / raw)
To: devicetree-u79uwXL29TY76Z2rM5mHXA, robh-DgEjT+Ai2ygdnm+yROfE0A,
mark.rutland-5wv7dgnIgG8, shawnguo-DgEjT+Ai2ygdnm+yROfE0A
Cc: scott.wood-3arQi8VN3Tc, stuart.yoder-3arQi8VN3Tc,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
Abhimanyu Saini, Priyanka Jain, Ashish Kumar
In-Reply-To: <1483938896-2221-1-git-send-email-abhimanyu.saini-3arQi8VN3Tc@public.gmane.org>
This patch adds the device tree support for FSL LS2088A SoC based on
ARMv8 architecture.
Following levels of DTSI/DTS files have been created for the LS2088A
SoC family:
- fsl-ls2088a.dtsi:
DTS-Include file for FSL LS2088A SoC.
- fsl-ls2088a-qds.dts:
DTS file for FSL LS2088A QDS board.
- fsl-ls2088a-rdb.dts:
DTS file for FSL LS2088A RDB board.
Signed-off-by: Priyanka Jain <priyanka.jain-3arQi8VN3Tc@public.gmane.org>
Signed-off-by: Ashish Kumar <ashish.kumar-3arQi8VN3Tc@public.gmane.org>
Signed-off-by: Abhimanyu Saini <abhimanyu.saini-3arQi8VN3Tc@public.gmane.org>
---
Changes for v2:
- reorganize LS2088A device tree to use common
nodes from LS2080A device trees.
arch/arm64/boot/dts/freescale/Makefile | 2 +
arch/arm64/boot/dts/freescale/fsl-ls2088a-qds.dts | 65 +++++++++
arch/arm64/boot/dts/freescale/fsl-ls2088a-rdb.dts | 65 +++++++++
arch/arm64/boot/dts/freescale/fsl-ls2088a.dtsi | 162 ++++++++++++++++++++++
4 files changed, 294 insertions(+)
create mode 100644 arch/arm64/boot/dts/freescale/fsl-ls2088a-qds.dts
create mode 100644 arch/arm64/boot/dts/freescale/fsl-ls2088a-rdb.dts
create mode 100644 arch/arm64/boot/dts/freescale/fsl-ls2088a.dtsi
diff --git a/arch/arm64/boot/dts/freescale/Makefile b/arch/arm64/boot/dts/freescale/Makefile
index 6602718..854868e 100644
--- a/arch/arm64/boot/dts/freescale/Makefile
+++ b/arch/arm64/boot/dts/freescale/Makefile
@@ -5,6 +5,8 @@ dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1046a-rdb.dtb
dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls2080a-qds.dtb
dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls2080a-rdb.dtb
dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls2080a-simu.dtb
+dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls2088a-qds.dtb
+dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls2088a-rdb.dtb
always := $(dtb-y)
subdir-y := $(dts-dirs)
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls2088a-qds.dts b/arch/arm64/boot/dts/freescale/fsl-ls2088a-qds.dts
new file mode 100644
index 0000000..74bcb5d
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/fsl-ls2088a-qds.dts
@@ -0,0 +1,65 @@
+/*
+ * Device Tree file for Freescale LS2088A QDS Board.
+ *
+ * Copyright (C) 2015-17, Freescale Semiconductor
+ *
+ * Abhimanyu Saini <abhimanyu.saini-3arQi8VN3Tc@public.gmane.org>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPLv2 or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ * a) This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This library 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.
+ *
+ * Or, alternatively,
+ *
+ * b) Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+
+#include "fsl-ls2088a.dtsi"
+
+/ {
+ model = "Freescale Layerscape 2088A QDS Board";
+ compatible = "fsl,ls2088a-qds", "fsl,ls2088a";
+
+ aliases {
+ serial0 = &serial0;
+ serial1 = &serial1;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+};
+
+#include "fsl-ls208xa-qds.dtsi"
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls2088a-rdb.dts b/arch/arm64/boot/dts/freescale/fsl-ls2088a-rdb.dts
new file mode 100644
index 0000000..801eadd
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/fsl-ls2088a-rdb.dts
@@ -0,0 +1,65 @@
+/*
+ * Device Tree file for Freescale LS2080a RDB Board.
+ *
+ * Copyright (C) 2015-17, Freescale Semiconductor
+ *
+ * Abhimanyu Saini <abhimanyu.saini-3arQi8VN3Tc@public.gmane.org>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPLv2 or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ * a) This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This library 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.
+ *
+ * Or, alternatively,
+ *
+ * b) Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+
+#include "fsl-ls2088a.dtsi"
+
+/ {
+ model = "Freescale Layerscape 2088A RDB Board";
+ compatible = "fsl,ls2088a-rdb", "fsl,ls2088a";
+
+ aliases {
+ serial0 = &serial0;
+ serial1 = &serial1;
+ };
+
+ chosen {
+ stdout-path = "serial1:115200n8";
+ };
+};
+
+#include "fsl-ls208xa-rdb.dtsi"
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls2088a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls2088a.dtsi
new file mode 100644
index 0000000..f3e22d2
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/fsl-ls2088a.dtsi
@@ -0,0 +1,162 @@
+/*
+ * Device Tree Include file for Freescale Layerscape-2088A family SoC.
+ *
+ * Copyright (C) 2015-17, Freescale Semiconductor
+ *
+ * Abhimanyu Saini <abhimanyu.saini-3arQi8VN3Tc@public.gmane.org>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPLv2 or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ * a) This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This library 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.
+ *
+ * Or, alternatively,
+ *
+ * b) Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/ {
+ compatible = "fsl,ls2080a";
+ interrupt-parent = <&gic>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu0: cpu@0 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a72";
+ reg = <0x0>;
+ clocks = <&clockgen 1 0>;
+ next-level-cache = <&cluster0_l2>;
+ #cooling-cells = <2>;
+ };
+
+ cpu1: cpu@1 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a72";
+ reg = <0x1>;
+ clocks = <&clockgen 1 0>;
+ next-level-cache = <&cluster0_l2>;
+ };
+
+ cpu2: cpu@100 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a72";
+ reg = <0x100>;
+ clocks = <&clockgen 1 1>;
+ next-level-cache = <&cluster1_l2>;
+ #cooling-cells = <2>;
+ };
+
+ cpu3: cpu@101 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a72";
+ reg = <0x101>;
+ clocks = <&clockgen 1 1>;
+ next-level-cache = <&cluster1_l2>;
+ };
+
+ cpu4: cpu@200 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a72";
+ reg = <0x200>;
+ clocks = <&clockgen 1 2>;
+ next-level-cache = <&cluster2_l2>;
+ #cooling-cells = <2>;
+ };
+
+ cpu5: cpu@201 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a72";
+ reg = <0x201>;
+ clocks = <&clockgen 1 2>;
+ next-level-cache = <&cluster2_l2>;
+ };
+
+ cpu6: cpu@300 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a72";
+ reg = <0x300>;
+ clocks = <&clockgen 1 3>;
+ next-level-cache = <&cluster3_l2>;
+ #cooling-cells = <2>;
+ };
+
+ cpu7: cpu@301 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a72";
+ reg = <0x301>;
+ clocks = <&clockgen 1 3>;
+ next-level-cache = <&cluster3_l2>;
+ };
+
+ cluster0_l2: l2-cache0 {
+ compatible = "cache";
+ };
+
+ cluster1_l2: l2-cache1 {
+ compatible = "cache";
+ };
+
+ cluster2_l2: l2-cache2 {
+ compatible = "cache";
+ };
+
+ cluster3_l2: l2-cache3 {
+ compatible = "cache";
+ };
+ };
+ #include "fsl-ls208xa.dtsi"
+};
+
+&pcie1 {
+ ranges = <0x81000000 0x0 0x00000000 0x20 0x00010000 0x0 0x00010000
+ 0x82000000 0x0 0x40000000 0x20 0x40000000 0x0 0x40000000>;
+};
+
+&pcie2 {
+ ranges = <0x81000000 0x0 0x00000000 0x28 0x00010000 0x0 0x00010000
+ 0x82000000 0x0 0x40000000 0x28 0x40000000 0x0 0x40000000>;
+};
+
+&pcie3 {
+ ranges = <0x81000000 0x0 0x00000000 0x30 0x00010000 0x0 0x00010000
+ 0x82000000 0x0 0x40000000 0x30 0x40000000 0x0 0x40000000>;
+};
+
+&pcie4 {
+ ranges = <0x81000000 0x0 0x00000000 0x38 0x00010000 0x0 0x00010000
+ 0x82000000 0x0 0x40000000 0x38 0x40000000 0x0 0x40000000>;
+};
--
1.9.1
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH v11 1/3] of: Add vendor prefix for Lattice Semiconductor
From: Joel Holdsworth @ 2017-01-09 5:23 UTC (permalink / raw)
To: atull-yzvPICuk2ABMcg4IHK0kFoH6Mc4MB0Vx,
moritz.fischer-+aYTwkv1SeIAvxtiuMwx3w,
robh-DgEjT+Ai2ygdnm+yROfE0A, devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-spi-u79uwXL29TY76Z2rM5mHXA, marex-ynQEQJNshbs,
linux-fpga-u79uwXL29TY76Z2rM5mHXA,
vladimir_zapolskiy-nmGgyN9QBj3QT0dZR+AlfA,
geert-Td1EMuHUCqxL1ZNQvxDV9g
Cc: Joel Holdsworth
Lattice Semiconductor Corporation is a manufacturer of integrated
circuits and IP products, including low-power FPGAs, video connectivity
devices and millimeter wave wireless products.
Website: http://latticesemi.com
Signed-off-by: Joel Holdsworth <joel-IJEoVVyKhCJXvIrf17iDB/XRex20P6io@public.gmane.org>
Acked-by: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
Acked-by: Alan Tull <atull-yzvPICuk2ABMcg4IHK0kFoH6Mc4MB0Vx@public.gmane.org>
Acked-by: Moritz Fischer <moritz.fischer-+aYTwkv1SeIAvxtiuMwx3w@public.gmane.org>
---
Documentation/devicetree/bindings/vendor-prefixes.txt | 1 +
1 file changed, 1 insertion(+)
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index 4ec84b7..5f8e533 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -159,6 +159,7 @@ kosagi Sutajio Ko-Usagi PTE Ltd.
kyo Kyocera Corporation
lacie LaCie
lantiq Lantiq Semiconductor
+lattice Lattice Semiconductor
lenovo Lenovo Group Ltd.
lg LG Corporation
licheepi Lichee Pi
--
2.7.4
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH v11 2/3] Documentation: Add binding document for Lattice iCE40 FPGA manager
From: Joel Holdsworth @ 2017-01-09 5:23 UTC (permalink / raw)
To: atull, moritz.fischer, robh, devicetree, linux-kernel, linux-spi,
marex, linux-fpga, vladimir_zapolskiy, geert
Cc: Joel Holdsworth
In-Reply-To: <1483939426-4941-1-git-send-email-joel@airwebreathe.org.uk>
This adds documentation of the device tree bindings of the Lattice iCE40
FPGA driver for the FPGA manager framework.
Signed-off-by: Joel Holdsworth <joel@airwebreathe.org.uk>
Acked-by: Rob Herring <robh@kernel.org>
Acked-by: Alan Tull <atull@opensource.altera.com>
Acked-by: Moritz Fischer <moritz.fischer@ettus.com>
Acked-by: Marek Vasut <marex@denx.de>
---
.../bindings/fpga/lattice-ice40-fpga-mgr.txt | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
create mode 100644 Documentation/devicetree/bindings/fpga/lattice-ice40-fpga-mgr.txt
diff --git a/Documentation/devicetree/bindings/fpga/lattice-ice40-fpga-mgr.txt b/Documentation/devicetree/bindings/fpga/lattice-ice40-fpga-mgr.txt
new file mode 100644
index 0000000..4dc4124
--- /dev/null
+++ b/Documentation/devicetree/bindings/fpga/lattice-ice40-fpga-mgr.txt
@@ -0,0 +1,21 @@
+Lattice iCE40 FPGA Manager
+
+Required properties:
+- compatible: Should contain "lattice,ice40-fpga-mgr"
+- reg: SPI chip select
+- spi-max-frequency: Maximum SPI frequency (>=1000000, <=25000000)
+- cdone-gpios: GPIO input connected to CDONE pin
+- reset-gpios: Active-low GPIO output connected to CRESET_B pin. Note
+ that unless the GPIO is held low during startup, the
+ FPGA will enter Master SPI mode and drive SCK with a
+ clock signal potentially jamming other devices on the
+ bus until the firmware is loaded.
+
+Example:
+ fpga: fpga@0 {
+ compatible = "lattice,ice40-fpga-mgr";
+ reg = <0>;
+ spi-max-frequency = <1000000>;
+ cdone-gpios = <&gpio 24 GPIO_ACTIVE_HIGH>;
+ reset-gpios = <&gpio 22 GPIO_ACTIVE_LOW>;
+ };
--
2.7.4
^ permalink raw reply related
* [PATCH v11 3/3] fpga: Add support for Lattice iCE40 FPGAs
From: Joel Holdsworth @ 2017-01-09 5:23 UTC (permalink / raw)
To: atull-yzvPICuk2ABMcg4IHK0kFoH6Mc4MB0Vx,
moritz.fischer-+aYTwkv1SeIAvxtiuMwx3w,
robh-DgEjT+Ai2ygdnm+yROfE0A, devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-spi-u79uwXL29TY76Z2rM5mHXA, marex-ynQEQJNshbs,
linux-fpga-u79uwXL29TY76Z2rM5mHXA,
vladimir_zapolskiy-nmGgyN9QBj3QT0dZR+AlfA,
geert-Td1EMuHUCqxL1ZNQvxDV9g
Cc: Joel Holdsworth
In-Reply-To: <1483939426-4941-1-git-send-email-joel-IJEoVVyKhCJXvIrf17iDB/XRex20P6io@public.gmane.org>
This patch adds support to the FPGA manager for configuring the SRAM of
iCE40LM, iCE40LP, iCE40HX, iCE40 Ultra, iCE40 UltraLite and iCE40
UltraPlus devices, through slave SPI.
Signed-off-by: Joel Holdsworth <joel-IJEoVVyKhCJXvIrf17iDB/XRex20P6io@public.gmane.org>
Reviewed-by: Marek Vasut <marex-ynQEQJNshbs@public.gmane.org>
Reviewed-by: Moritz Fischer <moritz.fischer-+aYTwkv1SeIAvxtiuMwx3w@public.gmane.org>
Acked-by: Alan Tull <atull-yzvPICuk2ABMcg4IHK0kFoH6Mc4MB0Vx@public.gmane.org>
---
drivers/fpga/Kconfig | 6 ++
drivers/fpga/Makefile | 1 +
drivers/fpga/ice40-spi.c | 207 +++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 214 insertions(+)
create mode 100644 drivers/fpga/ice40-spi.c
diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig
index ce861a2..967cda4 100644
--- a/drivers/fpga/Kconfig
+++ b/drivers/fpga/Kconfig
@@ -20,6 +20,12 @@ config FPGA_REGION
FPGA Regions allow loading FPGA images under control of
the Device Tree.
+config FPGA_MGR_ICE40_SPI
+ tristate "Lattice iCE40 SPI"
+ depends on OF && SPI
+ help
+ FPGA manager driver support for Lattice iCE40 FPGAs over SPI.
+
config FPGA_MGR_SOCFPGA
tristate "Altera SOCFPGA FPGA Manager"
depends on ARCH_SOCFPGA || COMPILE_TEST
diff --git a/drivers/fpga/Makefile b/drivers/fpga/Makefile
index 8df07bc..cc0d364 100644
--- a/drivers/fpga/Makefile
+++ b/drivers/fpga/Makefile
@@ -6,6 +6,7 @@
obj-$(CONFIG_FPGA) += fpga-mgr.o
# FPGA Manager Drivers
+obj-$(CONFIG_FPGA_MGR_ICE40_SPI) += ice40-spi.o
obj-$(CONFIG_FPGA_MGR_SOCFPGA) += socfpga.o
obj-$(CONFIG_FPGA_MGR_SOCFPGA_A10) += socfpga-a10.o
obj-$(CONFIG_FPGA_MGR_ZYNQ_FPGA) += zynq-fpga.o
diff --git a/drivers/fpga/ice40-spi.c b/drivers/fpga/ice40-spi.c
new file mode 100644
index 0000000..6a4194b
--- /dev/null
+++ b/drivers/fpga/ice40-spi.c
@@ -0,0 +1,207 @@
+/*
+ * FPGA Manager Driver for Lattice iCE40.
+ *
+ * Copyright (c) 2016 Joel Holdsworth
+ *
+ * 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 driver adds support to the FPGA manager for configuring the SRAM of
+ * Lattice iCE40 FPGAs through slave SPI.
+ */
+
+#include <linux/fpga/fpga-mgr.h>
+#include <linux/gpio/consumer.h>
+#include <linux/module.h>
+#include <linux/of_gpio.h>
+#include <linux/spi/spi.h>
+#include <linux/stringify.h>
+
+#define ICE40_SPI_MAX_SPEED 25000000 /* Hz */
+#define ICE40_SPI_MIN_SPEED 1000000 /* Hz */
+
+#define ICE40_SPI_RESET_DELAY 1 /* us (>200ns) */
+#define ICE40_SPI_HOUSEKEEPING_DELAY 1200 /* us */
+
+#define ICE40_SPI_NUM_ACTIVATION_BYTES DIV_ROUND_UP(49, 8)
+
+struct ice40_fpga_priv {
+ struct spi_device *dev;
+ struct gpio_desc *reset;
+ struct gpio_desc *cdone;
+};
+
+static enum fpga_mgr_states ice40_fpga_ops_state(struct fpga_manager *mgr)
+{
+ struct ice40_fpga_priv *priv = mgr->priv;
+
+ return gpiod_get_value(priv->cdone) ? FPGA_MGR_STATE_OPERATING :
+ FPGA_MGR_STATE_UNKNOWN;
+}
+
+static int ice40_fpga_ops_write_init(struct fpga_manager *mgr,
+ struct fpga_image_info *info,
+ const char *buf, size_t count)
+{
+ struct ice40_fpga_priv *priv = mgr->priv;
+ struct spi_device *dev = priv->dev;
+ struct spi_message message;
+ struct spi_transfer assert_cs_then_reset_delay = {
+ .cs_change = 1,
+ .delay_usecs = ICE40_SPI_RESET_DELAY
+ };
+ struct spi_transfer housekeeping_delay_then_release_cs = {
+ .delay_usecs = ICE40_SPI_HOUSEKEEPING_DELAY
+ };
+ int ret;
+
+ if ((info->flags & FPGA_MGR_PARTIAL_RECONFIG)) {
+ dev_err(&dev->dev,
+ "Partial reconfiguration is not supported\n");
+ return -ENOTSUPP;
+ }
+
+ /* Lock the bus, assert CRESET_B and SS_B and delay >200ns */
+ spi_bus_lock(dev->master);
+
+ gpiod_set_value(priv->reset, 1);
+
+ spi_message_init(&message);
+ spi_message_add_tail(&assert_cs_then_reset_delay, &message);
+ ret = spi_sync_locked(dev, &message);
+
+ /* Come out of reset */
+ gpiod_set_value(priv->reset, 0);
+
+ /* Abort if the chip-select failed */
+ if (ret)
+ goto fail;
+
+ /* Check CDONE is de-asserted i.e. the FPGA is reset */
+ if (gpiod_get_value(priv->cdone)) {
+ dev_err(&dev->dev, "Device reset failed, CDONE is asserted\n");
+ ret = -EIO;
+ goto fail;
+ }
+
+ /* Wait for the housekeeping to complete, and release SS_B */
+ spi_message_init(&message);
+ spi_message_add_tail(&housekeeping_delay_then_release_cs, &message);
+ ret = spi_sync_locked(dev, &message);
+
+fail:
+ spi_bus_unlock(dev->master);
+
+ return ret;
+}
+
+static int ice40_fpga_ops_write(struct fpga_manager *mgr,
+ const char *buf, size_t count)
+{
+ struct ice40_fpga_priv *priv = mgr->priv;
+
+ return spi_write(priv->dev, buf, count);
+}
+
+static int ice40_fpga_ops_write_complete(struct fpga_manager *mgr,
+ struct fpga_image_info *info)
+{
+ struct ice40_fpga_priv *priv = mgr->priv;
+ struct spi_device *dev = priv->dev;
+ const u8 padding[ICE40_SPI_NUM_ACTIVATION_BYTES] = {0};
+
+ /* Check CDONE is asserted */
+ if (!gpiod_get_value(priv->cdone)) {
+ dev_err(&dev->dev,
+ "CDONE was not asserted after firmware transfer\n");
+ return -EIO;
+ }
+
+ /* Send of zero-padding to activate the firmware */
+ return spi_write(dev, padding, sizeof(padding));
+}
+
+static const struct fpga_manager_ops ice40_fpga_ops = {
+ .state = ice40_fpga_ops_state,
+ .write_init = ice40_fpga_ops_write_init,
+ .write = ice40_fpga_ops_write,
+ .write_complete = ice40_fpga_ops_write_complete,
+};
+
+static int ice40_fpga_probe(struct spi_device *spi)
+{
+ struct device *dev = &spi->dev;
+ struct ice40_fpga_priv *priv;
+ int ret;
+
+ priv = devm_kzalloc(&spi->dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->dev = spi;
+
+ /* Check board setup data. */
+ if (spi->max_speed_hz > ICE40_SPI_MAX_SPEED) {
+ dev_err(dev, "SPI speed is too high, maximum speed is "
+ __stringify(ICE40_SPI_MAX_SPEED) "\n");
+ return -EINVAL;
+ }
+
+ if (spi->max_speed_hz < ICE40_SPI_MIN_SPEED) {
+ dev_err(dev, "SPI speed is too low, minimum speed is "
+ __stringify(ICE40_SPI_MIN_SPEED) "\n");
+ return -EINVAL;
+ }
+
+ if (spi->mode & SPI_CPHA) {
+ dev_err(dev, "Bad SPI mode, CPHA not supported\n");
+ return -EINVAL;
+ }
+
+ /* Set up the GPIOs */
+ priv->cdone = devm_gpiod_get(dev, "cdone", GPIOD_IN);
+ if (IS_ERR(priv->cdone)) {
+ ret = PTR_ERR(priv->cdone);
+ dev_err(dev, "Failed to get CDONE GPIO: %ld\n", ret);
+ return ret;
+ }
+
+ priv->reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
+ if (IS_ERR(priv->reset)) {
+ ret = PTR_ERR(priv->reset);
+ dev_err(dev, "Failed to get CRESET_B GPIO: %ld\n", ret);
+ return ret;
+ }
+
+ /* Register with the FPGA manager */
+ return fpga_mgr_register(dev, "Lattice iCE40 FPGA Manager",
+ &ice40_fpga_ops, priv);
+}
+
+static int ice40_fpga_remove(struct spi_device *spi)
+{
+ fpga_mgr_unregister(&spi->dev);
+ return 0;
+}
+
+static const struct of_device_id ice40_fpga_of_match[] = {
+ { .compatible = "lattice,ice40-fpga-mgr", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, ice40_fpga_of_match);
+
+static struct spi_driver ice40_fpga_driver = {
+ .probe = ice40_fpga_probe,
+ .remove = ice40_fpga_remove,
+ .driver = {
+ .name = "ice40spi",
+ .of_match_table = of_match_ptr(ice40_fpga_of_match),
+ },
+};
+
+module_spi_driver(ice40_fpga_driver);
+
+MODULE_AUTHOR("Joel Holdsworth <joel-IJEoVVyKhCJXvIrf17iDB/XRex20P6io@public.gmane.org>");
+MODULE_DESCRIPTION("Lattice iCE40 FPGA Manager");
+MODULE_LICENSE("GPL v2");
--
2.7.4
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox