* Re: [PATCH 2/5] clk: sunxi-ng: add support for V3s CCU
From: Maxime Ripard @ 2017-01-12 17:41 UTC (permalink / raw)
To: Icenowy Zheng
Cc: linux-kernel, linux-sunxi,
linux-gpio-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org,
Stephen Boyd, devicetree-u79uwXL29TY76Z2rM5mHXA, Linus Walleij,
linux-doc-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-clk-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, Chen-Yu Tsai
In-Reply-To: <20170112203149.VhtuR9dM-fU7thrOZ3Cs0PDqKvflMoHmW9unr2Ajn@public.gmane.org>
[-- Attachment #1: Type: text/plain, Size: 2051 bytes --]
On Fri, Jan 13, 2017 at 01:31:41AM +0800, Icenowy Zheng wrote:
>
> 2017年1月13日 01:19于 Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>写道:
> >
> > On Thu, Jan 12, 2017 at 03:44:53AM +0800, Icenowy Zheng wrote:
> > >
> > >
> > > 12.01.2017, 03:40, "Icenowy Zheng" <icenowy-ymACFijhrKM@public.gmane.org>:
> > > > 11.01.2017, 02:10, "Maxime Ripard" <maxime.ripard-wi1+55ScJUtKEb57/3fJTGGXanvQGlWp@public.gmane.orgm>:
> > > >> On Tue, Jan 03, 2017 at 11:16:26PM +0800, Icenowy Zheng wrote:
> > > >>> V3s has a similar but cut-down CCU to H3.
> > > >>>
> > > >>> Add support for it.
> > > >>>
> > > >>> Signed-off-by: Icenowy Zheng <icenowy-ymACFijhrKM@public.gmane.org>
> > > >>
> > > >> It looks like there's nothing different but the clocks that you
> > > >> register with the H3, please just use the H3 driver.
> > > >
> > > > Nope.
> > > >
> > > > It has a different PLL (PLL_ISP) at different address, and some
> > > > different muxes.
> > >
> > > Forgot to mention the missing of PLL_DE and related misses.
> >
> > Those are not conflicting, it's just a slightly different set of
> > clocks.
>
> If saying so, we can have only one ccu driver, and make every ccu
> register different set ;-)
>
> V3s itself is a totally different SoC with H3.
>
> The relationship of V3s and H3 can be farther than the relationship
> of A33 and H3😃
A33 and H3 are an entirely different story. The H3 and A33 have
conflicting clocks (ie same clocks with different parameters). This is
not your case.
Maxime
--
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
--
You received this message because you are subscribed to the Google Groups "linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email to linux-sunxi+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org
For more options, visit https://groups.google.com/d/optout.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 801 bytes --]
^ permalink raw reply
* Re: [PATCH v2 2/2] Support for DW CSI-2 Host IPK
From: Ramiro Oliveira @ 2017-01-12 17:43 UTC (permalink / raw)
To: Hans Verkuil, Ramiro Oliveira, robh+dt, mark.rutland, mchehab,
devicetree, linux-kernel, linux-media
Cc: davem, gregkh, geert+renesas, akpm, linux,
laurent.pinchart+renesas, arnd, sudipm.mukherjee, tiffany.lin,
minghsiu.tsai, jean-christophe.trotin, andrew-ct.chen,
simon.horman, songjun.wu, bparrot, CARLOS.PALMINHA, Sakari Ailus
In-Reply-To: <eb89af79-f868-ceba-ac69-558bac77613d@xs4all.nl>
Hi Hans,
Thank you for your feedback.
On 1/11/2017 11:54 AM, Hans Verkuil wrote:
> Hi Ramiro,
>
> See my review comments below:
>
> On 12/12/16 16:00, Ramiro Oliveira wrote:
>> Add support for the DesignWare CSI-2 Host IP Prototyping Kit
>>
>> Signed-off-by: Ramiro Oliveira <roliveir@synopsys.com>
[snip]
>> +static int
>> +dw_mipi_csi_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg,
>> + struct v4l2_subdev_format *fmt)
>> +{
>> + struct mipi_csi_dev *dev = sd_to_mipi_csi_dev(sd);
>> + struct mipi_fmt const *dev_fmt;
>> + struct v4l2_mbus_framefmt *mf;
>> + unsigned int i = 0;
>> + const struct v4l2_bt_timings *bt_r = &v4l2_dv_timings_presets[0].bt;
>> +
>> + mf = __dw_mipi_csi_get_format(dev, cfg, fmt->which);
>> +
>> + dev_fmt = dw_mipi_csi_try_format(&fmt->format);
>> + if (dev_fmt) {
>> + *mf = fmt->format;
>> + if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE)
>> + dev->fmt = dev_fmt;
>> + dw_mipi_csi_set_ipi_fmt(dev);
>> + }
>> + while (v4l2_dv_timings_presets[i].bt.width) {
>> + const struct v4l2_bt_timings *bt =
>> + &v4l2_dv_timings_presets[i].bt;
>> + if (mf->width == bt->width && mf->height == bt->width) {
>> + __dw_mipi_csi_fill_timings(dev, bt);
>> + return 0;
>> + }
>> + i++;
>> + }
>> +
>> + __dw_mipi_csi_fill_timings(dev, bt_r);
>
> This code is weird. The video source can be either from a sensor or from an
> HDMI input, right?
>
> But if it is from a sensor, then using v4l2_dv_timings_presets since that's for
> an HDMI input. Sensors will typically not follow these preset timings.
>
> For HDMI input I expect that this driver supports the s_dv_timings op and will
> just use the timings set there and override the width/height in v4l2_subdev_format.
>
> For sensors I am actually not quite certain how this is done. I've CC-ed Sakari
> since he'll know. But let us know first whether it is indeed the intention that
> this should also work with a sensor.
>
Actually the video source, at the moment, can only be from a sensor. I'm using
v4l2_dv_timings_presets as a reference since we usually use this setup with a
Test Equipment in which we can configure every parameter.
I'll wait for Sakari to answer, and change it to what he recommends.
>> + return 0;
>> +
>> +}
>> +
>> +static int
>> +dw_mipi_csi_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg,
>> + struct v4l2_subdev_format *fmt)
>> +{
>> + struct mipi_csi_dev *dev = sd_to_mipi_csi_dev(sd);
>> + struct v4l2_mbus_framefmt *mf;
>> +
>> + mf = __dw_mipi_csi_get_format(dev, cfg, fmt->which);
>> + if (!mf)
>> + return -EINVAL;
>> +
>> + mutex_lock(&dev->lock);
>> + fmt->format = *mf;
>> + mutex_unlock(&dev->lock);
>> + return 0;
>> +}
>> +
>> +static int
>> +dw_mipi_csi_s_power(struct v4l2_subdev *sd, int on)
>> +{
>> + struct mipi_csi_dev *dev = sd_to_mipi_csi_dev(sd);
>> +
>> + if (on) {
>> + dw_mipi_csi_hw_stdby(dev);
>> + dw_mipi_csi_start(dev);
>> + } else {
>> + dw_mipi_csi_mask_irq_power_off(dev);
>> + }
>> +
>> + return 0;
>> +}
>> +
>> +static int
>> +dw_mipi_csi_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
>> +{
>> + struct v4l2_mbus_framefmt *format =
>> + v4l2_subdev_get_try_format(sd, fh->pad, 0);
>> +
>> + format->colorspace = V4L2_COLORSPACE_SRGB;
>> + format->code = dw_mipi_csi_formats[0].code;
>> + format->width = MIN_WIDTH;
>> + format->height = MIN_HEIGHT;
>> + format->field = V4L2_FIELD_NONE;
>
> Don't do this. Instead implement the init_cfg pad op and initialize this there.
>
> You can then drop this function.
>
I'll do that.
>> +
>> + return 0;
>> +}
>> +
>> +static const struct v4l2_subdev_internal_ops dw_mipi_csi_sd_internal_ops = {
>> + .open = dw_mipi_csi_open,
>> +};
>> +
>> +static struct v4l2_subdev_core_ops dw_mipi_csi_core_ops = {
>> + .s_power = dw_mipi_csi_s_power,
>> +};
>> +
>> +static struct v4l2_subdev_pad_ops dw_mipi_csi_pad_ops = {
>> + .enum_mbus_code = dw_mipi_csi_enum_mbus_code,
>> + .get_fmt = dw_mipi_csi_get_fmt,
>> + .set_fmt = dw_mipi_csi_set_fmt,
>> +};
>> +
>> +static struct v4l2_subdev_ops dw_mipi_csi_subdev_ops = {
>> + .core = &dw_mipi_csi_core_ops,
>> + .pad = &dw_mipi_csi_pad_ops,
>> +};
>> +
>> +static irqreturn_t
>> +dw_mipi_csi_irq1(int irq, void *dev_id)
>> +{
>> + struct mipi_csi_dev *csi_dev = dev_id;
>> + u32 global_int_status, i_sts;
>> + unsigned long flags;
>> + struct device *dev = &csi_dev->pdev->dev;
>> +
>> + global_int_status = dw_mipi_csi_read(csi_dev, R_CSI2_INTERRUPT);
>> + spin_lock_irqsave(&csi_dev->slock, flags);
>> +
>> + if (global_int_status & CSI2_INT_PHY_FATAL) {
>> + i_sts = dw_mipi_csi_read(csi_dev, R_CSI2_INT_PHY_FATAL);
>> + dev_dbg_ratelimited(dev, "CSI INT PHY FATAL: %08X\n", i_sts);
>> + }
>> +
>> + if (global_int_status & CSI2_INT_PKT_FATAL) {
>> + i_sts = dw_mipi_csi_read(csi_dev, R_CSI2_INT_PKT_FATAL);
>> + dev_dbg_ratelimited(dev, "CSI INT PKT FATAL: %08X\n", i_sts);
>> + }
>> +
>> + if (global_int_status & CSI2_INT_FRAME_FATAL) {
>> + i_sts = dw_mipi_csi_read(csi_dev, R_CSI2_INT_FRAME_FATAL);
>> + dev_dbg_ratelimited(dev, "CSI INT FRAME FATAL: %08X\n", i_sts);
>> + }
>> +
>> + if (global_int_status & CSI2_INT_PHY) {
>> + i_sts = dw_mipi_csi_read(csi_dev, R_CSI2_INT_PHY);
>> + dev_dbg_ratelimited(dev, "CSI INT PHY: %08X\n", i_sts);
>> + }
>> +
>> + if (global_int_status & CSI2_INT_PKT) {
>> + i_sts = dw_mipi_csi_read(csi_dev, R_CSI2_INT_PKT);
>> + dev_dbg_ratelimited(dev, "CSI INT PKT: %08X\n", i_sts);
>> + }
>> +
>> + if (global_int_status & CSI2_INT_LINE) {
>> + i_sts = dw_mipi_csi_read(csi_dev, R_CSI2_INT_LINE);
>> + dev_dbg_ratelimited(dev, "CSI INT LINE: %08X\n", i_sts);
>> + }
>> +
>> + if (global_int_status & CSI2_INT_IPI) {
>> + i_sts = dw_mipi_csi_read(csi_dev, R_CSI2_INT_IPI);
>> + dev_dbg_ratelimited(dev, "CSI INT IPI: %08X\n", i_sts);
>> + }
>> + spin_unlock_irqrestore(&csi_dev->slock, flags);
>> + return IRQ_HANDLED;
>> +}
>> +
>> +static int
>> +dw_mipi_csi_parse_dt(struct platform_device *pdev, struct mipi_csi_dev *dev)
>> +{
>> + struct device_node *node = pdev->dev.of_node;
>> + int reg;
>> + int ret = 0;
>> +
>> + /* Device tree information */
>
> I would expect to see a call to v4l2_of_parse_endpoint here.
>
You're right. I'll add it.
>> + ret = of_property_read_u32(node, "data-lanes", &dev->hw.num_lanes);
>> + if (ret) {
>> + dev_err(&pdev->dev, "Couldn't read data-lanes\n");
>> + return ret;
>> + }
>> +
>> + ret = of_property_read_u32(node, "output-type", &dev->hw.output_type);
>> + if (ret) {
>> + dev_err(&pdev->dev, "Couldn't read output-type\n");
>> + return ret;
>> + }
>> +
>> + ret = of_property_read_u32(node, "ipi-mode", &dev->hw.ipi_mode);
>> + if (ret) {
>> + dev_err(&pdev->dev, "Couldn't read ipi-mode\n");
>> + return ret;
>> + }
>> +
>> + ret =
>> + of_property_read_u32(node, "ipi-auto-flush",
>> + &dev->hw.ipi_auto_flush);
>> + if (ret) {
>> + dev_err(&pdev->dev, "Couldn't read ipi-auto-flush\n");
>> + return ret;
>> + }
>> +
>> + ret =
>> + of_property_read_u32(node, "ipi-color-mode",
>> + &dev->hw.ipi_color_mode);
>> + if (ret) {
>> + dev_err(&pdev->dev, "Couldn't read ipi-color-mode\n");
>> + return ret;
>> + }
>> +
>> + ret =
>> + of_property_read_u32(node, "virtual-channel", &dev->hw.virtual_ch);
>> + if (ret) {
>> + dev_err(&pdev->dev, "Couldn't read virtual-channel\n");
>> + return ret;
>> + }
>> +
>> + node = of_get_child_by_name(node, "port");
>> + if (!node)
>> + return -EINVAL;
>> +
>> + ret = of_property_read_u32(node, "reg", ®);
>> + if (ret) {
>> + dev_err(&pdev->dev, "Couldn't read reg value\n");
>> + return ret;
>> + }
>> + dev->index = reg - 1;
>> +
>> + if (dev->index >= CSI_MAX_ENTITIES)
>> + return -ENXIO;
>> +
>> + return 0;
>> +}
>> +
[snip]
>> diff --git a/drivers/media/platform/dwc/plat_ipk.c
>> b/drivers/media/platform/dwc/plat_ipk.c
>> new file mode 100644
>> index 0000000..02dcf36
>> --- /dev/null
>> +++ b/drivers/media/platform/dwc/plat_ipk.c
>> @@ -0,0 +1,818 @@
>> +/**
>> + * DWC MIPI CSI-2 Host IPK platform device driver
>
> What does IPK stand for?
>
IPK stands for IP Prototyping Kit. However any reference to this will probably
disappear in the next patchset.
[snip]
>> +
>> +static const struct plat_ipk_fmt *
>> +vid_dev_find_format(struct v4l2_format *f, int index)
>> +{
>> + const struct plat_ipk_fmt *fmt = NULL;
>> + unsigned int i;
>> +
>> + if (index >= (int) ARRAY_SIZE(vid_dev_formats))
>> + return NULL;
>
> ???
>
> What's the purpose of the index argument? I get the feeling it is
> a left-over from older code.
>
Yes. It's a left-over. I'll remove it.
>> +
>> + for (i = 0; i < ARRAY_SIZE(vid_dev_formats); ++i) {
>> + fmt = &vid_dev_formats[i];
>> + if (fmt->fourcc == f->fmt.pix.pixelformat)
>> + return fmt;
>> + }
>> + return NULL;
>> +}
>> +
>> +/*
>> + * Video node ioctl operations
>> + */
>> +static int
>> +vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *cap)
>> +{
>> + struct video_device_dev *vid_dev = video_drvdata(file);
>> +
>> + strlcpy(cap->driver, VIDEO_DEVICE_NAME, sizeof(cap->driver));
>> + strlcpy(cap->card, VIDEO_DEVICE_NAME, sizeof(cap->card));
>> + snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s",
>> + dev_name(&vid_dev->pdev->dev));
>> +
>> + cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
>> + cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
>
> Set the device_caps in struct video_device and drop these two lines.
> The core will fill those in for you.
>
I'll change them to where I configure the struct video_device.
>> + return 0;
>> +}
>> +
>> +static int
>> +vidioc_enum_fmt_vid_cap(struct file *file, void *priv, struct v4l2_fmtdesc *f)
>> +{
>> + const struct plat_ipk_fmt *p_fmt;
>> +
>> + if (f->index >= ARRAY_SIZE(vid_dev_formats))
>> + return -EINVAL;
>> +
>> + p_fmt = &vid_dev_formats[f->index];
>> +
>> + strlcpy(f->description, p_fmt->name, sizeof(f->description));
>
> Don't set the description, the core will do that for you.
>
OK.
>> + f->pixelformat = p_fmt->fourcc;
>> +
>> + return 0;
>> +}
>> +
>> +static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
>> + struct v4l2_format *f)
>> +{
>> + struct video_device_dev *dev = video_drvdata(file);
>> +
>> + memcpy(&f->fmt.pix, &dev->format.fmt.pix,
>> + sizeof(struct v4l2_pix_format));
>
> Use f->fmt.pix = dev->format.fmt.pix;
>
I'll do that
>> +
>> + return 0;
>> +}
>> +
>> +static int
>> +vidioc_try_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f)
>> +{
>> + const struct plat_ipk_fmt *fmt;
>> +
>> + fmt = vid_dev_find_format(f, -1);
>> + if (!fmt) {
>> + f->fmt.pix.pixelformat = V4L2_PIX_FMT_RGB565;
>> + fmt = vid_dev_find_format(f, -1);
>> + }
>> +
>> + f->fmt.pix.field = V4L2_FIELD_NONE;
>> + v4l_bound_align_image(&f->fmt.pix.width, 48, MAX_WIDTH, 2,
>> + &f->fmt.pix.height, 32, MAX_HEIGHT, 0, 0);
>> +
>> + f->fmt.pix.bytesperline = (f->fmt.pix.width * fmt->depth) >> 3;
>> + f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
>> + f->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB;
>> + return 0;
>> +}
>> +
>> +static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
>> + struct v4l2_format *f)
>> +{
>> + struct video_device_dev *dev = video_drvdata(file);
>> + int ret;
>> + struct v4l2_subdev_format fmt;
>> + struct v4l2_pix_format *dev_fmt_pix = &dev->format.fmt.pix;
>> +
>> + if (vb2_is_busy(&dev->vb_queue))
>> + return -EBUSY;
>> +
>> + ret = vidioc_try_fmt_vid_cap(file, dev, f);
>> + if (ret)
>> + return ret;
>> +
>> + dev->fmt = vid_dev_find_format(f, -1);
>> + dev_fmt_pix->pixelformat = f->fmt.pix.pixelformat;
>> + dev_fmt_pix->width = f->fmt.pix.width;
>> + dev_fmt_pix->height = f->fmt.pix.height;
>> + dev_fmt_pix->bytesperline = dev_fmt_pix->width * (dev->fmt->depth / 8);
>> + dev_fmt_pix->sizeimage =
>> + dev_fmt_pix->height * dev_fmt_pix->bytesperline;
>> +
>> + fmt.format.colorspace = V4L2_COLORSPACE_SRGB;
>> + fmt.format.code = dev->fmt->mbus_code;
>> +
>> + fmt.format.width = dev_fmt_pix->width;
>> + fmt.format.height = dev_fmt_pix->height;
>> +
>> + ret = plat_ipk_pipeline_call(&dev->ve, set_format, &fmt);
>> +
>> + return 0;
>> +}
>> +
>> +static int vidioc_enum_framesizes(struct file *file, void *fh,
>> + struct v4l2_frmsizeenum *fsize)
>> +{
>> + static const struct v4l2_frmsize_stepwise sizes = {
>> + 48, MAX_WIDTH, 4,
>> + 32, MAX_HEIGHT, 1
>> + };
>> + int i;
>> +
>> + if (fsize->index)
>> + return -EINVAL;
>> + for (i = 0; i < ARRAY_SIZE(vid_dev_formats); i++)
>> + if (vid_dev_formats[i].fourcc == fsize->pixel_format)
>> + break;
>> + if (i == ARRAY_SIZE(vid_dev_formats))
>> + return -EINVAL;
>> + fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
>> + fsize->stepwise = sizes;
>> + return 0;
>> +}
>> +
>> +static int vidioc_enum_input(struct file *file, void *priv,
>> + struct v4l2_input *input)
>> +{
>> + if (input->index != 0)
>> + return -EINVAL;
>> +
>> + input->type = V4L2_INPUT_TYPE_CAMERA;
>> + input->std = V4L2_STD_ALL; /* Not sure what should go here */
>
> Set this to 0, or just drop the line.
>
Thanks.
>> + strcpy(input->name, "Camera");
>> + return 0;
>> +}
>> +
[snip]
>> +
>> +static int vid_dev_subdev_s_power(struct v4l2_subdev *sd, int on)
>> +{
>> + return 0;
>> +}
>
> Just drop this empty function, shouldn't be needed.
>
When I start my system I'm hoping all the subdevs have s_power registered. If it
doesn't exist should I change the way I handle it, or will the core handle it
for me?
>> +
>> +static int vid_dev_subdev_registered(struct v4l2_subdev *sd)
>> +{
>> + struct video_device_dev *vid_dev = v4l2_get_subdevdata(sd);
>> + struct vb2_queue *q = &vid_dev->vb_queue;
>> + struct video_device *vfd = &vid_dev->ve.vdev;
>> + int ret;
>> +
>> + memset(vfd, 0, sizeof(*vfd));
>> +
>> + strlcpy(vfd->name, VIDEO_DEVICE_NAME, sizeof(vfd->name));
>> +
>> + vfd->fops = &vid_dev_fops;
>> + vfd->ioctl_ops = &vid_dev_ioctl_ops;
>> + vfd->v4l2_dev = sd->v4l2_dev;
>> + vfd->minor = -1;
>> + vfd->release = video_device_release_empty;
>> + vfd->queue = q;
>> +
>> + INIT_LIST_HEAD(&vid_dev->vidq.active);
>> + init_waitqueue_head(&vid_dev->vidq.wq);
>> + memset(q, 0, sizeof(*q));
>> + q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
>> + q->io_modes = VB2_MMAP | VB2_USERPTR;
>
> Add VB2_DMABUF and VB2_READ.
>
I'll add them, but I'm not using them, is it standard procedure to add them all
even if they aren't used?
>> + q->ops = &vb2_video_qops;
>> + q->mem_ops = &vb2_vmalloc_memops;
>
> Why is vmalloc used? Can't you use dma_contig or dma_sg and avoid having to copy
> the image data? That's a really bad design given the amount of video data that
> you have to copy.
>
When I started development, the arch I was using (ARC) didn't support
dma_contig, so I was forced to use vmalloc.
Since then things have changed and I'm already using dma_contig, however it
wasn't included in this patch. I'll add it to the next patch.
>> + q->buf_struct_size = sizeof(struct rx_buffer);
>> + q->drv_priv = vid_dev;
>> + q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
>> + q->lock = &vid_dev->lock;
>> +
>> + ret = vb2_queue_init(q);
>> + if (ret < 0)
>> + return ret;
>> +
>> + vid_dev->vd_pad.flags = MEDIA_PAD_FL_SINK;
>> + ret = media_entity_pads_init(&vfd->entity, 1, &vid_dev->vd_pad);
>> + if (ret < 0)
>> + return ret;
>> +
>> + video_set_drvdata(vfd, vid_dev);
>> + vid_dev->ve.pipe = v4l2_get_subdev_hostdata(sd);
>> +
>> + ret = video_register_device(vfd, VFL_TYPE_GRABBER, -1);
>> + if (ret < 0) {
>> + media_entity_cleanup(&vfd->entity);
>> + vid_dev->ve.pipe = NULL;
>> + return ret;
>> + }
>> +
>> + v4l2_info(sd->v4l2_dev, "Registered %s as /dev/%s\n",
>> + vfd->name, video_device_node_name(vfd));
>> + return 0;
>> +}
>> +
[snip]
>
> Regards,
>
> Hans
BRs,
Ramiro
^ permalink raw reply
* Re: [PATCH v8 2/5] i2c: Add STM32F4 I2C driver
From: Uwe Kleine-König @ 2017-01-12 17:49 UTC (permalink / raw)
To: M'boumba Cedric Madianga
Cc: devicetree, Alexandre Torgue, Wolfram Sang, linux-kernel,
Linus Walleij, Patrice Chotard, Russell King, Rob Herring,
linux-i2c, Maxime Coquelin, linux-arm-kernel
In-Reply-To: <CAOAejn289GLOSP-nPJnO_VpXLpyhTsF1bWQ7Ns9OfgPQCa8YTw@mail.gmail.com>
On Thu, Jan 12, 2017 at 02:47:42PM +0100, M'boumba Cedric Madianga wrote:
> 2017-01-12 13:03 GMT+01:00 Uwe Kleine-König <u.kleine-koenig@pengutronix.de>:
> > Hello Cedric,
> >
> > On Thu, Jan 12, 2017 at 12:23:12PM +0100, M'boumba Cedric Madianga wrote:
> >> 2017-01-11 16:39 GMT+01:00 Uwe Kleine-König <u.kleine-koenig@pengutronix.de>:
> >> > On Wed, Jan 11, 2017 at 02:58:44PM +0100, M'boumba Cedric Madianga wrote:
> >> >> 2017-01-11 9:22 GMT+01:00 Uwe Kleine-König <u.kleine-koenig@pengutronix.de>:
> >> >> > This is surprising. I didn't recheck the manual, but that looks very
> >> >> > uncomfortable.
> >> >>
> >> >> I agree but this exactly the hardware way of working described in the
> >> >> reference manual.
> >> >
> >> > IMHO that's a hw bug. This makes it for example impossible to implement
> >> > SMBus block transfers (I think).
> >>
> >> This is not correct.
> >> Setting STOP/START bit does not mean the the pulse will be sent right now.
> >> Here we have just to prepare the hardware for the 2 next pulse but the
> >> STOP/START/ACK pulse will be generated at the right time as required
> >> by I2C specification.
> >> So SMBus block transfer will be possible.
> >
> > A block transfer consists of a byte that specifies the count of bytes
> > yet to come. So the device sends for example:
> >
> > 0x01 0xab
> >
> > So when you read the 1 in the first byte it's already too late to set
> > STOP to get it after the 2nd byte.
> >
> > Not sure I got all the required details right, though.
>
> Ok I understand your use case but I always think that the harware manages it.
> If I take the above example, the I2C SMBus block read transaction will
> be as below:
> S Addr Wr [A] Comm [A]
> S Addr Rd [A] [Count] A [Data1] A [Data2] NA P
>
> The first message is a single byte-transmission so there is no problem.
>
> The second message is a N-byte reception with N = 3
>
> When the I2C controller has finished to send the device address (S
> Addr Rd), the ADDR flag is set and an interrupt is raised.
> In the routine that handles ADDR event, we set ACK bit in order to
> generate ACK pulse as soon as a data byte is received in the shift
> register and then we clear the ADDR flag.
> Please note that the SCL line is stretched low until ADDR flag is cleared.
> So, as far I understand, the device could not sent any data as long as
> the SCL line is stretched low. Right ?
>
> Then, as soon as the SCL line is high, the device could send the first
> data byte (Count).
> When this byte is received in the shift register, an ACK is
> automatically generated as defined during adress match phase and the
> data byte is pushed in DR (data register).
> Then, an interrupt is raised as RXNE (RX not empty) flag is set.
> In the routine that handles RXNE event, as N=3, we just clear all
> buffer interrupts in order to avoid another system preemption due to
> RXNE event but we does not read the data in DR.
In my example I want to receive a block of length 1, so only two bytes
are read, a 1 (the length) and the data byte (0xab in my example). I
think that as soon as you read the 1 it's already to late to schedule
the NA after the next byte?
Best regards
Uwe
--
Pengutronix e.K. | Uwe Kleine-König |
Industrial Linux Solutions | http://www.pengutronix.de/ |
^ permalink raw reply
* [PATCH v5 1/3] Bluetooth: btusb: Use an error label for error paths
From: Rajat Jain @ 2017-01-12 18:01 UTC (permalink / raw)
To: Rob Herring, Mark Rutland, Marcel Holtmann, Gustavo Padovan,
Johan Hedberg, Amitkumar Karwar, Wei-Ning Huang, Xinming Hu,
netdev, devicetree, linux-bluetooth, Brian Norris, linux-kernel
Cc: Rajat Jain, rajatxjain
Use a label to remove the repetetive cleanup, for error cases.
Signed-off-by: Rajat Jain <rajatja@google.com>
Reviewed-by: Brian Norris <briannorris@chromium.org>
---
v5: same as v4
v4: same as v3
v3: Added Brian's "Reviewed-by"
v2: same as v1
drivers/bluetooth/btusb.c | 19 +++++++++----------
1 file changed, 9 insertions(+), 10 deletions(-)
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index 2f633df9f4e6..ce22cefceed1 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -2991,18 +2991,15 @@ static int btusb_probe(struct usb_interface *intf,
err = usb_set_interface(data->udev, 0, 0);
if (err < 0) {
BT_ERR("failed to set interface 0, alt 0 %d", err);
- hci_free_dev(hdev);
- return err;
+ goto out_free_dev;
}
}
if (data->isoc) {
err = usb_driver_claim_interface(&btusb_driver,
data->isoc, data);
- if (err < 0) {
- hci_free_dev(hdev);
- return err;
- }
+ if (err < 0)
+ goto out_free_dev;
}
#ifdef CONFIG_BT_HCIBTUSB_BCM
@@ -3016,14 +3013,16 @@ static int btusb_probe(struct usb_interface *intf,
#endif
err = hci_register_dev(hdev);
- if (err < 0) {
- hci_free_dev(hdev);
- return err;
- }
+ if (err < 0)
+ goto out_free_dev;
usb_set_intfdata(intf, data);
return 0;
+
+out_free_dev:
+ hci_free_dev(hdev);
+ return err;
}
static void btusb_disconnect(struct usb_interface *intf)
--
2.11.0.390.gc69c2f50cf-goog
^ permalink raw reply related
* [PATCH v5 2/3] Bluetooth: btusb: Add out-of-band wakeup support
From: Rajat Jain @ 2017-01-12 18:01 UTC (permalink / raw)
To: Rob Herring, Mark Rutland, Marcel Holtmann, Gustavo Padovan,
Johan Hedberg, Amitkumar Karwar, Wei-Ning Huang, Xinming Hu,
netdev, devicetree, linux-bluetooth, Brian Norris, linux-kernel
Cc: Rajat Jain, rajatxjain
In-Reply-To: <20170112180107.63244-1-rajatja@google.com>
Some onboard BT chips (e.g. Marvell 8997) contain a wakeup pin that
can be connected to a gpio on the CPU side, and can be used to wakeup
the host out-of-band. This can be useful in situations where the
in-band wakeup is not possible or not preferable (e.g. the in-band
wakeup may require the USB host controller to remain active, and
hence consuming more system power during system sleep).
The oob gpio interrupt to be used for wakeup on the CPU side, is
read from the device tree node, (using standard interrupt descriptors).
A devcie tree binding document is also added for the driver. The
compatible string is in compliance with
Documentation/devicetree/bindings/usb/usb-device.txt
Signed-off-by: Rajat Jain <rajatja@google.com>
Reviewed-by: Brian Norris <briannorris@chromium.org>
Acked-by: Rob Herring <robh@kernel.org>
---
v5: Move the call to pm_wakeup_event() to the begining of irq handler.
v4: Move the set_bit(BTUSB_OOB_WAKE_DISABLED,..) call to the beginning of
btusb_config_oob_wake()
v3: Add Brian's "Reviewed-by"
v2: * Use interrupt-names ("wakeup") instead of assuming first interrupt.
* Leave it on device tree to specify IRQ flags (level /edge triggered)
* Mark the device as non wakeable on exit.
Documentation/devicetree/bindings/net/btusb.txt | 40 ++++++++++++
drivers/bluetooth/btusb.c | 85 +++++++++++++++++++++++++
2 files changed, 125 insertions(+)
create mode 100644 Documentation/devicetree/bindings/net/btusb.txt
diff --git a/Documentation/devicetree/bindings/net/btusb.txt b/Documentation/devicetree/bindings/net/btusb.txt
new file mode 100644
index 000000000000..2c0355c85972
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/btusb.txt
@@ -0,0 +1,40 @@
+Generic Bluetooth controller over USB (btusb driver)
+---------------------------------------------------
+
+Required properties:
+
+ - compatible : should comply with the format "usbVID,PID" specified in
+ Documentation/devicetree/bindings/usb/usb-device.txt
+ At the time of writing, the only OF supported devices
+ (more may be added later) are:
+
+ "usb1286,204e" (Marvell 8997)
+
+Optional properties:
+
+ - interrupt-parent: phandle of the parent interrupt controller
+ - interrupt-names: (see below)
+ - interrupts : The interrupt specified by the name "wakeup" is the interrupt
+ that shall be used for out-of-band wake-on-bt. Driver will
+ request this interrupt for wakeup. During system suspend, the
+ irq will be enabled so that the bluetooth chip can wakeup host
+ platform out of band. During system resume, the irq will be
+ disabled to make sure unnecessary interrupt is not received.
+
+Example:
+
+Following example uses irq pin number 3 of gpio0 for out of band wake-on-bt:
+
+&usb_host1_ehci {
+ status = "okay";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ mvl_bt1: bt@1 {
+ compatible = "usb1286,204e";
+ reg = <1>;
+ interrupt-parent = <&gpio0>;
+ interrupt-name = "wakeup";
+ interrupts = <3 IRQ_TYPE_LEVEL_LOW>;
+ };
+};
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index ce22cefceed1..0a777bb407b1 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -24,6 +24,8 @@
#include <linux/module.h>
#include <linux/usb.h>
#include <linux/firmware.h>
+#include <linux/of_device.h>
+#include <linux/of_irq.h>
#include <asm/unaligned.h>
#include <net/bluetooth/bluetooth.h>
@@ -369,6 +371,7 @@ static const struct usb_device_id blacklist_table[] = {
#define BTUSB_BOOTING 9
#define BTUSB_RESET_RESUME 10
#define BTUSB_DIAG_RUNNING 11
+#define BTUSB_OOB_WAKE_DISABLED 12
struct btusb_data {
struct hci_dev *hdev;
@@ -416,6 +419,8 @@ struct btusb_data {
int (*recv_bulk)(struct btusb_data *data, void *buffer, int count);
int (*setup_on_usb)(struct hci_dev *hdev);
+
+ int oob_wake_irq; /* irq for out-of-band wake-on-bt */
};
static inline void btusb_free_frags(struct btusb_data *data)
@@ -2728,6 +2733,66 @@ static int btusb_bcm_set_diag(struct hci_dev *hdev, bool enable)
}
#endif
+#ifdef CONFIG_PM
+static irqreturn_t btusb_oob_wake_handler(int irq, void *priv)
+{
+ struct btusb_data *data = priv;
+
+ pm_wakeup_event(&data->udev->dev, 0);
+
+ /* Disable only if not already disabled (keep it balanced) */
+ if (!test_and_set_bit(BTUSB_OOB_WAKE_DISABLED, &data->flags)) {
+ disable_irq_nosync(irq);
+ disable_irq_wake(irq);
+ }
+ return IRQ_HANDLED;
+}
+
+static const struct of_device_id btusb_match_table[] = {
+ { .compatible = "usb1286,204e" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, btusb_match_table);
+
+/* Use an oob wakeup pin? */
+static int btusb_config_oob_wake(struct hci_dev *hdev)
+{
+ struct btusb_data *data = hci_get_drvdata(hdev);
+ struct device *dev = &data->udev->dev;
+ int irq, ret;
+
+ set_bit(BTUSB_OOB_WAKE_DISABLED, &data->flags);
+
+ if (!of_match_device(btusb_match_table, dev))
+ return 0;
+
+ /* Move on if no IRQ specified */
+ irq = of_irq_get_byname(dev->of_node, "wakeup");
+ if (irq <= 0) {
+ bt_dev_dbg(hdev, "%s: no OOB Wakeup IRQ in DT", __func__);
+ return 0;
+ }
+
+ ret = devm_request_irq(&hdev->dev, irq, btusb_oob_wake_handler,
+ 0, "OOB Wake-on-BT", data);
+ if (ret) {
+ bt_dev_err(hdev, "%s: IRQ request failed", __func__);
+ return ret;
+ }
+
+ ret = device_init_wakeup(dev, true);
+ if (ret) {
+ bt_dev_err(hdev, "%s: failed to init_wakeup\n", __func__);
+ return ret;
+ }
+
+ data->oob_wake_irq = irq;
+ disable_irq(irq);
+ bt_dev_info(hdev, "OOB Wake-on-BT configured at IRQ %u\n", irq);
+ return 0;
+}
+#endif
+
static int btusb_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
@@ -2849,6 +2914,11 @@ static int btusb_probe(struct usb_interface *intf,
hdev->send = btusb_send_frame;
hdev->notify = btusb_notify;
+#ifdef CONFIG_PM
+ err = btusb_config_oob_wake(hdev);
+ if (err)
+ goto out_free_dev;
+#endif
if (id->driver_info & BTUSB_CW6622)
set_bit(HCI_QUIRK_BROKEN_STORED_LINK_KEY, &hdev->quirks);
@@ -3061,6 +3131,9 @@ static void btusb_disconnect(struct usb_interface *intf)
usb_driver_release_interface(&btusb_driver, data->isoc);
}
+ if (data->oob_wake_irq)
+ device_init_wakeup(&data->udev->dev, false);
+
hci_free_dev(hdev);
}
@@ -3089,6 +3162,12 @@ static int btusb_suspend(struct usb_interface *intf, pm_message_t message)
btusb_stop_traffic(data);
usb_kill_anchored_urbs(&data->tx_anchor);
+ if (data->oob_wake_irq && device_may_wakeup(&data->udev->dev)) {
+ clear_bit(BTUSB_OOB_WAKE_DISABLED, &data->flags);
+ enable_irq_wake(data->oob_wake_irq);
+ enable_irq(data->oob_wake_irq);
+ }
+
/* Optionally request a device reset on resume, but only when
* wakeups are disabled. If wakeups are enabled we assume the
* device will stay powered up throughout suspend.
@@ -3126,6 +3205,12 @@ static int btusb_resume(struct usb_interface *intf)
if (--data->suspend_count)
return 0;
+ /* Disable only if not already disabled (keep it balanced) */
+ if (!test_and_set_bit(BTUSB_OOB_WAKE_DISABLED, &data->flags)) {
+ disable_irq(data->oob_wake_irq);
+ disable_irq_wake(data->oob_wake_irq);
+ }
+
if (!test_bit(HCI_RUNNING, &hdev->flags))
goto done;
--
2.11.0.390.gc69c2f50cf-goog
^ permalink raw reply related
* [PATCH v5 3/3] Bluetooth: btusb: Configure Marvell to use one of the pins for oob wakeup
From: Rajat Jain @ 2017-01-12 18:01 UTC (permalink / raw)
To: Rob Herring, Mark Rutland, Marcel Holtmann, Gustavo Padovan,
Johan Hedberg, Amitkumar Karwar, Wei-Ning Huang, Xinming Hu,
netdev, devicetree, linux-bluetooth, Brian Norris, linux-kernel
Cc: Rajat Jain, rajatxjain
In-Reply-To: <20170112180107.63244-1-rajatja@google.com>
The Marvell devices may have many gpio pins, and hence for wakeup
on these out-of-band pins, the chip needs to be told which pin is
to be used for wakeup, using an hci command.
Thus, we read the pin number etc from the device tree node and send
a command to the chip.
Signed-off-by: Rajat Jain <rajatja@google.com>
Reviewed-by: Brian Norris <briannorris@chromium.org>
Acked-by: Rob Herring <robh@kernel.org>
---
v5: same as v5
v4: same as v3
v3: * remove the Marvell specific id table and check
* Add reference to marvell-bt-8xxx.txt in btusb.txt
* Add "Reviewed-by" and "Acked-by"
v2: Fix the binding document to specify to use "wakeup" interrupt-name
Documentation/devicetree/bindings/net/btusb.txt | 3 ++
.../{marvell-bt-sd8xxx.txt => marvell-bt-8xxx.txt} | 46 +++++++++++++++----
drivers/bluetooth/btusb.c | 51 ++++++++++++++++++++++
3 files changed, 92 insertions(+), 8 deletions(-)
rename Documentation/devicetree/bindings/net/{marvell-bt-sd8xxx.txt => marvell-bt-8xxx.txt} (50%)
diff --git a/Documentation/devicetree/bindings/net/btusb.txt b/Documentation/devicetree/bindings/net/btusb.txt
index 2c0355c85972..01fa2d4188d4 100644
--- a/Documentation/devicetree/bindings/net/btusb.txt
+++ b/Documentation/devicetree/bindings/net/btusb.txt
@@ -10,6 +10,9 @@ Required properties:
"usb1286,204e" (Marvell 8997)
+Also, vendors that use btusb may have device additional properties, e.g:
+Documentation/devicetree/bindings/net/marvell-bt-8xxx.txt
+
Optional properties:
- interrupt-parent: phandle of the parent interrupt controller
diff --git a/Documentation/devicetree/bindings/net/marvell-bt-sd8xxx.txt b/Documentation/devicetree/bindings/net/marvell-bt-8xxx.txt
similarity index 50%
rename from Documentation/devicetree/bindings/net/marvell-bt-sd8xxx.txt
rename to Documentation/devicetree/bindings/net/marvell-bt-8xxx.txt
index 6a9a63cb0543..9be1059ff03f 100644
--- a/Documentation/devicetree/bindings/net/marvell-bt-sd8xxx.txt
+++ b/Documentation/devicetree/bindings/net/marvell-bt-8xxx.txt
@@ -1,16 +1,21 @@
-Marvell 8897/8997 (sd8897/sd8997) bluetooth SDIO devices
+Marvell 8897/8997 (sd8897/sd8997) bluetooth devices (SDIO or USB based)
------
+The 8997 devices supports multiple interfaces. When used on SDIO interfaces,
+the btmrvl driver is used and when used on USB interface, the btusb driver is
+used.
Required properties:
- compatible : should be one of the following:
- * "marvell,sd8897-bt"
- * "marvell,sd8997-bt"
+ * "marvell,sd8897-bt" (for SDIO)
+ * "marvell,sd8997-bt" (for SDIO)
+ * "usb1286,204e" (for USB)
Optional properties:
- marvell,cal-data: Calibration data downloaded to the device during
initialization. This is an array of 28 values(u8).
+ This is only applicable to SDIO devices.
- marvell,wakeup-pin: It represents wakeup pin number of the bluetooth chip.
firmware will use the pin to wakeup host system (u16).
@@ -18,10 +23,15 @@ Optional properties:
platform. The value will be configured to firmware. This
is needed to work chip's sleep feature as expected (u16).
- interrupt-parent: phandle of the parent interrupt controller
- - interrupts : interrupt pin number to the cpu. Driver will request an irq based
- on this interrupt number. During system suspend, the irq will be
- enabled so that the bluetooth chip can wakeup host platform under
- certain condition. During system resume, the irq will be disabled
+ - interrupt-names: Used only for USB based devices (See below)
+ - interrupts : specifies the interrupt pin number to the cpu. For SDIO, the
+ driver will use the first interrupt specified in the interrupt
+ array. For USB based devices, the driver will use the interrupt
+ named "wakeup" from the interrupt-names and interrupt arrays.
+ The driver will request an irq based on this interrupt number.
+ During system suspend, the irq will be enabled so that the
+ bluetooth chip can wakeup host platform under certain
+ conditions. During system resume, the irq will be disabled
to make sure unnecessary interrupt is not received.
Example:
@@ -29,7 +39,9 @@ Example:
IRQ pin 119 is used as system wakeup source interrupt.
wakeup pin 13 and gap 100ms are configured so that firmware can wakeup host
using this device side pin and wakeup latency.
-calibration data is also available in below example.
+
+Example for SDIO device follows (calibration data is also available in
+below example).
&mmc3 {
status = "okay";
@@ -54,3 +66,21 @@ calibration data is also available in below example.
marvell,wakeup-gap-ms = /bits/ 16 <0x64>;
};
};
+
+Example for USB device:
+
+&usb_host1_ohci {
+ status = "okay";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ mvl_bt1: bt@1 {
+ compatible = "usb1286,204e";
+ reg = <1>;
+ interrupt-parent = <&gpio0>;
+ interrupt-names = "wakeup";
+ interrupts = <119 IRQ_TYPE_LEVEL_LOW>;
+ marvell,wakeup-pin = /bits/ 16 <0x0d>;
+ marvell,wakeup-gap-ms = /bits/ 16 <0x64>;
+ };
+};
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index 0a777bb407b1..a1079c19b96f 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -2343,6 +2343,50 @@ static int btusb_shutdown_intel(struct hci_dev *hdev)
return 0;
}
+#ifdef CONFIG_PM
+/* Configure an out-of-band gpio as wake-up pin, if specified in device tree */
+static int marvell_config_oob_wake(struct hci_dev *hdev)
+{
+ struct sk_buff *skb;
+ struct btusb_data *data = hci_get_drvdata(hdev);
+ struct device *dev = &data->udev->dev;
+ u16 pin, gap, opcode;
+ int ret;
+ u8 cmd[5];
+
+ /* Move on if no wakeup pin specified */
+ if (of_property_read_u16(dev->of_node, "marvell,wakeup-pin", &pin) ||
+ of_property_read_u16(dev->of_node, "marvell,wakeup-gap-ms", &gap))
+ return 0;
+
+ /* Vendor specific command to configure a GPIO as wake-up pin */
+ opcode = hci_opcode_pack(0x3F, 0x59);
+ cmd[0] = opcode & 0xFF;
+ cmd[1] = opcode >> 8;
+ cmd[2] = 2; /* length of parameters that follow */
+ cmd[3] = pin;
+ cmd[4] = gap; /* time in ms, for which wakeup pin should be asserted */
+
+ skb = bt_skb_alloc(sizeof(cmd), GFP_KERNEL);
+ if (!skb) {
+ bt_dev_err(hdev, "%s: No memory\n", __func__);
+ return -ENOMEM;
+ }
+
+ memcpy(skb_put(skb, sizeof(cmd)), cmd, sizeof(cmd));
+ hci_skb_pkt_type(skb) = HCI_COMMAND_PKT;
+
+ ret = btusb_send_frame(hdev, skb);
+ if (ret) {
+ bt_dev_err(hdev, "%s: configuration failed\n", __func__);
+ kfree_skb(skb);
+ return ret;
+ }
+
+ return 0;
+}
+#endif
+
static int btusb_set_bdaddr_marvell(struct hci_dev *hdev,
const bdaddr_t *bdaddr)
{
@@ -2918,6 +2962,13 @@ static int btusb_probe(struct usb_interface *intf,
err = btusb_config_oob_wake(hdev);
if (err)
goto out_free_dev;
+
+ /* Marvell devices may need a specific chip configuration */
+ if (id->driver_info & BTUSB_MARVELL && data->oob_wake_irq) {
+ err = marvell_config_oob_wake(hdev);
+ if (err)
+ goto out_free_dev;
+ }
#endif
if (id->driver_info & BTUSB_CW6622)
set_bit(HCI_QUIRK_BROKEN_STORED_LINK_KEY, &hdev->quirks);
--
2.11.0.390.gc69c2f50cf-goog
^ permalink raw reply related
* Re: [PATCH v2 2/2] Support for DW CSI-2 Host IPK
From: Hans Verkuil @ 2017-01-12 18:06 UTC (permalink / raw)
To: Ramiro Oliveira, robh+dt, mark.rutland, mchehab, devicetree,
linux-kernel, linux-media
Cc: davem, gregkh, geert+renesas, akpm, linux,
laurent.pinchart+renesas, arnd, sudipm.mukherjee, tiffany.lin,
minghsiu.tsai, jean-christophe.trotin, andrew-ct.chen,
simon.horman, songjun.wu, bparrot, CARLOS.PALMINHA, Sakari Ailus
In-Reply-To: <8823670a-8456-87d0-3265-cb427e3445eb@synopsys.com>
On 01/12/2017 06:43 PM, Ramiro Oliveira wrote:
> Hi Hans,
>
> Thank you for your feedback.
>
> On 1/11/2017 11:54 AM, Hans Verkuil wrote:
>> Hi Ramiro,
>>
>> See my review comments below:
>>
>> On 12/12/16 16:00, Ramiro Oliveira wrote:
>>> Add support for the DesignWare CSI-2 Host IP Prototyping Kit
>>>
>>> Signed-off-by: Ramiro Oliveira <roliveir@synopsys.com>
>
> [snip]
>>> +
>>> +static int vid_dev_subdev_s_power(struct v4l2_subdev *sd, int on)
>>> +{
>>> + return 0;
>>> +}
>>
>> Just drop this empty function, shouldn't be needed.
>>
>
> When I start my system I'm hoping all the subdevs have s_power registered. If it
> doesn't exist should I change the way I handle it, or will the core handle it
> for me?
If it isn't provided, then it is just skipped. The general rule is that
you only provide these ops if they do something useful.
>
>>> +
>>> +static int vid_dev_subdev_registered(struct v4l2_subdev *sd)
>>> +{
>>> + struct video_device_dev *vid_dev = v4l2_get_subdevdata(sd);
>>> + struct vb2_queue *q = &vid_dev->vb_queue;
>>> + struct video_device *vfd = &vid_dev->ve.vdev;
>>> + int ret;
>>> +
>>> + memset(vfd, 0, sizeof(*vfd));
>>> +
>>> + strlcpy(vfd->name, VIDEO_DEVICE_NAME, sizeof(vfd->name));
>>> +
>>> + vfd->fops = &vid_dev_fops;
>>> + vfd->ioctl_ops = &vid_dev_ioctl_ops;
>>> + vfd->v4l2_dev = sd->v4l2_dev;
>>> + vfd->minor = -1;
>>> + vfd->release = video_device_release_empty;
>>> + vfd->queue = q;
>>> +
>>> + INIT_LIST_HEAD(&vid_dev->vidq.active);
>>> + init_waitqueue_head(&vid_dev->vidq.wq);
>>> + memset(q, 0, sizeof(*q));
>>> + q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
>>> + q->io_modes = VB2_MMAP | VB2_USERPTR;
>>
>> Add VB2_DMABUF and VB2_READ.
>>
>
> I'll add them, but I'm not using them, is it standard procedure to add them all
> even if they aren't used?
You may not use them, but others might. And it doesn't cost anything to add them.
>
>>> + q->ops = &vb2_video_qops;
>>> + q->mem_ops = &vb2_vmalloc_memops;
>>
>> Why is vmalloc used? Can't you use dma_contig or dma_sg and avoid having to copy
>> the image data? That's a really bad design given the amount of video data that
>> you have to copy.
>>
>
> When I started development, the arch I was using (ARC) didn't support
> dma_contig, so I was forced to use vmalloc.
>
> Since then things have changed and I'm already using dma_contig, however it
> wasn't included in this patch. I'll add it to the next patch.
Ah, good. If you are switching to dma_contig, then remove VB2_USERPTR.
VB2_DMABUF should be used instead.
Regards,
Hans
^ permalink raw reply
* [PATCH] ARM: dts: r7s72100: fix sdhi clock define
From: Chris Brandt @ 2017-01-12 18:11 UTC (permalink / raw)
To: Geert Uytterhoeven, Simon Horman, Magnus Damm, Rob Herring,
Mark Rutland
Cc: devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-renesas-soc-u79uwXL29TY76Z2rM5mHXA, Chris Brandt
Now that all the clocks in the boot loader are disabled before booting
the kernel, and the mstp driver has been fixed for RZ/A1, here is a typo
that was missed during original testing.
Fixes: 7c8522b7047c ("ARM: dts: r7s72100: add sdhi clock to device tree")
Signed-off-by: Chris Brandt <chris.brandt-zM6kxYcvzFBBDgjK7y7TUQ@public.gmane.org>
---
include/dt-bindings/clock/r7s72100-clock.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/include/dt-bindings/clock/r7s72100-clock.h b/include/dt-bindings/clock/r7s72100-clock.h
index 29e01ed..318ab14 100644
--- a/include/dt-bindings/clock/r7s72100-clock.h
+++ b/include/dt-bindings/clock/r7s72100-clock.h
@@ -46,6 +46,6 @@
/* MSTP12 */
#define R7S72100_CLK_SDHI0 3
-#define R7S72100_CLK_SDHI1 2
+#define R7S72100_CLK_SDHI1 1
#endif /* __DT_BINDINGS_CLOCK_R7S72100_H__ */
--
2.10.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 v2 1/2] of: base: add support to find the level of the last cache
From: Sudeep Holla @ 2017-01-12 18:29 UTC (permalink / raw)
To: linux-arm-kernel
Cc: Sudeep Holla, Rob Herring, Catalin Marinas, Will Deacon,
devicetree, linux-kernel, Tan Xiaojun, Mark Rutland
It is useful to have helper function just to get the number of cache
levels for a given logical cpu. We can obtain the same by just checking
the level at which the last cache is present. This patch adds support
to find the level of the last cache for a given cpu.
It will be used on ARM64 platform where the device tree provides the
information for the additional non-architected/transparent/external
last level caches that are not integrated with the processors.
Suggested-by: Rob Herring <robh+dt@kernel.org>
Cc: Rob Herring <robh+dt@kernel.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
---
drivers/of/base.c | 27 +++++++++++++++++++++++++++
include/linux/of.h | 1 +
2 files changed, 28 insertions(+)
v1->v2:
- Moved to using "cache-level" in the last level cache instead
of counting through all the nodes as suggested by Rob
diff --git a/drivers/of/base.c b/drivers/of/base.c
index d4bea3c797d6..c1128a077aea 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -25,6 +25,7 @@
#include <linux/cpu.h>
#include <linux/module.h>
#include <linux/of.h>
+#include <linux/of_device.h>
#include <linux/of_graph.h>
#include <linux/spinlock.h>
#include <linux/slab.h>
@@ -2268,6 +2269,32 @@ struct device_node *of_find_next_cache_node(const struct device_node *np)
}
/**
+ * of_find_last_cache_level - Find the level at which the last cache is
+ * present for the given logical cpu
+ *
+ * @cpu: cpu number(logical index) for which the last cache level is needed
+ *
+ * Returns the the level at which the last cache is present. It is exactly
+ * same as the total number of cache levels for the given logical cpu.
+ */
+int of_find_last_cache_level(unsigned int cpu)
+{
+ int cache_level = 0;
+ struct device_node *prev = NULL, *np = of_cpu_device_node_get(cpu);
+
+ while (np) {
+ prev = np;
+ of_node_put(np);
+ np = of_find_next_cache_node(np);
+ }
+
+ if (prev)
+ of_property_read_u32(prev, "cache-level", &cache_level);
+
+ return cache_level;
+}
+
+/**
* of_graph_parse_endpoint() - parse common endpoint node properties
* @node: pointer to endpoint device_node
* @endpoint: pointer to the OF endpoint data structure
diff --git a/include/linux/of.h b/include/linux/of.h
index d72f01009297..21e6323de0f3 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -280,6 +280,7 @@ extern struct device_node *of_get_child_by_name(const struct device_node *node,
/* cache lookup */
extern struct device_node *of_find_next_cache_node(const struct device_node *);
+extern int of_find_last_cache_level(unsigned int cpu);
extern struct device_node *of_find_node_with_property(
struct device_node *from, const char *prop_name);
--
2.7.4
^ permalink raw reply related
* [PATCH v2 2/2] arm64: cacheinfo: add support to override cache levels via device tree
From: Sudeep Holla @ 2017-01-12 18:29 UTC (permalink / raw)
To: linux-arm-kernel
Cc: Sudeep Holla, Rob Herring, Catalin Marinas, Will Deacon,
devicetree, linux-kernel, Tan Xiaojun, Mark Rutland
In-Reply-To: <1484245772-31511-1-git-send-email-sudeep.holla@arm.com>
The cache hierarchy can be identified through Cache Level ID(CLIDR)
architected system register. However in some cases it will provide
only the number of cache levels that are integrated into the processor
itself. In other words, it can't provide any information about the
caches that are external and/or transparent.
Some platforms require to export the information about all such external
caches to the userspace applications via the sysfs interface.
This patch adds support to override the cache levels using device tree
to take such external non-architected caches into account.
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
---
arch/arm64/kernel/cacheinfo.c | 13 ++++++++++++-
1 file changed, 12 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/kernel/cacheinfo.c b/arch/arm64/kernel/cacheinfo.c
index 9617301f76b5..3f2250fc391b 100644
--- a/arch/arm64/kernel/cacheinfo.c
+++ b/arch/arm64/kernel/cacheinfo.c
@@ -84,7 +84,7 @@ static void ci_leaf_init(struct cacheinfo *this_leaf,
static int __init_cache_level(unsigned int cpu)
{
- unsigned int ctype, level, leaves;
+ unsigned int ctype, level, leaves, of_level;
struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu);
for (level = 1, leaves = 0; level <= MAX_CACHE_LEVEL; level++) {
@@ -97,6 +97,17 @@ static int __init_cache_level(unsigned int cpu)
leaves += (ctype == CACHE_TYPE_SEPARATE) ? 2 : 1;
}
+ of_level = of_find_last_cache_level(cpu);
+ if (level < of_level) {
+ /*
+ * some external caches not specified in CLIDR_EL1
+ * the information may be available in the device tree
+ * only unified external caches are considered here
+ */
+ leaves += (of_level - level);
+ level = of_level;
+ }
+
this_cpu_ci->num_levels = level;
this_cpu_ci->num_leaves = leaves;
return 0;
--
2.7.4
^ permalink raw reply related
* Re: [PATCH v2] i2c: do not enable fall back to Host Notify by default
From: Wolfram Sang @ 2017-01-12 18:41 UTC (permalink / raw)
To: Dmitry Torokhov
Cc: Rob Herring, Benjamin Tissoires, Pali Rohár,
Michał Kępień, Jean Delvare, Takashi Iwai,
linux-i2c, devicetree, linux-kernel
In-Reply-To: <20170105045722.GA17958@dtor-ws>
On Wed, Jan 04, 2017 at 08:57:22PM -0800, Dmitry Torokhov wrote:
> Falling back unconditionally to HostNotify as primary client's interrupt
> breaks some drivers which alter their functionality depending on whether
> interrupt is present or not, so let's introduce a board flag telling I2C
> core explicitly if we want wired interrupt or HostNotify-based one:
> I2C_CLIENT_HOST_NOTIFY.
>
> For DT-based systems we introduce "host-notify" property that we convert
> to I2C_CLIENT_HOST_NOTIFY board flag.
>
> Tested-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
> Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Applied to for-current, thanks!
How do we handle driver fixes? Shall I take them via I2C to have the
dependency clear? Or can they go seperately?
^ permalink raw reply
* [PATCH 0/2] clocksource: Add renesas-ostm timer driver
From: Chris Brandt @ 2017-01-12 18:59 UTC (permalink / raw)
To: Rob Herring, Mark Rutland, Simon Horman, Magnus Damm,
Russell King, Daniel Lezcano, Thomas Gleixner, Geert Uytterhoeven
Cc: devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-renesas-soc-u79uwXL29TY76Z2rM5mHXA, Chris Brandt
This patch set adds a new clocksource driver that uses the OS Timer
(OSTM) that exists in the R7S72100 (RZ/A1) SoC.
The operation of the driver was tested with a simple user application
that does multiple calls to nanosleep() and gettimeofday().
The purpose of adding this driver is to get better time keeping
accuracy over the default MTU2 clocksource timer.
Chris Brandt (2):
dt-bindings: document renesas-ostm timer
clocksource: Add renesas-ostm timer driver
.../devicetree/bindings/timer/renesas,ostm.txt | 36 ++
arch/arm/mach-shmobile/Kconfig | 1 +
drivers/clocksource/Kconfig | 12 +
drivers/clocksource/Makefile | 1 +
drivers/clocksource/renesas-ostm.c | 389 +++++++++++++++++++++
5 files changed, 439 insertions(+)
create mode 100644 Documentation/devicetree/bindings/timer/renesas,ostm.txt
create mode 100644 drivers/clocksource/renesas-ostm.c
--
2.10.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/2] dt-bindings: document renesas-ostm timer
From: Chris Brandt @ 2017-01-12 18:59 UTC (permalink / raw)
To: Rob Herring, Mark Rutland, Simon Horman, Magnus Damm,
Russell King, Daniel Lezcano, Thomas Gleixner, Geert Uytterhoeven
Cc: devicetree, linux-renesas-soc, Chris Brandt
In-Reply-To: <20170112185952.2780-1-chris.brandt@renesas.com>
Signed-off-by: Chris Brandt <chris.brandt@renesas.com>
---
.../devicetree/bindings/timer/renesas,ostm.txt | 36 ++++++++++++++++++++++
1 file changed, 36 insertions(+)
create mode 100644 Documentation/devicetree/bindings/timer/renesas,ostm.txt
diff --git a/Documentation/devicetree/bindings/timer/renesas,ostm.txt b/Documentation/devicetree/bindings/timer/renesas,ostm.txt
new file mode 100644
index 0000000..46e1f27
--- /dev/null
+++ b/Documentation/devicetree/bindings/timer/renesas,ostm.txt
@@ -0,0 +1,36 @@
+* Renesas OS Timer (OSTM)
+
+The OSTM comes with 2 independent channels.
+We will use the first channel (OSTM0) as a free running clocksource and the
+second channel (OSTM1) as a interrupt driven clock event.
+
+Additionally we will use the clocksource channel (OTSM0) for the system
+schedule timer sched_clock().
+
+Required Properties:
+
+ - compatible: must be one or more of the following:
+ - "renesas,ostm-r7s72100" for the r7s72100 OSTM
+ - "renesas,ostm" for any OSTM
+ This is a fallback for the above renesas,ostm-* entries
+
+ - reg: base address and length of the registers block for each timer channel.
+ There should be 2 sets of addresses, one for each channel.
+
+ - interrupts: interrupt specifiers for the timers. There should be 2
+ interupts, one for each channel.
+
+ - clocks: a list of phandle + clock-specifier pairs, one for each entry
+ channel. There should be 2 sets, one for each channel.
+
+Example: R7S72100 (RZ/A1H) OSTM node
+
+ ostm: ostm@fcfec000 {
+ compatible = "renesas,ostm-r7s72100", "renesas,ostm";
+ reg = <0xfcfec000 0x30>,
+ <0xfcfec400 0x30>;
+ interrupts = <GIC_SPI 102 IRQ_TYPE_EDGE_RISING
+ GIC_SPI 103 IRQ_TYPE_EDGE_RISING>;
+
+ clocks = <&mstp5_clks R7S72100_CLK_OSTM0>, <&mstp5_clks R7S72100_CLK_OSTM1>;
+ };
--
2.10.1
^ permalink raw reply related
* [PATCH 2/2] clocksource: Add renesas-ostm timer driver
From: Chris Brandt @ 2017-01-12 18:59 UTC (permalink / raw)
To: Rob Herring, Mark Rutland, Simon Horman, Magnus Damm,
Russell King, Daniel Lezcano, Thomas Gleixner, Geert Uytterhoeven
Cc: devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-renesas-soc-u79uwXL29TY76Z2rM5mHXA, Chris Brandt
In-Reply-To: <20170112185952.2780-1-chris.brandt-zM6kxYcvzFBBDgjK7y7TUQ@public.gmane.org>
This patch adds a OSTM driver for the Renesas architecture.
Signed-off-by: Chris Brandt <chris.brandt-zM6kxYcvzFBBDgjK7y7TUQ@public.gmane.org>
---
arch/arm/mach-shmobile/Kconfig | 1 +
drivers/clocksource/Kconfig | 12 ++
drivers/clocksource/Makefile | 1 +
drivers/clocksource/renesas-ostm.c | 389 +++++++++++++++++++++++++++++++++++++
4 files changed, 403 insertions(+)
create mode 100644 drivers/clocksource/renesas-ostm.c
diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig
index 2bb4b09..b928634 100644
--- a/arch/arm/mach-shmobile/Kconfig
+++ b/arch/arm/mach-shmobile/Kconfig
@@ -57,6 +57,7 @@ config ARCH_R7S72100
select PM
select PM_GENERIC_DOMAINS
select SYS_SUPPORTS_SH_MTU2
+ select SYS_SUPPORTS_RENESAS_OSTM
config ARCH_R8A73A4
bool "R-Mobile APE6 (R8A73A40)"
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index 4866f7a..95c8d56 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -431,6 +431,9 @@ config MTK_TIMER
config SYS_SUPPORTS_SH_MTU2
bool
+config SYS_SUPPORTS_RENESAS_OSTM
+ bool
+
config SYS_SUPPORTS_SH_TMU
bool
@@ -467,6 +470,15 @@ config SH_TIMER_MTU2
Timer Pulse Unit 2 (MTU2) hardware available on SoCs from Renesas.
This hardware comes with 16 bit-timer registers.
+config RENESAS_OSTM
+ bool "Renesas OSTM timer driver" if COMPILE_TEST
+ depends on GENERIC_CLOCKEVENTS
+ select CLKSRC_MMIO
+ default SYS_SUPPORTS_RENESAS_OSTM
+ help
+ This enables the build of the OSTM timer driver.
+ It creates a clock source and clock event device.
+
config SH_TIMER_TMU
bool "Renesas TMU timer driver" if COMPILE_TEST
depends on GENERIC_CLOCKEVENTS
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index a14111e..bbd163b 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_CS5535_CLOCK_EVENT_SRC) += cs5535-clockevt.o
obj-$(CONFIG_CLKSRC_JCORE_PIT) += jcore-pit.o
obj-$(CONFIG_SH_TIMER_CMT) += sh_cmt.o
obj-$(CONFIG_SH_TIMER_MTU2) += sh_mtu2.o
+obj-$(CONFIG_RENESAS_OSTM) += renesas-ostm.o
obj-$(CONFIG_SH_TIMER_TMU) += sh_tmu.o
obj-$(CONFIG_EM_TIMER_STI) += em_sti.o
obj-$(CONFIG_CLKBLD_I8253) += i8253.o
diff --git a/drivers/clocksource/renesas-ostm.c b/drivers/clocksource/renesas-ostm.c
new file mode 100644
index 0000000..3b417b9
--- /dev/null
+++ b/drivers/clocksource/renesas-ostm.c
@@ -0,0 +1,389 @@
+/*
+ * Renesas Timer Support - OSTM
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/clockchips.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/pm_runtime.h>
+#include <linux/sched_clock.h>
+
+/*
+ * The OSTM comes with 2 independent channels.
+ * We will use the first channel (OSTM0) as a free running clocksource and the
+ * second channel (OSTM1) as a interrupt driven clock event.
+ *
+ * Additionally we will use the clocksource channel (OTSM0) for the system
+ * schedule timer sched_clock().
+ */
+
+struct ostm_channel {
+ int irq;
+ struct clk *clk;
+ unsigned long rate;
+ void __iomem *base;
+ unsigned long ticks_per_jiffy;
+ struct clock_event_device ced;
+ struct clocksource cs;
+};
+
+struct ostm_device {
+ struct platform_device *pdev;
+ struct ostm_channel clksrc; /* clock source ostm0 */
+ struct ostm_channel clkevt; /* clock event ostm1 */
+};
+
+static void __iomem *system_clock; /* For sched_clock() */
+
+/* OSTM REGISTERS */
+#define OSTM_CMP 0x000 /* RW,32 */
+#define OSTM_CNT 0x004 /* R,32 */
+#define OSTM_TE 0x010 /* R,8 */
+#define OSTM_TS 0x014 /* W,8 */
+#define OSTM_TT 0x018 /* W,8 */
+#define OSTM_CTL 0x020 /* RW,8 */
+
+#define TE 0x01
+#define TS 0x01
+#define TT 0x01
+#define CTL_PERIODIC 0x00
+#define CTL_ONESHOT 0x02
+#define CTL_FREERUN 0x02
+
+static struct ostm_channel *ced_to_ostm_ch(struct clock_event_device *ced)
+{
+ return container_of(ced, struct ostm_channel, ced);
+}
+
+static int __init ostm_init_clksrc(struct ostm_device *ostm)
+{
+ struct ostm_channel *cs = &ostm->clksrc;
+ struct resource *res;
+ int ret = -ENXIO;
+
+ res = platform_get_resource(ostm->pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(&ostm->pdev->dev, "failed to get I/O memory\n");
+ goto err;
+ }
+ cs->base = ioremap_nocache(res->start, resource_size(res));
+ if (!cs->base) {
+ dev_err(&ostm->pdev->dev, "failed to remap I/O memory\n");
+ goto err;
+ }
+
+ /* irq not used (clock sources don't use interrupts) */
+ cs->irq = platform_get_irq(ostm->pdev, 0);
+ if (cs->irq < 0) {
+ dev_err(&ostm->pdev->dev, "failed to get irq\n");
+ goto err_iounmap;
+ }
+
+ cs->clk = of_clk_get(ostm->pdev->dev.of_node, 0);
+ if (IS_ERR(cs->clk)) {
+ dev_err(&ostm->pdev->dev, "failed to get clock\n");
+ goto err_iounmap;
+ }
+
+ ret = clk_prepare_enable(cs->clk);
+ if (ret) {
+ dev_err(&ostm->pdev->dev, "failed to enable clock\n");
+ goto err_iounmap;
+ }
+ cs->rate = clk_get_rate(cs->clk);
+
+ /* stop counter */
+ iowrite8(TT, cs->base + OSTM_TT);
+ while (ioread8(cs->base + OSTM_TE) & TE)
+ ;
+
+ /* setup as freerun */
+ iowrite32(0, cs->base + OSTM_CMP);
+ iowrite8(CTL_FREERUN, cs->base + OSTM_CTL);
+ iowrite8(TS, cs->base + OSTM_TS);
+
+ /* register */
+ clocksource_mmio_init(cs->base + OSTM_CNT,
+ "ostm", cs->rate,
+ 300, 32, clocksource_mmio_readl_up);
+
+ return 0;
+
+err_iounmap:
+ iounmap(cs->base);
+err:
+ return ret;
+}
+
+static u64 notrace ostm_read_sched_clock(void)
+{
+ return ioread32(system_clock);
+}
+
+/*
+ * Setup sched_clock using clocksource device (uses ostm.0)
+ */
+static int __init ostm_init_sched_clock(struct ostm_channel *cs)
+{
+ unsigned long flags;
+
+ system_clock = cs->base + OSTM_CNT; /* ostm0 */
+ local_irq_save(flags);
+ local_irq_disable();
+ sched_clock_register(ostm_read_sched_clock, 32, cs->rate);
+ local_irq_restore(flags);
+ return 0;
+}
+
+static void ostm_clkevt_timer_stop(struct ostm_channel *ch)
+{
+ if (ioread8(ch->base + OSTM_TE) & TE) {
+ iowrite8(TT, ch->base + OSTM_TT);
+ while (ioread8(ch->base + OSTM_TE) & TE)
+ ;
+ }
+}
+
+static int ostm_clock_event_next(unsigned long delta,
+ struct clock_event_device *ced)
+{
+ struct ostm_channel *ch = ced_to_ostm_ch(ced);
+
+ WARN_ON(!clockevent_state_oneshot(ced));
+
+ ostm_clkevt_timer_stop(ch);
+
+ iowrite32(delta, ch->base + OSTM_CMP);
+ iowrite8(CTL_ONESHOT, ch->base + OSTM_CTL);
+ iowrite8(TS, ch->base + OSTM_TS);
+
+ return 0;
+}
+
+static int ostm_shutdown(struct clock_event_device *ced)
+{
+ struct ostm_channel *ch = ced_to_ostm_ch(ced);
+
+ ostm_clkevt_timer_stop(ch);
+ return 0;
+}
+static int ostm_set_periodic(struct clock_event_device *ced)
+{
+ struct ostm_channel *ch = ced_to_ostm_ch(ced);
+
+ if (clockevent_state_oneshot(ced) || clockevent_state_periodic(ced))
+ ostm_clkevt_timer_stop(ch);
+
+ iowrite32(ch->ticks_per_jiffy - 1, ch->base + OSTM_CMP);
+ iowrite8(CTL_PERIODIC, ch->base + OSTM_CTL);
+ iowrite8(TS, ch->base + OSTM_TS);
+
+ return 0;
+}
+
+static int ostm_set_oneshot(struct clock_event_device *ced)
+{
+ struct ostm_channel *ch = ced_to_ostm_ch(ced);
+
+ ostm_clkevt_timer_stop(ch);
+
+ return 0;
+}
+
+static irqreturn_t ostm_timer_interrupt(int irq, void *dev_id)
+{
+ struct ostm_channel *ch = dev_id;
+
+ if (clockevent_state_oneshot(&ch->ced))
+ ostm_clkevt_timer_stop(ch);
+
+ /* notify clockevent layer */
+ if (ch->ced.event_handler)
+ ch->ced.event_handler(&ch->ced);
+
+ return IRQ_HANDLED;
+}
+
+static int __init ostm_init_clkevt(struct ostm_device *ostm)
+{
+ struct ostm_channel *ce = &ostm->clkevt;
+ struct resource *res;
+ struct clock_event_device *ced;
+ int ret = -ENXIO;
+
+ res = platform_get_resource(ostm->pdev, IORESOURCE_MEM, 1);
+ if (!res) {
+ dev_err(&ostm->pdev->dev, "failed to get I/O memory\n");
+ goto err;
+ }
+
+ ce->base = ioremap_nocache(res->start, resource_size(res));
+ if (!ce->base) {
+ dev_err(&ostm->pdev->dev, "failed to remap I/O memory\n");
+ goto err;
+ }
+
+ ce->irq = platform_get_irq(ostm->pdev, 1);
+ if (ce->irq < 0) {
+ dev_err(&ostm->pdev->dev, "failed to get irq\n");
+ goto err_iounmap;
+ }
+
+ ce->clk = of_clk_get(ostm->pdev->dev.of_node, 1);
+ if (IS_ERR(ce->clk)) {
+ PTR_ERR(ce->clk);
+ dev_err(&ostm->pdev->dev, "failed to get clock\n");
+ goto err_iounmap;
+ }
+ ret = clk_prepare_enable(ce->clk);
+ if (ret) {
+ dev_err(&ostm->pdev->dev, "failed to enable clock\n");
+ goto err_iounmap;
+ }
+ ce->rate = clk_get_rate(ce->clk);
+
+ ce->ticks_per_jiffy = (ce->rate + HZ / 2) / HZ;
+
+ ret = request_irq(ce->irq, ostm_timer_interrupt,
+ IRQF_TIMER | IRQF_IRQPOLL | IRQF_NOBALANCING,
+ "ostm.1", ce);
+
+
+ if (ret) {
+ dev_err(&ostm->pdev->dev, "failed to request irq\n");
+ goto err_iounmap;
+ }
+
+ ced = &ce->ced;
+ ced->name = "ostm";
+ ced->features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC;
+ ced->set_state_shutdown = ostm_shutdown;
+ ced->set_state_periodic = ostm_set_periodic;
+ ced->set_state_oneshot = ostm_set_oneshot;
+ ced->set_next_event = ostm_clock_event_next;
+ ced->shift = 32;
+ ced->rating = 300;
+ ced->cpumask = cpumask_of(0);
+ clockevents_config_and_register(ced, ce->rate, 0xf, 0xffffffff);
+
+ ret = 0;
+ return ret;
+
+err_iounmap:
+ iounmap(ce->base);
+err:
+ return ret;
+}
+
+static int __init ostm_timer_init(struct ostm_device *ostm)
+{
+ int ret = 0;
+
+ /* ostm0 will be clock source */
+ ret = ostm_init_clksrc(ostm);
+ if (ret)
+ goto err;
+
+ /* use ostm0 as system scheduling clock */
+ ret = ostm_init_sched_clock(&ostm->clksrc);
+ if (ret)
+ goto err;
+
+ /* ostm1 will be clock event */
+ ret = ostm_init_clkevt(ostm);
+err:
+ return ret;
+}
+
+static int __init ostm_probe(struct platform_device *pdev)
+{
+ struct ostm_device *ostm;
+ int ret = 0;
+
+ if (!is_early_platform_device(pdev)) {
+ pm_runtime_set_active(&pdev->dev);
+ pm_runtime_enable(&pdev->dev);
+ }
+
+ ostm = platform_get_drvdata(pdev);
+ if (ostm) {
+ dev_info(&pdev->dev, "kept as earlytimer\n");
+ goto out;
+ }
+
+ ostm = kzalloc(sizeof(*ostm), GFP_KERNEL);
+ if (!ostm) {
+ dev_info(&pdev->dev, "failed to allocate memory\n");
+ return -ENOMEM;
+ }
+
+ ostm->pdev = pdev;
+ platform_set_drvdata(ostm->pdev, ostm);
+
+ ret = ostm_timer_init(ostm);
+ if (ret) {
+ kfree(ostm);
+ platform_set_drvdata(pdev, NULL);
+ pm_runtime_idle(&pdev->dev);
+ return ret;
+ }
+
+ if (is_early_platform_device(pdev))
+ return ret;
+
+out:
+ pm_runtime_irq_safe(&pdev->dev);
+
+ return ret;
+}
+
+static int ostm_remove(struct platform_device *pdev)
+{
+ return -EBUSY; /* cannot unregister clockevent */
+}
+
+static const struct of_device_id ostm_of_table[] __maybe_unused = {
+ { .compatible = "renesas,ostm" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, ostm_of_table);
+
+static struct platform_driver ostm_timer = {
+ .probe = ostm_probe,
+ .remove = ostm_remove,
+ .driver = {
+ .name = "ostm",
+ .of_match_table = of_match_ptr(ostm_of_table),
+ },
+};
+
+static int __init ostm_init(void)
+{
+ return platform_driver_register(&ostm_timer);
+}
+
+static void __exit ostm_exit(void)
+{
+ platform_driver_unregister(&ostm_timer);
+}
+
+early_platform_init("earlytimer", &ostm_timer);
+subsys_initcall(ostm_init);
+module_exit(ostm_exit);
+
+MODULE_AUTHOR("Chris Brandt");
+MODULE_DESCRIPTION("Renesas OSTM Timer Driver");
+MODULE_LICENSE("GPL v2");
--
2.10.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 0/3] ARM: dts: add ostm support for r7s72100
From: Chris Brandt @ 2017-01-12 19:01 UTC (permalink / raw)
To: Simon Horman, Magnus Damm, Rob Herring, Mark Rutland,
Russell King, Thomas Gleixner, Geert Uytterhoeven
Cc: devicetree, linux-renesas-soc, Chris Brandt
This patch set enables the use of the newly created driver
renesas-ostm.c for the r7s72100 SoC.
This patch set depends on the acceptance of:
[PATCH 1/2] dt-bindings: document renesas-ostm timer
[PATCH 2/2] clocksource: Add renesas-ostm timer driver
Chris Brandt (3):
ARM: dts: r7s72100: add ostm clock to device tree
ARM: dts: r7s72100: add ostm to device tree
ARM: dts: rskrza1: add ostm DT support
arch/arm/boot/dts/r7s72100-rskrza1.dts | 4 ++++
arch/arm/boot/dts/r7s72100.dtsi | 21 +++++++++++++++++++++
include/dt-bindings/clock/r7s72100-clock.h | 4 ++++
3 files changed, 29 insertions(+)
--
2.10.1
^ permalink raw reply
* [PATCH 1/3] ARM: dts: r7s72100: add ostm clock to device tree
From: Chris Brandt @ 2017-01-12 19:01 UTC (permalink / raw)
To: Simon Horman, Magnus Damm, Rob Herring, Mark Rutland,
Russell King, Thomas Gleixner, Geert Uytterhoeven
Cc: devicetree, linux-renesas-soc, Chris Brandt
In-Reply-To: <20170112190108.2856-1-chris.brandt@renesas.com>
Signed-off-by: Chris Brandt <chris.brandt@renesas.com>
---
arch/arm/boot/dts/r7s72100.dtsi | 9 +++++++++
include/dt-bindings/clock/r7s72100-clock.h | 4 ++++
2 files changed, 13 insertions(+)
diff --git a/arch/arm/boot/dts/r7s72100.dtsi b/arch/arm/boot/dts/r7s72100.dtsi
index 3dd427d..d5946df 100644
--- a/arch/arm/boot/dts/r7s72100.dtsi
+++ b/arch/arm/boot/dts/r7s72100.dtsi
@@ -108,6 +108,15 @@
clock-output-names = "scif0", "scif1", "scif2", "scif3", "scif4", "scif5", "scif6", "scif7";
};
+ mstp5_clks: mstp5_clks@fcfe0428 {
+ #clock-cells = <1>;
+ compatible = "renesas,r7s72100-mstp-clocks", "renesas,cpg-mstp-clocks";
+ reg = <0xfcfe0428 4>;
+ clocks = <&p0_clk>, <&p0_clk>;
+ clock-indices = <R7S72100_CLK_OSTM0 R7S72100_CLK_OSTM1>;
+ clock-output-names = "ostm0", "ostm1";
+ };
+
mstp7_clks: mstp7_clks@fcfe0430 {
#clock-cells = <1>;
compatible = "renesas,r7s72100-mstp-clocks", "renesas,cpg-mstp-clocks";
diff --git a/include/dt-bindings/clock/r7s72100-clock.h b/include/dt-bindings/clock/r7s72100-clock.h
index 29e01ed..ce09915 100644
--- a/include/dt-bindings/clock/r7s72100-clock.h
+++ b/include/dt-bindings/clock/r7s72100-clock.h
@@ -25,6 +25,10 @@
#define R7S72100_CLK_SCIF6 1
#define R7S72100_CLK_SCIF7 0
+/* MSTP5 */
+#define R7S72100_CLK_OSTM0 1
+#define R7S72100_CLK_OSTM1 0
+
/* MSTP7 */
#define R7S72100_CLK_ETHER 4
--
2.10.1
^ permalink raw reply related
* [PATCH 2/3] ARM: dts: r7s72100: add ostm to device tree
From: Chris Brandt @ 2017-01-12 19:01 UTC (permalink / raw)
To: Simon Horman, Magnus Damm, Rob Herring, Mark Rutland,
Russell King, Thomas Gleixner, Geert Uytterhoeven
Cc: devicetree, linux-renesas-soc, Chris Brandt
In-Reply-To: <20170112190108.2856-1-chris.brandt@renesas.com>
Signed-off-by: Chris Brandt <chris.brandt@renesas.com>
---
arch/arm/boot/dts/r7s72100.dtsi | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/arch/arm/boot/dts/r7s72100.dtsi b/arch/arm/boot/dts/r7s72100.dtsi
index d5946df..247bbe0 100644
--- a/arch/arm/boot/dts/r7s72100.dtsi
+++ b/arch/arm/boot/dts/r7s72100.dtsi
@@ -505,4 +505,15 @@
cap-sdio-irq;
status = "disabled";
};
+
+ ostm: ostm@fcfec000 {
+ compatible = "renesas,ostm-r7s72100", "renesas,ostm";
+ reg = <0xfcfec000 0x30>,
+ <0xfcfec400 0x30>;
+ interrupts = <GIC_SPI 102 IRQ_TYPE_EDGE_RISING
+ GIC_SPI 103 IRQ_TYPE_EDGE_RISING>;
+
+ clocks = <&mstp5_clks R7S72100_CLK_OSTM0>, <&mstp5_clks R7S72100_CLK_OSTM1>;
+ status = "disabled";
+ };
};
--
2.10.1
^ permalink raw reply related
* [PATCH 3/3] ARM: dts: rskrza1: add ostm DT support
From: Chris Brandt @ 2017-01-12 19:01 UTC (permalink / raw)
To: Simon Horman, Magnus Damm, Rob Herring, Mark Rutland,
Russell King, Thomas Gleixner, Geert Uytterhoeven
Cc: devicetree, linux-renesas-soc, Chris Brandt
In-Reply-To: <20170112190108.2856-1-chris.brandt@renesas.com>
Signed-off-by: Chris Brandt <chris.brandt@renesas.com>
---
arch/arm/boot/dts/r7s72100-rskrza1.dts | 4 ++++
arch/arm/boot/dts/r7s72100.dtsi | 3 ++-
2 files changed, 6 insertions(+), 1 deletion(-)
diff --git a/arch/arm/boot/dts/r7s72100-rskrza1.dts b/arch/arm/boot/dts/r7s72100-rskrza1.dts
index dd44181..e7b6afa 100644
--- a/arch/arm/boot/dts/r7s72100-rskrza1.dts
+++ b/arch/arm/boot/dts/r7s72100-rskrza1.dts
@@ -61,6 +61,10 @@
status = "okay";
};
+&ostm {
+ status = "okay";
+};
+
&scif2 {
status = "okay";
};
diff --git a/arch/arm/boot/dts/r7s72100.dtsi b/arch/arm/boot/dts/r7s72100.dtsi
index 247bbe0..974c084 100644
--- a/arch/arm/boot/dts/r7s72100.dtsi
+++ b/arch/arm/boot/dts/r7s72100.dtsi
@@ -513,7 +513,8 @@
interrupts = <GIC_SPI 102 IRQ_TYPE_EDGE_RISING
GIC_SPI 103 IRQ_TYPE_EDGE_RISING>;
- clocks = <&mstp5_clks R7S72100_CLK_OSTM0>, <&mstp5_clks R7S72100_CLK_OSTM1>;
+ clocks = <&mstp5_clks R7S72100_CLK_OSTM0>,
+ <&mstp5_clks R7S72100_CLK_OSTM1>;
status = "disabled";
};
};
--
2.10.1
^ permalink raw reply related
* Re: [PATCH v3 3/5] i2c: mux: pca954x: Add interrupt controller support
From: Wolfram Sang @ 2017-01-12 19:15 UTC (permalink / raw)
To: Phil Reid
Cc: peda-koto5C5qi+TLoDKTGw+V6w, robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
mark.rutland-5wv7dgnIgG8, linux-i2c-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1483952576-5308-4-git-send-email-preid-qgqNFa1JUf/o2iN0hyhwsIdd74u8MsAO@public.gmane.org>
On Mon, Jan 09, 2017 at 05:02:54PM +0800, Phil Reid wrote:
> Various muxes can aggregate multiple interrupts from each i2c bus.
> All of the muxes with interrupt support combine the active low irq lines
> using an internal 'and' function and generate a combined active low
> output. The muxes do provide the ability to read a control register to
> determine which irq is active. By making the mux an irq controller isr
> latency can potentially be reduced by reading the status register and
> then only calling the registered isr on that bus segment.
>
> As there is no irq masking on the mux irq are disabled until irq_unmask is
> called at least once.
>
> Signed-off-by: Phil Reid <preid-qgqNFa1JUf/o2iN0hyhwsIdd74u8MsAO@public.gmane.org>
Is the ack from Peda here forgotten or still missing?
@peda: Once you are happy, do you want to take these patches via your
shiny new mux-tree or do you prefer if I pick them?
Regards,
Wolfram
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH v3 10/24] ARM: dts: imx6-sabreauto: add pinctrl for gpt input capture
From: Tim Harvey @ 2017-01-12 19:37 UTC (permalink / raw)
To: Steve Longerbeam
Cc: Rob Herring, Mark Rutland, Shawn Guo, Sascha Hauer, Fabio Estevam,
Russell King - ARM Linux, mchehab, Hans Verkuil, Nick Dyer,
markus.heiser, Philipp Zabel, laurent.pinchart+renesas, bparrot,
geert, Arnd Bergmann, Sudip Mukherjee, minghsiu.tsai, Tiffany Lin,
Jean-Christophe TROTIN, Simon Horman
In-Reply-To: <1483755102-24785-11-git-send-email-steve_longerbeam@mentor.com>
On Fri, Jan 6, 2017 at 6:11 PM, Steve Longerbeam <slongerbeam@gmail.com> wrote:
> Add pinctrl groups for both GPT input capture channels.
>
> Signed-off-by: Steve Longerbeam <steve_longerbeam@mentor.com>
> ---
> arch/arm/boot/dts/imx6qdl-sabreauto.dtsi | 12 ++++++++++++
> 1 file changed, 12 insertions(+)
>
> diff --git a/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi b/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi
> index 967c3b8..495709f 100644
> --- a/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi
> +++ b/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi
> @@ -457,6 +457,18 @@
> >;
> };
>
> + pinctrl_gpt_input_capture0: gptinputcapture0grp {
> + fsl,pins = <
> + MX6QDL_PAD_SD1_DAT0__GPT_CAPTURE1 0x1b0b0
> + >;
> + };
> +
> + pinctrl_gpt_input_capture1: gptinputcapture1grp {
> + fsl,pins = <
> + MX6QDL_PAD_SD1_DAT1__GPT_CAPTURE2 0x1b0b0
> + >;
> + };
> +
> pinctrl_spdif: spdifgrp {
> fsl,pins = <
> MX6QDL_PAD_KEY_COL3__SPDIF_IN 0x1b0b0
> --
Steve,
These are not used anywhere.
Tim
^ permalink raw reply
* Re: [PATCH] ARM: dts: r7s72100: fix sdhi clock define
From: Geert Uytterhoeven @ 2017-01-12 19:57 UTC (permalink / raw)
To: Chris Brandt
Cc: Simon Horman, Magnus Damm, Rob Herring, Mark Rutland,
devicetree@vger.kernel.org, Linux-Renesas
In-Reply-To: <20170112181149.29035-1-chris.brandt@renesas.com>
Hi Chris,
On Thu, Jan 12, 2017 at 7:11 PM, Chris Brandt <chris.brandt@renesas.com> wrote:
> Now that all the clocks in the boot loader are disabled before booting
> the kernel, and the mstp driver has been fixed for RZ/A1, here is a typo
> that was missed during original testing.
>
> Fixes: 7c8522b7047c ("ARM: dts: r7s72100: add sdhi clock to device tree")
> Signed-off-by: Chris Brandt <chris.brandt@renesas.com>
> ---
> include/dt-bindings/clock/r7s72100-clock.h | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/include/dt-bindings/clock/r7s72100-clock.h b/include/dt-bindings/clock/r7s72100-clock.h
> index 29e01ed..318ab14 100644
> --- a/include/dt-bindings/clock/r7s72100-clock.h
> +++ b/include/dt-bindings/clock/r7s72100-clock.h
> @@ -46,6 +46,6 @@
>
> /* MSTP12 */
> #define R7S72100_CLK_SDHI0 3
> -#define R7S72100_CLK_SDHI1 2
> +#define R7S72100_CLK_SDHI1 1
This is strange. There are two SDHI channels, but the STBCR12 documentation
(all versions up to rev. 3.00) says the register has MSTP bits for four SD
host interfaces?
Can you please enlighten me? Thanks!
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
^ permalink raw reply
* [PATCH v3] ARM: dts: Add LEGO MINDSTORMS EV3 dts
From: David Lechner @ 2017-01-12 20:32 UTC (permalink / raw)
To: devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
Cc: David Lechner, Sekhar Nori, Kevin Hilman, Rob Herring,
Mark Rutland, linux-kernel-u79uwXL29TY76Z2rM5mHXA
This adds a device tree definition file for LEGO MINDSTORMS EV3.
What is working:
* Pin muxing
* Pinconf
* GPIOs
* MicroSD card reader
* UART on input port 1
* Buttons
* LEDs
* Poweroff/reset
* Flash memory
* EEPROM
* USB host port
* USB peripheral port
What is not working/to be added later:
* Speaker - have patch submitted to get pwm-beeper working - maybe someday
it will have a real sound driver that uses PRU
* A/DC chip - have driver submitted and accepted - waiting for ack on
device tree bindings
* Display - waiting for "simple DRM" to be mainlined
* Bluetooth - needs new driver for sequencing power/enable/clock
* Input and output ports - need some sort of new phy or extcon driver as
well as PRU UART and PRU I2C drivers
* Battery indication - needs new power supply driver
Note on flash partitions:
These partitions are based on the official EV3 firmware from LEGO. It is
expected that most users of the mainline kernel on EV3 will be booting from
an SD card while retaining the official firmware in the flash memory.
Furthermore, the official firmware uses an ancient U-Boot (2009) that has
no device tree support. So, it makes sense to have this partition table in
the EV3 device tree file. In the unlikely case that anyone does create their
own firmware image with different partitioning, they can use a modern
U-Boot in their own firmware image that modifies the device tree with the
custom partitions.
Signed-off-by: David Lechner <david-nq/r/kbU++upp/zk7JDF2g@public.gmane.org>
---
v3 changes:
* required defconfig patches have been picked up in linux-davinci tree, so this
is the only patch left in the series
* Added aliases node for consistent naming of serial ports
* Added memory node
* Removed nodes that are not finalized yet
* Renamed button labels to match EV3 users manual
v2 changes:
* Dropped defconfig patches that have already been pick up
* Added some new defconfig patches
* Updated device tree file based on feedback and new available bindings
* Renamed file to include da850- prefix
* Changed button labels
* Fixed LED names
* Added beeper device for sound
* Added regulators for USB and A/DC
* Removed unused pinmux nodes
* Added pinconf for buttons
* Enabled pwms
* Used preferred bindings for flash partitions
* Added A/DC spi device
* Enabled USB
arch/arm/boot/dts/Makefile | 3 +-
arch/arm/boot/dts/da850-lego-ev3.dts | 313 +++++++++++++++++++++++++++++++++++
2 files changed, 315 insertions(+), 1 deletion(-)
create mode 100644 arch/arm/boot/dts/da850-lego-ev3.dts
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index 78a94b7..1a19e7a 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -130,7 +130,8 @@ dtb-$(CONFIG_ARCH_CLPS711X) += \
dtb-$(CONFIG_ARCH_DAVINCI) += \
da850-lcdk.dtb \
da850-enbw-cmc.dtb \
- da850-evm.dtb
+ da850-evm.dtb \
+ da850-lego-ev3.dtb
dtb-$(CONFIG_ARCH_DIGICOLOR) += \
cx92755_equinox.dtb
dtb-$(CONFIG_ARCH_EFM32) += \
diff --git a/arch/arm/boot/dts/da850-lego-ev3.dts b/arch/arm/boot/dts/da850-lego-ev3.dts
new file mode 100644
index 0000000..7aaf902
--- /dev/null
+++ b/arch/arm/boot/dts/da850-lego-ev3.dts
@@ -0,0 +1,313 @@
+/*
+ * Device tree for LEGO MINDSTORMS EV3
+ *
+ * Copyright (C) 2017 David Lechner <david-nq/r/kbU++upp/zk7JDF2g@public.gmane.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation, version 2.
+ */
+
+/dts-v1/;
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/linux-event-codes.h>
+#include <dt-bindings/pwm/pwm.h>
+
+#include "da850.dtsi"
+
+/ {
+ compatible = "lego,ev3", "ti,da850";
+ model = "LEGO MINDSTORMS EV3";
+
+ aliases {
+ serial1 = &serial1;
+ };
+
+ memory@c0000000 {
+ device_type = "memory";
+ reg = <0xc0000000 0x04000000>;
+ };
+
+ /*
+ * The buttons on the EV3 are mapped to keyboard keys.
+ */
+ gpio_keys {
+ compatible = "gpio-keys";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ label = "EV3 Brick Buttons";
+ pinctrl-names = "default";
+ pinctrl-0 = <&button_pins>, <&button_bias>;
+
+ center {
+ label = "Center";
+ linux,code = <KEY_ENTER>;
+ gpios = <&gpio 29 GPIO_ACTIVE_HIGH>;
+ };
+
+ left {
+ label = "Left";
+ linux,code = <KEY_LEFT>;
+ gpios = <&gpio 102 GPIO_ACTIVE_HIGH>;
+ };
+
+ back {
+ label = "Back";
+ linux,code = <KEY_BACKSPACE>;
+ gpios = <&gpio 106 GPIO_ACTIVE_HIGH>;
+ };
+
+ right {
+ label = "Right";
+ linux,code = <KEY_RIGHT>;
+ gpios = <&gpio 124 GPIO_ACTIVE_HIGH>;
+ };
+
+ down {
+ label = "Down";
+ linux,code = <KEY_DOWN>;
+ gpios = <&gpio 126 GPIO_ACTIVE_HIGH>;
+ };
+
+ up {
+ label = "Up";
+ linux,code = <KEY_UP>;
+ gpios = <&gpio 127 GPIO_ACTIVE_HIGH>;
+ };
+ };
+
+ /*
+ * The EV3 has two built-in bi-color LEDs behind the buttons.
+ */
+ leds {
+ compatible = "gpio-leds";
+ pinctrl-names = "default";
+ pinctrl-0 = <&led_pins>;
+
+ left_green {
+ label = "led0:green:brick-status";
+ /* GP6[13] */
+ gpios = <&gpio 103 GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "default-on";
+ };
+
+ right_red {
+ label = "led1:red:brick-status";
+ /* GP6[7] */
+ gpios = <&gpio 108 GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "default-on";
+ };
+
+ left_red {
+ label = "led0:red:brick-status";
+ /* GP6[12] */
+ gpios = <&gpio 109 GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "default-on";
+ };
+
+ right_green {
+ label = "led1:green:brick-status";
+ /* GP6[14] */
+ gpios = <&gpio 110 GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "default-on";
+ };
+ };
+
+ /*
+ * The EV3 is powered down by turning off the main 5V supply.
+ */
+ gpio-poweroff {
+ compatible = "gpio-poweroff";
+ gpios = <&gpio 107 GPIO_ACTIVE_LOW>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&system_power_pin>;
+ };
+
+ /*
+ * This is a 5V current limiting regulator that is shared by USB,
+ * the sensor (input) ports, the motor (output) ports and the A/DC.
+ */
+ vcc5v: regulator1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&vcc5v_pins>;
+ compatible = "regulator-fixed";
+ regulator-name = "vcc5v";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ gpio = <&gpio 101 0>;
+ over-current-gpios = <&gpio 99 GPIO_ACTIVE_LOW>;
+ enable-active-high;
+ regulator-boot-on;
+ };
+};
+
+&pmx_core {
+ status = "okay";
+
+ spi0_cs3_pin: pinmux_spi0_cs3_pin {
+ pinctrl-single,bits = <
+ /* CS3 */
+ 0xc 0x01000000 0x0f000000
+ >;
+ };
+
+ mmc0_cd_pin: pinmux_mmc0_cd {
+ pinctrl-single,bits = <
+ /* GP5[14] */
+ 0x2C 0x00000080 0x000000f0
+ >;
+ };
+
+ button_pins: pinmux_button_pins {
+ pinctrl-single,bits = <
+ /* GP1[13] */
+ 0x8 0x00000800 0x00000f00
+ /* GP6[10] */
+ 0x34 0x00800000 0x00f00000
+ /* GP6[6] */
+ 0x38 0x00000080 0x000000f0
+ /* GP7[12], GP7[14], GP7[15] */
+ 0x40 0x00808800 0x00f0ff00
+ >;
+ };
+
+ led_pins: pinmux_led_pins {
+ pinctrl-single,bits = <
+ /* GP6[12], GP6[13], GP6[14] */
+ 0x34 0x00008880 0x0000fff0
+ /* GP6[7] */
+ 0x38 0x00000008 0x0000000f
+ >;
+ };
+
+ system_power_pin: pinmux_system_power {
+ pinctrl-single,bits = <
+ /* GP6[11] */
+ 0x34 0x00080000 0x000f0000
+ >;
+ };
+
+ vcc5v_pins: pinmux_vcc5v {
+ pinctrl-single,bits = <
+ /* GP6[5] */
+ 0x40 0x00000080 0x000000f0
+ /* GP6[3] */
+ 0x4c 0x00008000 0x0000f000
+ >;
+ };
+};
+
+&pinconf {
+ status = "okay";
+
+ /* Buttons have external pulldown resistors */
+ button_bias: button-bias-groups {
+ disable {
+ groups = "cp5", "cp24", "cp25", "cp28";
+ bias-disable;
+ };
+ };
+};
+
+/* Input port 1 */
+&serial1 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&serial1_rxtx_pins>;
+};
+
+&rtc0 {
+ status = "okay";
+};
+
+&i2c0 {
+ status = "okay";
+ clock-frequency = <400000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c0_pins>;
+
+ /*
+ * EEPROM contains the first stage bootloader, HW ID and Bluetooth MAC.
+ */
+ eeprom@50 {
+ compatible = "at24,24c128";
+ pagesize = <64>;
+ read-only;
+ reg = <0x50>;
+ };
+};
+
+&wdt {
+ status = "okay";
+};
+
+&mmc0 {
+ status = "okay";
+ max-frequency = <50000000>;
+ bus-width = <4>;
+ cd-gpios = <&gpio 94 GPIO_ACTIVE_LOW>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&mmc0_pins>, <&mmc0_cd_pin>;
+};
+
+&spi0 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&spi0_pins>, <&spi0_cs0_pin>, <&spi0_cs3_pin>;
+
+ flash@0 {
+ compatible = "n25q128a13", "jedec,spi-nor";
+ reg = <0>;
+ spi-max-frequency = <50000000>;
+ ti,spi-wdelay = <8>;
+
+ /* Partitions are based on the official firmware from LEGO */
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ partition@0 {
+ label = "U-Boot";
+ reg = <0 0x40000>;
+ };
+
+ partition@40000 {
+ label = "U-Boot Env";
+ reg = <0x40000 0x10000>;
+ };
+
+ partition@50000 {
+ label = "Kernel";
+ reg = <0x50000 0x200000>;
+ };
+
+ partition@250000 {
+ label = "Filesystem";
+ reg = <0x250000 0xa50000>;
+ };
+
+ partition@cb0000 {
+ label = "Storage";
+ reg = <0xcb0000 0x2f0000>;
+ };
+ };
+ };
+};
+
+&gpio {
+ status = "okay";
+};
+
+&usb_phy {
+ status = "okay";
+};
+
+&usb0 {
+ status = "okay";
+};
+
+&usb1 {
+ status = "okay";
+ vbus-supply = <&vcc5v>;
+};
--
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 v2] i2c: do not enable fall back to Host Notify by default
From: Dmitry Torokhov @ 2017-01-12 20:33 UTC (permalink / raw)
To: Wolfram Sang
Cc: Rob Herring, Benjamin Tissoires, Pali Rohár,
Michał Kępień, Jean Delvare, Takashi Iwai,
linux-i2c, devicetree, linux-kernel
In-Reply-To: <20170112184101.slxulrvreq7zl2pc@ninjato>
On Thu, Jan 12, 2017 at 07:41:01PM +0100, Wolfram Sang wrote:
> On Wed, Jan 04, 2017 at 08:57:22PM -0800, Dmitry Torokhov wrote:
> > Falling back unconditionally to HostNotify as primary client's interrupt
> > breaks some drivers which alter their functionality depending on whether
> > interrupt is present or not, so let's introduce a board flag telling I2C
> > core explicitly if we want wired interrupt or HostNotify-based one:
> > I2C_CLIENT_HOST_NOTIFY.
> >
> > For DT-based systems we introduce "host-notify" property that we convert
> > to I2C_CLIENT_HOST_NOTIFY board flag.
> >
> > Tested-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
> > Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
>
> Applied to for-current, thanks!
>
> How do we handle driver fixes? Shall I take them via I2C to have the
> dependency clear? Or can they go seperately?
The drivers that need this will go [hopefully] into next so they should
be OK to go through my tree.
--
Dmitry
^ permalink raw reply
* RE: [PATCH] ARM: dts: r7s72100: fix sdhi clock define
From: Chris Brandt @ 2017-01-12 20:34 UTC (permalink / raw)
To: Geert Uytterhoeven
Cc: Simon Horman, Magnus Damm, Rob Herring, Mark Rutland,
devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, Linux-Renesas
In-Reply-To: <CAMuHMdUz6nb-STMQK39hDqwHRt4R5t+Lndj150Lkg7prN=HQZQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
Hi Geert,
On Thursday, January 12, 2017, Geert Uytterhoeven wrote:
> This is strange. There are two SDHI channels, but the STBCR12
> documentation (all versions up to rev. 3.00) says the register has MSTP
> bits for four SD host interfaces?
>
> Can you please enlighten me? Thanks!
Ya, I saw that. There are 2 bits per SDHI channel. I did check and just
enabling the one works fine.
Honestly, I'm not sure why there are two clock enables.
I'll go back and ask the design team if they can tell me why there are 2.
As I said, I just re-tested and it works fine, but you can hold off on the
patch if you want until I come up with a real explanation.
Chris
^ permalink raw reply
* Re: [PATCH v8 2/5] i2c: Add STM32F4 I2C driver
From: M'boumba Cedric Madianga @ 2017-01-12 20:58 UTC (permalink / raw)
To: Uwe Kleine-König
Cc: Wolfram Sang, Rob Herring, Maxime Coquelin, Alexandre Torgue,
Linus Walleij, Patrice Chotard, Russell King,
linux-i2c-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20170112174902.j52foglkdouyz36n-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
2017-01-12 18:49 GMT+01:00 Uwe Kleine-König <u.kleine-koenig@pengutronix.de>:
> On Thu, Jan 12, 2017 at 02:47:42PM +0100, M'boumba Cedric Madianga wrote:
>> 2017-01-12 13:03 GMT+01:00 Uwe Kleine-König <u.kleine-koenig@pengutronix.de>:
>> > Hello Cedric,
>> >
>> > On Thu, Jan 12, 2017 at 12:23:12PM +0100, M'boumba Cedric Madianga wrote:
>> >> 2017-01-11 16:39 GMT+01:00 Uwe Kleine-König <u.kleine-koenig@pengutronix.de>:
>> >> > On Wed, Jan 11, 2017 at 02:58:44PM +0100, M'boumba Cedric Madianga wrote:
>> >> >> 2017-01-11 9:22 GMT+01:00 Uwe Kleine-König <u.kleine-koenig@pengutronix.de>:
>> >> >> > This is surprising. I didn't recheck the manual, but that looks very
>> >> >> > uncomfortable.
>> >> >>
>> >> >> I agree but this exactly the hardware way of working described in the
>> >> >> reference manual.
>> >> >
>> >> > IMHO that's a hw bug. This makes it for example impossible to implement
>> >> > SMBus block transfers (I think).
>> >>
>> >> This is not correct.
>> >> Setting STOP/START bit does not mean the the pulse will be sent right now.
>> >> Here we have just to prepare the hardware for the 2 next pulse but the
>> >> STOP/START/ACK pulse will be generated at the right time as required
>> >> by I2C specification.
>> >> So SMBus block transfer will be possible.
>> >
>> > A block transfer consists of a byte that specifies the count of bytes
>> > yet to come. So the device sends for example:
>> >
>> > 0x01 0xab
>> >
>> > So when you read the 1 in the first byte it's already too late to set
>> > STOP to get it after the 2nd byte.
>> >
>> > Not sure I got all the required details right, though.
>>
>> Ok I understand your use case but I always think that the harware manages it.
>> If I take the above example, the I2C SMBus block read transaction will
>> be as below:
>> S Addr Wr [A] Comm [A]
>> S Addr Rd [A] [Count] A [Data1] A [Data2] NA P
>>
>> The first message is a single byte-transmission so there is no problem.
>>
>> The second message is a N-byte reception with N = 3
>>
>> When the I2C controller has finished to send the device address (S
>> Addr Rd), the ADDR flag is set and an interrupt is raised.
>> In the routine that handles ADDR event, we set ACK bit in order to
>> generate ACK pulse as soon as a data byte is received in the shift
>> register and then we clear the ADDR flag.
>> Please note that the SCL line is stretched low until ADDR flag is cleared.
>> So, as far I understand, the device could not sent any data as long as
>> the SCL line is stretched low. Right ?
>>
>> Then, as soon as the SCL line is high, the device could send the first
>> data byte (Count).
>> When this byte is received in the shift register, an ACK is
>> automatically generated as defined during adress match phase and the
>> data byte is pushed in DR (data register).
>> Then, an interrupt is raised as RXNE (RX not empty) flag is set.
>> In the routine that handles RXNE event, as N=3, we just clear all
>> buffer interrupts in order to avoid another system preemption due to
>> RXNE event but we does not read the data in DR.
>
> In my example I want to receive a block of length 1, so only two bytes
> are read, a 1 (the length) and the data byte (0xab in my example). I
> think that as soon as you read the 1 it's already to late to schedule
> the NA after the next byte?
Not really. This 2-byte reception is also correctly managed.
Indeed, in this case, when the controller has sent the device address,
the ADDR flag is set and an interrupt is raised.
So, as long as the ADDR flag is not cleared, the SCL line is stretched
low and the device could not send any data.
During this address match phase, for a 2-byte reception, we enable
NACK and set POS bit (ACK/NACK position).
As POS=1, the NACK will be sent for the next byte which will be
received in the shift register instead of the current one.
So in this example, the next byte will be the last one.
After that, we clear the ADDR flag and the device is allowed to send data.
When the first data is received in the shift register, the RXNE flag
is set and an interrupt is raised.
As it is a 2-byte reception, we just clear all interrupts buffer to
avoid another preemption due to RXNE but we does not read DR.
Then, the second and last byte is received in the shift register.
The NACK is automatically sent by I2C controller as it was configured
to do that in the address match phase described above.
Moereover, as the first byte has not been read in DR, the BTF event
flag is set and an interrupt is raised.
Again, the SCL line is stretching low as long as data register has not
been read.
In the meantime, we set STOP bit to generate the pulse and we launch 2
consecutive read of DR to retrieve the 2 data bytes and release SCL
stretching.
In that way, NA and STOP are generated as expected even for a 2-byte reception.
Best regards,
Cedric
--
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
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